From 54d250bde4c890a7ac354ccd19f1958dc8e3a7db Mon Sep 17 00:00:00 2001
From: Omar Roth <omarroth@hotmail.com>
Date: Sun, 28 Apr 2019 18:14:16 -0500
Subject: [PATCH] Add 'since' to '/api/v1/auth/notifications'

---
 src/invidious.cr          | 60 ++++++++++++++++++++++++---------------
 src/invidious/channels.cr | 28 ++++++++++++++++++
 src/invidious/videos.cr   |  6 ++--
 3 files changed, 69 insertions(+), 25 deletions(-)

diff --git a/src/invidious.cr b/src/invidious.cr
index d92cb921..36e6f01d 100644
--- a/src/invidious.cr
+++ b/src/invidious.cr
@@ -3428,29 +3428,13 @@ get "/api/v1/popular" do |env|
 
   env.response.content_type = "application/json"
 
-  videos = JSON.build do |json|
+  JSON.build do |json|
     json.array do
       popular_videos.each do |video|
-        json.object do
-          json.field "title", video.title
-          json.field "videoId", video.id
-          json.field "videoThumbnails" do
-            generate_thumbnails(json, video.id, config, Kemal.config)
-          end
-
-          json.field "lengthSeconds", video.length_seconds
-
-          json.field "author", video.author
-          json.field "authorId", video.ucid
-          json.field "authorUrl", "/channel/#{video.ucid}"
-          json.field "published", video.published.to_unix
-          json.field "publishedText", translate(locale, "`x` ago", recode_date(video.published, locale))
-        end
+        video.to_json(locale, config, Kemal.config, json)
       end
     end
   end
-
-  videos
 end
 
 get "/api/v1/top" do |env|
@@ -3573,9 +3557,9 @@ get "/api/v1/channels/:ucid" do |env|
   metadata.each do |item|
     case item.content
     when .includes? "views"
-      total_views = item.content.delete("views •,").to_i64
+      total_views = item.content.gsub(/\D/, "").to_i64
     when .includes? "subscribers"
-      sub_count = item.content.delete("subscribers").delete(",").to_i64
+      sub_count = item.content.delete("subscribers").gsub(/\D/, "").to_i64
     when .includes? "Joined"
       joined = Time.parse(item.content.lchop("Joined "), "%b %-d, %Y", Time::Location.local)
     end
@@ -3788,7 +3772,7 @@ end
       next error_message
     end
 
-    response = JSON.build do |json|
+    JSON.build do |json|
       json.array do
         videos.each do |video|
           json.object do
@@ -3816,8 +3800,6 @@ end
         end
       end
     end
-
-    response
   end
 end
 
@@ -4295,10 +4277,42 @@ get "/api/v1/auth/notifications" do |env|
   topics = env.params.query["topics"]?.try &.split(",").uniq.first(1000)
   topics ||= [] of String
 
+  since = env.params.query["since"]?.try &.to_i?
+
   begin
     id = 0
 
     spawn do
+      if since
+        topics.try &.each do |topic|
+          case topic
+          when .match(/UC[A-Za-z0-9_-]{22}/)
+            PG_DB.query_all("SELECT * FROM channel_videos WHERE ucid = $1 AND published > $2 ORDER BY published DESC LIMIT 15",
+              topic, Time.unix(since.not_nil!), as: ChannelVideo).each do |video|
+              response = JSON.parse(video.to_json(locale, config, Kemal.config))
+
+              if fields_text = env.params.query["fields"]?
+                begin
+                  JSONFilter.filter(response, fields_text)
+                rescue ex
+                  env.response.status_code = 400
+                  response = {"error" => ex.message}
+                end
+              end
+
+              env.response.puts "id: #{id}"
+              env.response.puts "data: #{response.to_json}"
+              env.response.puts
+              env.response.flush
+
+              id += 1
+            end
+          else
+            # TODO
+          end
+        end
+      end
+
       PG.connect_listen(PG_URL, "notifications") do |event|
         notification = JSON.parse(event.payload)
         topic = notification["topic"].as_s
diff --git a/src/invidious/channels.cr b/src/invidious/channels.cr
index 96544b49..8e4aa0ec 100644
--- a/src/invidious/channels.cr
+++ b/src/invidious/channels.cr
@@ -9,6 +9,34 @@ struct InvidiousChannel
 end
 
 struct ChannelVideo
+  def to_json(locale, config, kemal_config, json : JSON::Builder)
+    json.object do
+      json.field "title", self.title
+      json.field "videoId", self.id
+      json.field "videoThumbnails" do
+        generate_thumbnails(json, self.id, config, Kemal.config)
+      end
+
+      json.field "lengthSeconds", self.length_seconds
+
+      json.field "author", self.author
+      json.field "authorId", self.ucid
+      json.field "authorUrl", "/channel/#{self.ucid}"
+      json.field "published", self.published.to_unix
+      json.field "publishedText", translate(locale, "`x` ago", recode_date(self.published, locale))
+    end
+  end
+
+  def to_json(locale, config, kemal_config, json : JSON::Builder | Nil = nil)
+    if json
+      to_json(locale, config, kemal_config, json)
+    else
+      JSON.build do |json|
+        to_json(locale, config, kemal_config, json)
+      end
+    end
+  end
+
   db_mapping({
     id:                 String,
     title:              String,
diff --git a/src/invidious/videos.cr b/src/invidious/videos.cr
index b039436a..643b7654 100644
--- a/src/invidious/videos.cr
+++ b/src/invidious/videos.cr
@@ -262,8 +262,10 @@ struct Video
           generate_storyboards(json, self.storyboards, config, kemal_config)
         end
 
-        json.field "description", html_to_content(self.description).last
-        json.field "descriptionHtml", html_to_content(self.description).first
+        description_html, description = html_to_content(self.description)
+
+        json.field "description", description
+        json.field "descriptionHtml", description_html
         json.field "published", self.published.to_unix
         json.field "publishedText", translate(locale, "`x` ago", recode_date(self.published, locale))
         json.field "keywords", self.keywords