initial commit

This commit is contained in:
2021-11-10 11:28:54 -06:00
commit b441e33c89
7 changed files with 188 additions and 0 deletions

20
.vscode/tasks.json vendored Normal file
View 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
View 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

Binary file not shown.

3
go.mod Normal file
View File

@@ -0,0 +1,3 @@
module GetCountryFromIP
go 1.17

56
ip_api.go Normal file
View 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
View 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
View 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, ",")
}
}