Include whois information
This commit is contained in:
parent
354eb02340
commit
f3d02a7912
13
go.mod
13
go.mod
|
@ -2,6 +2,15 @@ module github.com/chandlerswift/hats-domains
|
||||||
|
|
||||||
go 1.17
|
go 1.17
|
||||||
|
|
||||||
require github.com/tebeka/selenium v0.9.9
|
require (
|
||||||
|
github.com/likexian/whois v1.12.4
|
||||||
|
github.com/likexian/whois-parser v1.22.0
|
||||||
|
github.com/tebeka/selenium v0.9.9
|
||||||
|
)
|
||||||
|
|
||||||
require github.com/blang/semver v3.5.1+incompatible // indirect
|
require (
|
||||||
|
github.com/blang/semver v3.5.1+incompatible // indirect
|
||||||
|
github.com/likexian/gokit v0.25.6 // indirect
|
||||||
|
golang.org/x/net v0.0.0-20210929193557-e81a3d93ecf6 // indirect
|
||||||
|
golang.org/x/text v0.3.7 // indirect
|
||||||
|
)
|
||||||
|
|
16
go.sum
16
go.sum
|
@ -34,6 +34,12 @@ github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5m
|
||||||
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||||
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||||
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
||||||
|
github.com/likexian/gokit v0.25.6 h1:DZuMrmfgXErhdfI9SIS6tVMZ5QbRMP3aruHNq5lGcMI=
|
||||||
|
github.com/likexian/gokit v0.25.6/go.mod h1:q1LC+z3cBymJuE4oeiWiIPhJceUa0nptg4Id8tSzjZI=
|
||||||
|
github.com/likexian/whois v1.12.4 h1:NqUNc9LC4G5Fq62o6a3nw/HO8haJDULEudcJPyPMwXg=
|
||||||
|
github.com/likexian/whois v1.12.4/go.mod h1:SfdfmB72mSdrC/8eLjYkeaEJp9t1MPAgp0ebCzZfYXw=
|
||||||
|
github.com/likexian/whois-parser v1.22.0 h1:YXSNvDNBy+cZG+2JZWJvWbMHrDY35r6Etpu1TNDPYW0=
|
||||||
|
github.com/likexian/whois-parser v1.22.0/go.mod h1:2bJqtH4tNPanBvOp/3Kj3Sd12S9vxTbsJ0+0zjRc3ow=
|
||||||
github.com/tebeka/selenium v0.9.9 h1:cNziB+etNgyH/7KlNI7RMC1ua5aH1+5wUlFQyzeMh+w=
|
github.com/tebeka/selenium v0.9.9 h1:cNziB+etNgyH/7KlNI7RMC1ua5aH1+5wUlFQyzeMh+w=
|
||||||
github.com/tebeka/selenium v0.9.9/go.mod h1:5Fr8+pUvU6B1OiPfkdCKdXZyr5znvVkxuPd0NOdZCQc=
|
github.com/tebeka/selenium v0.9.9/go.mod h1:5Fr8+pUvU6B1OiPfkdCKdXZyr5znvVkxuPd0NOdZCQc=
|
||||||
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
||||||
|
@ -58,8 +64,10 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn
|
||||||
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859 h1:R/3boaszxrf1GEUWTVDzSKVwLmSJpwZ1yqXm8j0v2QI=
|
|
||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20210928044308-7d9f5e0b762b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
|
golang.org/x/net v0.0.0-20210929193557-e81a3d93ecf6 h1:Z04ewVs7JhXaYkmDhBERPi41gnltfQpMWDnTnQbaCqk=
|
||||||
|
golang.org/x/net v0.0.0-20210929193557-e81a3d93ecf6/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
|
@ -76,9 +84,15 @@ golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||||
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||||
|
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
|
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
|
||||||
|
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
|
68
main.go
68
main.go
|
@ -36,30 +36,58 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/likexian/whois"
|
||||||
|
whoisparser "github.com/likexian/whois-parser"
|
||||||
"github.com/tebeka/selenium"
|
"github.com/tebeka/selenium"
|
||||||
)
|
)
|
||||||
|
|
||||||
type HatsSite struct {
|
type HatsSite struct {
|
||||||
DomainName string
|
DomainName string
|
||||||
Owner string
|
Available bool
|
||||||
Since time.Time
|
FetchTime time.Time
|
||||||
|
DomainInfo *whoisparser.Domain
|
||||||
|
Registrar *whoisparser.Contact
|
||||||
|
Registrant *whoisparser.Contact
|
||||||
ScreenshotURL template.URL
|
ScreenshotURL template.URL
|
||||||
Title string
|
Title string
|
||||||
FetchTime time.Time
|
|
||||||
HTTPOpen bool
|
HTTPOpen bool
|
||||||
HTTPSOpen bool
|
HTTPSOpen bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func getSites(largest int, wd selenium.WebDriver) (sites []HatsSite, err error) {
|
func getSites(largest int, wd selenium.WebDriver) (sites []HatsSite, err error) {
|
||||||
|
// TODO: 1hat.com 0hats.com, hats.com; possibly onehat.com, twohats.com, etc
|
||||||
for i := 2; i <= largest; i++ {
|
for i := 2; i <= largest; i++ {
|
||||||
domainName := fmt.Sprintf("%vhats.com", i)
|
hatsSite := HatsSite{
|
||||||
|
DomainName: fmt.Sprintf("%dhats.com", i),
|
||||||
|
FetchTime: time.Now(),
|
||||||
|
}
|
||||||
|
log.Printf("Retrieving info for %v\n", hatsSite.DomainName)
|
||||||
|
|
||||||
err := wd.Get(fmt.Sprintf("http://%v/", domainName))
|
// Check if domain is registered
|
||||||
|
query_result, err := whois.Whois(hatsSite.DomainName)
|
||||||
|
if err != nil {
|
||||||
|
return sites, err
|
||||||
|
}
|
||||||
|
result, err := whoisparser.Parse(query_result)
|
||||||
|
if err == whoisparser.ErrNotFoundDomain {
|
||||||
|
hatsSite.Available = true
|
||||||
|
sites = append(sites, hatsSite)
|
||||||
|
continue
|
||||||
|
} else if err != nil {
|
||||||
|
return sites, err
|
||||||
|
}
|
||||||
|
hatsSite.Available = false
|
||||||
|
hatsSite.DomainInfo = result.Domain
|
||||||
|
hatsSite.Registrar = result.Registrar
|
||||||
|
hatsSite.Registrant = result.Registrant
|
||||||
|
|
||||||
|
// Get web page, take screenshot
|
||||||
|
err = wd.Get(fmt.Sprintf("http://%v/", hatsSite.DomainName))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return sites, err
|
return sites, err
|
||||||
}
|
}
|
||||||
|
|
||||||
title, err := wd.Title()
|
hatsSite.Title, err = wd.Title()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return sites, err
|
return sites, err
|
||||||
}
|
}
|
||||||
|
@ -68,22 +96,18 @@ func getSites(largest int, wd selenium.WebDriver) (sites []HatsSite, err error)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return sites, err
|
return sites, err
|
||||||
}
|
}
|
||||||
|
hatsSite.ScreenshotURL = template.URL(fmt.Sprintf("data:image/png;base64,%v", base64.StdEncoding.EncodeToString(screenshot)))
|
||||||
|
|
||||||
sites = append(sites, HatsSite{
|
sites = append(sites, hatsSite)
|
||||||
DomainName: domainName,
|
|
||||||
Owner: "unknown",
|
|
||||||
ScreenshotURL: template.URL(fmt.Sprintf("data:image/png;base64,%v", base64.StdEncoding.EncodeToString(screenshot))),
|
|
||||||
Title: title,
|
|
||||||
FetchTime: time.Now(),
|
|
||||||
HTTPOpen: false, // TODO
|
|
||||||
HTTPSOpen: false, // TODO
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
return sites, nil
|
return sites, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func generateHTML(sites []HatsSite, w io.Writer) error {
|
func generateHTML(sites []HatsSite, w io.Writer) error {
|
||||||
tmpl, err := template.New("main").Parse(`<!DOCTYPE html>
|
funcs := template.FuncMap{
|
||||||
|
"parseTime": func(s string) time.Time { time, _ := time.Parse(time.RFC3339, s); return time },
|
||||||
|
}
|
||||||
|
tmpl, err := template.New("main").Funcs(funcs).Parse(`<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
|
@ -101,7 +125,11 @@ func generateHTML(sites []HatsSite, w io.Writer) error {
|
||||||
<h3>Summary</h3>
|
<h3>Summary</h3>
|
||||||
<ol>
|
<ol>
|
||||||
{{range .}}
|
{{range .}}
|
||||||
<li><a href="#{{.DomainName}}">{{.DomainName}}</a> – Registered since TODO</li>
|
{{if .Available}}
|
||||||
|
<li><a href="#{{.DomainName}}">{{.DomainName}}</a> – Available!</li>
|
||||||
|
{{else}}
|
||||||
|
<li><a href="#{{.DomainName}}">{{.DomainName}}</a> – Registered since {{(parseTime .DomainInfo.CreatedDate).Format "Mon Jan 2 2006" }}</li>
|
||||||
|
{{end}}
|
||||||
{{end}}
|
{{end}}
|
||||||
</ol>
|
</ol>
|
||||||
{{range .}}
|
{{range .}}
|
||||||
|
@ -112,9 +140,11 @@ func generateHTML(sites []HatsSite, w io.Writer) error {
|
||||||
<dt>Title</dt>
|
<dt>Title</dt>
|
||||||
<dd>{{.Title}}</dd>
|
<dd>{{.Title}}</dd>
|
||||||
<dt>Owner</dt>
|
<dt>Owner</dt>
|
||||||
<dd>{{.Owner}}</dd>
|
<dd><a href="mailto:{{.Registrant.Email}}">{{.Registrant.Name}} <{{.Registrant.Email}}></a></dd>
|
||||||
|
{{with .DomainInfo.CreatedDate}}
|
||||||
<dt>Since</dt>
|
<dt>Since</dt>
|
||||||
<dd>{{.Since.Format "Mon Jan 2 2006" }}</dd>
|
<dd>{{(parseTime .).Format "Mon Jan 2 2006" }}</dd>
|
||||||
|
{{end}}
|
||||||
</dl>
|
</dl>
|
||||||
<img src="{{.ScreenshotURL}}" alt="screenshot of {{.DomainName}} as of {{.FetchTime.Format "Mon Jan 2 15:04:05 -0700 MST 2006" }}">
|
<img src="{{.ScreenshotURL}}" alt="screenshot of {{.DomainName}} as of {{.FetchTime.Format "Mon Jan 2 15:04:05 -0700 MST 2006" }}">
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
Loading…
Reference in a new issue