2019-09-20 23:08:30 +00:00
|
|
|
import httpclient, asyncdispatch, htmlparser, strformat
|
2019-10-02 20:28:53 +00:00
|
|
|
import sequtils, strutils, json, uri
|
2019-09-06 01:37:12 +00:00
|
|
|
|
2019-09-13 20:24:58 +00:00
|
|
|
import ".."/[types, parser, parserutils, formatters, query]
|
2019-09-20 13:03:18 +00:00
|
|
|
import utils, consts, media, search
|
2019-09-06 01:37:12 +00:00
|
|
|
|
2019-10-08 18:47:45 +00:00
|
|
|
proc getMedia(thread: Chain | Timeline; agent: string) {.async.} =
|
2019-10-02 20:28:53 +00:00
|
|
|
await all(getVideos(thread, agent),
|
|
|
|
getCards(thread, agent),
|
|
|
|
getPolls(thread, agent))
|
|
|
|
|
2019-10-21 21:12:40 +00:00
|
|
|
proc finishTimeline*(json: JsonNode; query: Query; after, agent: string;
|
|
|
|
media=true): Future[Timeline] {.async.} =
|
2019-09-20 13:03:18 +00:00
|
|
|
result = getResult[Tweet](json, query, after)
|
|
|
|
if json == nil: return
|
2019-09-06 01:37:12 +00:00
|
|
|
|
|
|
|
if json["new_latent_count"].to(int) == 0: return
|
|
|
|
if not json.hasKey("items_html"): return
|
|
|
|
|
2019-10-02 20:28:53 +00:00
|
|
|
let html = parseHtml(json["items_html"].to(string))
|
2019-10-23 06:34:03 +00:00
|
|
|
let timeline = parseChain(html)
|
2019-09-06 01:37:12 +00:00
|
|
|
|
2019-10-23 06:34:03 +00:00
|
|
|
if media: await getMedia(timeline, agent)
|
|
|
|
result.content = timeline.content
|
|
|
|
|
2019-12-08 11:38:55 +00:00
|
|
|
proc getProfileAndTimeline*(username, after, agent: string;
|
|
|
|
media=true): Future[(Profile, Timeline)] {.async.} =
|
2019-10-23 06:34:03 +00:00
|
|
|
var url = base / username
|
|
|
|
if after.len > 0:
|
|
|
|
url = url ? {"max_position": after}
|
|
|
|
|
|
|
|
let
|
|
|
|
headers = genHeaders(agent, base / username, auth=true)
|
|
|
|
html = await fetchHtml(url, headers)
|
|
|
|
timeline = parseTimeline(html.select("#timeline > .stream-container"), after)
|
|
|
|
profile = parseTimelineProfile(html)
|
|
|
|
|
|
|
|
if media: await getMedia(timeline, agent)
|
|
|
|
result = (profile, timeline)
|
2019-09-06 01:37:12 +00:00
|
|
|
|
2019-12-08 11:38:55 +00:00
|
|
|
proc getTimeline*(username, after, agent: string;
|
|
|
|
media=true): Future[Timeline] {.async.} =
|
2019-09-06 01:37:12 +00:00
|
|
|
var params = toSeq({
|
|
|
|
"include_available_features": "1",
|
|
|
|
"include_entities": "1",
|
|
|
|
"include_new_items_bar": "false",
|
|
|
|
"reset_error_state": "false"
|
|
|
|
})
|
|
|
|
|
|
|
|
if after.len > 0:
|
|
|
|
params.add {"max_position": after}
|
|
|
|
|
2019-10-02 20:28:53 +00:00
|
|
|
let headers = genHeaders(agent, base / username, xml=true)
|
2019-09-06 01:37:12 +00:00
|
|
|
let json = await fetchJson(base / (timelineUrl % username) ? params, headers)
|
2019-10-02 20:28:53 +00:00
|
|
|
|
2019-10-21 21:12:40 +00:00
|
|
|
result = await finishTimeline(json, Query(), after, agent, media)
|
2019-09-06 01:37:12 +00:00
|
|
|
|
2019-12-08 11:38:55 +00:00
|
|
|
proc getMediaTimeline*(username, after, agent: string;
|
|
|
|
media=true): Future[Timeline] {.async.} =
|
2019-10-23 06:34:03 +00:00
|
|
|
var params = toSeq({
|
|
|
|
"include_available_features": "1",
|
|
|
|
"include_entities": "1",
|
|
|
|
"reset_error_state": "false"
|
|
|
|
})
|
|
|
|
|
2019-09-06 01:37:12 +00:00
|
|
|
if after.len > 0:
|
2019-10-23 06:34:03 +00:00
|
|
|
params.add {"max_position": after}
|
2019-09-06 01:37:12 +00:00
|
|
|
|
2019-12-08 11:38:55 +00:00
|
|
|
let
|
|
|
|
headers = genHeaders(agent, base / username, xml=true)
|
|
|
|
json = await fetchJson(base / (timelineMediaUrl % username) ? params, headers)
|
|
|
|
query = Query(kind: QueryKind.media)
|
2019-09-06 01:37:12 +00:00
|
|
|
|
2019-12-08 11:38:55 +00:00
|
|
|
result = await finishTimeline(json, query, after, agent, media)
|
2019-10-23 06:34:03 +00:00
|
|
|
result.minId = getLastId(result)
|