expiration-check/checker/domains.go
2025-02-24 15:07:37 +01:00

159 lines
3.3 KiB
Go

package checker
import (
"encoding/json"
"fmt"
"math"
"net/http"
"regexp"
"strings"
"time"
"github.com/likexian/whois"
"gitnet.fr/deblan/expiration-check/logger"
)
type RdapResponseData struct {
Events []struct {
EventAction string `json:"eventAction"`
EventDate string `json:"eventDate"`
} `json:"events"`
}
type RdapServices struct {
Services [][][]string `json:"services"`
}
func GetRdapServices() map[string]string {
response, _ := http.Get("https://data.iana.org/rdap/dns.json")
values := make(map[string]string)
defer response.Body.Close()
var data RdapServices
json.NewDecoder(response.Body).Decode(&data)
for _, value := range data.Services {
for _, tld := range value[0] {
values[tld] = value[1][0]
}
}
return values
}
func ExtractTld(domain string) string {
elements := strings.Split(domain, ".")
if len(elements) == 1 {
return elements[0]
}
return strings.Join(elements[1:], ".")
}
func RdapCheck(domain, service string) Domain {
url := fmt.Sprintf("%sdomain/%s?jscard=1", service, domain)
response, _ := http.Get(url)
now := time.Now()
defer response.Body.Close()
var data RdapResponseData
json.NewDecoder(response.Body).Decode(&data)
for _, event := range data.Events {
if event.EventAction == "expiration" {
date, _ := time.Parse(time.RFC3339, event.EventDate)
daysLeft := date.Sub(now).Hours() / 24
d := Domain{
Name: domain,
DaysLeft: math.Floor(daysLeft),
Date: date.Format(time.DateTime),
}
logger.Get().Logf(`RdapCheck: domain="%s" value="%+v"`, domain, d)
return d
}
}
d := Domain{Name: domain, Failed: true}
logger.Get().Logf(`RdapCheck: domain="%s" value="%+v"`, domain, d)
return d
}
func WhoisCheck(domain string) Domain {
domainFailed := Domain{Name: domain, Failed: true}
result, err := whois.Whois(domain)
if err != nil {
return domainFailed
}
now := time.Now()
formats := []string{
"expiration date",
"expiry date",
"expires on",
"paid-till",
"renewal",
"expires",
"domain_datebilleduntil",
"expiration",
"registry expiry",
"registrar registration expiration",
}
result = strings.ToLower(result)
for _, format := range formats {
r, _ := regexp.Compile(fmt.Sprintf(`%s\s*:?\s*([^\s]+)`, format))
for i, match := range r.FindStringSubmatch(result) {
if i%2 == 1 {
date, err := time.Parse(time.RFC3339, strings.ToUpper(match))
if err == nil {
daysLeft := date.Sub(now).Hours() / 24
d := Domain{
Name: domain,
DaysLeft: math.Floor(daysLeft),
Date: date.Format(time.DateTime),
}
logger.Get().Logf(`WhoisCheck: domain="%s" value="%+v"`, domain, d)
return d
}
}
}
}
logger.Get().Logf(`WhoisCheck: domain="%s" value="%+v"`, domain, domainFailed)
return domainFailed
}
func CheckDomains(domains []string) []Domain {
values := []Domain{}
services := GetRdapServices()
for _, domain := range domains {
tld := ExtractTld(domain)
service := services[tld]
if service != "" {
logger.Get().Logf(`CheckDomains: domain="%s" rdap=true whois=false`, domain)
values = append(values, RdapCheck(domain, service))
} else {
logger.Get().Logf(`CheckDomains: domain="%s" rdap=false whois=true`, domain)
values = append(values, WhoisCheck(domain))
}
}
return values
}