package main
// https://pkg.go.dev/github.com/tebeka/selenium#example-package
// https://github.com/domainr/whois
// https://golangexample.com/dns-lookup-using-go/
/*
chandler@xenon ~/projects/hats-domains % for i in {1..50}; do [21:17:08]
dig ${i}hats.com | grep -i nxdomain >/dev/null && echo ${i}hats.com is available
done
5hats.com is available
16hats.com is available
26hats.com is available
28hats.com is available
30hats.com is available
35hats.com is available
36hats.com is available
37hats.com is available
41hats.com is available
43hats.com is available
44hats.com is available
46hats.com is available
48hats.com is available
49hats.com is available
[1] chandler@xenon ~/projects/hats-domains %
*/
import (
"flag"
"fmt"
"html/template"
"io"
"log"
"net/http"
"os"
"time"
"github.com/tebeka/selenium"
)
type HatsSite struct {
DomainName string
Owner string
Since time.Time
ScreenshotURL string
Title string
FetchTime time.Time
HTTPOpen bool
HTTPSOpen bool
}
func getSites(largest int, wd selenium.WebDriver) (sites []HatsSite, err error) {
for i := 2; i <= largest; i++ {
domainName := fmt.Sprintf("%vhats.com", i)
err := wd.Get(fmt.Sprintf("http://%v/", domainName))
if err != nil {
return sites, err
}
title, err := wd.Title()
if err != nil {
return sites, err
}
screenshot, err := wd.Screenshot()
if err != nil {
return sites, err
}
sites = append(sites, HatsSite{
DomainName: domainName,
Owner: "unknown",
ScreenshotURL: string(screenshot),
Title: title,
FetchTime: time.Now(),
HTTPOpen: false, // TODO
HTTPSOpen: false, // TODO
})
}
return sites, nil
}
func generateHTML(sites []HatsSite, w io.Writer) error {
tmpl, err := template.New("main").Parse(`
{n}hats.com domains
{n}hats.com domains
{{range .}}
{{.DomainName}}
- Fetched
- {{.FetchTime}}
- Title
- {{.Title}}
- Owner
- {{.Owner}}
- Since
- {{.Since}}
{{end}}
`)
if err != nil {
return err
}
return tmpl.Execute(w, sites)
}
func main() {
serve := flag.Bool("serve", false, "Serve HTTP rather than writing a file")
filename := flag.String("path", "index.html", "Output filename (if -serve=false, default)")
port := flag.Int("port", 8080, "Port to serve on")
largest := flag.Int("largest", 50, "largest n for {n}hats.com")
flag.Parse()
const (
// These paths will be different on your system.
seleniumPath = "deps/selenium-server-standalone-3.141.59.jar"
geckoDriverPath = "deps/geckodriver"
seleniumPort = 8080
)
opts := []selenium.ServiceOption{
selenium.StartFrameBuffer(), // Start an X frame buffer for the browser to run in.
selenium.GeckoDriver(geckoDriverPath), // Specify the path to GeckoDriver in order to use Firefox.
selenium.Output(nil),
}
selenium.SetDebug(true)
service, err := selenium.NewSeleniumService(seleniumPath, seleniumPort, opts...)
if err != nil {
panic(err) // panic is used only as an example and is not otherwise recommended.
}
defer service.Stop()
// Connect to the WebDriver instance running locally.
caps := selenium.Capabilities{"browserName": "firefox"}
wd, err := selenium.NewRemote(caps, fmt.Sprintf("http://localhost:%d/wd/hub", seleniumPort))
if err != nil {
panic(err)
}
defer wd.Quit()
if *serve {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
// err := generateHTML(w, *largest, wd)
// if err != nil {
// w.Write([]byte(err.Error()))
// }
})
fmt.Printf("Serving on %v\n", port)
log.Fatal(http.ListenAndServe(fmt.Sprintf(":%v", *port), nil))
} else {
file, err := os.Create(*filename)
if err != nil {
panic(err)
}
sites, err := getSites(*largest, wd)
if err != nil {
fmt.Println(err)
}
err = generateHTML(sites, file)
if err != nil {
fmt.Println(err)
}
}
}