From ae7091e69d7e3fbbf56b2897ef42111d37d43abb Mon Sep 17 00:00:00 2001 From: Zed Date: Wed, 26 Jan 2022 17:24:03 +0100 Subject: [PATCH] Add experimental GraphQL user parser --- src/api.nim | 6 ++-- src/experimental/parser/graphql.nim | 8 +++++ src/experimental/parser/user.nim | 46 ++++++++++++++++------------- src/experimental/types/graphql.nim | 12 ++++++++ src/experimental/types/user.nim | 1 + src/parser.nim | 10 ------- 6 files changed, 49 insertions(+), 34 deletions(-) create mode 100644 src/experimental/parser/graphql.nim create mode 100644 src/experimental/types/graphql.nim diff --git a/src/api.nim b/src/api.nim index 503af9e..8c97493 100644 --- a/src/api.nim +++ b/src/api.nim @@ -2,14 +2,14 @@ import asyncdispatch, httpclient, uri, strutils, sequtils, sugar import packedjson import types, query, formatters, consts, apiutils, parser -import experimental/parser/user +import experimental/parser/[user, graphql] proc getGraphUser*(id: string): Future[User] {.async.} = if id.len == 0 or id.any(c => not c.isDigit): return let variables = %*{"userId": id, "withSuperFollowsUserFields": true} - js = await fetch(graphUser ? {"variables": $variables}, Api.userRestId) - result = parseGraphUser(js, id) + js = await fetchRaw(graphUser ? {"variables": $variables}, Api.userRestId) + result = parseGraphUser(js) proc getGraphListBySlug*(name, list: string): Future[List] {.async.} = let diff --git a/src/experimental/parser/graphql.nim b/src/experimental/parser/graphql.nim new file mode 100644 index 0000000..df5c40a --- /dev/null +++ b/src/experimental/parser/graphql.nim @@ -0,0 +1,8 @@ +import jsony +import ../types/graphql, user +from ../../types import User + +proc parseGraphUser*(json: string): User = + let raw = json.fromJson(GraphUser) + result = toUser raw.data.user.result.legacy + result.id = raw.data.user.result.restId diff --git a/src/experimental/parser/user.nim b/src/experimental/parser/user.nim index 095d25c..767945b 100644 --- a/src/experimental/parser/user.nim +++ b/src/experimental/parser/user.nim @@ -37,6 +37,30 @@ proc getBanner(user: RawUser): string = if user.profileLinkColor.len > 0: return '#' & user.profileLinkColor +proc toUser*(raw: RawUser): User = + result = User( + id: raw.idStr, + username: raw.screenName, + fullname: raw.name, + location: raw.location, + bio: raw.description, + following: raw.friendsCount, + followers: raw.followersCount, + tweets: raw.statusesCount, + likes: raw.favouritesCount, + media: raw.mediaCount, + verified: raw.verified, + protected: raw.protected, + joinDate: parseTwitterDate(raw.createdAt), + banner: getBanner(raw), + userPic: getImageUrl(raw.profileImageUrlHttps).replace("_normal", "") + ) + + if raw.pinnedTweetIdsStr.len > 0: + result.pinnedTweet = parseBiggestInt(raw.pinnedTweetIdsStr[0]) + + result.expandUserEntities(raw) + proc parseUser*(json: string; username=""): User = handleErrors: case error.code @@ -44,24 +68,4 @@ proc parseUser*(json: string; username=""): User = of userNotFound: return else: echo "[error - parseUser]: ", error - let user = json.fromJson(RawUser) - - result = User( - id: user.idStr, - username: user.screenName, - fullname: user.name, - location: user.location, - bio: user.description, - following: user.friendsCount, - followers: user.followersCount, - tweets: user.statusesCount, - likes: user.favouritesCount, - media: user.mediaCount, - verified: user.verified, - protected: user.protected, - joinDate: parseTwitterDate(user.createdAt), - banner: getBanner(user), - userPic: getImageUrl(user.profileImageUrlHttps).replace("_normal", "") - ) - - result.expandUserEntities(user) + result = toUser json.fromJson(RawUser) diff --git a/src/experimental/types/graphql.nim b/src/experimental/types/graphql.nim new file mode 100644 index 0000000..6697d07 --- /dev/null +++ b/src/experimental/types/graphql.nim @@ -0,0 +1,12 @@ +import user + +type + GraphUserResult* = object + legacy*: RawUser + restId*: string + + GraphUserData* = object + result*: GraphUserResult + + GraphUser* = object + data*: tuple[user: GraphUserData] diff --git a/src/experimental/types/user.nim b/src/experimental/types/user.nim index e3afaf0..c048ba2 100644 --- a/src/experimental/types/user.nim +++ b/src/experimental/types/user.nim @@ -19,6 +19,7 @@ type profileBannerUrl*: string profileImageUrlHttps*: string profileLinkColor*: string + pinnedTweetIdsStr*: seq[string] Entities* = object url*: Urls diff --git a/src/parser.nim b/src/parser.nim index 4f3cc04..177eaed 100644 --- a/src/parser.nim +++ b/src/parser.nim @@ -26,16 +26,6 @@ proc parseUser(js: JsonNode; id=""): User = result.expandUserEntities(js) -proc parseGraphUser*(js: JsonNode; id: string): User = - if js.isNull: return - - with user, js{"data", "user", "result", "legacy"}: - result = parseUser(user, id) - - with pinned, user{"pinned_tweet_ids_str"}: - if pinned.kind == JArray and pinned.len > 0: - result.pinnedTweet = parseBiggestInt(pinned[0].getStr) - proc parseGraphList*(js: JsonNode): List = if js.isNull: return