nwaku/tools/networkmonitor/networkmonitor_utils.nim

53 lines
1.5 KiB
Nim
Raw Normal View History

when (NimMajor, NimMinor) < (1, 4):
{.push raises: [Defect].}
else:
{.push raises: [].}
import
std/[json,httpclient],
chronicles,
chronicles/topics_registry,
chronos,
stew/results
type
NodeLocation = object
country*: string
city*: string
lat*: string
long*: string
isp*: string
proc flatten*[T](a: seq[seq[T]]): seq[T] =
var aFlat = newSeq[T](0)
for subseq in a:
aFlat &= subseq
return aFlat
# using an external api retrieves some data associated with the ip
# TODO: use a cache
# TODO: use nim-presto's HTTP asynchronous client
proc ipToLocation*(ip: string,
client: Httpclient):
Future[Result[NodeLocation, string]] {.async.} =
# naive mechanism to avoid hitting the rate limit
# IP-API endpoints are now limited to 45 HTTP requests per minute
await sleepAsync(1400)
try:
let content = client.getContent("http://ip-api.com/json/" & ip)
let jsonContent = parseJson(content)
if $jsonContent["status"].getStr() != "success":
error "query failed", result=jsonContent
return err("query failed: " & $jsonContent)
return ok(NodeLocation(
country: jsonContent["country"].getStr(),
city: jsonContent["city"].getStr(),
lat: jsonContent["lat"].getStr(),
long: jsonContent["lon"].getStr(),
isp: jsonContent["isp"].getStr()
))
except:
error "failed to get the location for IP", ip=ip, error=getCurrentExceptionMsg()
return err("failed to get the location for IP '" & ip & "':" & getCurrentExceptionMsg())