myip/client.go

226 lines
4.5 KiB
Go
Raw Normal View History

2021-10-16 21:23:55 +00:00
package myip
2021-10-15 16:58:49 +00:00
import (
"errors"
"fmt"
"io/ioutil"
"log"
"net"
"net/http"
"os"
"sort"
2021-10-15 16:58:49 +00:00
"strings"
"time"
2021-10-15 16:58:49 +00:00
2021-10-16 18:22:55 +00:00
"github.com/jedib0t/go-pretty/v6/table"
2021-10-15 19:15:49 +00:00
"github.com/robfig/cron/v3"
2021-10-15 16:58:49 +00:00
"github.com/spf13/cobra"
)
var (
port string
host string
2021-10-15 19:15:49 +00:00
name string
2021-10-15 16:58:49 +00:00
showTitle bool
showList bool
showAll bool
showCell bool
noPub bool
secure bool
2021-10-15 19:15:49 +00:00
cronMode bool
cronSpec string
2021-10-15 16:58:49 +00:00
)
type Iface struct {
IP string
HardwareAddr string
Name string
}
2021-10-15 16:58:49 +00:00
var ClientCmd = &cobra.Command{
Use: "myip",
Short: "myip is a easy way to get public ip of current system.",
Run: func(cmd *cobra.Command, args []string) {
2021-10-15 19:15:49 +00:00
if cronMode {
block := make(chan struct{}, 1)
c := cron.New()
c.AddFunc(cronSpec, func() {
Scan()
fmt.Println()
})
c.Start()
<-block
} else {
Scan()
}
2021-10-15 16:58:49 +00:00
},
}
func init() {
ClientCmd.Flags().StringVarP(&port, "port", "p", "5080", "server port to connect")
ClientCmd.Flags().StringVarP(&host, "host", "u", "kumoly.io", "hostname to connect")
2021-10-15 19:15:49 +00:00
ClientCmd.Flags().StringVarP(&name, "name", "n", "", "tell the server who you are")
2021-10-15 16:58:49 +00:00
ClientCmd.Flags().BoolVarP(&showList, "list", "l", false, "show list")
ClientCmd.Flags().BoolVarP(&showTitle, "title", "t", false, "show title, used with --list")
2021-10-16 18:22:55 +00:00
ClientCmd.Flags().BoolVarP(&showCell, "pretty", "c", false, "show table cell, must used with --list")
2021-10-15 16:58:49 +00:00
ClientCmd.Flags().BoolVarP(&showAll, "all", "a", false, "show local ip")
ClientCmd.Flags().BoolVar(&noPub, "no-pub", false, "disable PublicIP")
ClientCmd.Flags().BoolVar(&secure, "secure", false, "use https")
2021-10-15 19:15:49 +00:00
ClientCmd.Flags().BoolVar(&cronMode, "cron", false, "run as cron service")
ClientCmd.Flags().StringVarP(&cronSpec, "spec", "s", "0 */5 * * * *", "hostname to connect")
2021-10-16 21:23:55 +00:00
ClientCmd.AddCommand(ServerCmd)
ClientCmd.AddCommand(LocalIPCmd)
2021-10-15 16:58:49 +00:00
}
func Scan() error {
// fmt.Printf("title: %v\nlist: %v\nall: %v\ntab: %v\n", showTitle, showList, showAll, showCell)
2021-10-16 18:22:55 +00:00
if name == "" {
name, _ = os.Hostname()
}
2021-10-15 16:58:49 +00:00
if !showAll {
if noPub {
return errors.New("`--no-pub` can only be used with `--all`")
}
ip, err := GetPublicIP()
if err != nil {
return err
}
fmt.Println(ip)
} else {
var ip string
var err error
if !noPub {
ip, err = GetPublicIP()
if err != nil {
return err
}
}
local, err := GetLocalIP()
if err != nil {
return err
}
if showList {
2021-10-16 18:22:55 +00:00
t := table.NewWriter()
t.SetOutputMirror(os.Stdout)
2021-10-15 16:58:49 +00:00
if showCell {
2021-10-16 18:22:55 +00:00
t.SetStyle(table.StyleLight)
} else {
t.Style().Options.DrawBorder = false
t.Style().Options.SeparateColumns = false
t.Style().Options.SeparateFooter = false
t.Style().Options.SeparateHeader = false
t.Style().Options.SeparateRows = false
2021-10-15 16:58:49 +00:00
}
if showTitle {
2021-10-16 18:22:55 +00:00
t.AppendHeader(table.Row{"Interface", "IP"})
2021-10-15 16:58:49 +00:00
if showCell {
2021-10-16 18:22:55 +00:00
t.AppendSeparator()
2021-10-15 16:58:49 +00:00
}
}
if !noPub {
2021-10-16 18:22:55 +00:00
t.AppendRow([]interface{}{"PublicIP", ip})
2021-10-15 16:58:49 +00:00
}
for _, iface := range local {
2021-10-16 18:22:55 +00:00
t.AppendRow([]interface{}{iface.Name, iface.IP})
2021-10-15 16:58:49 +00:00
}
2021-10-16 18:22:55 +00:00
t.Render()
// fmt.Println(t.Render())
return nil
2021-10-15 16:58:49 +00:00
} else {
if !noPub {
fmt.Printf("%v ", ip)
}
for _, v := range local {
fmt.Printf("%v ", v.IP)
2021-10-15 16:58:49 +00:00
}
fmt.Printf("\n")
}
}
return nil
}
func GetLocalIP() ([]Iface, error) {
ret := []Iface{}
2021-10-15 16:58:49 +00:00
ifaces, err := net.Interfaces()
if err != nil {
log.Println(err)
return ret, err
}
for _, i := range ifaces {
addrs, err := i.Addrs()
if err != nil {
log.Println(err)
return ret, err
}
for _, addr := range addrs {
var ip net.IP
switch v := addr.(type) {
case *net.IPNet:
ip = v.IP
if ip.IsLoopback() {
continue
}
if ip.To4() == nil {
continue
}
case *net.IPAddr:
continue
// ip = v.IP
// if ip.IsLoopback() {
// continue
// }
}
ret = append(ret, Iface{
IP: ip.String(),
Name: i.Name,
HardwareAddr: i.HardwareAddr.String(),
})
2021-10-15 16:58:49 +00:00
break
}
}
sort.Slice(ret, func(i, j int) bool {
return ret[i].Name < ret[j].Name
})
2021-10-15 16:58:49 +00:00
return ret, nil
}
func GetPublicIP() (string, error) {
protocol := "http://"
if secure {
protocol = "https://"
}
req, _ := http.NewRequest("GET", protocol+host+":"+port+"?name="+name, nil)
client := &http.Client{
Timeout: time.Second * 10,
}
res, err := client.Do(req)
2021-10-15 16:58:49 +00:00
if err != nil {
log.Println(err)
return "", err
}
if res.StatusCode != 200 {
err = errors.New("http status error: " + res.Status)
log.Println(err)
return "", err
}
defer res.Body.Close()
body, err := ioutil.ReadAll(res.Body)
if err != nil {
log.Println(err)
return "", err
}
return strings.TrimRight(string(body), "\r\n"), nil
}