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