invidious-experimenting/src/invidious/users.cr

107 lines
3.8 KiB
Crystal
Raw Normal View History

2018-11-09 07:38:03 +05:30
require "crypto/bcrypt/password"
# Materialized views may not be defined using bound parameters (`$1` as used elsewhere)
2019-07-09 20:04:19 +05:30
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 02:00:44 +05:30
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 02:00:44 +05:30
2019-02-11 00:03:29 +05:30
return user, sid
2018-08-05 02:00:44 +05:30
end
2018-11-11 21:14:16 +05:30
2021-12-07 08:27:18 +05:30
def get_subscription_feed(user, max_results = 40, page = 1)
2019-06-07 23:09:12 +05:30
limit = max_results.clamp(0, MAX_ITEMS_PER_PAGE)
offset = (page - 1) * limit
notifications = Invidious::Database::Users.select_notifications(user)
2019-06-07 23:09:12 +05:30
view_name = "subscriptions_#{sha256(user.email)}"
if user.preferences.notifications_only && !notifications.empty?
# Only show notifications
notifications = Invidious::Database::ChannelVideos.select(notifications)
2019-06-07 23:09:12 +05:30
videos = [] of ChannelVideo
2021-09-25 08:12:43 +05:30
notifications.sort_by!(&.published).reverse!
2019-06-07 23:09:12 +05:30
case user.preferences.sort
when "alphabetically"
2021-09-25 08:12:43 +05:30
notifications.sort_by!(&.title)
2019-06-07 23:09:12 +05:30
when "alphabetically - reverse"
2021-09-25 08:12:43 +05:30
notifications.sort_by!(&.title).reverse!
2019-06-07 23:09:12 +05:30
when "channel name"
2021-09-25 08:12:43 +05:30
notifications.sort_by!(&.author)
2019-06-07 23:09:12 +05:30
when "channel name - reverse"
2021-09-25 08:12:43 +05:30
notifications.sort_by!(&.author).reverse!
else nil # Ignore
2019-06-07 23:09:12 +05:30
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 18:38:26 +05:30
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-07 23:09:12 +05:30
else
# Show latest video from each channel
2019-08-27 18:38:26 +05:30
videos = PG_DB.query_all("SELECT DISTINCT ON (ucid) * FROM #{view_name} ORDER BY ucid, published DESC", as: ChannelVideo)
2019-06-07 23:09:12 +05:30
end
2021-09-25 08:12:43 +05:30
videos.sort_by!(&.published).reverse!
2019-06-07 23:09:12 +05:30
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 18:38:26 +05:30
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-07 23:09:12 +05:30
else
# Sort subscriptions as normal
2019-08-27 18:38:26 +05:30
videos = PG_DB.query_all("SELECT * FROM #{view_name} ORDER BY published DESC LIMIT $1 OFFSET $2", limit, offset, as: ChannelVideo)
2019-06-07 23:09:12 +05:30
end
end
case user.preferences.sort
when "published - reverse"
2021-09-25 08:12:43 +05:30
videos.sort_by!(&.published)
2019-06-07 23:09:12 +05:30
when "alphabetically"
2021-09-25 08:12:43 +05:30
videos.sort_by!(&.title)
2019-06-07 23:09:12 +05:30
when "alphabetically - reverse"
2021-09-25 08:12:43 +05:30
videos.sort_by!(&.title).reverse!
2019-06-07 23:09:12 +05:30
when "channel name"
2021-09-25 08:12:43 +05:30
videos.sort_by!(&.author)
2019-06-07 23:09:12 +05:30
when "channel name - reverse"
2021-09-25 08:12:43 +05:30
videos.sort_by!(&.author).reverse!
else nil # Ignore
2019-06-07 23:09:12 +05:30
end
notifications = Invidious::Database::Users.select_notifications(user)
2019-06-07 23:09:12 +05:30
notifications = videos.select { |v| notifications.includes? v.id }
videos = videos - notifications
end
return videos, notifications
end