initial commit
This commit is contained in:
20
.vscode/tasks.json
vendored
Normal file
20
.vscode/tasks.json
vendored
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
// See https://go.microsoft.com/fwlink/?LinkId=733558
|
||||||
|
// for the documentation about the tasks.json format
|
||||||
|
"version": "2.0.0",
|
||||||
|
"tasks": [
|
||||||
|
{
|
||||||
|
"label": "Go Build",
|
||||||
|
"type": "shell",
|
||||||
|
"command": "go build -o bin/",
|
||||||
|
"group": {
|
||||||
|
"kind": "build",
|
||||||
|
"isDefault": true
|
||||||
|
},
|
||||||
|
"presentation": {
|
||||||
|
"reveal": "silent",
|
||||||
|
"clear": true
|
||||||
|
},
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
23
README.md
Normal file
23
README.md
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
# GetCountryFromIP
|
||||||
|
|
||||||
|
Simple go executable to task an ip and get the results from ip-api
|
||||||
|
https://ip-api.com/
|
||||||
|
https://ip-api.com/docs/api:json
|
||||||
|
|
||||||
|
This is a fantastic site and I hope the continue to provide this
|
||||||
|
|
||||||
|
Allows flag -p to replace the properties output
|
||||||
|
|
||||||
|
## Usage Example
|
||||||
|
|
||||||
|
GetCountryFromIP.exe -ip 8.8.8.8
|
||||||
|
|
||||||
|
Output:
|
||||||
|
|
||||||
|
United States
|
||||||
|
|
||||||
|
GetCountryFromIP.exe -ip 8.8.8.8 -p country,isp
|
||||||
|
|
||||||
|
Output:
|
||||||
|
|
||||||
|
United States,Google LLC
|
||||||
BIN
bin/GetCountryFromIP.exe
Normal file
BIN
bin/GetCountryFromIP.exe
Normal file
Binary file not shown.
56
ip_api.go
Normal file
56
ip_api.go
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Build URL to query IP-API
|
||||||
|
// https://ip-api.com/docs/api:json
|
||||||
|
func buildURL(ip string) string {
|
||||||
|
return "http://ip-api.com/json/" + ip
|
||||||
|
}
|
||||||
|
|
||||||
|
func Lookup(ip string, properties []string) map[string]interface{} {
|
||||||
|
CheckValidIP(ip)
|
||||||
|
url := buildURL(ip)
|
||||||
|
resp, err := http.Get(url)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
debugOut(Error, err.Error())
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
var data map[string]interface{}
|
||||||
|
err = json.NewDecoder(resp.Body).Decode(&data)
|
||||||
|
if err != nil {
|
||||||
|
debugOut(Error, err.Error())
|
||||||
|
}
|
||||||
|
if data["status"] == "fail" {
|
||||||
|
debugOut(Error, data["message"].(string))
|
||||||
|
}
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetProperties(data map[string]interface{}) string {
|
||||||
|
|
||||||
|
var output string = ""
|
||||||
|
|
||||||
|
for _, property := range properties {
|
||||||
|
found := false
|
||||||
|
for key, value := range data {
|
||||||
|
if key == property {
|
||||||
|
if output != "" {
|
||||||
|
output += ","
|
||||||
|
}
|
||||||
|
output += value.(string)
|
||||||
|
found = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !found {
|
||||||
|
debugOut(Error, "Property '"+property+"' not found")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return output
|
||||||
|
}
|
||||||
15
main.go
Normal file
15
main.go
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
var verbose bool = false
|
||||||
|
var ip string
|
||||||
|
var properties []string
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
parseFlags()
|
||||||
|
|
||||||
|
result := GetProperties(Lookup(ip, properties))
|
||||||
|
|
||||||
|
fmt.Println(result)
|
||||||
|
}
|
||||||
71
utils.go
Normal file
71
utils.go
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"regexp"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Verbosity int
|
||||||
|
|
||||||
|
const (
|
||||||
|
Info Verbosity = iota
|
||||||
|
Warning
|
||||||
|
Error
|
||||||
|
Debug
|
||||||
|
)
|
||||||
|
|
||||||
|
func debugOut(level Verbosity, text string) {
|
||||||
|
switch level {
|
||||||
|
case Info:
|
||||||
|
if verbose {
|
||||||
|
fmt.Println("[INFO] " + text)
|
||||||
|
} else {
|
||||||
|
fmt.Println(text)
|
||||||
|
}
|
||||||
|
case Warning:
|
||||||
|
if verbose {
|
||||||
|
fmt.Println("[WARNING] " + text)
|
||||||
|
}
|
||||||
|
case Error:
|
||||||
|
fmt.Println("[ERROR] " + text)
|
||||||
|
os.Exit(1)
|
||||||
|
case Debug:
|
||||||
|
if verbose {
|
||||||
|
fmt.Println("[DEBUG] " + text)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func CheckValidIP(ip string) {
|
||||||
|
re := regexp.MustCompile(`^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$`)
|
||||||
|
if !re.MatchString(ip) {
|
||||||
|
debugOut(Error, "Please enter a valid IP address")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseFlags() {
|
||||||
|
_ip := flag.String("ip", "", "IP address to lookup")
|
||||||
|
_props := flag.String("p", "country", "Properties to retrieve")
|
||||||
|
_verbose := flag.Bool("v", false, "Verbose output")
|
||||||
|
flag.Parse()
|
||||||
|
_loose := flag.Args()
|
||||||
|
|
||||||
|
if *_verbose {
|
||||||
|
verbose = true
|
||||||
|
}
|
||||||
|
if *_ip == "" {
|
||||||
|
if len(_loose) == 0 {
|
||||||
|
debugOut(Error, "Please enter an IP address or use -h for help")
|
||||||
|
} else {
|
||||||
|
ip = _loose[0]
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ip = *_ip
|
||||||
|
}
|
||||||
|
if _props != nil {
|
||||||
|
properties = strings.Split(*_props, ",")
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user