summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/invidious.cr106
-rw-r--r--src/invidious/helpers.cr9
-rw-r--r--src/invidious/views/subscriptions.ecr20
3 files changed, 128 insertions, 7 deletions
diff --git a/src/invidious.cr b/src/invidious.cr
index 4b8f67ba..251769ae 100644
--- a/src/invidious.cr
+++ b/src/invidious.cr
@@ -955,7 +955,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
@@ -1010,6 +1010,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 "reverse_alphabetically"
+ videos.sort_by! { |video| video.title }.reverse!
+ when "channel_name"
+ videos.sort_by! { |video| video.author }
+ when "reverse_channel_name"
+ 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 d579abae..2172b032 100644
--- a/src/invidious/helpers.cr
+++ b/src/invidious/helpers.cr
@@ -139,6 +139,7 @@ class User
converter: PreferencesConverter,
},
password: String?,
+ token: String,
})
end
@@ -829,13 +830,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 cb818e81..5999c429 100644
--- a/src/invidious/views/subscriptions.ecr
+++ b/src/invidious/views/subscriptions.ecr
@@ -2,7 +2,19 @@
<title>Subscriptions - Invidious</title>
<% end %>
-<h3><a href="/subscription_manager">Manage subscriptions</a></h3>
+<div class="pure-g">
+ <div class="pure-u-1 pure-u-md-3-5">
+ <h3>
+ <a href="/subscription_manager">Manage subscriptions</a>
+ </h3>
+ </div>
+ <div class="pure-u-1 pure-u-md-1-5"></div>
+ <div style="text-align:right;" class="pure-u-1 pure-u-md-1-5">
+ <h3>
+ <a href="/feed/private?token=<%= user.token %>"><i class="fas fa-rss-square"></i></a>
+ </h3>
+ </div>
+</div>
<% if !notifications.empty? %>
<% notifications.each_slice(4) do |slice| %>
@@ -26,13 +38,13 @@
<div class="pure-g">
<div class="pure-u-1 pure-u-md-1-5">
<% if page > 2 %>
- <a href="/feed/subscriptions?maxResults=<%= max_results %>&page=<%= page - 1 %>">Previous page</a>
+ <a href="/feed/subscriptions?max_results=<%= max_results %>&page=<%= page - 1 %>">Previous page</a>
<% else %>
- <a href="/feed/subscriptions?maxResults=<%= max_results %>">Previous page</a>
+ <a href="/feed/subscriptions?max_results=<%= max_results %>">Previous page</a>
<% end %>
</div>
<div class="pure-u-1 pure-u-md-3-5"></div>
<div style="text-align:right;" class="pure-u-1 pure-u-md-1-5">
- <a href="/feed/subscriptions?maxResults=<%= max_results %>&page=<%= page + 1 %>">Next page</a>
+ <a href="/feed/subscriptions?max_results=<%= max_results %>&page=<%= page + 1 %>">Next page</a>
</div>
</div> \ No newline at end of file