|
|
@@ -0,0 +1,97 @@
|
|
|
+import std/[strutils, options, algorithm, json]
|
|
|
+import std/unicode except strip
|
|
|
+import utils, slices, media, user
|
|
|
+import ../types/tweet
|
|
|
+from ../types/media as mediaTypes import MediaType
|
|
|
+from ../../types import Tweet, User, TweetStats
|
|
|
+
|
|
|
+proc expandTweetEntities(tweet: var Tweet; raw: RawTweet) =
|
|
|
+ let
|
|
|
+ orig = raw.fullText.toRunes
|
|
|
+ textRange = raw.displayTextRange
|
|
|
+ textSlice = textRange[0] .. textRange[1]
|
|
|
+ hasCard = raw.card.isSome
|
|
|
+
|
|
|
+ var replyTo = ""
|
|
|
+ if tweet.replyId > 0:
|
|
|
+ tweet.reply.add raw.inReplyToScreenName
|
|
|
+ replyTo = raw.inReplyToScreenName
|
|
|
+
|
|
|
+ var replacements = newSeq[ReplaceSlice]()
|
|
|
+
|
|
|
+ for u in raw.entities.urls:
|
|
|
+ if u.url.len == 0 or u.url notin raw.fullText:
|
|
|
+ continue
|
|
|
+
|
|
|
+ replacements.extractUrls(u, textSlice.b, hideTwitter=raw.isQuoteStatus)
|
|
|
+ # if hasCard and u.url == get(tweet.card).url:
|
|
|
+ # get(tweet.card).url = u.expandedUrl
|
|
|
+
|
|
|
+ for m in raw.entities.media:
|
|
|
+ replacements.extractUrls(m, textSlice.b, hideTwitter=true)
|
|
|
+
|
|
|
+ for hashtag in raw.entities.hashtags:
|
|
|
+ replacements.extractHashtags(hashtag.indices)
|
|
|
+
|
|
|
+ for symbol in raw.entities.symbols:
|
|
|
+ replacements.extractHashtags(symbol.indices)
|
|
|
+
|
|
|
+ for mention in raw.entities.userMentions:
|
|
|
+ let
|
|
|
+ name = mention.screenName
|
|
|
+ idx = tweet.reply.find(name)
|
|
|
+
|
|
|
+ if mention.indices.a >= textSlice.a:
|
|
|
+ replacements.add ReplaceSlice(kind: rkMention, slice: mention.indices,
|
|
|
+ url: "/" & name, display: mention.name)
|
|
|
+ if idx > -1 and name != replyTo:
|
|
|
+ tweet.reply.delete idx
|
|
|
+ elif idx == -1 and tweet.replyId != 0:
|
|
|
+ tweet.reply.add name
|
|
|
+
|
|
|
+ replacements.dedupSlices
|
|
|
+ replacements.sort(cmp)
|
|
|
+
|
|
|
+ tweet.text = orig.replacedWith(replacements, textSlice)
|
|
|
+ .strip(leading=false)
|
|
|
+
|
|
|
+proc toTweet*(raw: RawTweet): Tweet =
|
|
|
+ result = Tweet(
|
|
|
+ id: raw.idStr.toId,
|
|
|
+ threadId: raw.conversationIdStr.toId,
|
|
|
+ replyId: raw.inReplyToStatusIdStr.toId,
|
|
|
+ time: parseTwitterDate(raw.createdAt),
|
|
|
+ hasThread: raw.selfThread.idStr.len > 0,
|
|
|
+ available: true,
|
|
|
+ user: User(id: raw.userIdStr),
|
|
|
+ stats: TweetStats(
|
|
|
+ replies: raw.replyCount,
|
|
|
+ retweets: raw.retweetCount,
|
|
|
+ likes: raw.favoriteCount,
|
|
|
+ quotes: raw.quoteCount
|
|
|
+ )
|
|
|
+ )
|
|
|
+
|
|
|
+ result.expandTweetEntities(raw)
|
|
|
+
|
|
|
+ if raw.card.isSome:
|
|
|
+ let card = raw.card.get
|
|
|
+ if "poll" in card.name:
|
|
|
+ result.poll = some parsePoll(card)
|
|
|
+ if "image" in card.name:
|
|
|
+ result.photos.add card.bindingValues{"image_large", "image_value", "url"}
|
|
|
+ .getStr.getImageUrl
|
|
|
+ # elif card.name == "amplify":
|
|
|
+ # discard
|
|
|
+ # # result.video = some(parsePromoVideo(jsCard{"binding_values"}))
|
|
|
+ # else:
|
|
|
+ # result.card = some parseCard(card, raw.entities.urls)
|
|
|
+
|
|
|
+ for m in raw.extendedEntities.media:
|
|
|
+ case m.kind
|
|
|
+ of photo: result.photos.add m.getImageUrl
|
|
|
+ of video:
|
|
|
+ result.video = some parseVideo(m)
|
|
|
+ if m.additionalMediaInfo.sourceUser.isSome:
|
|
|
+ result.attribution = some toUser get(m.additionalMediaInfo.sourceUser)
|
|
|
+ of animatedGif: result.gif = some parseGif(m)
|