apiutils.nim 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  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. raise rateLimitError()
  35. let headers = genHeaders(token)
  36. try:
  37. var resp: AsyncResponse
  38. let body = pool.use(headers):
  39. resp = await c.get($url)
  40. await resp.body
  41. if body.startsWith('{') or body.startsWith('['):
  42. result = parseJson(body)
  43. else:
  44. echo resp.status, ": ", body
  45. result = newJNull()
  46. if not oldApi and resp.headers.hasKey(rl & "reset"):
  47. let time = fromUnix(parseInt(resp.headers[rl & "reset"]))
  48. if token.reset != time:
  49. token.remaining = parseInt(resp.headers[rl & "limit"])
  50. token.reset = time
  51. if result.getError notin {invalidToken, forbidden, badToken}:
  52. token.lastUse = getTime()
  53. else:
  54. echo "fetch error: ", result.getError
  55. release(token, true)
  56. raise rateLimitError()
  57. except Exception as e:
  58. echo "error: ", e.msg, ", token: ", token[], ", url: ", url
  59. if "length" notin e.msg and "descriptor" notin e.msg:
  60. release(token, true)
  61. raise rateLimitError()