master
go 95 lines 2.05 KB
Raw
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 package whoisquery
4
5 import (
6 "errors"
7 "fmt"
8 "strings"
9 "time"
10
11 "github.com/araddon/dateparse"
12 "github.com/likexian/whois"
13 whoisparser "github.com/likexian/whois-parser"
14 )
15
16 type provider interface {
17 remainingTime() (float64, error)
18 }
19
20 type whoisClient struct {
21 domainAddress string
22 client *whois.Client
23 }
24
25 func newProvider(config Config) (provider, error) {
26 domain := config.Source
27 client := whois.NewClient()
28 client.SetTimeout(config.Timeout.Duration())
29
30 return &whoisClient{
31 domainAddress: domain,
32 client: client,
33 }, nil
34 }
35
36 func (c *whoisClient) remainingTime() (float64, error) {
37 info, err := c.queryWhoisInfo()
38 if err != nil {
39 return 0, err
40 }
41
42 if info.Domain.ExpirationDate == "" {
43 if !strings.HasPrefix(c.domainAddress, "=") {
44 // some servers support requesting extended data
45 // https://github.com/netdata/netdata/issues/17907#issuecomment-2171758380
46 c.domainAddress = fmt.Sprintf("= %s", c.domainAddress)
47 return c.remainingTime()
48 }
49 }
50
51 return parseWhoisInfoExpirationDate(info)
52 }
53
54 func (c *whoisClient) queryWhoisInfo() (*whoisparser.WhoisInfo, error) {
55 resp, err := c.client.Whois(c.domainAddress)
56 if err != nil {
57 return nil, err
58 }
59
60 info, err := whoisparser.Parse(resp)
61 if err != nil {
62 return nil, err
63 }
64
65 return &info, nil
66 }
67
68 func parseWhoisInfoExpirationDate(info *whoisparser.WhoisInfo) (float64, error) {
69 if info == nil || info.Domain == nil {
70 return 0, errors.New("nil Whois Info")
71 }
72
73 if info.Domain.ExpirationDateInTime != nil {
74 return time.Until(*info.Domain.ExpirationDateInTime).Seconds(), nil
75 }
76
77 date := info.Domain.ExpirationDate
78 if date == "" {
79 return 0, errors.New("no expiration date")
80 }
81
82 if strings.Contains(date, " ") {
83 // https://community.netdata.cloud/t/whois-query-monitor-cannot-parse-expiration-time/3485
84 if v, err := time.Parse("2006.01.02 15:04:05", date); err == nil {
85 return time.Until(v).Seconds(), nil
86 }
87 }
88
89 expire, err := dateparse.ParseAny(date)
90 if err != nil {
91 return 0, err
92 }
93
94 return time.Until(expire).Seconds(), nil
95 }