summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--config/config.yml6
-rw-r--r--config/sql/videos.sql3
-rw-r--r--src/invidious.cr23
-rw-r--r--src/invidious/helpers.cr57
-rw-r--r--src/invidious/views/components/subscription_video.ecr3
-rw-r--r--src/invidious/views/components/video.ecr3
-rw-r--r--src/invidious/views/preferences.ecr5
-rw-r--r--src/invidious/views/watch.ecr11
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>