From 42a25e6711079c495654df67e3ae62427639344c Mon Sep 17 00:00:00 2001 From: Uman Shahzad Date: Wed, 21 Apr 2021 14:42:57 +0500 Subject: [PATCH] add `map` cmd for opening map in browser given IPs. --- go.mod | 5 +-- go.sum | 8 +++-- ipinfo/cmd_asn.go | 5 +-- ipinfo/cmd_bulk.go | 72 ++---------------------------------------- ipinfo/cmd_default.go | 7 ++--- ipinfo/cmd_ip.go | 5 +-- ipinfo/cmd_map.go | 73 +++++++++++++++++++++++++++++++++++++++++++ ipinfo/cmd_myip.go | 5 +-- ipinfo/cmd_sum.go | 72 ++---------------------------------------- ipinfo/main.go | 14 ++++++--- ipinfo/utils_input.go | 57 +++++++++++++++++++++++++++++++++ 11 files changed, 159 insertions(+), 164 deletions(-) create mode 100644 ipinfo/cmd_map.go create mode 100644 ipinfo/utils_input.go diff --git a/go.mod b/go.mod index a969eef4..8da5ed6d 100644 --- a/go.mod +++ b/go.mod @@ -4,9 +4,10 @@ go 1.16 require ( github.com/fatih/color v1.10.0 - github.com/ipinfo/go/v2 v2.3.2 + github.com/ipinfo/go/v2 v2.4.0 github.com/jszwec/csvutil v1.4.0 + github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4 // indirect github.com/spf13/pflag v1.0.5 - golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c // indirect + golang.org/x/sys v0.0.0-20210420205809-ac73e9fd8988 // indirect golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf ) diff --git a/go.sum b/go.sum index 1aaab335..e3145da8 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,7 @@ github.com/fatih/color v1.10.0 h1:s36xzo75JdqLaaWoiEHk767eHiwo0598uUxyfiPkDsg= github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= -github.com/ipinfo/go/v2 v2.3.2 h1:/k0pBjBgJ7n68c7u7/M3UySDe6/AFdhEFVcw4xH6Ppo= -github.com/ipinfo/go/v2 v2.3.2/go.mod h1:2MrJVdUamrTc5VdC7yrbKGbsOOxMtdUpnpBJmtZgA8o= +github.com/ipinfo/go/v2 v2.4.0 h1:I83YiC4e6YZmUc7Z40311vLcJF0DJPV0MBhxg6AX6Ew= +github.com/ipinfo/go/v2 v2.4.0/go.mod h1:2MrJVdUamrTc5VdC7yrbKGbsOOxMtdUpnpBJmtZgA8o= github.com/jszwec/csvutil v1.4.0 h1:ro7gZN8PRsyNUEX8qE/eYPE5/kffEXMs+4eRcOd1oUk= github.com/jszwec/csvutil v1.4.0/go.mod h1:Rpu7Uu9giO9subDyMCIQfHVDuLrcaC36UA4YcJjGBkg= github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8= @@ -10,6 +10,8 @@ github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHX github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc= github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ= +github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4 h1:Qj1ukM4GlMWXNdMBuXcXfz/Kw9s1qm0CLY32QxuSImI= +github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4/go.mod h1:N6UoU20jOqggOuDwUaBQpluzLNDqif3kq9z2wpdYEfQ= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a h1:DcqTD9SDLc+1P/r1EmRBwnVsrOwW+kk2vWf9n+1sGhs= @@ -19,5 +21,7 @@ golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c h1:VwygUrnw9jn88c4u8GD3rZQbqrP/tgas88tPUbBxQrk= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210420205809-ac73e9fd8988 h1:EjgCl+fVlIaPJSori0ikSz3uV0DOHKWOJFpv1sAAhBM= +golang.org/x/sys v0.0.0-20210420205809-ac73e9fd8988/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf h1:MZ2shdL+ZM/XzY3ZGOnh4Nlpnxz5GSOhOmtHo3iPU6M= golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= diff --git a/ipinfo/cmd_asn.go b/ipinfo/cmd_asn.go index a58c0aad..1e885ff4 100644 --- a/ipinfo/cmd_asn.go +++ b/ipinfo/cmd_asn.go @@ -46,10 +46,7 @@ func cmdASN(asn string) error { return nil } - if err := prepareIpinfoClient(fTok); err != nil { - return err - } - + ii = prepareIpinfoClient(fTok) data, err := ii.GetASNDetails(asn) if err != nil { return err diff --git a/ipinfo/cmd_bulk.go b/ipinfo/cmd_bulk.go index 0a8fec01..61e786ba 100644 --- a/ipinfo/cmd_bulk.go +++ b/ipinfo/cmd_bulk.go @@ -3,9 +3,7 @@ package main import ( "fmt" "net" - "os" - "github.com/ipinfo/cli/lib" "github.com/ipinfo/go/v2/ipinfo" "github.com/spf13/pflag" ) @@ -73,80 +71,16 @@ func cmdBulk() (err error) { return nil } - if err := prepareIpinfoClient(fTok); err != nil { + ips, err = getInputIPs(pflag.Args()[1:]) + if err != nil { return err } - - args := pflag.Args()[1:] - - // check for stdin, implied or explicit. - if len(args) == 0 || (len(args) == 1 && args[0] == "-") { - stat, _ := os.Stdin.Stat() - if (stat.Mode() & os.ModeCharDevice) != 0 { - fmt.Println("** manual input mode **") - fmt.Println("Enter all IPs, one per line:") - } - ips = lib.IPsFromStdin() - - goto lookup - } - - // check for IP range. - if lib.IsIP(args[0]) { - if len(args) != 2 { - return lib.ErrIPRangeRequiresTwoIPs - } - if !lib.IsIP(args[1]) { - return lib.ErrNotIP - } - - ips, err = lib.IPsFromRange(args[0], args[1]) - if err != nil { - return err - } - - goto lookup - } - - // check for all CIDRs. - if lib.IsCIDR(args[0]) { - for _, arg := range args[1:] { - if !lib.IsCIDR(arg) { - return lib.ErrNotCIDR - } - } - - ips, err = lib.IPsFromCIDRs(args) - if err != nil { - return err - } - - goto lookup - } - - // check for all filepaths. - if fileExists(args[0]) { - for _, arg := range args[1:] { - if !fileExists(arg) { - return lib.ErrNotFile - } - } - - ips, err = lib.IPsFromFiles(args) - if err != nil { - return err - } - - goto lookup - } - -lookup: - if len(ips) == 0 { fmt.Println("no input ips") return nil } + ii = prepareIpinfoClient(fTok) data, err := ii.GetIPInfoBatch(ips, ipinfo.BatchReqOpts{}) if err != nil { return err diff --git a/ipinfo/cmd_default.go b/ipinfo/cmd_default.go index 7fdc66d2..dcf05d3a 100644 --- a/ipinfo/cmd_default.go +++ b/ipinfo/cmd_default.go @@ -20,6 +20,7 @@ Commands: myip get details for your IP. bulk get details for multiple IPs in bulk. summarize get summarized data for a group of IPs. + map open a URL to a map showing the locations of a group of IPs. prips print IP list from CIDR or range. grepip grep for IPs matching criteria from any source. login save an API token session. @@ -84,17 +85,13 @@ func cmdDefault() (err error) { return nil } - if err := prepareIpinfoClient(fTok); err != nil { - return err - } - ips = lib.IPsFromStdin() - if len(ips) == 0 { fmt.Println("no input ips") return nil } + ii = prepareIpinfoClient(fTok) data, err := ii.GetIPInfoBatch(ips, ipinfo.BatchReqOpts{}) if err != nil { return err diff --git a/ipinfo/cmd_ip.go b/ipinfo/cmd_ip.go index 1d782375..a9f67d0c 100644 --- a/ipinfo/cmd_ip.go +++ b/ipinfo/cmd_ip.go @@ -55,11 +55,8 @@ func cmdIP(ipStr string) error { return nil } - if err := prepareIpinfoClient(fTok); err != nil { - return err - } - ip := net.ParseIP(ipStr) + ii = prepareIpinfoClient(fTok) data, err := ii.GetIPInfo(ip) if err != nil { return err diff --git a/ipinfo/cmd_map.go b/ipinfo/cmd_map.go new file mode 100644 index 00000000..a6d5821e --- /dev/null +++ b/ipinfo/cmd_map.go @@ -0,0 +1,73 @@ +package main + +import ( + "fmt" + "net" + + "github.com/pkg/browser" + "github.com/spf13/pflag" +) + +func printHelpMap() { + fmt.Printf( + `Usage: %s map [] + +Description: + Accepts file paths, '-' for stdin, CIDRs and IP ranges. + + # Lookup all IPs from stdin ('-' can be implied). + $ %[1]s prips 8.8.8.0/24 | %[1]s map + $ %[1]s prips 8.8.8.0/24 | %[1]s map - + + # Lookup all IPs in 2 files. + $ %[1]s map /path/to/iplist1.txt /path/to/iplist2.txt + + # Lookup all IPs from CIDR. + $ %[1]s map 8.8.8.0/24 + + # Lookup all IPs from multiple CIDRs. + $ %[1]s map 8.8.8.0/24 8.8.2.0/24 8.8.1.0/24 + + # Lookup all IPs in an IP range. + $ %[1]s map 8.8.8.0 8.8.8.255 + +Options: + General: + --help, -h + show help. +`, progBase) +} + +func cmdMap() (err error) { + var ips []net.IP + var fHelp bool + + pflag.BoolVarP(&fHelp, "help", "h", false, "show help.") + pflag.Parse() + + if fHelp { + printHelpMap() + return nil + } + + ips, err = getInputIPs(pflag.Args()[1:]) + if err != nil { + return err + } + if len(ips) == 0 { + fmt.Println("no input ips") + return nil + } + + ii = prepareIpinfoClient("") + d, err := ii.GetIPMap(ips) + if err != nil { + return err + } + if err := browser.OpenURL(d.ReportURL); err != nil { + // if it fails, just print the URL. + fmt.Println(d.ReportURL) + } + + return nil +} diff --git a/ipinfo/cmd_myip.go b/ipinfo/cmd_myip.go index 3b0fe919..d2da0bf2 100644 --- a/ipinfo/cmd_myip.go +++ b/ipinfo/cmd_myip.go @@ -54,10 +54,7 @@ func cmdMyIP() error { return nil } - if err := prepareIpinfoClient(fTok); err != nil { - return err - } - + ii = prepareIpinfoClient(fTok) data, err := ii.GetIPInfo(nil) if err != nil { return err diff --git a/ipinfo/cmd_sum.go b/ipinfo/cmd_sum.go index e0d6f646..0122e104 100644 --- a/ipinfo/cmd_sum.go +++ b/ipinfo/cmd_sum.go @@ -3,13 +3,11 @@ package main import ( "fmt" "net" - "os" "sort" "strconv" "strings" "github.com/fatih/color" - "github.com/ipinfo/cli/lib" "github.com/ipinfo/go/v2/ipinfo" "github.com/spf13/pflag" ) @@ -70,80 +68,16 @@ func cmdSum() (err error) { return nil } - if err := prepareIpinfoClient(fTok); err != nil { + ips, err = getInputIPs(pflag.Args()[1:]) + if err != nil { return err } - - args := pflag.Args()[1:] - - // check for stdin, implied or explicit. - if len(args) == 0 || (len(args) == 1 && args[0] == "-") { - stat, _ := os.Stdin.Stat() - if (stat.Mode() & os.ModeCharDevice) != 0 { - fmt.Println("** manual input mode **") - fmt.Println("Enter all IPs, one per line:") - } - ips = lib.IPsFromStdin() - - goto lookup - } - - // check for IP range. - if lib.IsIP(args[0]) { - if len(args) != 2 { - return lib.ErrIPRangeRequiresTwoIPs - } - if !lib.IsIP(args[1]) { - return lib.ErrNotIP - } - - ips, err = lib.IPsFromRange(args[0], args[1]) - if err != nil { - return err - } - - goto lookup - } - - // check for all CIDRs. - if lib.IsCIDR(args[0]) { - for _, arg := range args[1:] { - if !lib.IsCIDR(arg) { - return lib.ErrNotCIDR - } - } - - ips, err = lib.IPsFromCIDRs(args) - if err != nil { - return err - } - - goto lookup - } - - // check for all filepaths. - if fileExists(args[0]) { - for _, arg := range args[1:] { - if !fileExists(arg) { - return lib.ErrNotFile - } - } - - ips, err = lib.IPsFromFiles(args) - if err != nil { - return err - } - - goto lookup - } - -lookup: - if len(ips) == 0 { fmt.Println("no input ips") return nil } + ii = prepareIpinfoClient(fTok) d, err := ii.GetIPSummary(ips) if err != nil { return err diff --git a/ipinfo/main.go b/ipinfo/main.go index 41e7d057..d179ce16 100644 --- a/ipinfo/main.go +++ b/ipinfo/main.go @@ -12,21 +12,23 @@ import ( ) var progBase = filepath.Base(os.Args[0]) -var version = "1.0.0" +var version = "1.1.0" var ii *ipinfo.Client -func prepareIpinfoClient(tok string) error { +func prepareIpinfoClient(tok string) *ipinfo.Client { + var _ii *ipinfo.Client + if tok == "" { tok, _ = restoreToken() } - ii = ipinfo.NewClient(nil, nil, tok) - ii.UserAgent = fmt.Sprintf( + _ii = ipinfo.NewClient(nil, nil, tok) + _ii.UserAgent = fmt.Sprintf( "IPinfoCli/%s (os/%s - arch/%s)", version, runtime.GOOS, runtime.GOARCH, ) - return nil + return _ii } func main() { @@ -49,6 +51,8 @@ func main() { err = cmdBulk() case cmd == "summarize": err = cmdSum() + case cmd == "map": + err = cmdMap() case cmd == "prips": err = cmdPrips() case cmd == "grepip": diff --git a/ipinfo/utils_input.go b/ipinfo/utils_input.go new file mode 100644 index 00000000..2510edcc --- /dev/null +++ b/ipinfo/utils_input.go @@ -0,0 +1,57 @@ +package main + +import ( + "fmt" + "net" + "os" + + "github.com/ipinfo/cli/lib" +) + +func getInputIPs(args []string) ([]net.IP, error) { + // check for stdin, implied or explicit. + if len(args) == 0 || (len(args) == 1 && args[0] == "-") { + stat, _ := os.Stdin.Stat() + if (stat.Mode() & os.ModeCharDevice) != 0 { + fmt.Println("** manual input mode **") + fmt.Println("Enter all IPs, one per line:") + } + return lib.IPsFromStdin(), nil + } + + // check for IP range. + if lib.IsIP(args[0]) { + if len(args) != 2 { + return nil, lib.ErrIPRangeRequiresTwoIPs + } + if !lib.IsIP(args[1]) { + return nil, lib.ErrNotIP + } + + return lib.IPsFromRange(args[0], args[1]) + } + + // check for all CIDRs. + if lib.IsCIDR(args[0]) { + for _, arg := range args[1:] { + if !lib.IsCIDR(arg) { + return nil, lib.ErrNotCIDR + } + } + + return lib.IPsFromCIDRs(args) + } + + // check for all filepaths. + if fileExists(args[0]) { + for _, arg := range args[1:] { + if !fileExists(arg) { + return nil, lib.ErrNotFile + } + } + + return lib.IPsFromFiles(args) + } + + return nil, nil +}