Add ability to disable all user notifications (#3473)

This commit is contained in:
Émilien Devos 2023-01-05 23:08:05 +00:00 committed by GitHub
parent 865704dc7b
commit 98301a2237
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 77 additions and 22 deletions

View file

@ -295,6 +295,17 @@ https_only: false
## ##
#admins: [""] #admins: [""]
##
## Enable/Disable the user notifications for all users
##
## Note: On large instances, it is recommended to set this option to 'false'
## in order to reduce the amount of data written to the database, and hence
## improve the overall performance of the instance.
##
## Accepted values: true, false
## Default: true
##
#enable_user_notifications: true
# ----------------------------- # -----------------------------
# Background jobs # Background jobs

View file

@ -228,7 +228,11 @@ def fetch_channel(ucid, pull_all_videos : Bool)
if was_insert if was_insert
LOGGER.trace("fetch_channel: #{ucid} : video #{video_id} : Inserted, updating subscriptions") LOGGER.trace("fetch_channel: #{ucid} : video #{video_id} : Inserted, updating subscriptions")
Invidious::Database::Users.add_notification(video) if CONFIG.enable_user_notifications
Invidious::Database::Users.add_notification(video)
else
Invidious::Database::Users.feed_needs_update(video)
end
else else
LOGGER.trace("fetch_channel: #{ucid} : video #{video_id} : Updated") LOGGER.trace("fetch_channel: #{ucid} : video #{video_id} : Updated")
end end
@ -264,7 +268,13 @@ def fetch_channel(ucid, pull_all_videos : Bool)
# so since they don't provide a published date here we can safely ignore them. # so since they don't provide a published date here we can safely ignore them.
if Time.utc - video.published > 1.minute if Time.utc - video.published > 1.minute
was_insert = Invidious::Database::ChannelVideos.insert(video) was_insert = Invidious::Database::ChannelVideos.insert(video)
Invidious::Database::Users.add_notification(video) if was_insert if was_insert
if CONFIG.enable_user_notifications
Invidious::Database::Users.add_notification(video)
else
Invidious::Database::Users.feed_needs_update(video)
end
end
end end
end end

View file

@ -110,6 +110,8 @@ class Config
property hsts : Bool? = true property hsts : Bool? = true
# Disable proxying server-wide: options: 'dash', 'livestreams', 'downloads', 'local' # Disable proxying server-wide: options: 'dash', 'livestreams', 'downloads', 'local'
property disable_proxy : Bool? | Array(String)? = false property disable_proxy : Bool? | Array(String)? = false
# Enable the user notifications for all users
property enable_user_notifications : Bool = true
# URL to the modified source code to be easily AGPL compliant # URL to the modified source code to be easily AGPL compliant
# Will display in the footer, next to the main source code link # Will display in the footer, next to the main source code link

View file

@ -154,6 +154,16 @@ module Invidious::Database::Users
# Update (misc) # Update (misc)
# ------------------- # -------------------
def feed_needs_update(video : ChannelVideo)
request = <<-SQL
UPDATE users
SET feed_needs_update = true
WHERE $1 = ANY(subscriptions)
SQL
PG_DB.exec(request, video.ucid)
end
def update_preferences(user : User) def update_preferences(user : User)
request = <<-SQL request = <<-SQL
UPDATE users UPDATE users

View file

@ -147,7 +147,7 @@ module Invidious::Routes::Embed
# PG_DB.exec("UPDATE users SET watched = array_append(watched, $1) WHERE email = $2", id, user.as(User).email) # PG_DB.exec("UPDATE users SET watched = array_append(watched, $1) WHERE email = $2", id, user.as(User).email)
# end # end
if notifications && notifications.includes? id if CONFIG.enable_user_notifications && notifications && notifications.includes? id
Invidious::Database::Users.remove_notification(user.as(User), id) Invidious::Database::Users.remove_notification(user.as(User), id)
env.get("user").as(User).notifications.delete(id) env.get("user").as(User).notifications.delete(id)
notifications.delete(id) notifications.delete(id)

View file

@ -96,12 +96,14 @@ module Invidious::Routes::Feeds
videos, notifications = get_subscription_feed(user, max_results, page) videos, notifications = get_subscription_feed(user, max_results, page)
# "updated" here is used for delivering new notifications, so if if CONFIG.enable_user_notifications
# we know a user has looked at their feed e.g. in the past 10 minutes, # "updated" here is used for delivering new notifications, so if
# they've already seen a video posted 20 minutes ago, and don't need # we know a user has looked at their feed e.g. in the past 10 minutes,
# to be notified. # they've already seen a video posted 20 minutes ago, and don't need
Invidious::Database::Users.clear_notifications(user) # to be notified.
user.notifications = [] of String Invidious::Database::Users.clear_notifications(user)
user.notifications = [] of String
end
env.set "user", user env.set "user", user
templated "feeds/subscriptions" templated "feeds/subscriptions"
@ -404,13 +406,15 @@ module Invidious::Routes::Feeds
video = get_video(id, force_refresh: true) video = get_video(id, force_refresh: true)
# Deliver notifications to `/api/v1/auth/notifications` if CONFIG.enable_user_notifications
payload = { # Deliver notifications to `/api/v1/auth/notifications`
"topic" => video.ucid, payload = {
"videoId" => video.id, "topic" => video.ucid,
"published" => published.to_unix, "videoId" => video.id,
}.to_json "published" => published.to_unix,
PG_DB.exec("NOTIFY notifications, E'#{payload}'") }.to_json
PG_DB.exec("NOTIFY notifications, E'#{payload}'")
end
video = ChannelVideo.new({ video = ChannelVideo.new({
id: id, id: id,
@ -426,7 +430,13 @@ module Invidious::Routes::Feeds
}) })
was_insert = Invidious::Database::ChannelVideos.insert(video, with_premiere_timestamp: true) was_insert = Invidious::Database::ChannelVideos.insert(video, with_premiere_timestamp: true)
Invidious::Database::Users.add_notification(video) if was_insert if was_insert
if CONFIG.enable_user_notifications
Invidious::Database::Users.add_notification(video)
else
Invidious::Database::Users.feed_needs_update(video)
end
end
end end
end end

View file

@ -80,7 +80,7 @@ module Invidious::Routes::Watch
Invidious::Database::Users.mark_watched(user.as(User), id) Invidious::Database::Users.mark_watched(user.as(User), id)
end end
if notifications && notifications.includes? id if CONFIG.enable_user_notifications && notifications && notifications.includes? id
Invidious::Database::Users.remove_notification(user.as(User), id) Invidious::Database::Users.remove_notification(user.as(User), id)
env.get("user").as(User).notifications.delete(id) env.get("user").as(User).notifications.delete(id)
notifications.delete(id) notifications.delete(id)

View file

@ -37,7 +37,9 @@ module Invidious::Routing
get "/feed/webhook/:token", Routes::Feeds, :push_notifications_get get "/feed/webhook/:token", Routes::Feeds, :push_notifications_get
post "/feed/webhook/:token", Routes::Feeds, :push_notifications_post post "/feed/webhook/:token", Routes::Feeds, :push_notifications_post
get "/modify_notifications", Routes::Notifications, :modify if CONFIG.enable_user_notifications
get "/modify_notifications", Routes::Notifications, :modify
end
{% end %} {% end %}
self.register_image_routes self.register_image_routes
@ -260,8 +262,10 @@ module Invidious::Routing
post "/api/v1/auth/tokens/register", {{namespace}}::Authenticated, :register_token post "/api/v1/auth/tokens/register", {{namespace}}::Authenticated, :register_token
post "/api/v1/auth/tokens/unregister", {{namespace}}::Authenticated, :unregister_token post "/api/v1/auth/tokens/unregister", {{namespace}}::Authenticated, :unregister_token
get "/api/v1/auth/notifications", {{namespace}}::Authenticated, :notifications if CONFIG.enable_user_notifications
post "/api/v1/auth/notifications", {{namespace}}::Authenticated, :notifications get "/api/v1/auth/notifications", {{namespace}}::Authenticated, :notifications
post "/api/v1/auth/notifications", {{namespace}}::Authenticated, :notifications
end
# Misc # Misc
get "/api/v1/stats", {{namespace}}::Misc, :stats get "/api/v1/stats", {{namespace}}::Misc, :stats

View file

@ -23,6 +23,8 @@
</div> </div>
</div> </div>
<% if CONFIG.enable_user_notifications %>
<center> <center>
<%= translate_count(locale, "subscriptions_unseen_notifs_count", notifications.size) %> <%= translate_count(locale, "subscriptions_unseen_notifs_count", notifications.size) %>
</center> </center>
@ -39,6 +41,8 @@
<% end %> <% end %>
</div> </div>
<% end %>
<div class="h-box"> <div class="h-box">
<hr> <hr>
</div> </div>

View file

@ -54,7 +54,7 @@
<div class="pure-u-1-4"> <div class="pure-u-1-4">
<a id="notification_ticker" title="<%= translate(locale, "Subscriptions") %>" href="/feed/subscriptions" class="pure-menu-heading"> <a id="notification_ticker" title="<%= translate(locale, "Subscriptions") %>" href="/feed/subscriptions" class="pure-menu-heading">
<% notification_count = env.get("user").as(Invidious::User).notifications.size %> <% notification_count = env.get("user").as(Invidious::User).notifications.size %>
<% if notification_count > 0 %> <% if CONFIG.enable_user_notifications && notification_count > 0 %>
<span id="notification_count"><%= notification_count %></span> <i class="icon ion-ios-notifications"></i> <span id="notification_count"><%= notification_count %></span> <i class="icon ion-ios-notifications"></i>
<% else %> <% else %>
<i class="icon ion-ios-notifications-outline"></i> <i class="icon ion-ios-notifications-outline"></i>
@ -170,7 +170,9 @@
}.to_pretty_json }.to_pretty_json
%> %>
</script> </script>
<% if CONFIG.enable_user_notifications %>
<script src="/js/notifications.js?v=<%= ASSET_COMMIT %>"></script> <script src="/js/notifications.js?v=<%= ASSET_COMMIT %>"></script>
<% end %>
<% end %> <% end %>
</body> </body>

View file

@ -244,6 +244,7 @@
<input name="unseen_only" id="unseen_only" type="checkbox" <% if preferences.unseen_only %>checked<% end %>> <input name="unseen_only" id="unseen_only" type="checkbox" <% if preferences.unseen_only %>checked<% end %>>
</div> </div>
<% if CONFIG.enable_user_notifications %>
<div class="pure-control-group"> <div class="pure-control-group">
<label for="notifications_only"><%= translate(locale, "preferences_notifications_only_label") %></label> <label for="notifications_only"><%= translate(locale, "preferences_notifications_only_label") %></label>
<input name="notifications_only" id="notifications_only" type="checkbox" <% if preferences.notifications_only %>checked<% end %>> <input name="notifications_only" id="notifications_only" type="checkbox" <% if preferences.notifications_only %>checked<% end %>>
@ -255,6 +256,7 @@
<a href="#" data-onclick="notification_requestPermission"><%= translate(locale, "Enable web notifications") %></a> <a href="#" data-onclick="notification_requestPermission"><%= translate(locale, "Enable web notifications") %></a>
</div> </div>
<% end %> <% end %>
<% end %>
<% end %> <% end %>
<% if env.get?("user") && CONFIG.admins.includes? env.get?("user").as(Invidious::User).email %> <% if env.get?("user") && CONFIG.admins.includes? env.get?("user").as(Invidious::User).email %>