diff options
| -rw-r--r-- | config/config.yml | 6 | ||||
| -rw-r--r-- | config/sql/videos.sql | 3 | ||||
| -rw-r--r-- | src/invidious.cr | 23 | ||||
| -rw-r--r-- | src/invidious/helpers.cr | 57 | ||||
| -rw-r--r-- | src/invidious/views/components/subscription_video.ecr | 3 | ||||
| -rw-r--r-- | src/invidious/views/components/video.ecr | 3 | ||||
| -rw-r--r-- | src/invidious/views/preferences.ecr | 5 | ||||
| -rw-r--r-- | src/invidious/views/watch.ecr | 11 |
8 files changed, 77 insertions, 34 deletions
diff --git a/config/config.yml b/config/config.yml index e631793f..a2cc5d9c 100644 --- a/config/config.yml +++ b/config/config.yml @@ -1,6 +1,6 @@ -crawl_threads: 5 -channel_threads: 5 -video_threads: 5 +crawl_threads: 1 +channel_threads: 1 +video_threads: 1 db: user: kemal password: kemal diff --git a/config/sql/videos.sql b/config/sql/videos.sql index 63a42e66..9f20e8c6 100644 --- a/config/sql/videos.sql +++ b/config/sql/videos.sql @@ -17,6 +17,9 @@ CREATE TABLE public.videos language text COLLATE pg_catalog."default", author text COLLATE pg_catalog."default", ucid text COLLATE pg_catalog."default", + allowed_regions text[] COLLATE pg_catalog."default", + is_family_friendly boolean, + genre text COLLATE pg_catalog."default", CONSTRAINT videos_pkey PRIMARY KEY (id) ) WITH ( diff --git a/src/invidious.cr b/src/invidious.cr index 19bdab78..cc8997f9 100644 --- a/src/invidious.cr +++ b/src/invidious.cr @@ -137,10 +137,10 @@ channel_threads.times do |i| begin id = rs.read(String) - channel = get_channel(id, client, PG_DB) + channel = fetch_channel(id, client, PG_DB, false) + PG_DB.exec("UPDATE channels SET updated = $1 WHERE id = $2", Time.now, id) rescue ex STDOUT << id << " : " << ex.message << "\n" - client = make_client(YT_URL) next end end @@ -411,7 +411,7 @@ get "/watch" do |env| templated "watch" end -get "/captions/:id" do |env| +get "/api/v1/captions/:id" do |env| id = env.params.url["id"] client = make_client(YT_URL) @@ -497,7 +497,7 @@ get "/captions/:id" do |env| webvtt end -get "/comments/:id" do |env| +get "/api/v1/comments/:id" do |env| id = env.params.url["id"] source = env.params.query["source"]? @@ -653,7 +653,7 @@ get "/comments/:id" do |env| end end -get "/videos/:id" do |env| +get "/api/v1/videos/:id" do |env| id = env.params.url["id"] client = make_client(YT_URL) @@ -733,6 +733,10 @@ get "/videos/:id" do |env| json.field "likeCount", video.likes json.field "dislikeCount", video.dislikes + json.field "isFamilyFriendly", video.is_family_friendly + json.field "allowedRegions", video.allowed_regions + json.field "genre", video.genre + json.field "author", video.author json.field "authorId", video.ucid json.field "authorUrl", "/channel/#{video.ucid}" @@ -984,7 +988,7 @@ get "/search" do |env| html = client.get("/results?q=#{URI.escape(query)}&page=#{page}&sp=EgIQAVAU").body html = XML.parse_html(html) - videos = [] of Video + videos = [] of ChannelVideo html.xpath_nodes(%q(//ol[@class="item-section"]/li)).each do |item| root = item.xpath_node(%q(div[contains(@class,"yt-lockup-video")]/div)) @@ -1009,7 +1013,7 @@ get "/search" do |env| author ||= "" ucid ||= "" - video = Video.new(id, HTTP::Params.parse(""), Time.now, title, 0_i64, 0, 0, 0.0, Time.now, "", nil, author, ucid) + video = ChannelVideo.new(id, title, Time.now, Time.now, ucid, author) videos << video end end @@ -1359,6 +1363,10 @@ post "/preferences" do |env| dark_mode ||= "off" dark_mode = dark_mode == "on" + thin_mode = env.params.body["thin_mode"]?.try &.as(String) + thin_mode ||= "off" + thin_mode = thin_mode == "on" + max_results = env.params.body["max_results"]?.try &.as(String).to_i max_results ||= 40 @@ -1376,6 +1384,7 @@ post "/preferences" do |env| "quality" => quality, "volume" => volume, "dark_mode" => dark_mode, + "thin_mode" => thin_mode, "max_results" => max_results, "sort" => sort, "latest_only" => latest_only, diff --git a/src/invidious/helpers.cr b/src/invidious/helpers.cr index 3448245b..fb7c573b 100644 --- a/src/invidious/helpers.cr +++ b/src/invidious/helpers.cr @@ -24,6 +24,7 @@ DEFAULT_USER_PREFERENCES = Preferences.from_json({ "quality" => "hd720", "volume" => 100, "dark_mode" => false, + "thin_mode " => false, "max_results" => 40, "sort" => "published", "latest_only" => false, @@ -85,17 +86,20 @@ class Video default: HTTP::Params.parse(""), converter: Video::HTTPParamConverter, }, - updated: Time, - title: String, - views: Int64, - likes: Int32, - dislikes: Int32, - wilson_score: Float64, - published: Time, - description: String, - language: String?, - author: String, - ucid: String, + updated: Time, + title: String, + views: Int64, + likes: Int32, + dislikes: Int32, + wilson_score: Float64, + published: Time, + description: String, + language: String?, + author: String, + ucid: String, + allowed_regions: Array(String), + is_family_friendly: Bool, + genre: String, }) end @@ -145,14 +149,20 @@ class User }) end +# TODO: Migrate preferences so this will not be nilable class Preferences JSON.mapping({ - video_loop: Bool, - autoplay: Bool, - speed: Float32, - quality: String, - volume: Int32, - dark_mode: Bool, + video_loop: Bool, + autoplay: Bool, + speed: Float32, + quality: String, + volume: Int32, + dark_mode: Bool, + thin_mode: { + type: Bool, + nilable: true, + default: false, + }, max_results: Int32, sort: String, latest_only: Bool, @@ -274,7 +284,11 @@ def fetch_video(id, client) published = html.xpath_node(%q(//meta[@itemprop="datePublished"])).not_nil!["content"] published = Time.parse(published, "%Y-%m-%d", Time::Location.local) - video = Video.new(id, info, Time.now, title, views, likes, dislikes, wilson_score, published, description, nil, author, ucid) + allowed_regions = html.xpath_node(%q(//meta[@itemprop="regionsAllowed"])).not_nil!["content"].split(",") + is_family_friendly = html.xpath_node(%q(//meta[@itemprop="isFamilyFriendly"])).not_nil!["content"] == "True" + genre = html.xpath_node(%q(//meta[@itemprop="genre"])).not_nil!["content"] + + video = Video.new(id, info, Time.now, title, views, likes, dislikes, wilson_score, published, description, nil, author, ucid, allowed_regions, is_family_friendly, genre) return video end @@ -290,7 +304,8 @@ def get_video(id, client, db, refresh = true) video_array = video.to_a args = arg_array(video_array[1..-1], 2) - db.exec("UPDATE videos SET (info,updated,title,views,likes,dislikes,wilson_score,published,description,language,author,ucid)\ + db.exec("UPDATE videos SET (info,updated,title,views,likes,dislikes,wilson_score,\ + published,description,language,author,ucid, allowed_regions, is_family_friendly, genre)\ = (#{args}) WHERE id = $1", video_array) rescue ex db.exec("DELETE FROM videos * WHERE id = $1", id) @@ -665,7 +680,7 @@ def fetch_channel(ucid, client, db, pull_all_videos = true) video = ChannelVideo.new(video_id, title, published, Time.now, ucid, author) db.exec("UPDATE users SET notifications = notifications || $1 \ - WHERE updated < $2 AND $3 = ANY(subscriptions) AND $1 <> ALL(notifications)", video.id, Time.now, ucid) + WHERE updated < $2 AND $3 = ANY(subscriptions) AND $1 <> ALL(notifications)", video.id, video.published, ucid) video_array = video.to_a args = arg_array(video_array) @@ -983,7 +998,7 @@ def generate_captcha(key) <text x="17.091" y="34" text-anchor="middle" fill="black" font-family="Arial" font-size="10px">10</text> <text x="31" y="20.091" text-anchor="middle" fill="black" font-family="Arial" font-size="10px">11</text> <text x="50" y="15" text-anchor="middle" fill="black" font-family="Arial" font-size="10px">12</text> - + <circle cx="50" cy="50" r="3" fill="black"></circle> <line id="minute" transform="rotate(#{minute_angle}, 50, 50)" x1="50" y1="50" x2="50" y2="16" fill="black" stroke="black" stroke-width="2"></line> <line id="hour" transform="rotate(#{hour_angle}, 50, 50)" x1="50" y1="50" x2="50" y2="24" fill="black" stroke="black" stroke-width="2"></line> diff --git a/src/invidious/views/components/subscription_video.ecr b/src/invidious/views/components/subscription_video.ecr index 377f51cb..f1ad4bb3 100644 --- a/src/invidious/views/components/subscription_video.ecr +++ b/src/invidious/views/components/subscription_video.ecr @@ -1,7 +1,10 @@ <div class="pure-u-1 pure-u-md-1-4"> <div class="h-box"> <a style="width:100%;" href="/watch?v=<%= video.id %>"> + <% if env.get?("user") && env.get("user").as(User).preferences.thin_mode %> + <% else %> <img style="width:100%;" src="https://i.ytimg.com/vi/<%= video.id %>/mqdefault.jpg"/> + <% end %> <p><%= video.title %></p> </a> <p> diff --git a/src/invidious/views/components/video.ecr b/src/invidious/views/components/video.ecr index 804080cc..d145270f 100644 --- a/src/invidious/views/components/video.ecr +++ b/src/invidious/views/components/video.ecr @@ -1,7 +1,10 @@ <div class="pure-u-1 pure-u-md-1-4"> <div class="h-box"> <a style="width:100%;" href="/watch?v=<%= video.id %>"> + <% if env.get?("user") && env.get("user").as(User).preferences.thin_mode %> + <% else %> <img style="width:100%;" src="https://i.ytimg.com/vi/<%= video.id %>/mqdefault.jpg"/> + <% end %> <p><%= video.title %></p> </a> <p> diff --git a/src/invidious/views/preferences.ecr b/src/invidious/views/preferences.ecr index 370dfc0f..50e8b0e9 100644 --- a/src/invidious/views/preferences.ecr +++ b/src/invidious/views/preferences.ecr @@ -53,6 +53,11 @@ function update_value(element) { <input name="dark_mode" id="dark_mode" type="checkbox" <% if user.preferences.dark_mode %>checked<% end %>> </div> + <div class="pure-control-group"> + <label for="thin_mode">Thin mode: </label> + <input name="thin_mode" id="thin_mode" type="checkbox" <% if user.preferences.thin_mode %>checked<% end %>> + </div> + <legend>Subscription preferences</legend> <div class="pure-control-group"> <label for="max_results">Number of videos shown in feed: </label> diff --git a/src/invidious/views/watch.ecr b/src/invidious/views/watch.ecr index 06dd3d5a..962c3235 100644 --- a/src/invidious/views/watch.ecr +++ b/src/invidious/views/watch.ecr @@ -49,7 +49,7 @@ <% end %> <% captions.each do |caption| %> - <track kind="captions" src="/captions/<%= video.id %>?label=<%= caption["name"]["simpleText"] %>" + <track kind="captions" src="/api/v1/captions/<%= video.id %>?label=<%= caption["name"]["simpleText"] %>" srclang="<%= caption["languageCode"] %>" label="<%= caption["name"]["simpleText"]%> "> <% end %> <% end %> @@ -158,7 +158,7 @@ for ( var i = 0; i < currentSources.length; i++ ) { player.src(currentSources); <% end %> -fetch("/comments/<%= video.id %>?source=reddit") +fetch("/api/v1/comments/<%= video.id %>?source=reddit") .then(function(response) { return response.json(); }) @@ -217,6 +217,8 @@ String.prototype.supplant = function (o) { <p><i class="fa fa-eye" aria-hidden="true"></i> <%= number_with_separator(video.views) %></p> <p><i class="fa fa-thumbs-up" aria-hidden="true"></i> <%= number_with_separator(video.likes) %></p> <p><i class="fa fa-thumbs-down" aria-hidden="true"></i> <%= number_with_separator(video.dislikes) %></p> + <p id="Genre">Genre : <%= video.genre %></p> + <p id="FamilyFriendly">Family Friendly? <%= video.is_family_friendly %></p> <p id="Wilson">Wilson Score : <%= video.wilson_score.round(4) %></p> <p id="Rating">Rating : <%= rating.round(4) %> / 5</p> <p id="Engagement">Engagement : <%= engagement.round(2) %>%</p> @@ -278,7 +280,10 @@ String.prototype.supplant = function (o) { <% rvs.each do |rv| %> <% if rv.has_key?("id") %> <a href="/watch?v=<%= rv["id"] %>"> - <img style="width:100%;" alt="thumbnail" src="<%= rv["iurlmq"] %>"> + <% if preferences && preferences.thin_mode %> + <% else %> + <img style="width:100%;" src="<%= rv["iurlmq"] %>"> + <% end %> <p style="width:100%"><%= rv["title"] %></p> <p> <b style="width: 100%"><%= rv["author"] %></b> |
