package main import ( "encoding/json" "flag" "fmt" "net/http" "net/url" "os" "strings" "github.com/fatih/color" ) var Version = "develop" func main() { fs := flag.NewFlagSet("isitup", flag.ExitOnError) versionFlag := fs.Bool("version", false, "Display version and exit") fs.BoolVar(versionFlag, "v", *versionFlag, "--version") if err := fs.Parse(os.Args[1:]); err != nil { fmt.Println(err) return } if *versionFlag { fmt.Printf("isitup %s\n", Version) return } if fs.NArg() < 1 { fmt.Println("isitup requires a host to check") return } host := fs.Arg(0) r, err := Check(host) if err != nil { fmt.Println(err) return } var status string switch r.StatusCode { case 1: status = color.GreenString("up") case 2: status = color.RedString("down") case 3: status = color.BlackString("an invalid domain") default: fmt.Printf("isitup returned an invalid status %d\n", r.StatusCode) return } fmt.Printf("%s is %s!\n", color.YellowString(host), status) } // Response is a response from the API type Response struct { Domain string `json:"domain"` Port int `json:"port"` StatusCode int `json:"status_code"` ResponseIP string `json:"response_ip"` ResponseCode int `json:"response_code"` ResponseTime float64 `json:"response_time"` } // Check checks a given host func Check(host string) (*Response, error) { u, err := url.Parse(host) if err != nil { return nil, fmt.Errorf("could not parse host %q: %w", host, err) } var h string switch { case u.Scheme != "": h = u.Hostname() case u.Path != "": p := strings.TrimPrefix(u.Path, "/") h = strings.Split(p, "/")[0] default: return nil, fmt.Errorf("could not derive host from %q", host) } res, err := http.Get(fmt.Sprintf("https://isitup.org/%s.json", h)) if err != nil { return nil, fmt.Errorf("could not get from API: %w", err) } var r Response if err := json.NewDecoder(res.Body).Decode(&r); err != nil { return nil, fmt.Errorf("could not decode response body: %w", err) } return &r, nil }