github.com/wtfutil/wtf@v0.43.0/modules/ipaddresses/ipapi/widget.go (about) 1 package ipapi 2 3 import ( 4 "bytes" 5 "encoding/json" 6 "fmt" 7 "net/http" 8 "strconv" 9 "strings" 10 "text/template" 11 12 "github.com/rivo/tview" 13 "github.com/wtfutil/wtf/utils" 14 "github.com/wtfutil/wtf/view" 15 ) 16 17 // Widget widget struct 18 type Widget struct { 19 view.TextWidget 20 21 result string 22 settings *Settings 23 } 24 25 type ipinfo struct { 26 Query string `json:"query"` 27 ISP string `json:"isp"` 28 AS string `json:"as"` 29 ASName string `json:"asname"` 30 District string `json:"district"` 31 City string `json:"city"` 32 Region string `json:"region"` 33 RegionName string `json:"regionName"` 34 Country string `json:"country"` 35 CountryCode string `json:"countryCode"` 36 Continent string `json:"continent"` 37 ContinentCode string `json:"continentCode"` 38 Latitude float64 `json:"lat"` 39 Longitude float64 `json:"lon"` 40 PostalCode string `json:"zip"` 41 Currency string `json:"currency"` 42 Organization string `json:"org"` 43 Timezone string `json:"timezone"` 44 ReverseDNS string `json:"reverse"` 45 } 46 47 var argLookup = map[string]string{ 48 "ip": "IP Address", 49 "isp": "ISP", 50 "as": "AS", 51 "asname": "AS Name", 52 "district": "District", 53 "city": "City", 54 "region": "Region", 55 "regionname": "Region Name", 56 "country": "Country", 57 "countrycode": "Country Code", 58 "continent": "Continent", 59 "continentcode": "Continent Code", 60 "coordinates": "Coordinates", 61 "postalcode": "Postal Code", 62 "currency": "Currency", 63 "organization": "Organization", 64 "timezone": "Timezone", 65 "reversedns": "Reverse DNS", 66 } 67 68 // NewWidget constructor 69 func NewWidget(tviewApp *tview.Application, redrawChan chan bool, settings *Settings) *Widget { 70 widget := Widget{ 71 TextWidget: view.NewTextWidget(tviewApp, redrawChan, nil, settings.Common), 72 73 settings: settings, 74 } 75 76 widget.View.SetWrap(false) 77 78 return &widget 79 } 80 81 // Refresh refresh the module 82 func (widget *Widget) Refresh() { 83 widget.ipinfo() 84 85 widget.Redraw(func() (string, string, bool) { return widget.CommonSettings().Title, widget.result, false }) 86 } 87 88 // this method reads the config and calls ipinfo for ip information 89 func (widget *Widget) ipinfo() { 90 client := &http.Client{} 91 req, err := http.NewRequest("GET", "http://ip-api.com/json?fields=66846719", http.NoBody) 92 if err != nil { 93 widget.result = err.Error() 94 return 95 } 96 req.Header.Set("User-Agent", "curl") 97 response, err := client.Do(req) 98 if err != nil { 99 widget.result = err.Error() 100 return 101 } 102 defer func() { _ = response.Body.Close() }() 103 var info ipinfo 104 err = json.NewDecoder(response.Body).Decode(&info) 105 if err != nil { 106 widget.result = err.Error() 107 return 108 } 109 110 widget.setResult(&info) 111 } 112 113 func (widget *Widget) setResult(info *ipinfo) { 114 115 args := utils.ToStrs(widget.settings.args) 116 117 // if no arguments are defined set default 118 if len(args) == 0 { 119 args = []string{"ip", "isp", "as", "city", "region", "country", "coordinates", "postalCode", "organization", "timezone"} 120 } 121 122 format := "" 123 124 for _, arg := range args { 125 if val, ok := argLookup[strings.ToLower(arg)]; ok { 126 format = format + formatableText(val, strings.ToLower(arg)) 127 } 128 } 129 130 resultTemplate, _ := template.New("ipinfo_result").Parse(format) 131 132 resultBuffer := new(bytes.Buffer) 133 134 err := resultTemplate.Execute(resultBuffer, map[string]string{ 135 "nameColor": widget.settings.colors.name, 136 "valueColor": widget.settings.colors.value, 137 "ip": info.Query, 138 "isp": info.ISP, 139 "as": info.AS, 140 "asname": info.ASName, 141 "district": info.District, 142 "city": info.City, 143 "region": info.Region, 144 "regionname": info.RegionName, 145 "country": info.Country, 146 "countrycode": info.CountryCode, 147 "continent": info.Continent, 148 "continentcode": info.ContinentCode, 149 "coordinates": strconv.FormatFloat(info.Latitude, 'f', 6, 64) + "," + strconv.FormatFloat(info.Longitude, 'f', 6, 64), 150 "postalcode": info.PostalCode, 151 "currency": info.Currency, 152 "organization": info.Organization, 153 "timezone": info.Timezone, 154 "reversedns": info.ReverseDNS, 155 }) 156 157 if err != nil { 158 widget.result = err.Error() 159 } 160 161 widget.result = resultBuffer.String() 162 } 163 164 func formatableText(key, value string) string { 165 return fmt.Sprintf(" [{{.nameColor}}]%s: [{{.valueColor}}]{{.%s}}\n", key, value) 166 }