mirror of https://github.com/waku-org/nwaku.git
53 lines
1.5 KiB
Nim
53 lines
1.5 KiB
Nim
|
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())
|