domain.go raw
1 package goinwx
2
3 import (
4 "errors"
5 "strconv"
6 "time"
7
8 "github.com/fatih/structs"
9 "github.com/go-viper/mapstructure/v2"
10 )
11
12 const (
13 methodDomainCheck = "domain.check"
14 methodDomainCreate = "domain.create"
15 methodDomainDelete = "domain.delete"
16 methodDomainGetPrices = "domain.getPrices"
17 methodDomainGetRules = "domain.getRules"
18 methodDomainInfo = "domain.info"
19 methodDomainList = "domain.list"
20 methodDomainLog = "domain.log"
21 methodDomainPush = "domain.push"
22 methodDomainRenew = "domain.renew"
23 methodDomainRestore = "domain.restore"
24 methodDomainStats = "domain.stats"
25 methodDomainTrade = "domain.trade"
26 methodDomainTransfer = "domain.transfer"
27 methodDomainTransferOut = "domain.transferOut"
28 methodDomainUpdate = "domain.update"
29 methodDomainWhois = "domain.whois"
30 )
31
32 // DomainService API access to Domain.
33 type DomainService service
34
35 // Check checks domains.
36 func (s *DomainService) Check(domains []string) ([]DomainCheckResponse, error) {
37 req := s.client.NewRequest(methodDomainCheck, map[string]any{
38 "domain": domains,
39 "wide": "2",
40 })
41
42 resp, err := s.client.Do(req)
43 if err != nil {
44 return nil, err
45 }
46
47 root := new(domainCheckResponseRoot)
48
49 err = mapstructure.Decode(resp, &root)
50 if err != nil {
51 return nil, err
52 }
53
54 return root.Domains, nil
55 }
56
57 // GetPrices gets TLDS prices.
58 func (s *DomainService) GetPrices(tlds []string) ([]DomainPriceResponse, error) {
59 req := s.client.NewRequest(methodDomainGetPrices, map[string]any{
60 "tld": tlds,
61 "vat": false,
62 })
63
64 resp, err := s.client.Do(req)
65 if err != nil {
66 return nil, err
67 }
68
69 root := new(domainPriceResponseRoot)
70
71 err = mapstructure.Decode(resp, &root)
72 if err != nil {
73 return nil, err
74 }
75
76 return root.Prices, nil
77 }
78
79 // Register registers a domain.
80 func (s *DomainService) Register(request *DomainRegisterRequest) (*DomainRegisterResponse, error) {
81 req := s.client.NewRequest(methodDomainCreate, structs.Map(request))
82
83 resp, err := s.client.Do(req)
84 if err != nil {
85 return nil, err
86 }
87
88 var result DomainRegisterResponse
89
90 err = mapstructure.Decode(resp, &result)
91 if err != nil {
92 return nil, err
93 }
94
95 return &result, nil
96 }
97
98 // Delete deletes a domain.
99 func (s *DomainService) Delete(domain string, scheduledDate time.Time) error {
100 req := s.client.NewRequest(methodDomainDelete, map[string]any{
101 "domain": domain,
102 "scDate": scheduledDate.Format(time.RFC3339),
103 })
104
105 _, err := s.client.Do(req)
106
107 return err
108 }
109
110 // Info gets information about a domain.
111 func (s *DomainService) Info(domain string, roID int) (*DomainInfoResponse, error) {
112 req := s.client.NewRequest(methodDomainInfo, map[string]any{
113 "domain": domain,
114 "wide": "2",
115 })
116 if roID != 0 {
117 req.Args["roId"] = roID
118 }
119
120 resp, err := s.client.Do(req)
121 if err != nil {
122 return nil, err
123 }
124
125 var result DomainInfoResponse
126
127 err = mapstructure.Decode(resp, &result)
128 if err != nil {
129 return nil, err
130 }
131
132 return &result, nil
133 }
134
135 // List lists domains.
136 func (s *DomainService) List(request *DomainListRequest) (*DomainList, error) {
137 if request == nil {
138 return nil, errors.New("request can't be nil")
139 }
140
141 requestMap := structs.Map(request)
142 requestMap["wide"] = "2"
143
144 req := s.client.NewRequest(methodDomainList, requestMap)
145
146 resp, err := s.client.Do(req)
147 if err != nil {
148 return nil, err
149 }
150
151 // This is a (temporary) workaround to convert the API response from string to int.
152 // The code only applies when string is being return, otherwise it's being skipped.
153 // As per docs at https://www.inwx.com/en/help/apidoc/f/ch02s08.html#domain.list we should get int here, but apparently it's not the case.
154 // Ticket 10026265 with INWX was raised.
155 if countStr, ok := resp["count"].(string); ok {
156 // If we land here, we got string back, but we expect int.
157 // Converting value to int and writing it to the response.
158 if num, ok := strconv.Atoi(countStr); ok == nil {
159 resp["count"] = num
160 }
161 }
162
163 var result DomainList
164
165 err = mapstructure.Decode(resp, &result)
166 if err != nil {
167 return nil, err
168 }
169
170 return &result, nil
171 }
172
173 // Whois information about a domains.
174 func (s *DomainService) Whois(domain string) (string, error) {
175 req := s.client.NewRequest(methodDomainWhois, map[string]any{
176 "domain": domain,
177 })
178
179 resp, err := s.client.Do(req)
180 if err != nil {
181 return "", err
182 }
183
184 var result map[string]string
185
186 err = mapstructure.Decode(resp, &result)
187 if err != nil {
188 return "", err
189 }
190
191 return result["whois"], nil
192 }
193
194 // Update updates domain information.
195 func (s *DomainService) Update(request *DomainUpdateRequest) (float32, error) {
196 req := s.client.NewRequest(methodDomainUpdate, structs.Map(request))
197
198 resp, err := s.client.Do(req)
199 if err != nil {
200 return 0, err
201 }
202
203 var result DomainUpdateResponse
204
205 err = mapstructure.Decode(resp, &result)
206 if err != nil {
207 return 0, err
208 }
209
210 return result.Price, nil
211 }
212
213 type domainCheckResponseRoot struct {
214 Domains []DomainCheckResponse `mapstructure:"domain"`
215 }
216
217 // DomainCheckResponse API model.
218 type DomainCheckResponse struct {
219 Available int `mapstructure:"avail"`
220 Status string `mapstructure:"status"`
221 Name string `mapstructure:"name"`
222 Domain string `mapstructure:"domain"`
223 TLD string `mapstructure:"tld"`
224 CheckMethod string `mapstructure:"checkmethod"`
225 Price float32 `mapstructure:"price"`
226 CheckTime float32 `mapstructure:"checktime"`
227 }
228
229 type domainPriceResponseRoot struct {
230 Prices []DomainPriceResponse `mapstructure:"price"`
231 }
232
233 // DomainPriceResponse API model.
234 type DomainPriceResponse struct {
235 Tld string `mapstructure:"tld"`
236 Currency string `mapstructure:"currency"`
237 CreatePrice float32 `mapstructure:"createPrice"`
238 MonthlyCreatePrice float32 `mapstructure:"monthlyCreatePrice"`
239 TransferPrice float32 `mapstructure:"transferPrice"`
240 RenewalPrice float32 `mapstructure:"renewalPrice"`
241 MonthlyRenewalPrice float32 `mapstructure:"monthlyRenewalPrice"`
242 UpdatePrice float32 `mapstructure:"updatePrice"`
243 TradePrice float32 `mapstructure:"tradePrice"`
244 TrusteePrice float32 `mapstructure:"trusteePrice"`
245 MonthlyTrusteePrice float32 `mapstructure:"monthlyTrusteePrice"`
246 CreatePeriod int `mapstructure:"createPeriod"`
247 TransferPeriod int `mapstructure:"transferPeriod"`
248 RenewalPeriod int `mapstructure:"renewalPeriod"`
249 TradePeriod int `mapstructure:"tradePeriod"`
250 }
251
252 // DomainRegisterRequest API model.
253 type DomainRegisterRequest struct {
254 Domain string `structs:"domain"`
255 Period string `structs:"period,omitempty"`
256 Registrant int `structs:"registrant"`
257 Admin int `structs:"admin"`
258 Tech int `structs:"tech"`
259 Billing int `structs:"billing"`
260 Nameservers []string `structs:"ns,omitempty"`
261 TransferLock string `structs:"transferLock,omitempty"`
262 RenewalMode string `structs:"renewalMode,omitempty"`
263 WhoisProvider string `structs:"whoisProvider,omitempty"`
264 WhoisURL string `structs:"whoisUrl,omitempty"`
265 ScDate string `structs:"scDate,omitempty"`
266 ExtDate string `structs:"extDate,omitempty"`
267 Asynchron string `structs:"asynchron,omitempty"`
268 Voucher string `structs:"voucher,omitempty"`
269 Testing string `structs:"testing,omitempty"`
270 }
271
272 // DomainRegisterResponse API model.
273 type DomainRegisterResponse struct {
274 RoID int `mapstructure:"roId"`
275 Price float32 `mapstructure:"price"`
276 Currency string `mapstructure:"currency"`
277 }
278
279 // DomainInfoResponse API model.
280 type DomainInfoResponse struct {
281 RoID int `mapstructure:"roId"`
282 Domain string `mapstructure:"domain"`
283 DomainAce string `mapstructure:"domainAce"`
284 Period string `mapstructure:"period"`
285 CrDate time.Time `mapstructure:"crDate"`
286 ExDate time.Time `mapstructure:"exDate"`
287 UpDate time.Time `mapstructure:"upDate"`
288 ReDate time.Time `mapstructure:"reDate"`
289 ScDate time.Time `mapstructure:"scDate"`
290 TransferLock bool `mapstructure:"transferLock"`
291 Status string `mapstructure:"status"`
292 AuthCode string `mapstructure:"authCode"`
293 RenewalMode string `mapstructure:"renewalMode"`
294 TransferMode string `mapstructure:"transferMode"`
295 Registrant int `mapstructure:"registrant"`
296 Admin int `mapstructure:"admin"`
297 Tech int `mapstructure:"tech"`
298 Billing int `mapstructure:"billing"`
299 Nameservers []string `mapstructure:"ns"`
300 NoDelegation bool `mapstructure:"noDelegation"`
301 Contacts map[string]Contact `mapstructure:"contact"`
302 }
303
304 // Contact API model.
305 type Contact struct {
306 RoID int `mapstructure:"roId"`
307 ID string `mapstructure:"id"`
308 Type string `mapstructure:"type"`
309 Name string `mapstructure:"name"`
310 Org string `mapstructure:"org"`
311 Street string `mapstructure:"street"`
312 City string `mapstructure:"city"`
313 PostalCode string `mapstructure:"pc"`
314 StateProvince string `mapstructure:"sp"`
315 Country string `mapstructure:"cc"`
316 Phone string `mapstructure:"voice"`
317 Fax string `mapstructure:"fax"`
318 Email string `mapstructure:"email"`
319 Remarks string `mapstructure:"remarks"`
320 Protection string `mapstructure:"protection"`
321 }
322
323 // DomainListRequest API model.
324 type DomainListRequest struct {
325 Domain string `structs:"domain,omitempty"`
326 RoID int `structs:"roId,omitempty"`
327 Status int `structs:"status,omitempty"`
328 Registrant int `structs:"registrant,omitempty"`
329 Admin int `structs:"admin,omitempty"`
330 Tech int `structs:"tech,omitempty"`
331 Billing int `structs:"billing,omitempty"`
332 RenewalMode int `structs:"renewalMode,omitempty"`
333 TransferLock int `structs:"transferLock,omitempty"`
334 NoDelegation int `structs:"noDelegation,omitempty"`
335 Tag int `structs:"tag,omitempty"`
336 Order int `structs:"order,omitempty"`
337 Page int `structs:"page,omitempty"`
338 PageLimit int `structs:"pagelimit,omitempty"`
339 }
340
341 // DomainList API model.
342 type DomainList struct {
343 Count int `mapstructure:"count"`
344 Domains []DomainInfoResponse `mapstructure:"domain"`
345 }
346
347 // DomainUpdateRequest API model.
348 type DomainUpdateRequest struct {
349 Domain string `structs:"domain"`
350 Nameservers []string `structs:"ns,omitempty"`
351 TransferLock int `structs:"transferLock,omitempty"`
352 RenewalMode string `structs:"renewalMode,omitempty"`
353 TransferMode string `structs:"transferMode,omitempty"`
354 // unsupported fields:
355 // registrant: New owner contact handle id (int, false)
356 // admin: New administrative contact handle id (int, false)
357 // tech: New technical contact handle id (int, false)
358 // billing: New billing contact handle id (int, false)
359 // authCode: Authorization code (if supported) (text64, false)
360 // scDate: Time of scheduled execution (timestamp, false)
361 // whoisProvider: Whois provider (token0255, false)
362 // whoisUrl: Whois url (token0255, false)
363 // extData: Domain extra data (extData, false)
364 // asynchron: Asynchron domain update boolean (false, false)
365 // testing: Execute command in testing mode boolean (false, false)
366 }
367
368 // DomainUpdateResponse API model.
369 type DomainUpdateResponse struct {
370 Price float32 `mapstructure:"price"`
371 }
372