invidious-mod/src/invidious/users.cr

107 行
3.8 KiB
Crystal
Raw 通常表示 履歴

2018-11-09 11:08:03 +09:00
require "crypto/bcrypt/password"
# Materialized views may not be defined using bound parameters (`$1` as used elsewhere)
2019-07-09 23:34:19 +09:00
MATERIALIZED_VIEW_SQL = ->(email : String) { "SELECT cv.* FROM channel_videos cv WHERE EXISTS (SELECT subscriptions FROM users u WHERE cv.ucid = ANY (u.subscriptions) AND u.email = E'#{email.gsub({'\'' => "\\'", '\\' => "\\\\"})}') ORDER BY published DESC" }
2018-08-05 05:30:44 +09:00
def create_user(sid, email, password)
password = Crypto::Bcrypt::Password.create(password, cost: 10)
token = Base64.urlsafe_encode(Random::Secure.random_bytes(32))
user = Invidious::User.new({
updated: Time.utc,
notifications: [] of String,
subscriptions: [] of String,
email: email,
preferences: Preferences.new(CONFIG.default_user_preferences.to_tuple),
password: password.to_s,
token: token,
watched: [] of String,
feed_needs_update: true,
})
2018-08-05 05:30:44 +09:00
2019-02-11 03:33:29 +09:00
return user, sid
2018-08-05 05:30:44 +09:00
end
2018-11-12 00:44:16 +09:00
2021-12-07 11:57:18 +09:00
def get_subscription_feed(user, max_results = 40, page = 1)
2019-06-08 02:39:12 +09:00
limit = max_results.clamp(0, MAX_ITEMS_PER_PAGE)
offset = (page - 1) * limit
notifications = Invidious::Database::Users.select_notifications(user)
2019-06-08 02:39:12 +09:00
view_name = "subscriptions_#{sha256(user.email)}"
if user.preferences.notifications_only && !notifications.empty?
# Only show notifications
notifications = Invidious::Database::ChannelVideos.select(notifications)
2019-06-08 02:39:12 +09:00
videos = [] of ChannelVideo
2021-09-25 11:42:43 +09:00
notifications.sort_by!(&.published).reverse!
2019-06-08 02:39:12 +09:00
case user.preferences.sort
when "alphabetically"
2021-09-25 11:42:43 +09:00
notifications.sort_by!(&.title)
2019-06-08 02:39:12 +09:00
when "alphabetically - reverse"
2021-09-25 11:42:43 +09:00
notifications.sort_by!(&.title).reverse!
2019-06-08 02:39:12 +09:00
when "channel name"
2021-09-25 11:42:43 +09:00
notifications.sort_by!(&.author)
2019-06-08 02:39:12 +09:00
when "channel name - reverse"
2021-09-25 11:42:43 +09:00
notifications.sort_by!(&.author).reverse!
else nil # Ignore
2019-06-08 02:39:12 +09:00
end
else
if user.preferences.latest_only
if user.preferences.unseen_only
# Show latest video from a channel that a user hasn't watched
# "unseen_only" isn't really correct here, more accurate would be "unwatched_only"
if user.watched.empty?
values = "'{}'"
else
values = "VALUES #{user.watched.map { |id| %(('#{id}')) }.join(",")}"
end
2019-08-27 22:08:26 +09:00
videos = PG_DB.query_all("SELECT DISTINCT ON (ucid) * FROM #{view_name} WHERE NOT id = ANY (#{values}) ORDER BY ucid, published DESC", as: ChannelVideo)
2019-06-08 02:39:12 +09:00
else
# Show latest video from each channel
2019-08-27 22:08:26 +09:00
videos = PG_DB.query_all("SELECT DISTINCT ON (ucid) * FROM #{view_name} ORDER BY ucid, published DESC", as: ChannelVideo)
2019-06-08 02:39:12 +09:00
end
2021-09-25 11:42:43 +09:00
videos.sort_by!(&.published).reverse!
2019-06-08 02:39:12 +09:00
else
if user.preferences.unseen_only
# Only show unwatched
if user.watched.empty?
values = "'{}'"
else
values = "VALUES #{user.watched.map { |id| %(('#{id}')) }.join(",")}"
end
2019-08-27 22:08:26 +09:00
videos = PG_DB.query_all("SELECT * FROM #{view_name} WHERE NOT id = ANY (#{values}) ORDER BY published DESC LIMIT $1 OFFSET $2", limit, offset, as: ChannelVideo)
2019-06-08 02:39:12 +09:00
else
# Sort subscriptions as normal
2019-08-27 22:08:26 +09:00
videos = PG_DB.query_all("SELECT * FROM #{view_name} ORDER BY published DESC LIMIT $1 OFFSET $2", limit, offset, as: ChannelVideo)
2019-06-08 02:39:12 +09:00
end
end
case user.preferences.sort
when "published - reverse"
2021-09-25 11:42:43 +09:00
videos.sort_by!(&.published)
2019-06-08 02:39:12 +09:00
when "alphabetically"
2021-09-25 11:42:43 +09:00
videos.sort_by!(&.title)
2019-06-08 02:39:12 +09:00
when "alphabetically - reverse"
2021-09-25 11:42:43 +09:00
videos.sort_by!(&.title).reverse!
2019-06-08 02:39:12 +09:00
when "channel name"
2021-09-25 11:42:43 +09:00
videos.sort_by!(&.author)
2019-06-08 02:39:12 +09:00
when "channel name - reverse"
2021-09-25 11:42:43 +09:00
videos.sort_by!(&.author).reverse!
else nil # Ignore
2019-06-08 02:39:12 +09:00
end
notifications = Invidious::Database::Users.select_notifications(user)
2019-06-08 02:39:12 +09:00
notifications = videos.select { |v| notifications.includes? v.id }
videos = videos - notifications
end
return videos, notifications
end