diff --git a/src/api.nim b/src/api.nim index d0bfd8c..ef60812 100644 --- a/src/api.nim +++ b/src/api.nim @@ -71,10 +71,20 @@ proc getGraphListMembers*(list: List; after=""): Future[Result[User]] {.async.} proc getFavorites*(id: string; cfg: Config; after=""): Future[Profile] {.async.} = if id.len == 0: return - let - ps = genParams({"userId": id}, after) - url = consts.favorites / (id & ".json") ? ps - result = parseTimeline(await fetch(url, Api.favorites), after) + var + variables = %*{ + "userId": id, + "includePromotedContent":false, + "withClientEventToken":false, + "withBirdwatchNotes":false, + "withVoice":true, + "withV2Timeline":false + } + if after.len > 0: + variables["cursor"] = % after + let + url = consts.favorites ? {"variables": $variables, "features": gqlFeatures} + result = parseGraphTimeline(await fetch(url, Api.favorites), after) proc getGraphTweetResult*(id: string): Future[Tweet] {.async.} = if id.len == 0: return diff --git a/src/apiutils.nim b/src/apiutils.nim index 22e75c9..3627ffd 100644 --- a/src/apiutils.nim +++ b/src/apiutils.nim @@ -49,7 +49,7 @@ proc getOauthHeader(url, oauthToken, oauthTokenSecret: string): string = proc genHeaders*(url, oauthToken, oauthTokenSecret: string): HttpHeaders = let header = getOauthHeader(url, oauthToken, oauthTokenSecret) - + result = newHttpHeaders({ "connection": "keep-alive", "authorization": header, @@ -149,18 +149,27 @@ template retry(bod) = proc fetch*(url: Uri; api: Api; additional_headers: HttpHeaders = newHttpHeaders()): Future[JsonNode] {.async.} = - if len(cfg.cookieHeader) != 0: - additional_headers.add("Cookie", cfg.cookieHeader) - if len(cfg.xCsrfToken) != 0: - additional_headers.add("x-csrf-token", cfg.xCsrfToken) - retry: var body: string fetchImpl(body, additional_headers): if body.startsWith('{') or body.startsWith('['): result = parseJson(body) + echo "-------------" + echo "api: ", api + echo "-------------" + echo "url: ", url + echo "-------------" + echo "added headers: ", additional_headers + echo "-------------" else: echo resp.status, ": ", body, " --- url: ", url + echo "*************" + echo url + echo "*************" + echo api + echo "*************" + echo additional_headers + echo "*************" result = newJNull() let error = result.getError diff --git a/src/config.nim b/src/config.nim index fe4aba5..2c216a2 100644 --- a/src/config.nim +++ b/src/config.nim @@ -41,9 +41,7 @@ proc getConfig*(path: string): (Config, parseCfg.Config) = enableRss: cfg.get("Config", "enableRSS", true), enableDebug: cfg.get("Config", "enableDebug", false), proxy: cfg.get("Config", "proxy", ""), - proxyAuth: cfg.get("Config", "proxyAuth", ""), - cookieHeader: cfg.get("Config", "cookieHeader", ""), - xCsrfToken: cfg.get("Config", "xCsrfToken", "") + proxyAuth: cfg.get("Config", "proxyAuth", "") ) return (conf, cfg) diff --git a/src/parser.nim b/src/parser.nim index fac0bd6..95a1fbc 100644 --- a/src/parser.nim +++ b/src/parser.nim @@ -33,6 +33,7 @@ proc parseGraphUser(js: JsonNode): User = var user = js{"user_result", "result"} if user.isNull: user = ? js{"user_results", "result"} + result = parseUser(user{"legacy"}) if result.verifiedType == VerifiedType.none and user{"is_blue_verified"}.getBool(false): @@ -534,7 +535,8 @@ proc parseGraphTimeline*(js: JsonNode; root: string; after=""): Profile = let instructions = if root == "list": ? js{"data", "list", "timeline_response", "timeline", "instructions"} - else: ? js{"data", "user_result", "result", "timeline_response", "timeline", "instructions"} + elif root == "user": ? js{"data", "user_result", "result", "timeline_response", "timeline", "instructions"} + else: ? js{"data", "user", "result", "timeline", "timeline", "instructions"} if instructions.len == 0: return @@ -554,6 +556,21 @@ proc parseGraphTimeline*(js: JsonNode; root: string; after=""): Profile = result.tweets.content.add thread.content elif entryId.startsWith("cursor-bottom"): result.tweets.bottom = e{"content", "value"}.getStr + # TODO cleanup + if i{"type"}.getStr == "TimelineAddEntries": + for e in i{"entries"}: + let entryId = e{"entryId"}.getStr + if entryId.startsWith("tweet"): + with tweetResult, e{"content", "itemContent", "tweet_results", "result"}: + let tweet = parseGraphTweet(tweetResult, false) + if not tweet.available: + tweet.id = parseBiggestInt(entryId.getId()) + result.tweets.content.add tweet + elif "-conversation-" in entryId or entryId.startsWith("homeConversation"): + let (thread, self) = parseGraphThread(e) + result.tweets.content.add thread.content + elif entryId.startsWith("cursor-bottom"): + result.tweets.bottom = e{"content", "value"}.getStr if after.len == 0 and i{"__typename"}.getStr == "TimelinePinEntry": with tweetResult, i{"entry", "content", "content", "tweetResult", "result"}: let tweet = parseGraphTweet(tweetResult, false) diff --git a/src/types.nim b/src/types.nim index 5e58716..a99aed5 100644 --- a/src/types.nim +++ b/src/types.nim @@ -282,9 +282,7 @@ type redisConns*: int redisMaxConns*: int redisPassword*: string - - cookieHeader*: string - xCsrfToken*: string + redisDb*: int Rss* = object feed*, cursor*: string