expiration-check/checker/domains.go
Simon Vieille 3616ac7d70
All checks were successful
ci/woodpecker/push/build Pipeline was successful
ci/woodpecker/tag/build Pipeline was successful
add whois as RDAP fallback
2024-07-22 14:32:50 +02:00

140 lines
2.7 KiB
Go

package checker
import (
"encoding/json"
"fmt"
"math"
"net/http"
"regexp"
"strings"
"time"
"github.com/likexian/whois"
)
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
return Domain{
Name: domain,
DaysLeft: math.Floor(daysLeft),
Date: date.Format(time.DateTime),
}
}
}
return Domain{Name: domain, Failed: true}
}
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
return Domain{
Name: domain,
DaysLeft: math.Floor(daysLeft),
Date: date.Format(time.DateTime),
}
}
}
}
}
return domainFailed
}
func CheckDomains(domains []string) []Domain {
values := []Domain{}
services := GetRdapServices()
for _, domain := range domains {
tld := ExtractTld(domain)
service := services[tld]
if service != "" {
values = append(values, RdapCheck(domain, service))
} else {
values = append(values, WhoisCheck(domain))
}
}
return values
}