2019-09-06 01:37:12 +00:00
|
|
|
import httpclient, asyncdispatch, htmlparser
|
2019-09-20 02:04:28 +00:00
|
|
|
import strutils, json, xmltree, uri
|
2019-09-06 01:37:12 +00:00
|
|
|
|
2019-09-20 02:04:28 +00:00
|
|
|
import ".."/[types, parser, parserutils, query]
|
|
|
|
import utils, consts, timeline
|
2019-09-06 01:37:12 +00:00
|
|
|
|
2019-09-20 13:03:18 +00:00
|
|
|
proc getResult*[T](json: JsonNode; query: Query; after: string): Result[T] =
|
|
|
|
if json == nil: return Result[T](beginning: true, query: query)
|
2019-09-13 20:24:58 +00:00
|
|
|
Result[T](
|
|
|
|
hasMore: json["has_more_items"].to(bool),
|
|
|
|
maxId: json.getOrDefault("max_position").getStr(""),
|
|
|
|
minId: json.getOrDefault("min_position").getStr("").cleanPos(),
|
2019-09-19 00:23:22 +00:00
|
|
|
query: query,
|
2019-09-13 20:24:58 +00:00
|
|
|
beginning: after.len == 0
|
|
|
|
)
|
|
|
|
|
|
|
|
proc getSearch*[T](query: Query; after, agent: string): Future[Result[T]] {.async.} =
|
|
|
|
let
|
|
|
|
kind = if query.kind == users: "users" else: "tweets"
|
|
|
|
pos = when T is Tweet: genPos(after) else: after
|
|
|
|
|
|
|
|
param = genQueryParam(query)
|
|
|
|
encoded = encodeUrl(param, usePlus=false)
|
|
|
|
|
|
|
|
headers = newHttpHeaders({
|
|
|
|
"Accept": jsonAccept,
|
|
|
|
"Referer": $(base / ("search?f=$1&q=$2&src=typd" % [kind, encoded])),
|
|
|
|
"User-Agent": agent,
|
|
|
|
"X-Requested-With": "XMLHttpRequest",
|
|
|
|
"Authority": "twitter.com",
|
|
|
|
"Accept-Language": lang
|
|
|
|
})
|
|
|
|
|
|
|
|
params = {
|
|
|
|
"f": kind,
|
|
|
|
"vertical": "default",
|
|
|
|
"q": param,
|
|
|
|
"src": "typd",
|
|
|
|
"include_available_features": "1",
|
|
|
|
"include_entities": "1",
|
|
|
|
"max_position": if pos.len > 0: pos else: "0",
|
|
|
|
"reset_error_state": "false"
|
|
|
|
}
|
2019-09-06 01:37:12 +00:00
|
|
|
|
|
|
|
let json = await fetchJson(base / searchUrl ? params, headers)
|
2019-09-19 02:51:17 +00:00
|
|
|
if json == nil: return Result[T](query: query, beginning: true)
|
2019-09-13 20:24:58 +00:00
|
|
|
|
|
|
|
result = getResult[T](json, query, after)
|
|
|
|
if not json.hasKey("items_html"): return
|
|
|
|
|
|
|
|
when T is Tweet:
|
2019-09-19 00:23:22 +00:00
|
|
|
result = await finishTimeline(json, query, after, agent)
|
2019-09-13 20:24:58 +00:00
|
|
|
elif T is Profile:
|
2019-09-20 13:03:18 +00:00
|
|
|
let html = json["items_html"].to(string)
|
|
|
|
result.hasMore = html != "\n"
|
|
|
|
for p in parseHtml(html).selectAll(".js-stream-item"):
|
2019-09-13 20:24:58 +00:00
|
|
|
result.content.add parsePopupProfile(p, ".ProfileCard")
|