From bfcb74c6cc7cfa51b392f27fa794b0884f08c12d Mon Sep 17 00:00:00 2001 From: Zed Date: Tue, 6 Aug 2019 19:02:38 +0200 Subject: [PATCH] Cache videos --- src/api.nim | 24 ++++++++++++++++++++---- src/nitter.nim | 6 +++--- src/parser.nim | 3 ++- src/types.nim | 34 ++++++++++++++++++++++------------ 4 files changed, 47 insertions(+), 20 deletions(-) diff --git a/src/api.nim b/src/api.nim index 080259c..2d52569 100644 --- a/src/api.nim +++ b/src/api.nim @@ -117,7 +117,7 @@ proc getGuestToken(agent: string; force=false): Future[string] {.async.} = result = json["guest_token"].to(string) guestToken = result -proc getVideo*(tweet: Tweet; token, agent: string) {.async.} = +proc getVideoFetch*(tweet: Tweet; token, agent: string) {.async.} = if tweet.video.isNone(): return let headers = newHttpHeaders({ @@ -135,16 +135,32 @@ proc getVideo*(tweet: Tweet; token, agent: string) {.async.} = if getTime() - tokenUpdated > initDuration(seconds=1): tokenUpdated = getTime() discard await getGuestToken(agent, force=true) - await getVideo(tweet, guestToken, agent) + await getVideoFetch(tweet, guestToken, agent) return if tweet.card.isNone: - tweet.video = some(parseVideo(json)) + tweet.video = some(parseVideo(json, tweet.id)) else: - get(tweet.card).video = some(parseVideo(json)) + get(tweet.card).video = some(parseVideo(json, tweet.id)) tweet.video = none(Video) tokenUses.inc +proc getVideoVar*(tweet: Tweet): var Option[Video] = + if tweet.card.isSome(): + return get(tweet.card).video + else: + return tweet.video + +proc getVideo*(tweet: Tweet; token, agent: string; force=false) {.async.} = + withDb: + try: + getVideoVar(tweet) = some(Video.getOne("videoId = ?", tweet.id)) + except KeyError: + await getVideoFetch(tweet, token, agent) + var video = getVideoVar(tweet) + if video.isSome(): + get(video).insert() + proc getPoll*(tweet: Tweet; agent: string) {.async.} = if tweet.poll.isNone(): return diff --git a/src/nitter.nim b/src/nitter.nim index ba582be..2bd1c57 100644 --- a/src/nitter.nim +++ b/src/nitter.nim @@ -1,4 +1,4 @@ -import asyncdispatch, asyncfile, httpclient, strutils, strformat, uri, os +import asyncdispatch, asyncfile, httpclient, sequtils, strutils, strformat, uri, os from net import Port import jester, regex @@ -34,11 +34,11 @@ proc showMultiTimeline(names: seq[string]; after, agent: string; query: Option[Q q = some(Query(kind: multi, fromUser: names, excludes: @["replies"])) var timeline = renderMulti(await getTimelineSearch(get(q), after, agent), names.join(",")) - return renderMain(timeline, title=cfg.title, titleText=names.join(" | ")) + return renderMain(timeline, title=cfg.title, titleText="Multi") proc showTimeline(name, after: string; query: Option[Query]): Future[string] {.async.} = let agent = getAgent() - let names = name.strip(chars={'/'}).split(",") + let names = name.strip(chars={'/'}).split(",").filterIt(it.len > 0) if names.len == 1: return await showSingleTimeline(names[0], after, agent, query) diff --git a/src/parser.nim b/src/parser.nim index db8f654..c75884d 100644 --- a/src/parser.nim +++ b/src/parser.nim @@ -125,7 +125,7 @@ proc parseConversation*(node: XmlNode): Conversation = else: result.replies.add parseThread(thread) -proc parseVideo*(node: JsonNode): Video = +proc parseVideo*(node: JsonNode; tweetId: string): Video = let track = node{"track"} cType = track["contentType"].to(string) @@ -148,6 +148,7 @@ proc parseVideo*(node: JsonNode): Video = else: echo "Can't parse video of type ", cType + result.videoId = tweetId result.thumb = node["posterImage"].to(string) proc parsePoll*(node: XmlNode): Poll = diff --git a/src/types.nim b/src/types.nim index eef6d1e..5807bfc 100644 --- a/src/types.nim +++ b/src/types.nim @@ -3,6 +3,10 @@ import norm/sqlite export sqlite, options +type + VideoType* = enum + vmap, m3u8, mp4 + db("cache.db", "", "", ""): type Profile* = object @@ -30,6 +34,24 @@ db("cache.db", "", "", ""): formatIt: getTime().toUnix() .}: Time + Video* = object + videoId*: string + contentId*: string + durationMs*: int + url*: string + thumb*: string + views*: string + playbackType* {. + dbType: "STRING", + parseIt: parseEnum[VideoType](it.s), + formatIt: $it, + .}: VideoType + available* {. + dbType: "STRING", + parseIt: parseBool(it.s) + formatIt: $it + .}: bool + type QueryKind* = enum replies, media, multi, custom = "search" @@ -42,18 +64,6 @@ type fromUser*: seq[string] sep*: string - VideoType* = enum - vmap, m3u8, mp4 - - Video* = object - contentId*: string - playbackType*: VideoType - durationMs*: int - url*: string - thumb*: string - views*: string - available*: bool - Gif* = object url*: string thumb*: string