Refactor nil checks, remove getAttr
This commit is contained in:
		
							parent
							
								
									a43950dcf5
								
							
						
					
					
						commit
						e2039ec81c
					
				| 
						 | 
					@ -498,6 +498,7 @@ nav {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.thread-last .status-el::before {
 | 
					.thread-last .status-el::before {
 | 
				
			||||||
    background: unset;
 | 
					    background: unset;
 | 
				
			||||||
 | 
					    min-width: unset;
 | 
				
			||||||
    width: 0;
 | 
					    width: 0;
 | 
				
			||||||
    margin: 0;
 | 
					    margin: 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										15
									
								
								src/api.nim
								
								
								
								
							
							
						
						
									
										15
									
								
								src/api.nim
								
								
								
								
							| 
						 | 
					@ -96,7 +96,7 @@ proc getVideo*(tweet: Tweet; token: string) {.async.} =
 | 
				
			||||||
    url = apiBase / (videoUrl % tweet.id)
 | 
					    url = apiBase / (videoUrl % tweet.id)
 | 
				
			||||||
    json = await fetchJson(url, headers)
 | 
					    json = await fetchJson(url, headers)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if json.isNil:
 | 
					  if json == nil:
 | 
				
			||||||
    if getTime() - tokenUpdated > initDuration(seconds=1):
 | 
					    if getTime() - tokenUpdated > initDuration(seconds=1):
 | 
				
			||||||
      tokenUpdated = getTime()
 | 
					      tokenUpdated = getTime()
 | 
				
			||||||
      guestToken = await getGuestToken(force=true)
 | 
					      guestToken = await getGuestToken(force=true)
 | 
				
			||||||
| 
						 | 
					@ -134,8 +134,7 @@ proc getProfileFallback(username: string; headers: HttpHeaders): Future[Profile]
 | 
				
			||||||
    url = base / profileIntentUrl ? {"screen_name": username}
 | 
					    url = base / profileIntentUrl ? {"screen_name": username}
 | 
				
			||||||
    html = await fetchHtml(url, headers)
 | 
					    html = await fetchHtml(url, headers)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if html.isNil:
 | 
					  if html == nil: return Profile()
 | 
				
			||||||
    return Profile()
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  result = parseIntentProfile(html)
 | 
					  result = parseIntentProfile(html)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -158,10 +157,9 @@ proc getProfile*(username: string): Future[Profile] {.async.} =
 | 
				
			||||||
    url = base / profilePopupUrl ? params
 | 
					    url = base / profilePopupUrl ? params
 | 
				
			||||||
    html = await fetchHtml(url, headers, jsonKey="html")
 | 
					    html = await fetchHtml(url, headers, jsonKey="html")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if html.isNil:
 | 
					  if html == nil: return Profile()
 | 
				
			||||||
    return Profile()
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if not html.select(".ProfileCard-sensitiveWarningContainer").isNil:
 | 
					  if html.select(".ProfileCard-sensitiveWarningContainer") != nil:
 | 
				
			||||||
    return await getProfileFallback(username, headers)
 | 
					    return await getProfileFallback(username, headers)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  result = parsePopupProfile(html)
 | 
					  result = parsePopupProfile(html)
 | 
				
			||||||
| 
						 | 
					@ -182,7 +180,7 @@ proc getTimeline*(username: string; after=""): Future[Timeline] {.async.} =
 | 
				
			||||||
    url &= "&max_position=" & cleanAfter
 | 
					    url &= "&max_position=" & cleanAfter
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  let json = await fetchJson(base / url, headers)
 | 
					  let json = await fetchJson(base / url, headers)
 | 
				
			||||||
  if json.isNil: return Timeline()
 | 
					  if json == nil: return Timeline()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  result = Timeline(
 | 
					  result = Timeline(
 | 
				
			||||||
    hasMore: json["has_more_items"].to(bool),
 | 
					    hasMore: json["has_more_items"].to(bool),
 | 
				
			||||||
| 
						 | 
					@ -213,8 +211,7 @@ proc getTweet*(username: string; id: string): Future[Conversation] {.async.} =
 | 
				
			||||||
    url = base / username / tweetUrl / id
 | 
					    url = base / username / tweetUrl / id
 | 
				
			||||||
    html = await fetchHtml(url, headers)
 | 
					    html = await fetchHtml(url, headers)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if html.isNil:
 | 
					  if html == nil: return
 | 
				
			||||||
    return
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  result = parseConversation(html)
 | 
					  result = parseConversation(html)
 | 
				
			||||||
  await getConversationVideos(result)
 | 
					  await getConversationVideos(result)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -44,7 +44,7 @@ routes:
 | 
				
			||||||
    cond '.' notin @"name"
 | 
					    cond '.' notin @"name"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let conversation = await getTweet(@"name", @"id")
 | 
					    let conversation = await getTweet(@"name", @"id")
 | 
				
			||||||
    if conversation.isNil or conversation.tweet.id.len == 0:
 | 
					    if conversation == nil or conversation.tweet.id.len == 0:
 | 
				
			||||||
      resp Http404, showError("Tweet not found")
 | 
					      resp Http404, showError("Tweet not found")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let title = pageTitle(conversation.tweet.profile)
 | 
					    let title = pageTitle(conversation.tweet.profile)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4,7 +4,7 @@ import ./types, ./parserutils, ./formatters
 | 
				
			||||||
 | 
					
 | 
				
			||||||
proc parsePopupProfile*(node: XmlNode): Profile =
 | 
					proc parsePopupProfile*(node: XmlNode): Profile =
 | 
				
			||||||
  let profile = node.select(".profile-card")
 | 
					  let profile = node.select(".profile-card")
 | 
				
			||||||
  if profile.isNil: return
 | 
					  if profile == nil: return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  result = Profile(
 | 
					  result = Profile(
 | 
				
			||||||
    fullname:  profile.getName(".fullname"),
 | 
					    fullname:  profile.getName(".fullname"),
 | 
				
			||||||
| 
						 | 
					@ -24,8 +24,8 @@ proc parseIntentProfile*(profile: XmlNode): Profile =
 | 
				
			||||||
    username:  profile.getUsername(".nickname"),
 | 
					    username:  profile.getUsername(".nickname"),
 | 
				
			||||||
    bio:       profile.getBio("p.note"),
 | 
					    bio:       profile.getBio("p.note"),
 | 
				
			||||||
    userpic:   profile.select(".profile.summary").getAvatar("img.photo"),
 | 
					    userpic:   profile.select(".profile.summary").getAvatar("img.photo"),
 | 
				
			||||||
    verified:  not profile.select("li.verified").isNil,
 | 
					    verified:  profile.select("li.verified") != nil,
 | 
				
			||||||
    protected: not profile.select("li.protected").isNil,
 | 
					    protected: profile.select("li.protected") != nil,
 | 
				
			||||||
    banner:    getBanner(profile)
 | 
					    banner:    getBanner(profile)
 | 
				
			||||||
  )
 | 
					  )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -33,22 +33,22 @@ proc parseIntentProfile*(profile: XmlNode): Profile =
 | 
				
			||||||
 | 
					
 | 
				
			||||||
proc parseTweetProfile*(profile: XmlNode): Profile =
 | 
					proc parseTweetProfile*(profile: XmlNode): Profile =
 | 
				
			||||||
  result = Profile(
 | 
					  result = Profile(
 | 
				
			||||||
    fullname: profile.getAttr("data-name").stripText(),
 | 
					    fullname: profile.attr("data-name").stripText(),
 | 
				
			||||||
    username: profile.getAttr("data-screen-name"),
 | 
					    username: profile.attr("data-screen-name"),
 | 
				
			||||||
    userpic:  profile.getAvatar(".avatar"),
 | 
					    userpic:  profile.getAvatar(".avatar"),
 | 
				
			||||||
    verified: isVerified(profile)
 | 
					    verified: isVerified(profile)
 | 
				
			||||||
  )
 | 
					  )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
proc parseQuote*(quote: XmlNode): Quote =
 | 
					proc parseQuote*(quote: XmlNode): Quote =
 | 
				
			||||||
  result = Quote(
 | 
					  result = Quote(
 | 
				
			||||||
    id:   quote.getAttr("data-item-id"),
 | 
					    id:   quote.attr("data-item-id"),
 | 
				
			||||||
    link: quote.getAttr("href"),
 | 
					    link: quote.attr("href"),
 | 
				
			||||||
    text: getQuoteText(quote)
 | 
					    text: getQuoteText(quote)
 | 
				
			||||||
  )
 | 
					  )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  result.profile = Profile(
 | 
					  result.profile = Profile(
 | 
				
			||||||
    fullname: quote.selectText(".QuoteTweet-fullname").stripText(),
 | 
					    fullname: quote.selectText(".QuoteTweet-fullname").stripText(),
 | 
				
			||||||
    username: quote.getAttr("data-screen-name"),
 | 
					    username: quote.attr("data-screen-name"),
 | 
				
			||||||
    verified: isVerified(quote)
 | 
					    verified: isVerified(quote)
 | 
				
			||||||
  )
 | 
					  )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -56,17 +56,17 @@ proc parseQuote*(quote: XmlNode): Quote =
 | 
				
			||||||
 | 
					
 | 
				
			||||||
proc parseTweet*(node: XmlNode): Tweet =
 | 
					proc parseTweet*(node: XmlNode): Tweet =
 | 
				
			||||||
  let tweet = node.select(".tweet")
 | 
					  let tweet = node.select(".tweet")
 | 
				
			||||||
  if tweet.isNil():
 | 
					  if tweet == nil: return Tweet()
 | 
				
			||||||
    return Tweet()
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  result = Tweet(
 | 
					  result = Tweet(
 | 
				
			||||||
    id:        tweet.getAttr("data-item-id"),
 | 
					    id:        tweet.attr("data-item-id"),
 | 
				
			||||||
    link:      tweet.getAttr("data-permalink-path"),
 | 
					    link:      tweet.attr("data-permalink-path"),
 | 
				
			||||||
    profile:   parseTweetProfile(tweet),
 | 
					 | 
				
			||||||
    text:      getTweetText(tweet),
 | 
					    text:      getTweetText(tweet),
 | 
				
			||||||
    time:      getTimestamp(tweet),
 | 
					    time:      getTimestamp(tweet),
 | 
				
			||||||
    shortTime: getShortTime(tweet),
 | 
					    shortTime: getShortTime(tweet),
 | 
				
			||||||
    pinned:    "pinned" in tweet.getAttr("class")
 | 
					    profile:   parseTweetProfile(tweet),
 | 
				
			||||||
 | 
					    pinned:    "pinned" in tweet.attr("class"),
 | 
				
			||||||
 | 
					    available: true
 | 
				
			||||||
  )
 | 
					  )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  result.getTweetStats(tweet)
 | 
					  result.getTweetStats(tweet)
 | 
				
			||||||
| 
						 | 
					@ -75,14 +75,14 @@ proc parseTweet*(node: XmlNode): Tweet =
 | 
				
			||||||
  let by = tweet.selectText(".js-retweet-text > a > b")
 | 
					  let by = tweet.selectText(".js-retweet-text > a > b")
 | 
				
			||||||
  if by.len > 0:
 | 
					  if by.len > 0:
 | 
				
			||||||
    result.retweetBy = some(by.stripText())
 | 
					    result.retweetBy = some(by.stripText())
 | 
				
			||||||
    result.retweetId = some(tweet.getAttr("data-retweet-id"))
 | 
					    result.retweetId = some(tweet.attr("data-retweet-id"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  let quote = tweet.select(".QuoteTweet-innerContainer")
 | 
					  let quote = tweet.select(".QuoteTweet-innerContainer")
 | 
				
			||||||
  if not quote.isNil:
 | 
					  if quote != nil:
 | 
				
			||||||
    result.quote = some(parseQuote(quote))
 | 
					    result.quote = some(parseQuote(quote))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
proc parseTweets*(node: XmlNode): Tweets =
 | 
					proc parseTweets*(node: XmlNode): Tweets =
 | 
				
			||||||
  if node.isNil or node.kind == xnText: return
 | 
					  if node == nil or node.kind == xnText: return
 | 
				
			||||||
  node.selectAll(".stream-item").map(parseTweet)
 | 
					  node.selectAll(".stream-item").map(parseTweet)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
proc parseConversation*(node: XmlNode): Conversation =
 | 
					proc parseConversation*(node: XmlNode): Conversation =
 | 
				
			||||||
| 
						 | 
					@ -92,7 +92,7 @@ proc parseConversation*(node: XmlNode): Conversation =
 | 
				
			||||||
  )
 | 
					  )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  let replies = node.select(".replies-to", ".stream-items")
 | 
					  let replies = node.select(".replies-to", ".stream-items")
 | 
				
			||||||
  if replies.isNil: return
 | 
					  if replies == nil: return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  for reply in replies.filterIt(it.kind != xnText):
 | 
					  for reply in replies.filterIt(it.kind != xnText):
 | 
				
			||||||
    if "selfThread" in reply.attr("class"):
 | 
					    if "selfThread" in reply.attr("class"):
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -10,24 +10,22 @@ const
 | 
				
			||||||
  gifRegex = re".+thumb/([^\.']+)\.jpg.*"
 | 
					  gifRegex = re".+thumb/([^\.']+)\.jpg.*"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
proc selectAll*(node: XmlNode; selector: string): seq[XmlNode] =
 | 
					proc selectAll*(node: XmlNode; selector: string): seq[XmlNode] =
 | 
				
			||||||
 | 
					  if node == nil: return
 | 
				
			||||||
  q.select(node, selector)
 | 
					  q.select(node, selector)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
proc select*(node: XmlNode; selector: string): XmlNode =
 | 
					proc select*(node: XmlNode; selector: string): XmlNode =
 | 
				
			||||||
 | 
					  if node == nil: return
 | 
				
			||||||
  let nodes = node.selectAll(selector)
 | 
					  let nodes = node.selectAll(selector)
 | 
				
			||||||
  if nodes.len > 0: nodes[0] else: nil
 | 
					  if nodes.len > 0: nodes[0] else: nil
 | 
				
			||||||
 | 
					
 | 
				
			||||||
proc select*(node: XmlNode; parent, child: string): XmlNode =
 | 
					proc select*(node: XmlNode; parent, child: string): XmlNode =
 | 
				
			||||||
  let parentNode = node.select(parent)
 | 
					  let parentNode = node.select(parent)
 | 
				
			||||||
  if parentNode.isNil(): return
 | 
					  if parentNode == nil: return
 | 
				
			||||||
  result = parentNode.select(child)
 | 
					  result = parentNode.select(child)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
proc getAttr*(node: XmlNode; attr: string; default=""): string =
 | 
					proc selectAttr*(node: XmlNode; selector: string; attr: string): string =
 | 
				
			||||||
  if node.isNil or node.attrs.isNil: return default
 | 
					 | 
				
			||||||
  return node.attrs.getOrDefault(attr)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
proc selectAttr*(node: XmlNode; selector: string; attr: string; default=""): string =
 | 
					 | 
				
			||||||
  let res = node.select(selector)
 | 
					  let res = node.select(selector)
 | 
				
			||||||
  if res == nil: "" else: res.getAttr(attr, default)
 | 
					  if res == nil: "" else: res.attr(attr)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
proc selectText*(node: XmlNode; selector: string): string =
 | 
					proc selectText*(node: XmlNode; selector: string): string =
 | 
				
			||||||
  let res = node.select(selector)
 | 
					  let res = node.select(selector)
 | 
				
			||||||
| 
						 | 
					@ -35,9 +33,9 @@ proc selectText*(node: XmlNode; selector: string): string =
 | 
				
			||||||
 | 
					
 | 
				
			||||||
proc getHeader(profile: XmlNode): XmlNode =
 | 
					proc getHeader(profile: XmlNode): XmlNode =
 | 
				
			||||||
  result = profile.select(".permalink-header")
 | 
					  result = profile.select(".permalink-header")
 | 
				
			||||||
  if result.isNil:
 | 
					  if result == nil:
 | 
				
			||||||
    result = profile.select(".stream-item-header")
 | 
					    result = profile.select(".stream-item-header")
 | 
				
			||||||
  if result.isNil:
 | 
					  if result == nil:
 | 
				
			||||||
    result = profile.select(".ProfileCard-userFields")
 | 
					    result = profile.select(".ProfileCard-userFields")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
proc isVerified*(profile: XmlNode): bool =
 | 
					proc isVerified*(profile: XmlNode): bool =
 | 
				
			||||||
| 
						 | 
					@ -54,7 +52,7 @@ proc getUsername*(profile: XmlNode; selector: string): string =
 | 
				
			||||||
 | 
					
 | 
				
			||||||
proc emojify*(node: XmlNode) =
 | 
					proc emojify*(node: XmlNode) =
 | 
				
			||||||
  for i in node.selectAll(".Emoji"):
 | 
					  for i in node.selectAll(".Emoji"):
 | 
				
			||||||
    i.add newText(i.getAttr("alt"))
 | 
					    i.add newText(i.attr("alt"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
proc getQuoteText*(tweet: XmlNode): string =
 | 
					proc getQuoteText*(tweet: XmlNode): string =
 | 
				
			||||||
  let text = tweet.select(".QuoteTweet-text")
 | 
					  let text = tweet.select(".QuoteTweet-text")
 | 
				
			||||||
| 
						 | 
					@ -71,7 +69,7 @@ proc getTweetText*(tweet: XmlNode): string =
 | 
				
			||||||
  emojify(text)
 | 
					  emojify(text)
 | 
				
			||||||
  result = stripText(text.innerText())
 | 
					  result = stripText(text.innerText())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if not quote.isNil and link.len > 0:
 | 
					  if quote != nil and link.len > 0:
 | 
				
			||||||
    result = result.replace(link, "")
 | 
					    result = result.replace(link, "")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  result = stripTwitterUrls(result)
 | 
					  result = stripTwitterUrls(result)
 | 
				
			||||||
| 
						 | 
					@ -80,8 +78,8 @@ proc getTime(tweet: XmlNode): XmlNode =
 | 
				
			||||||
  tweet.select(".js-short-timestamp")
 | 
					  tweet.select(".js-short-timestamp")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
proc getTimestamp*(tweet: XmlNode): Time =
 | 
					proc getTimestamp*(tweet: XmlNode): Time =
 | 
				
			||||||
  let time = getTime(tweet).getAttr("data-time", "0")
 | 
					  let time = getTime(tweet).attr("data-time")
 | 
				
			||||||
  fromUnix(parseInt(time))
 | 
					  fromUnix(if time.len > 0: parseInt(time) else: 0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
proc getShortTime*(tweet: XmlNode): string =
 | 
					proc getShortTime*(tweet: XmlNode): string =
 | 
				
			||||||
  getTime(tweet).innerText()
 | 
					  getTime(tweet).innerText()
 | 
				
			||||||
| 
						 | 
					@ -105,8 +103,8 @@ proc getBanner*(tweet: XmlNode): string =
 | 
				
			||||||
 | 
					
 | 
				
			||||||
proc getPopupStats*(profile: var Profile; node: XmlNode) =
 | 
					proc getPopupStats*(profile: var Profile; node: XmlNode) =
 | 
				
			||||||
  for s in node.selectAll( ".ProfileCardStats-statLink"):
 | 
					  for s in node.selectAll( ".ProfileCardStats-statLink"):
 | 
				
			||||||
    let text = s.getAttr("title").split(" ")[0]
 | 
					    let text = s.attr("title").split(" ")[0]
 | 
				
			||||||
    case s.getAttr("href").split("/")[^1]
 | 
					    case s.attr("href").split("/")[^1]
 | 
				
			||||||
    of "followers": profile.followers = text
 | 
					    of "followers": profile.followers = text
 | 
				
			||||||
    of "following": profile.following = text
 | 
					    of "following": profile.following = text
 | 
				
			||||||
    else: profile.tweets = text
 | 
					    else: profile.tweets = text
 | 
				
			||||||
| 
						 | 
					@ -115,7 +113,7 @@ proc getIntentStats*(profile: var Profile; node: XmlNode) =
 | 
				
			||||||
  profile.tweets = "?"
 | 
					  profile.tweets = "?"
 | 
				
			||||||
  for s in node.selectAll( "dd.count > a"):
 | 
					  for s in node.selectAll( "dd.count > a"):
 | 
				
			||||||
    let text = s.innerText()
 | 
					    let text = s.innerText()
 | 
				
			||||||
    case s.getAttr("href").split("/")[^1]
 | 
					    case s.attr("href").split("/")[^1]
 | 
				
			||||||
    of "followers": profile.followers = text
 | 
					    of "followers": profile.followers = text
 | 
				
			||||||
    of "following": profile.following = text
 | 
					    of "following": profile.following = text
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -132,7 +130,7 @@ proc getTweetStats*(tweet: Tweet; node: XmlNode) =
 | 
				
			||||||
 | 
					
 | 
				
			||||||
proc getGif(player: XmlNode): Gif =
 | 
					proc getGif(player: XmlNode): Gif =
 | 
				
			||||||
  let
 | 
					  let
 | 
				
			||||||
    thumb = player.getAttr("style").replace(thumbRegex, "$1")
 | 
					    thumb = player.attr("style").replace(thumbRegex, "$1")
 | 
				
			||||||
    id = thumb.replace(gifRegex, "$1")
 | 
					    id = thumb.replace(gifRegex, "$1")
 | 
				
			||||||
    url = fmt"https://video.twimg.com/tweet_video/{id}.mp4"
 | 
					    url = fmt"https://video.twimg.com/tweet_video/{id}.mp4"
 | 
				
			||||||
  Gif(url: url, thumb: thumb)
 | 
					  Gif(url: url, thumb: thumb)
 | 
				
			||||||
| 
						 | 
					@ -142,28 +140,28 @@ proc getTweetMedia*(tweet: Tweet; node: XmlNode) =
 | 
				
			||||||
    tweet.photos.add photo.attrs["data-image-url"]
 | 
					    tweet.photos.add photo.attrs["data-image-url"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  let player = node.select(".PlayableMedia")
 | 
					  let player = node.select(".PlayableMedia")
 | 
				
			||||||
  if player.isNil:
 | 
					  if player == nil:
 | 
				
			||||||
    return
 | 
					    return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if "gif" in player.getAttr("class"):
 | 
					  if "gif" in player.attr("class"):
 | 
				
			||||||
    tweet.gif = some(getGif(player.select(".PlayableMedia-player")))
 | 
					    tweet.gif = some(getGif(player.select(".PlayableMedia-player")))
 | 
				
			||||||
  elif "video" in player.getAttr("class"):
 | 
					  elif "video" in player.attr("class"):
 | 
				
			||||||
    tweet.video = some(Video())
 | 
					    tweet.video = some(Video())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
proc getQuoteMedia*(quote: var Quote; node: XmlNode) =
 | 
					proc getQuoteMedia*(quote: var Quote; node: XmlNode) =
 | 
				
			||||||
  let sensitive = node.select(".QuoteTweet--sensitive")
 | 
					  let sensitive = node.select(".QuoteTweet--sensitive")
 | 
				
			||||||
  if not sensitive.isNil:
 | 
					  if sensitive != nil:
 | 
				
			||||||
    quote.sensitive = true
 | 
					    quote.sensitive = true
 | 
				
			||||||
    return
 | 
					    return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  let media = node.select(".QuoteMedia")
 | 
					  let media = node.select(".QuoteMedia")
 | 
				
			||||||
  if not media.isNil:
 | 
					  if media != nil:
 | 
				
			||||||
    quote.thumb = some(media.selectAttr("img", "src"))
 | 
					    quote.thumb = some(media.selectAttr("img", "src"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  let badge = node.select(".AdaptiveMedia-badgeText")
 | 
					  let badge = node.select(".AdaptiveMedia-badgeText")
 | 
				
			||||||
  let gifBadge = node.select(".Icon--gifBadge")
 | 
					  let gifBadge = node.select(".Icon--gifBadge")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if not badge.isNil:
 | 
					  if badge != nil:
 | 
				
			||||||
    quote.badge = some(badge.innerText())
 | 
					    quote.badge = some(badge.innerText())
 | 
				
			||||||
  elif not gifBadge.isNil:
 | 
					  elif gifBadge != nil:
 | 
				
			||||||
    quote.badge = some("GIF")
 | 
					    quote.badge = some("GIF")
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue