1package goinwx
2
3import (
4	"errors"
5	"fmt"
6	"time"
7
8	"github.com/fatih/structs"
9	"github.com/mitchellh/mapstructure"
10)
11
12const (
13	methodNameserverCheck        = "nameserver.check"
14	methodNameserverCreate       = "nameserver.create"
15	methodNameserverCreateRecord = "nameserver.createRecord"
16	methodNameserverDelete       = "nameserver.delete"
17	methodNameserverDeleteRecord = "nameserver.deleteRecord"
18	methodNameserverInfo         = "nameserver.info"
19	methodNameserverList         = "nameserver.list"
20	methodNameserverUpdate       = "nameserver.update"
21	methodNameserverUpdateRecord = "nameserver.updateRecord"
22)
23
24// NameserverService API access to Nameservers.
25type NameserverService service
26
27// Check Checks a domain on nameservers.
28func (s *NameserverService) Check(domain string, nameservers []string) (*NameserverCheckResponse, error) {
29	req := s.client.NewRequest(methodNameserverCheck, map[string]interface{}{
30		"domain": domain,
31		"ns":     nameservers,
32	})
33
34	resp, err := s.client.Do(*req)
35	if err != nil {
36		return nil, err
37	}
38
39	var result NameserverCheckResponse
40	err = mapstructure.Decode(*resp, &result)
41	if err != nil {
42		return nil, err
43	}
44
45	return &result, nil
46}
47
48// Info Gets information.
49func (s *NameserverService) Info(request *NameserverInfoRequest) (*NamserverInfoResponse, error) {
50	req := s.client.NewRequest(methodNameserverInfo, structs.Map(request))
51
52	resp, err := s.client.Do(*req)
53	if err != nil {
54		return nil, err
55	}
56
57	result := NamserverInfoResponse{}
58	err = mapstructure.Decode(*resp, &result)
59	if err != nil {
60		return nil, err
61	}
62
63	return &result, nil
64}
65
66// List List nameservers for a domain.
67func (s *NameserverService) List(domain string) (*NamserverListResponse, error) {
68	requestMap := map[string]interface{}{
69		"domain": "*",
70		"wide":   2,
71	}
72
73	if domain != "" {
74		requestMap["domain"] = domain
75	}
76
77	req := s.client.NewRequest(methodNameserverList, requestMap)
78
79	resp, err := s.client.Do(*req)
80	if err != nil {
81		return nil, err
82	}
83
84	result := NamserverListResponse{}
85	err = mapstructure.Decode(*resp, &result)
86	if err != nil {
87		return nil, err
88	}
89
90	return &result, nil
91}
92
93// Create Creates a nameserver.
94func (s *NameserverService) Create(request *NameserverCreateRequest) (int, error) {
95	req := s.client.NewRequest(methodNameserverCreate, structs.Map(request))
96
97	resp, err := s.client.Do(*req)
98	if err != nil {
99		return 0, err
100	}
101
102	var result map[string]int
103	err = mapstructure.Decode(*resp, &result)
104	if err != nil {
105		return 0, err
106	}
107
108	return result["roId"], nil
109}
110
111// CreateRecord Creates a DNS record.
112func (s *NameserverService) CreateRecord(request *NameserverRecordRequest) (int, error) {
113	req := s.client.NewRequest(methodNameserverCreateRecord, structs.Map(request))
114
115	resp, err := s.client.Do(*req)
116	if err != nil {
117		return 0, err
118	}
119
120	var result map[string]int
121	err = mapstructure.Decode(*resp, &result)
122	if err != nil {
123		return 0, err
124	}
125
126	return result["id"], nil
127}
128
129// UpdateRecord Updates a DNS record.
130func (s *NameserverService) UpdateRecord(recID int, request *NameserverRecordRequest) error {
131	if request == nil {
132		return errors.New("request can't be nil")
133	}
134
135	requestMap := structs.Map(request)
136	requestMap["id"] = recID
137
138	req := s.client.NewRequest(methodNameserverUpdateRecord, requestMap)
139
140	_, err := s.client.Do(*req)
141	if err != nil {
142		return err
143	}
144
145	return nil
146}
147
148// DeleteRecord Deletes a DNS record.
149func (s *NameserverService) DeleteRecord(recID int) error {
150	req := s.client.NewRequest(methodNameserverDeleteRecord, map[string]interface{}{
151		"id": recID,
152	})
153
154	_, err := s.client.Do(*req)
155	if err != nil {
156		return err
157	}
158
159	return nil
160}
161
162// FindRecordByID Search a DNS record by ID.
163func (s *NameserverService) FindRecordByID(recID int) (*NameserverRecord, *NameserverDomain, error) {
164	listResp, err := s.client.Nameservers.List("")
165	if err != nil {
166		return nil, nil, err
167	}
168
169	for _, domainItem := range listResp.Domains {
170		resp, err := s.client.Nameservers.Info(&NameserverInfoRequest{RoID: domainItem.RoID})
171		if err != nil {
172			return nil, nil, err
173		}
174
175		for _, record := range resp.Records {
176			if record.ID == recID {
177				return &record, &domainItem, nil
178			}
179		}
180	}
181
182	return nil, nil, fmt.Errorf("couldn't find INWX Record for id %d", recID)
183}
184
185// NameserverCheckResponse API model.
186type NameserverCheckResponse struct {
187	Details []string
188	Status  string
189}
190
191// NameserverRecordRequest API model.
192type NameserverRecordRequest struct {
193	RoID                   int    `structs:"roId,omitempty"`
194	Domain                 string `structs:"domain,omitempty"`
195	Type                   string `structs:"type"`
196	Content                string `structs:"content"`
197	Name                   string `structs:"name,omitempty"`
198	TTL                    int    `structs:"ttl,omitempty"`
199	Priority               int    `structs:"prio,omitempty"`
200	URLRedirectType        string `structs:"urlRedirectType,omitempty"`
201	URLRedirectTitle       string `structs:"urlRedirectTitle,omitempty"`
202	URLRedirectDescription string `structs:"urlRedirectDescription,omitempty"`
203	URLRedirectFavIcon     string `structs:"urlRedirectFavIcon,omitempty"`
204	URLRedirectKeywords    string `structs:"urlRedirectKeywords,omitempty"`
205}
206
207// NameserverCreateRequest API model.
208type NameserverCreateRequest struct {
209	Domain                 string   `structs:"domain"`
210	Type                   string   `structs:"type"`
211	Nameservers            []string `structs:"ns,omitempty"`
212	MasterIP               string   `structs:"masterIp,omitempty"`
213	Web                    string   `structs:"web,omitempty"`
214	Mail                   string   `structs:"mail,omitempty"`
215	SoaEmail               string   `structs:"soaEmail,omitempty"`
216	URLRedirectType        string   `structs:"urlRedirectType,omitempty"`
217	URLRedirectTitle       string   `structs:"urlRedirectTitle,omitempty"`
218	URLRedirectDescription string   `structs:"urlRedirectDescription,omitempty"`
219	URLRedirectFavIcon     string   `structs:"urlRedirectFavIcon,omitempty"`
220	URLRedirectKeywords    string   `structs:"urlRedirectKeywords,omitempty"`
221	Testing                bool     `structs:"testing,omitempty"`
222}
223
224// NameserverInfoRequest API model.
225type NameserverInfoRequest struct {
226	Domain   string `structs:"domain,omitempty"`
227	RoID     int    `structs:"roId,omitempty"`
228	RecordID int    `structs:"recordId,omitempty"`
229	Type     string `structs:"type,omitempty"`
230	Name     string `structs:"name,omitempty"`
231	Content  string `structs:"content,omitempty"`
232	TTL      int    `structs:"ttl,omitempty"`
233	Priority int    `structs:"prio,omitempty"`
234}
235
236// NamserverInfoResponse API model.
237type NamserverInfoResponse struct {
238	RoID          int                `mapstructure:"roId"`
239	Domain        string             `mapstructure:"domain"`
240	Type          string             `mapstructure:"type"`
241	MasterIP      string             `mapstructure:"masterIp"`
242	LastZoneCheck time.Time          `mapstructure:"lastZoneCheck"`
243	SlaveDNS      []SlaveInfo        `mapstructure:"slaveDns"`
244	SOASerial     string             `mapstructure:"SOAserial"`
245	Count         int                `mapstructure:"count"`
246	Records       []NameserverRecord `mapstructure:"record"`
247}
248
249// SlaveInfo API model.
250type SlaveInfo struct {
251	Name string `mapstructure:"name"`
252	IP   string `mapstructure:"ip"`
253}
254
255// NameserverRecord API model.
256type NameserverRecord struct {
257	ID                     int    `mapstructure:"id"`
258	Name                   string `mapstructure:"name"`
259	Type                   string `mapstructure:"type"`
260	Content                string `mapstructure:"content"`
261	TTL                    int    `mapstructure:"TTL"`
262	Priority               int    `mapstructure:"prio"`
263	URLRedirectType        string `mapstructure:"urlRedirectType"`
264	URLRedirectTitle       string `mapstructure:"urlRedirectTitle"`
265	URLRedirectDescription string `mapstructure:"urlRedirectDescription"`
266	URLRedirectKeywords    string `mapstructure:"urlRedirectKeywords"`
267	URLRedirectFavIcon     string `mapstructure:"urlRedirectFavIcon"`
268}
269
270// NamserverListResponse API model.
271type NamserverListResponse struct {
272	Count   int
273	Domains []NameserverDomain `mapstructure:"domains"`
274}
275
276// NameserverDomain API model.
277type NameserverDomain struct {
278	RoID     int    `mapstructure:"roId"`
279	Domain   string `mapstructure:"domain"`
280	Type     string `mapstructure:"type"`
281	MasterIP string `mapstructure:"masterIp"`
282	Mail     string `mapstructure:"mail"`
283	Web      string `mapstructure:"web"`
284	URL      string `mapstructure:"url"`
285	Ipv4     string `mapstructure:"ipv4"`
286	Ipv6     string `mapstructure:"ipv6"`
287}
288