diff --git a/src/invidious.cr b/src/invidious.cr index 73a8eee39..954f13e67 100644 --- a/src/invidious.cr +++ b/src/invidious.cr @@ -920,7 +920,7 @@ get "/feed/subscriptions" do |env| end max_results = preferences.max_results - max_results ||= env.params.query["maxResults"]?.try &.to_i + max_results ||= env.params.query["max_results"]?.try &.to_i max_results ||= 40 page = env.params.query["page"]?.try &.to_i @@ -975,6 +975,110 @@ get "/feed/subscriptions" do |env| end end +get "/feed/private" do |env| + token = env.params.query["token"]? + + if !token + halt env, status_code: 401 + end + + user = PG_DB.query_one?("SELECT * FROM users WHERE token = $1", token, as: User) + if !user + halt env, status_code: 401 + end + + max_results = env.params.query["max_results"]?.try &.to_i + max_results ||= 40 + + page = env.params.query["page"]?.try &.to_i + page ||= 1 + + if max_results < 0 + limit = nil + offset = (page - 1) * 1 + else + limit = max_results + offset = (page - 1) * max_results + end + + latest_only = env.params.query["latest_only"]?.try &.to_i + latest_only ||= 0 + latest_only = latest_only == 1 + + if latest_only + args = arg_array(user.subscriptions) + videos = PG_DB.query_all("SELECT DISTINCT ON (ucid) * FROM channel_videos WHERE \ + ucid IN (#{args}) ORDER BY ucid, published DESC", user.subscriptions, as: ChannelVideo) + videos.sort_by! { |video| video.published }.reverse! + else + args = arg_array(user.subscriptions, 3) + videos = PG_DB.query_all("SELECT * FROM channel_videos WHERE ucid IN (#{args}) \ + ORDER BY published DESC LIMIT $1 OFFSET $2", [limit, offset] + user.subscriptions, as: ChannelVideo) + end + + sort = env.params.query["sort"]? + sort ||= "published" + + case sort + when "alphabetically" + videos.sort_by! { |video| video.title } + when "alphabetically - reverse" + videos.sort_by! { |video| video.title }.reverse! + when "channel name" + videos.sort_by! { |video| video.author } + when "channel name - reverse" + videos.sort_by! { |video| video.author }.reverse! + end + + if Kemal.config.ssl + scheme = "https://" + else + scheme = "http://" + end + + if !limit + videos = videos[0..max_results] + end + + host = env.request.headers["Host"] + path = env.request.path + query = env.request.query.not_nil! + + feed = XML.build(indent: " ", encoding: "UTF-8") do |xml| + xml.element("feed", xmlns: "http://www.w3.org/2005/Atom", "xmlns:media": "http://search.yahoo.com/mrss/", "xml:lang": "en-US") do + xml.element("link", "type": "text/html", rel: "alternate", href: "#{scheme}#{host}/feed/subscriptions") + xml.element("link", "type": "application/atom+xml", rel: "self", href: "#{scheme}#{host}#{path}?#{query}") + xml.element("title") { xml.text "Invidious Private Feed for #{user.email}" } + + videos.each do |video| + xml.element("entry") do + xml.element("id") { xml.text "yt:video:#{video.id}" } + xml.element("yt:videoId") { xml.text video.id } + xml.element("yt:channelId") { xml.text video.ucid } + xml.element("title") { xml.text video.title } + xml.element("link", rel: "alternate", href: "#{scheme}#{host}/watch?v=#{video.id}") + + xml.element("author") do + xml.element("name") { xml.text video.author } + xml.element("uri") { xml.text "#{scheme}#{host}/channel/#{video.ucid}" } + end + + xml.element("published") { xml.text video.published.to_s("%Y-%m-%dT%H:%M:%S%:z") } + xml.element("updated") { xml.text video.updated.to_s("%Y-%m-%dT%H:%M:%S%:z") } + + xml.element("media:group") do + xml.element("media:title") { xml.text video.title } + xml.element("media:thumbnail", url: "https://i.ytimg.com/vi/#{video.id}/hqdefault.jpg", width: "480", height: "360") + end + end + end + end + end + + env.response.content_type = "application/atom+xml" + feed +end + # Function that is useful if you have multiple channels that don't have # the bell dinged. Request parameters are fairly self-explanatory, # receive_all_updates = true and receive_post_updates = true will ding all diff --git a/src/invidious/helpers.cr b/src/invidious/helpers.cr index c33af1b86..6af9cb6f4 100644 --- a/src/invidious/helpers.cr +++ b/src/invidious/helpers.cr @@ -139,6 +139,7 @@ class User converter: PreferencesConverter, }, password: String?, + token: String, }) end @@ -815,13 +816,17 @@ def fetch_user(sid, client, headers, db) email = "" end - user = User.new(sid, Time.now, [] of String, channels, email, DEFAULT_USER_PREFERENCES, nil) + token = Base64.encode(Random::Secure.random_bytes(32)) + + user = User.new(sid, Time.now, [] of String, channels, email, DEFAULT_USER_PREFERENCES, nil, token) return user end def create_user(sid, email, password) password = Crypto::Bcrypt::Password.create(password, cost: 10) - user = User.new(sid, Time.now, [] of String, [] of String, email, DEFAULT_USER_PREFERENCES, password.to_s) + token = Base64.encode(Random::Secure.random_bytes(32)) + + user = User.new(sid, Time.now, [] of String, [] of String, email, DEFAULT_USER_PREFERENCES, password.to_s, token) return user end diff --git a/src/invidious/views/subscriptions.ecr b/src/invidious/views/subscriptions.ecr index cb818e817..5999c429b 100644 --- a/src/invidious/views/subscriptions.ecr +++ b/src/invidious/views/subscriptions.ecr @@ -2,7 +2,19 @@