timeline.nim 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253
  1. import httpclient, asyncdispatch, htmlparser, strformat
  2. import sequtils, strutils, json, uri
  3. import ".."/[types, parser, parserutils, formatters, query]
  4. import utils, consts, media, search
  5. proc getMedia(thread: Chain | Timeline; agent: string) {.async.} =
  6. await all(getVideos(thread, agent),
  7. getCards(thread, agent),
  8. getPolls(thread, agent))
  9. proc finishTimeline*(json: JsonNode; query: Query; after, agent: string): Future[Timeline] {.async.} =
  10. result = getResult[Tweet](json, query, after)
  11. if json == nil: return
  12. if json["new_latent_count"].to(int) == 0: return
  13. if not json.hasKey("items_html"): return
  14. let html = parseHtml(json["items_html"].to(string))
  15. let thread = parseChain(html)
  16. await getMedia(thread, agent)
  17. result.content = thread.content
  18. proc getTimeline*(username, after, agent: string): Future[Timeline] {.async.} =
  19. var params = toSeq({
  20. "include_available_features": "1",
  21. "include_entities": "1",
  22. "include_new_items_bar": "false",
  23. "reset_error_state": "false"
  24. })
  25. if after.len > 0:
  26. params.add {"max_position": after}
  27. let headers = genHeaders(agent, base / username, xml=true)
  28. let json = await fetchJson(base / (timelineUrl % username) ? params, headers)
  29. result = await finishTimeline(json, Query(), after, agent)
  30. proc getProfileAndTimeline*(username, agent, after: string): Future[(Profile, Timeline)] {.async.} =
  31. var url = base / username
  32. if after.len > 0:
  33. url = url ? {"max_position": after}
  34. let
  35. headers = genHeaders(agent, base / username, auth=true)
  36. html = await fetchHtml(url, headers)
  37. timeline = parseTimeline(html.select("#timeline > .stream-container"), after)
  38. profile = parseTimelineProfile(html)
  39. await getMedia(timeline, agent)
  40. result = (profile, timeline)