Rearchitect profile, support pins, Profile -> User
This commit is contained in:
@@ -4,9 +4,9 @@ import packedjson, packedjson/deserialiser
|
||||
import types, parserutils, utils
|
||||
import experimental/parser/unifiedcard
|
||||
|
||||
proc parseProfile(js: JsonNode; id=""): Profile =
|
||||
proc parseUser(js: JsonNode; id=""): User =
|
||||
if js.isNull: return
|
||||
result = Profile(
|
||||
result = User(
|
||||
id: if id.len > 0: id else: js{"id_str"}.getStr,
|
||||
username: js{"screen_name"}.getStr,
|
||||
fullname: js{"name"}.getStr,
|
||||
@@ -24,7 +24,17 @@ proc parseProfile(js: JsonNode; id=""): Profile =
|
||||
joinDate: js{"created_at"}.getTime
|
||||
)
|
||||
|
||||
result.expandProfileEntities(js)
|
||||
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
|
||||
@@ -45,21 +55,30 @@ proc parseGraphList*(js: JsonNode): List =
|
||||
banner: list{"custom_banner_media", "media_info", "url"}.getImageStr
|
||||
)
|
||||
|
||||
proc parseListMembers*(js: JsonNode; cursor: string): Result[Profile] =
|
||||
result = Result[Profile](
|
||||
proc parseGraphListMembers*(js: JsonNode; cursor: string): Result[User] =
|
||||
result = Result[User](
|
||||
beginning: cursor.len == 0,
|
||||
query: Query(kind: userList)
|
||||
)
|
||||
|
||||
if js.isNull: return
|
||||
|
||||
result.top = js{"previous_cursor_str"}.getStr
|
||||
result.bottom = js{"next_cursor_str"}.getStr
|
||||
if result.bottom.len == 1:
|
||||
result.bottom.setLen 0
|
||||
# result.top = js{"previous_cursor_str"}.getStr
|
||||
# result.bottom = js{"next_cursor_str"}.getStr
|
||||
# if result.bottom.len == 1:
|
||||
# result.bottom.setLen 0
|
||||
|
||||
let root = js{"data", "list", "members_timeline", "timeline", "instructions"}
|
||||
for instruction in root:
|
||||
if instruction{"type"}.getStr == "TimelineAddEntries":
|
||||
for entry in instruction{"entries"}:
|
||||
let content = entry{"content"}
|
||||
if content{"entryType"}.getStr == "TimelineTimelineItem":
|
||||
with legacy, content{"itemContent", "user_results", "result", "legacy"}:
|
||||
result.content.add parseUser(legacy)
|
||||
elif content{"cursorType"}.getStr == "Bottom":
|
||||
result.bottom = content{"value"}.getStr
|
||||
|
||||
for u in js{"users"}:
|
||||
result.content.add parseProfile(u)
|
||||
|
||||
proc parsePoll(js: JsonNode): Poll =
|
||||
let vals = js{"binding_values"}
|
||||
@@ -206,7 +225,7 @@ proc parseTweet(js: JsonNode): Tweet =
|
||||
time: js{"created_at"}.getTime,
|
||||
hasThread: js{"self_thread"}.notNull,
|
||||
available: true,
|
||||
profile: Profile(id: js{"user_id_str"}.getStr),
|
||||
user: User(id: js{"user_id_str"}.getStr),
|
||||
stats: TweetStats(
|
||||
replies: js{"reply_count"}.getInt,
|
||||
retweets: js{"retweet_count"}.getInt,
|
||||
@@ -244,7 +263,7 @@ proc parseTweet(js: JsonNode): Tweet =
|
||||
of "video":
|
||||
result.video = some(parseVideo(m))
|
||||
with user, m{"additional_media_info", "source_user"}:
|
||||
result.attribution = some(parseProfile(user))
|
||||
result.attribution = some(parseUser(user))
|
||||
of "animated_gif":
|
||||
result.gif = some(parseGif(m))
|
||||
else: discard
|
||||
@@ -298,36 +317,32 @@ proc parseGlobalObjects(js: JsonNode): GlobalObjects =
|
||||
users = ? js{"globalObjects", "users"}
|
||||
|
||||
for k, v in users:
|
||||
result.users[k] = parseProfile(v, k)
|
||||
result.users[k] = parseUser(v, k)
|
||||
|
||||
for k, v in tweets:
|
||||
var tweet = parseTweet(v)
|
||||
if tweet.profile.id in result.users:
|
||||
tweet.profile = result.users[tweet.profile.id]
|
||||
if tweet.user.id in result.users:
|
||||
tweet.user = result.users[tweet.user.id]
|
||||
result.tweets[k] = tweet
|
||||
|
||||
proc parseThread(js: JsonNode; global: GlobalObjects): tuple[thread: Chain, self: bool] =
|
||||
result.thread = Chain()
|
||||
for t in js{"content", "timelineModule", "items"}:
|
||||
let content = t{"item", "content"}
|
||||
if "Self" in content{"tweet", "displayType"}.getStr:
|
||||
|
||||
let thread = js{"content", "item", "content", "conversationThread"}
|
||||
with cursor, thread{"showMoreCursor"}:
|
||||
result.thread.cursor = cursor{"value"}.getStr
|
||||
result.thread.hasMore = true
|
||||
|
||||
for t in thread{"conversationComponents"}:
|
||||
let content = t{"conversationTweetComponent", "tweet"}
|
||||
|
||||
if content{"displayType"}.getStr == "SelfThread":
|
||||
result.self = true
|
||||
|
||||
let entry = t{"entryId"}.getStr
|
||||
if "show_more" in entry:
|
||||
let
|
||||
cursor = content{"timelineCursor"}
|
||||
more = cursor{"displayTreatment", "actionText"}.getStr
|
||||
result.thread.cursor = cursor{"value"}.getStr
|
||||
if more.len > 0 and more[0].isDigit():
|
||||
result.thread.more = parseInt(more[0 ..< more.find(" ")])
|
||||
else:
|
||||
result.thread.more = -1
|
||||
else:
|
||||
var tweet = finalizeTweet(global, t.getEntryId)
|
||||
if not tweet.available:
|
||||
tweet.tombstone = getTombstone(content{"tombstone"})
|
||||
result.thread.content.add tweet
|
||||
var tweet = finalizeTweet(global, content{"id"}.getStr)
|
||||
if not tweet.available:
|
||||
tweet.tombstone = getTombstone(content{"tombstone"})
|
||||
result.thread.content.add tweet
|
||||
|
||||
proc parseConversation*(js: JsonNode; tweetId: string): Conversation =
|
||||
result = Conversation(replies: Result[Chain](beginning: true))
|
||||
@@ -373,8 +388,8 @@ proc parseInstructions[T](res: var Result[T]; global: GlobalObjects; js: JsonNod
|
||||
elif "bottom" in r{"entryId"}.getStr:
|
||||
res.bottom = r.getCursor
|
||||
|
||||
proc parseUsers*(js: JsonNode; after=""): Result[Profile] =
|
||||
result = Result[Profile](beginning: after.len == 0)
|
||||
proc parseUsers*(js: JsonNode; after=""): Result[User] =
|
||||
result = Result[User](beginning: after.len == 0)
|
||||
let global = parseGlobalObjects(? js)
|
||||
|
||||
let instructions = ? js{"timeline", "instructions"}
|
||||
@@ -404,7 +419,7 @@ proc parseTimeline*(js: JsonNode; after=""): Timeline =
|
||||
|
||||
for e in instructions[0]{"addEntries", "entries"}:
|
||||
let entry = e{"entryId"}.getStr
|
||||
if "tweet" in entry or "sq-I-t" in entry or "tombstone" in entry:
|
||||
if "tweet" in entry or entry.startsWith("sq-I-t") or "tombstone" in entry:
|
||||
let tweet = finalizeTweet(global, e.getEntryId)
|
||||
if not tweet.available: continue
|
||||
result.content.add tweet
|
||||
@@ -412,6 +427,12 @@ proc parseTimeline*(js: JsonNode; after=""): Timeline =
|
||||
result.top = e.getCursor
|
||||
elif "cursor-bottom" in entry:
|
||||
result.bottom = e.getCursor
|
||||
elif entry.startsWith("sq-C"):
|
||||
with cursor, e{"content", "operation", "cursor"}:
|
||||
if cursor{"cursorType"}.getStr == "Bottom":
|
||||
result.bottom = cursor{"value"}.getStr
|
||||
else:
|
||||
result.top = cursor{"value"}.getStr
|
||||
|
||||
proc parsePhotoRail*(js: JsonNode): PhotoRail =
|
||||
for tweet in js:
|
||||
|
||||
Reference in New Issue
Block a user