test build on WSL ubuntu

This commit is contained in:
2022-01-12 13:40:14 -06:00
parent a54d4d6d64
commit 55d2147a6c
10 changed files with 444 additions and 444 deletions

View File

@@ -1,25 +1,25 @@
name: Go name: Go
on: on:
push: push:
branches: [ master ] branches: [ master ]
pull_request: pull_request:
branches: [ master ] branches: [ master ]
jobs: jobs:
build: build:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- name: Set up Go - name: Set up Go
uses: actions/setup-go@v2 uses: actions/setup-go@v2
with: with:
go-version: 1.17 go-version: 1.17
- name: Build - name: Build
run: go build -v ./... run: go build -v ./...
- name: Test - name: Test
run: go test -v ./... run: go test -v ./...

4
.gitignore vendored
View File

@@ -1,2 +1,2 @@
bin/ bin/*
lookupip lookupip

50
.vscode/tasks.json vendored
View File

@@ -1,26 +1,26 @@
{ {
// See https://go.microsoft.com/fwlink/?LinkId=733558 // See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format // for the documentation about the tasks.json format
"version": "2.0.0", "version": "2.0.0",
"tasks": [ "tasks": [
{ {
"label": "Go Build", "label": "Go Build",
"type": "shell", "type": "shell",
"command": "go build -o bin/", "command": "go build -o bin/",
"group": { "group": {
"kind": "build", "kind": "build",
"isDefault": true "isDefault": true
}, },
"presentation": { "presentation": {
"reveal": "silent", "reveal": "silent",
"clear": true "clear": true
} }
}, },
{ {
"label": "Go Test All", "label": "Go Test All",
"type": "shell", "type": "shell",
"command": "go test ./...", "command": "go test ./...",
"problemMatcher": [] "problemMatcher": []
} }
] ]
} }

120
README.md
View File

@@ -1,60 +1,60 @@
# lookupip # lookupip
Simple go executable to task an ip and get the results from ip-api Simple go executable to task an ip and get the results from ip-api
https://ip-api.com/ https://ip-api.com/
This is a fantastic site and I hope the continue to provide this This is a fantastic site and I hope the continue to provide this
Allows flag -p to replace the properties output Allows flag -p to replace the properties output
## Build ## Build
I build this on Windows with I build this on Windows with
go build -o bin/ go build -o bin/
## Usage ## Usage
> **Default (Country Name)** > **Default (Country Name)**
> >
> lookupip.exe -ip 8.8.8.8 > lookupip.exe -ip 8.8.8.8
> >
> **Output:** > **Output:**
> >
> United States > United States
> **Custom return (Country Name and ISP)** > **Custom return (Country Name and ISP)**
> >
> lookupip.exe -ip 8.8.8.8 -p country,isp > lookupip.exe -ip 8.8.8.8 -p country,isp
> >
> **Output:** > **Output:**
> >
> United States,Google LLC > United States,Google LLC
## Custom Properties ## Custom Properties
https://ip-api.com/docs/api:json https://ip-api.com/docs/api:json
| name | description | example | type | | name | description | example | type |
| ------------- | ------------------------------------------ | ------------------- | ------ | | ------------- | ------------------------------------------ | ------------------- | ------ |
| Continent | Continent name | North America | string | | Continent | Continent name | North America | string |
| ContinentCode | Two-letter continent code | NA | string | | ContinentCode | Two-letter continent code | NA | string |
| Country | Country name | United States | string | | Country | Country name | United States | string |
| CountryCode | Two-letter country code ISO 3166-1 alpha-2 | US | string | | CountryCode | Two-letter country code ISO 3166-1 alpha-2 | US | string |
| Region | Region/state short code (FIPS or ISO) | CA or 10 | string | | Region | Region/state short code (FIPS or ISO) | CA or 10 | string |
| RegionName | Region/state | California | string | | RegionName | Region/state | California | string |
| City | City | Mountain View | string | | City | City | Mountain View | string |
| District | District (subdivision of city) | Old Farm District | string | | District | District (subdivision of city) | Old Farm District | string |
| Zip | Zip code | 94043 | string | | Zip | Zip code | 94043 | string |
| Lat | Latitude | 37.4192 | float | | Lat | Latitude | 37.4192 | float |
| Lon | Longitude | -122.0574 | float | | Lon | Longitude | -122.0574 | float |
| Timezone | Timezone (tz) | America/Los_Angeles | string | | Timezone | Timezone (tz) | America/Los_Angeles | string |
| Offset | Timezone UTC DST offset in seconds | -25200 | int | | Offset | Timezone UTC DST offset in seconds | -25200 | int |
| Currency | National currency | USD | string | | Currency | National currency | USD | string |
| ISP | ISP name | Google | string | | ISP | ISP name | Google | string |
| Org | Organization name | Google | string | | Org | Organization name | Google | string |
| AS | AS number and organization (RIR). | AS15169 Google Inc. | string | | AS | AS number and organization (RIR). | AS15169 Google Inc. | string |
| ASName | AS name (RIR). | GOOGLE | string | | ASName | AS name (RIR). | GOOGLE | string |
| Reverse | Reverse DNS of the IP (can delay response) | wi-in-f94.1e100.net | string | | Reverse | Reverse DNS of the IP (can delay response) | wi-in-f94.1e100.net | string |
| Hosting | Hosting, colocated or data center | true | bool | | Hosting | Hosting, colocated or data center | true | bool |
| Query | IP used for the query | 173.194.67.94 | string | | Query | IP used for the query | 173.194.67.94 | string |

52
main.go
View File

@@ -1,26 +1,26 @@
package main package main
import ( import (
"flag" "flag"
"github.com/ryanehamil/lookupip/src/ipapi" "github.com/ryanehamil/lookupip/src/ipapi"
"github.com/ryanehamil/lookupip/src/utils" "github.com/ryanehamil/lookupip/src/utils"
) )
func main() { func main() {
ip := flag.String("ip", "", "IP address to lookup") ip := flag.String("ip", "", "IP address to lookup")
properties := flag.String("p", "", "Properties to retrieve") properties := flag.String("p", "", "Properties to retrieve")
detail := flag.Bool("d", false, "Show Detail") detail := flag.Bool("d", false, "Show Detail")
flag.Parse() flag.Parse()
// Use the IP-API to lookup the IP address // Use the IP-API to lookup the IP address
data, err := ipapi.Lookup(*ip) data, err := ipapi.Lookup(*ip)
utils.HandleError(err) utils.HandleError(err)
// Format the data to a string // Format the data to a string
result := ipapi.GetProperties(data, *properties, *detail) result := ipapi.GetProperties(data, *properties, *detail)
// Print result with PrintOut // Print result with PrintOut
utils.PrintOut(result) utils.PrintOut(result)
utils.Exit(0) utils.Exit(0)
} }

View File

@@ -1,38 +1,38 @@
package main package main
import ( import (
"testing" "testing"
"github.com/ryanehamil/lookupip/src/ipapi" "github.com/ryanehamil/lookupip/src/ipapi"
"github.com/ryanehamil/lookupip/src/utils" "github.com/ryanehamil/lookupip/src/utils"
) )
// TestBuildURL // TestBuildURL
// Tests that the buildURL function returns a correct URL // Tests that the buildURL function returns a correct URL
func TestLookup(t *testing.T) { func TestLookup(t *testing.T) {
var tests = []struct { var tests = []struct {
input string input string
want string want string
explain string explain string
}{ }{
{"", "Any IPV4", "Lookup my own IP"}, {"", "Any IPV4", "Lookup my own IP"},
{"8.8.8.8", "United States", "Lookup Google's DNS"}, {"8.8.8.8", "United States", "Lookup Google's DNS"},
} }
for _, test := range tests { for _, test := range tests {
ip := test.input ip := test.input
// Use the IP-API to lookup anything // Use the IP-API to lookup anything
data, _ := ipapi.Lookup(ip) data, _ := ipapi.Lookup(ip)
got := ipapi.GetProperties(data, "", false) got := ipapi.GetProperties(data, "", false)
if test.want == "Any IPV4" { if test.want == "Any IPV4" {
if !utils.CheckValidIP(data.Query) { if !utils.CheckValidIP(data.Query) {
t.Errorf("%q. error-buildURL(%q) = %v, want %v", test.explain, test.input, got, test.want) t.Errorf("%q. error-buildURL(%q) = %v, want %v", test.explain, test.input, got, test.want)
} }
} else if got != test.want { } else if got != test.want {
t.Errorf("%q. lookup(%q) = %v, want %v", test.explain, test.input, got, test.want) t.Errorf("%q. lookup(%q) = %v, want %v", test.explain, test.input, got, test.want)
} }
} }
} }

View File

@@ -1,115 +1,115 @@
package ipapi package ipapi
import ( import (
"encoding/json" "encoding/json"
"errors" "errors"
"fmt" "fmt"
"net/http" "net/http"
"reflect" "reflect"
"strings" "strings"
"github.com/ryanehamil/lookupip/src/utils" "github.com/ryanehamil/lookupip/src/utils"
) )
// IP-API data struct // IP-API data struct
// https://ip-api.com/docs/api:json // https://ip-api.com/docs/api:json
type IPAPI struct { type IPAPI struct {
Continent string `json:"continent"` Continent string `json:"continent"`
ContinentCode string `json:"continentCode"` ContinentCode string `json:"continentCode"`
Country string `json:"country"` Country string `json:"country"`
CountryCode string `json:"countryCode"` CountryCode string `json:"countryCode"`
Region string `json:"region"` Region string `json:"region"`
RegionName string `json:"regionName"` RegionName string `json:"regionName"`
City string `json:"city"` City string `json:"city"`
Zip string `json:"zip"` Zip string `json:"zip"`
Lat float32 `json:"lat"` Lat float32 `json:"lat"`
Lon float32 `json:"lon"` Lon float32 `json:"lon"`
Timezone string `json:"timezone"` Timezone string `json:"timezone"`
Offset int `json:"offset"` Offset int `json:"offset"`
Currency string `json:"currency"` Currency string `json:"currency"`
ISP string `json:"isp"` ISP string `json:"isp"`
Org string `json:"org"` Org string `json:"org"`
AS string `json:"as"` AS string `json:"as"`
ASName string `json:"asname"` ASName string `json:"asname"`
Reverse string `json:"reverse"` Reverse string `json:"reverse"`
Hosting bool `json:"hosting"` Hosting bool `json:"hosting"`
Query string `json:"query"` Query string `json:"query"`
Status string `json:"status"` Status string `json:"status"`
Message string `json:"message"` Message string `json:"message"`
} }
// Add the .String() method to IPAPI // Add the .String() method to IPAPI
func (i *IPAPI) String() string { func (i *IPAPI) String() string {
return i.Query return i.Query
} }
// Build URL to query IP-API // Build URL to query IP-API
// https://ip-api.com/docs/api:json // https://ip-api.com/docs/api:json
func buildURL(ip string) (string, error) { func buildURL(ip string) (string, error) {
url := "http://ip-api.com/json" url := "http://ip-api.com/json"
if ip != "" { if ip != "" {
ip = strings.TrimSpace(ip) ip = strings.TrimSpace(ip)
if !utils.CheckValidIP(ip) { if !utils.CheckValidIP(ip) {
var err = errors.New("invalid IP address, failed CheckValidIP") var err = errors.New("invalid IP address, failed CheckValidIP")
return url, err return url, err
} }
url += fmt.Sprintf("/%s", ip) url += fmt.Sprintf("/%s", ip)
} }
return url, nil return url, nil
} }
// Get IP-API data about IP // Get IP-API data about IP
// //
// https://ip-api.com/docs/api:json // https://ip-api.com/docs/api:json
func Lookup(ip string) (data IPAPI, err error) { func Lookup(ip string) (data IPAPI, err error) {
url, error := buildURL(ip) url, error := buildURL(ip)
if error != nil { if error != nil {
return data, error return data, error
} }
resp, err := http.Get(url) resp, err := http.Get(url)
if error != nil { if error != nil {
return data, error return data, error
} }
defer resp.Body.Close() defer resp.Body.Close()
err = json.NewDecoder(resp.Body).Decode(&data) err = json.NewDecoder(resp.Body).Decode(&data)
if error != nil { if error != nil {
return data, error return data, error
} }
if data.Status == "fail" { if data.Status == "fail" {
utils.PrintOut("IP-API returned an error: " + data.Message) utils.PrintOut("IP-API returned an error: " + data.Message)
utils.Exit(1) utils.Exit(1)
} }
return data, nil return data, nil
} }
func GetProperties(data IPAPI, properties_string string, detail bool) (output string) { func GetProperties(data IPAPI, properties_string string, detail bool) (output string) {
if properties_string == "" { if properties_string == "" {
properties_string = "Country" properties_string = "Country"
} }
result := "" result := ""
properties := strings.Split(properties_string, ",") properties := strings.Split(properties_string, ",")
for _, property := range properties { for _, property := range properties {
datafield := reflect.Indirect(reflect.ValueOf(data)).FieldByName(property).String() datafield := reflect.Indirect(reflect.ValueOf(data)).FieldByName(property).String()
if datafield != "" { if datafield != "" {
result = datafield result = datafield
} else { } else {
result = "" result = ""
} }
if detail { if detail {
output += property + ": " + result + "\n" output += property + ": " + result + "\n"
} else { } else {
if output != "" { if output != "" {
output += "," output += ","
} }
output += result output += result
} }
} }
return output return output
} }

View File

@@ -1,87 +1,87 @@
package ipapi package ipapi
import ( import (
"testing" "testing"
"github.com/ryanehamil/lookupip/src/utils" "github.com/ryanehamil/lookupip/src/utils"
) )
// TestBuildURL // TestBuildURL
// Tests that the buildURL function returns a correct URL // Tests that the buildURL function returns a correct URL
func TestBuildURL(t *testing.T) { func TestBuildURL(t *testing.T) {
var tests = []struct { var tests = []struct {
ip string ip string
want string want string
explain string explain string
}{ }{
{"127.0.0.1", "http://ip-api.com/json/127.0.0.1", "Valid IP"}, {"127.0.0.1", "http://ip-api.com/json/127.0.0.1", "Valid IP"},
{" 127.0.0.1 ", "http://ip-api.com/json/127.0.0.1", "Dirty IP"}, {" 127.0.0.1 ", "http://ip-api.com/json/127.0.0.1", "Dirty IP"},
{"127.foo.bar.1", "invalid IP address, failed CheckValidIP", "Unsantized input"}, {"127.foo.bar.1", "invalid IP address, failed CheckValidIP", "Unsantized input"},
} }
for _, test := range tests { for _, test := range tests {
got, err := buildURL(test.ip) got, err := buildURL(test.ip)
if err != nil { if err != nil {
if err.Error() != test.want { if err.Error() != test.want {
t.Errorf("%q. error-buildURL(%q) = %v, want %v", test.explain, test.ip, got, test.want) t.Errorf("%q. error-buildURL(%q) = %v, want %v", test.explain, test.ip, got, test.want)
} }
} else if got != test.want { } else if got != test.want {
t.Errorf("%q. buildURL(%q) = %v, want %v", test.explain, test.ip, got, test.want) t.Errorf("%q. buildURL(%q) = %v, want %v", test.explain, test.ip, got, test.want)
} }
} }
} }
// TestLookup // TestLookup
// Tests that the lookup function returns IPAPI data and no error // Tests that the lookup function returns IPAPI data and no error
func TestLookup(t *testing.T) { func TestLookup(t *testing.T) {
var tests = []struct { var tests = []struct {
ip string ip string
want string want string
explain string explain string
}{ }{
{"8.8.8.8", "United States", "Google Public DNS"}, {"8.8.8.8", "United States", "Google Public DNS"},
{"199.211.133.90", "United States", "Naval Oceanography"}, {"199.211.133.90", "United States", "Naval Oceanography"},
{"116.202.3.251", "Germany", "JAM Software Germany"}, {"116.202.3.251", "Germany", "JAM Software Germany"},
{"", "Any IP", "Get my IP"}, {"", "Any IP", "Get my IP"},
} }
for _, test := range tests { for _, test := range tests {
data, err := Lookup(test.ip) data, err := Lookup(test.ip)
got := data.Country got := data.Country
if err != nil && err.Error() != test.want { if err != nil && err.Error() != test.want {
t.Errorf("%q. error-buildURL(%q) = %v, want %v", test.explain, test.ip, got, test.want) t.Errorf("%q. error-buildURL(%q) = %v, want %v", test.explain, test.ip, got, test.want)
} else if test.want == "Any IP" { } else if test.want == "Any IP" {
if !utils.CheckValidIP(data.Query) { if !utils.CheckValidIP(data.Query) {
t.Errorf("%q. error-buildURL(%q) = %v, want %v", test.explain, test.ip, got, test.want) t.Errorf("%q. error-buildURL(%q) = %v, want %v", test.explain, test.ip, got, test.want)
} }
} else if got != test.want { } else if got != test.want {
t.Errorf("%q. buildURL(%q) = %v, want %v", test.explain, test.ip, got, test.want) t.Errorf("%q. buildURL(%q) = %v, want %v", test.explain, test.ip, got, test.want)
} }
} }
} }
func TestGetProperties(t *testing.T) { func TestGetProperties(t *testing.T) {
var tests = []struct { var tests = []struct {
properties string properties string
want string want string
explain string explain string
}{ }{
{"", "United States", "No properties requested"}, {"", "United States", "No properties requested"},
{"Country", "United States", "Properties: Country"}, {"Country", "United States", "Properties: Country"},
{"Country,ISP", "United States,Google LLC", "Properties: Country,ISP"}, {"Country,ISP", "United States,Google LLC", "Properties: Country,ISP"},
} }
for _, test := range tests { for _, test := range tests {
// This test relies on the lookup function // This test relies on the lookup function
ip := "8.8.8.8" ip := "8.8.8.8"
// Use the IP-API to lookup anything // Use the IP-API to lookup anything
data, _ := Lookup(ip) data, _ := Lookup(ip)
got := GetProperties(data, test.properties, false) got := GetProperties(data, test.properties, false)
if got != test.want { if got != test.want {
t.Errorf("%q. GetProperties(%q) = %v, want %v", test.explain, test.properties, got, test.want) t.Errorf("%q. GetProperties(%q) = %v, want %v", test.explain, test.properties, got, test.want)
} }
} }
} }

View File

@@ -1,42 +1,42 @@
package utils package utils
import ( import (
"fmt" "fmt"
"os" "os"
"regexp" "regexp"
) )
// For printing to the console // For printing to the console
// //
// Currently using fmt.Println // Currently using fmt.Println
func PrintOut(msg ...interface{}) { func PrintOut(msg ...interface{}) {
fmt.Println(msg...) fmt.Println(msg...)
} }
// Check if a string is a valid ipv4 address // Check if a string is a valid ipv4 address
// //
// Currently using regexp.MustCompile and regexp.MatchString to return boolean // Currently using regexp.MustCompile and regexp.MatchString to return boolean
func CheckValidIP(ip string) bool { func CheckValidIP(ip string) bool {
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])$`) 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])$`)
return re.MatchString(ip) return re.MatchString(ip)
} }
// Error handler for the program // Error handler for the program
// //
// Checks if error !nil and prints the error to the console // Checks if error !nil and prints the error to the console
func HandleError(err error) { func HandleError(err error) {
if err != nil { if err != nil {
PrintOut(err) PrintOut(err)
Exit(1) Exit(1)
} }
} }
// Simple Exit function to handle exit codes // Simple Exit function to handle exit codes
// //
// Might need to be changed to a more robust one // Might need to be changed to a more robust one
func Exit(code int) { func Exit(code int) {
if code != 0 { if code != 0 {
panic("exit") panic("exit")
} }
os.Exit(code) os.Exit(code)
} }

View File

@@ -1,24 +1,24 @@
package utils package utils
import ( import (
"testing" "testing"
) )
func TestCheckValidIP(t *testing.T) { func TestCheckValidIP(t *testing.T) {
var tests = []struct { var tests = []struct {
ip string ip string
want bool want bool
explain string explain string
}{ }{
{"127.0.0.1", true, "Valid IP"}, {"127.0.0.1", true, "Valid IP"},
{"127.X.X.1", false, "Invalid IP"}, {"127.X.X.1", false, "Invalid IP"},
} }
for _, test := range tests { for _, test := range tests {
got := CheckValidIP(test.ip) got := CheckValidIP(test.ip)
if got != test.want { if got != test.want {
t.Errorf("%q. CheckValidIP(%q) = %v", test.explain, test.ip, got) t.Errorf("%q. CheckValidIP(%q) = %v", test.explain, test.ip, got)
} }
} }
} }