apiutils.nim 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. import httpclient, asyncdispatch, options, times, strutils, uri
  2. import packedjson
  3. import types, tokens, consts, parserutils, http_pool
  4. const rl = "x-rate-limit-"
  5. var pool {.threadvar.}: HttpPool
  6. proc genParams*(pars: openarray[(string, string)] = @[]; cursor="";
  7. count="20"; ext=true): seq[(string, string)] =
  8. result = timelineParams
  9. for p in pars:
  10. result &= p
  11. if ext:
  12. result &= ("ext", "mediaStats")
  13. if cursor.len > 0:
  14. result &= ("cursor", cursor)
  15. if count.len > 0:
  16. result &= ("count", count)
  17. proc genHeaders*(token: Token = nil): HttpHeaders =
  18. result = newHttpHeaders({
  19. "connection": "keep-alive",
  20. "authorization": auth,
  21. "content-type": "application/json",
  22. "x-guest-token": if token == nil: "" else: token.tok,
  23. "x-twitter-active-user": "yes",
  24. "authority": "api.twitter.com",
  25. "accept-language": "en-US,en;q=0.9",
  26. "accept": "*/*",
  27. "DNT": "1"
  28. })
  29. proc fetch*(url: Uri; oldApi=false): Future[JsonNode] {.async.} =
  30. once:
  31. pool = HttpPool()
  32. var token = await getToken()
  33. if token.tok.len == 0:
  34. result = newJNull()
  35. let headers = genHeaders(token)
  36. try:
  37. let
  38. resp = pool.use(headers): await c.get($url)
  39. body = await resp.body
  40. if body.startsWith('{') or body.startsWith('['):
  41. result = parseJson(body)
  42. else:
  43. echo resp.status, ": ", body
  44. result = newJNull()
  45. if not oldApi and resp.headers.hasKey(rl & "limit"):
  46. token.remaining = parseInt(resp.headers[rl & "remaining"])
  47. token.reset = fromUnix(parseInt(resp.headers[rl & "reset"]))
  48. if result.getError notin {invalidToken, forbidden, badToken}:
  49. token.release()
  50. except Exception:
  51. echo "error: ", url
  52. result = newJNull()