From 12b2ab5da81cbe433cc73815ffc6219a290df4de Mon Sep 17 00:00:00 2001
From: Omar Roth
Date: Sat, 8 Jun 2019 13:31:41 -0500
Subject: [PATCH] Add 'to_json' into respective structs
---
src/invidious.cr | 324 ++----------------------
src/invidious/channels.cr | 4 +-
src/invidious/mixes.cr | 4 +-
src/invidious/playlists.cr | 28 ++
src/invidious/search.cr | 114 +++++++++
src/invidious/videos.cr | 282 +++++++++++----------
src/invidious/views/components/item.ecr | 2 +-
7 files changed, 307 insertions(+), 451 deletions(-)
diff --git a/src/invidious.cr b/src/invidious.cr
index 80ae4395f..1a02741b1 100644
--- a/src/invidious.cr
+++ b/src/invidious.cr
@@ -3405,31 +3405,10 @@ get "/api/v1/trending" do |env|
videos = JSON.build do |json|
json.array do
trending.each do |video|
- json.object do
- json.field "title", video.title
- json.field "videoId", video.id
- json.field "videoThumbnails" do
- generate_thumbnails(json, video.id, config, Kemal.config)
+ video.to_json(locale, config, Kemal.config, json)
end
-
- json.field "lengthSeconds", video.length_seconds
- json.field "viewCount", video.views
-
- json.field "author", video.author
- json.field "authorId", video.ucid
- json.field "authorUrl", "/channel/#{video.ucid}"
-
- json.field "published", video.published.to_unix
- json.field "publishedText", translate(locale, "`x` ago", recode_date(video.published, locale))
- json.field "description", video.description
- json.field "descriptionHtml", video.description_html
- json.field "liveNow", video.live_now
- json.field "paid", video.paid
- json.field "premium", video.premium
end
end
- end
- end
videos
end
@@ -3459,9 +3438,12 @@ get "/api/v1/top" do |env|
next error_message
end
- videos = JSON.build do |json|
+ JSON.build do |json|
json.array do
top_videos.each do |video|
+ # Top videos have much more information than provided below (adaptiveFormats, etc)
+ # but can be very out of date, so we only provide a subset here
+
json.object do
json.field "title", video.title
json.field "videoId", video.id
@@ -3487,8 +3469,6 @@ get "/api/v1/top" do |env|
end
end
end
-
- videos
end
get "/api/v1/channels/:ucid" do |env|
@@ -3577,6 +3557,7 @@ get "/api/v1/channels/:ucid" do |env|
end
channel_info = JSON.build do |json|
+ # TODO: Refactor into `to_json` for InvidiousChannel
json.object do
json.field "author", author
json.field "authorId", ucid
@@ -3634,35 +3615,7 @@ get "/api/v1/channels/:ucid" do |env|
json.field "latestVideos" do
json.array do
videos.each do |video|
- json.object do
- json.field "title", video.title
- json.field "videoId", video.id
-
- if auto_generated
- json.field "author", video.author
- json.field "authorId", video.ucid
- json.field "authorUrl", "/channel/#{video.ucid}"
- else
- json.field "author", author
- json.field "authorId", ucid
- json.field "authorUrl", "/channel/#{ucid}"
- end
-
- json.field "videoThumbnails" do
- generate_thumbnails(json, video.id, config, Kemal.config)
- end
-
- json.field "description", video.description
- json.field "descriptionHtml", video.description_html
-
- json.field "viewCount", video.views
- json.field "published", video.published.to_unix
- json.field "publishedText", translate(locale, "`x` ago", recode_date(video.published, locale))
- json.field "lengthSeconds", video.length_seconds
- json.field "liveNow", video.live_now
- json.field "paid", video.paid
- json.field "premium", video.premium
- end
+ video.to_json(locale, config, Kemal.config, json)
end
end
end
@@ -3727,45 +3680,15 @@ end
next error_message
end
- result = JSON.build do |json|
+ JSON.build do |json|
json.array do
videos.each do |video|
- json.object do
- json.field "title", video.title
- json.field "videoId", video.id
-
- if auto_generated
- json.field "author", video.author
- json.field "authorId", video.ucid
- json.field "authorUrl", "/channel/#{video.ucid}"
- else
- json.field "author", author
- json.field "authorId", ucid
- json.field "authorUrl", "/channel/#{ucid}"
+ video.to_json(locale, config, Kemal.config, json)
end
-
- json.field "videoThumbnails" do
- generate_thumbnails(json, video.id, config, Kemal.config)
end
-
- json.field "description", video.description
- json.field "descriptionHtml", video.description_html
-
- json.field "viewCount", video.views
- json.field "published", video.published.to_unix
- json.field "publishedText", translate(locale, "`x` ago", recode_date(video.published, locale))
- json.field "lengthSeconds", video.length_seconds
- json.field "liveNow", video.live_now
- json.field "paid", video.paid
- json.field "premium", video.premium
end
end
end
- end
-
- result
- end
-end
{"/api/v1/channels/:ucid/latest", "/api/v1/channels/latest/:ucid"}.each do |route|
get route do |env|
@@ -3786,33 +3709,12 @@ end
JSON.build do |json|
json.array do
videos.each do |video|
- json.object do
- json.field "title", video.title
- json.field "videoId", video.id
-
- json.field "authorId", ucid
- json.field "authorUrl", "/channel/#{ucid}"
-
- json.field "videoThumbnails" do
- generate_thumbnails(json, video.id, config, Kemal.config)
+ video.to_json(locale, config, Kemal.config, json)
end
-
- json.field "description", video.description
- json.field "descriptionHtml", video.description_html
-
- json.field "viewCount", video.views
- json.field "published", video.published.to_unix
- json.field "publishedText", translate(locale, "`x` ago", recode_date(video.published, locale))
- json.field "lengthSeconds", video.length_seconds
- json.field "liveNow", video.live_now
- json.field "paid", video.paid
- json.field "premium", video.premium
end
end
end
end
- end
-end
{"/api/v1/channels/:ucid/playlists", "/api/v1/channels/playlists/:ucid"}.each do |route|
get route do |env|
@@ -3841,32 +3743,8 @@ end
json.field "playlists" do
json.array do
items.each do |item|
- json.object do
- if item.is_a?(SearchPlaylist)
- json.field "title", item.title
- json.field "playlistId", item.id
-
- json.field "author", item.author
- json.field "authorId", item.ucid
- json.field "authorUrl", "/channel/#{item.ucid}"
-
- json.field "videoCount", item.video_count
- json.field "videos" do
- json.array do
- item.videos.each do |video|
- json.object do
- json.field "title", video.title
- json.field "videoId", video.id
- json.field "lengthSeconds", video.length_seconds
-
- json.field "videoThumbnails" do
- generate_thumbnails(json, video.id, config, Kemal.config)
- end
- end
- end
- end
- end
- end
+ if item.is_a?(SearchPlaylist)
+ item.to_json(locale, config, Kemal.config, json)
end
end
end
@@ -3894,90 +3772,13 @@ get "/api/v1/channels/search/:ucid" do |env|
page ||= 1
count, search_results = channel_search(query, page, ucid)
- response = JSON.build do |json|
+ JSON.build do |json|
json.array do
search_results.each do |item|
- json.object do
- case item
- when SearchVideo
- json.field "type", "video"
- json.field "title", item.title
- json.field "videoId", item.id
-
- json.field "author", item.author
- json.field "authorId", item.ucid
- json.field "authorUrl", "/channel/#{item.ucid}"
-
- json.field "videoThumbnails" do
- generate_thumbnails(json, item.id, config, Kemal.config)
- end
-
- json.field "description", item.description
- json.field "descriptionHtml", item.description_html
-
- json.field "viewCount", item.views
- json.field "published", item.published.to_unix
- json.field "publishedText", translate(locale, "`x` ago", recode_date(item.published, locale))
- json.field "lengthSeconds", item.length_seconds
- json.field "liveNow", item.live_now
- json.field "paid", item.paid
- json.field "premium", item.premium
- when SearchPlaylist
- json.field "type", "playlist"
- json.field "title", item.title
- json.field "playlistId", item.id
-
- json.field "author", item.author
- json.field "authorId", item.ucid
- json.field "authorUrl", "/channel/#{item.ucid}"
-
- json.field "videoCount", item.video_count
- json.field "videos" do
- json.array do
- item.videos.each do |video|
- json.object do
- json.field "title", video.title
- json.field "videoId", video.id
- json.field "lengthSeconds", video.length_seconds
-
- json.field "videoThumbnails" do
- generate_thumbnails(json, video.id, config, Kemal.config)
- end
- end
- end
- end
- end
- when SearchChannel
- json.field "type", "channel"
- json.field "author", item.author
- json.field "authorId", item.ucid
- json.field "authorUrl", "/channel/#{item.ucid}"
-
- json.field "authorThumbnails" do
- json.array do
- qualities = {32, 48, 76, 100, 176, 512}
-
- qualities.each do |quality|
- json.object do
- json.field "url", item.author_thumbnail.gsub("=s176-", "=s#{quality}-")
- json.field "width", quality
- json.field "height", quality
- end
- end
- end
- end
-
- json.field "subCount", item.subscriber_count
- json.field "videoCount", item.video_count
- json.field "description", item.description
- json.field "descriptionHtml", item.description_html
- end
- end
+ item.to_json(locale, config, Kemal.config, json)
end
end
end
-
- response
end
get "/api/v1/search" do |env|
@@ -4019,90 +3820,13 @@ get "/api/v1/search" do |env|
end
count, search_results = search(query, page, search_params, proxies, region).as(Tuple)
- response = JSON.build do |json|
+ JSON.build do |json|
json.array do
search_results.each do |item|
- json.object do
- case item
- when SearchVideo
- json.field "type", "video"
- json.field "title", item.title
- json.field "videoId", item.id
-
- json.field "author", item.author
- json.field "authorId", item.ucid
- json.field "authorUrl", "/channel/#{item.ucid}"
-
- json.field "videoThumbnails" do
- generate_thumbnails(json, item.id, config, Kemal.config)
- end
-
- json.field "description", item.description
- json.field "descriptionHtml", item.description_html
-
- json.field "viewCount", item.views
- json.field "published", item.published.to_unix
- json.field "publishedText", translate(locale, "`x` ago", recode_date(item.published, locale))
- json.field "lengthSeconds", item.length_seconds
- json.field "liveNow", item.live_now
- json.field "paid", item.paid
- json.field "premium", item.premium
- when SearchPlaylist
- json.field "type", "playlist"
- json.field "title", item.title
- json.field "playlistId", item.id
-
- json.field "author", item.author
- json.field "authorId", item.ucid
- json.field "authorUrl", "/channel/#{item.ucid}"
-
- json.field "videoCount", item.video_count
- json.field "videos" do
- json.array do
- item.videos.each do |video|
- json.object do
- json.field "title", video.title
- json.field "videoId", video.id
- json.field "lengthSeconds", video.length_seconds
-
- json.field "videoThumbnails" do
- generate_thumbnails(json, video.id, config, Kemal.config)
- end
- end
- end
- end
- end
- when SearchChannel
- json.field "type", "channel"
- json.field "author", item.author
- json.field "authorId", item.ucid
- json.field "authorUrl", "/channel/#{item.ucid}"
-
- json.field "authorThumbnails" do
- json.array do
- qualities = {32, 48, 76, 100, 176, 512}
-
- qualities.each do |quality|
- json.object do
- json.field "url", item.author_thumbnail.gsub("=s176-", "=s#{quality}-")
- json.field "width", quality
- json.field "height", quality
- end
- end
- end
- end
-
- json.field "subCount", item.subscriber_count
- json.field "videoCount", item.video_count
- json.field "description", item.description
- json.field "descriptionHtml", item.description_html
- end
- end
+ item.to_json(locale, config, Kemal.config, json)
end
end
end
-
- response
end
get "/api/v1/playlists/:plid" do |env|
@@ -4170,26 +3894,12 @@ get "/api/v1/playlists/:plid" do |env|
json.field "videos" do
json.array do
videos.each do |video|
- json.object do
- json.field "title", video.title
- json.field "videoId", video.id
-
- json.field "author", video.author
- json.field "authorId", video.ucid
- json.field "authorUrl", "/channel/#{video.ucid}"
-
- json.field "videoThumbnails" do
- generate_thumbnails(json, video.id, config, Kemal.config)
- end
-
- json.field "index", video.index
- json.field "lengthSeconds", video.length_seconds
+ video.to_json(locale, config, Kemal.config, json)
end
end
end
end
end
- end
if format == "html"
response = JSON.parse(response)
diff --git a/src/invidious/channels.cr b/src/invidious/channels.cr
index b7b6f5534..0582eb2fd 100644
--- a/src/invidious/channels.cr
+++ b/src/invidious/channels.cr
@@ -135,9 +135,7 @@ def get_batch_channels(channels, db, refresh = false, pull_all_videos = true, ma
end
def get_channel(id, db, refresh = true, pull_all_videos = true)
- if db.query_one?("SELECT EXISTS (SELECT true FROM channels WHERE id = $1)", id, as: Bool)
- channel = db.query_one("SELECT * FROM channels WHERE id = $1", id, as: InvidiousChannel)
-
+ if channel = db.query_one?("SELECT * FROM channels WHERE id = $1", id, as: InvidiousChannel)
if refresh && Time.utc - channel.updated > 10.minutes
channel = fetch_channel(id, db, pull_all_videos: pull_all_videos)
channel_array = channel.to_a
diff --git a/src/invidious/mixes.cr b/src/invidious/mixes.cr
index 47c480d7f..8664f83da 100644
--- a/src/invidious/mixes.cr
+++ b/src/invidious/mixes.cr
@@ -6,7 +6,7 @@ struct MixVideo
ucid: String,
length_seconds: Int32,
index: Int32,
- mixes: Array(String),
+ rdid: String,
})
end
@@ -70,7 +70,7 @@ def fetch_mix(rdid, video_id, cookies = nil, locale = nil)
ucid,
length_seconds,
index,
- [rdid]
+ rdid
)
end
diff --git a/src/invidious/playlists.cr b/src/invidious/playlists.cr
index 6eb0fd39e..54b7af0ae 100644
--- a/src/invidious/playlists.cr
+++ b/src/invidious/playlists.cr
@@ -1,4 +1,32 @@
struct PlaylistVideo
+ def to_json(locale, config, kemal_config, json : JSON::Builder)
+ json.object do
+ json.field "title", self.title
+ json.field "videoId", self.id
+
+ json.field "author", self.author
+ json.field "authorId", self.ucid
+ json.field "authorUrl", "/channel/#{self.ucid}"
+
+ json.field "videoThumbnails" do
+ generate_thumbnails(json, self.id, config, kemal_config)
+ end
+
+ json.field "index", self.index
+ json.field "lengthSeconds", self.length_seconds
+ end
+ end
+
+ def to_json(locale, config, kemal_config, json : JSON::Builder | Nil = nil)
+ if json
+ to_json(locale, config, kemal_config, json)
+ else
+ JSON.build do |json|
+ to_json(locale, config, kemal_config, json)
+ end
+ end
+ end
+
db_mapping({
title: String,
id: String,
diff --git a/src/invidious/search.cr b/src/invidious/search.cr
index 12aa81b99..49aa422ac 100644
--- a/src/invidious/search.cr
+++ b/src/invidious/search.cr
@@ -50,6 +50,43 @@ struct SearchVideo
end
end
+ def to_json(locale, config, kemal_config, json : JSON::Builder)
+ json.object do
+ json.field "type", "video"
+ json.field "title", self.title
+ json.field "videoId", self.id
+
+ json.field "author", self.author
+ json.field "authorId", self.ucid
+ json.field "authorUrl", "/channel/#{self.ucid}"
+
+ json.field "videoThumbnails" do
+ generate_thumbnails(json, self.id, config, kemal_config)
+ end
+
+ json.field "description", self.description
+ json.field "descriptionHtml", self.description_html
+
+ json.field "viewCount", self.views
+ json.field "published", self.published.to_unix
+ json.field "publishedText", translate(locale, "`x` ago", recode_date(self.published, locale))
+ json.field "lengthSeconds", self.length_seconds
+ json.field "liveNow", self.live_now
+ json.field "paid", self.paid
+ json.field "premium", self.premium
+ end
+ end
+
+ def to_json(locale, config, kemal_config, json : JSON::Builder | Nil = nil)
+ if json
+ to_json(locale, config, kemal_config, json)
+ else
+ JSON.build do |json|
+ to_json(locale, config, kemal_config, json)
+ end
+ end
+ end
+
db_mapping({
title: String,
id: String,
@@ -76,6 +113,45 @@ struct SearchPlaylistVideo
end
struct SearchPlaylist
+ def to_json(locale, config, kemal_config, json : JSON::Builder)
+ json.object do
+ json.field "type", "playlist"
+ json.field "title", self.title
+ json.field "playlistId", self.id
+
+ json.field "author", self.author
+ json.field "authorId", self.ucid
+ json.field "authorUrl", "/channel/#{self.ucid}"
+
+ json.field "videoCount", self.video_count
+ json.field "videos" do
+ json.array do
+ self.videos.each do |video|
+ json.object do
+ json.field "title", video.title
+ json.field "videoId", video.id
+ json.field "lengthSeconds", video.length_seconds
+
+ json.field "videoThumbnails" do
+ generate_thumbnails(json, video.id, config, Kemal.config)
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+
+ def to_json(locale, config, kemal_config, json : JSON::Builder | Nil = nil)
+ if json
+ to_json(locale, config, kemal_config, json)
+ else
+ JSON.build do |json|
+ to_json(locale, config, kemal_config, json)
+ end
+ end
+ end
+
db_mapping({
title: String,
id: String,
@@ -88,6 +164,44 @@ struct SearchPlaylist
end
struct SearchChannel
+ def to_json(locale, config, kemal_config, json : JSON::Builder)
+ json.object do
+ json.field "type", "channel"
+ json.field "author", self.author
+ json.field "authorId", self.ucid
+ json.field "authorUrl", "/channel/#{self.ucid}"
+
+ json.field "authorThumbnails" do
+ json.array do
+ qualities = {32, 48, 76, 100, 176, 512}
+
+ qualities.each do |quality|
+ json.object do
+ json.field "url", self.author_thumbnail.gsub("=s176-", "=s#{quality}-")
+ json.field "width", quality
+ json.field "height", quality
+ end
+ end
+ end
+ end
+
+ json.field "subCount", self.subscriber_count
+ json.field "videoCount", self.video_count
+ json.field "description", self.description
+ json.field "descriptionHtml", self.description_html
+ end
+ end
+
+ def to_json(locale, config, kemal_config, json : JSON::Builder | Nil = nil)
+ if json
+ to_json(locale, config, kemal_config, json)
+ else
+ JSON.build do |json|
+ to_json(locale, config, kemal_config, json)
+ end
+ end
+ end
+
db_mapping({
author: String,
ucid: String,
diff --git a/src/invidious/videos.cr b/src/invidious/videos.cr
index 78a52db3a..854c059c3 100644
--- a/src/invidious/videos.cr
+++ b/src/invidious/videos.cr
@@ -273,184 +273,182 @@ struct Video
end
end
- def to_json(locale, config, kemal_config, decrypt_function)
- JSON.build do |json|
- json.object do
- json.field "type", "video"
+ def to_json(locale, config, kemal_config, decrypt_function, json : JSON::Builder)
+ json.object do
+ json.field "type", "video"
- json.field "title", self.title
- json.field "videoId", self.id
- json.field "videoThumbnails" do
- generate_thumbnails(json, self.id, config, kemal_config)
- end
- json.field "storyboards" do
- generate_storyboards(json, self.id, self.storyboards, config, kemal_config)
- end
+ json.field "title", self.title
+ json.field "videoId", self.id
+ json.field "videoThumbnails" do
+ generate_thumbnails(json, self.id, config, kemal_config)
+ end
+ json.field "storyboards" do
+ generate_storyboards(json, self.id, self.storyboards, config, kemal_config)
+ end
- description_html, description = html_to_content(self.description)
+ description_html, description = html_to_content(self.description)
- json.field "description", description
- json.field "descriptionHtml", description_html
- json.field "published", self.published.to_unix
- json.field "publishedText", translate(locale, "`x` ago", recode_date(self.published, locale))
- json.field "keywords", self.keywords
+ json.field "description", description
+ json.field "descriptionHtml", description_html
+ json.field "published", self.published.to_unix
+ json.field "publishedText", translate(locale, "`x` ago", recode_date(self.published, locale))
+ json.field "keywords", self.keywords
- json.field "viewCount", self.views
- json.field "likeCount", self.likes
- json.field "dislikeCount", self.dislikes
+ json.field "viewCount", self.views
+ json.field "likeCount", self.likes
+ json.field "dislikeCount", self.dislikes
- json.field "paid", self.paid
- json.field "premium", self.premium
- json.field "isFamilyFriendly", self.is_family_friendly
- json.field "allowedRegions", self.allowed_regions
- json.field "genre", self.genre
- json.field "genreUrl", self.genre_url
+ json.field "paid", self.paid
+ json.field "premium", self.premium
+ json.field "isFamilyFriendly", self.is_family_friendly
+ json.field "allowedRegions", self.allowed_regions
+ json.field "genre", self.genre
+ json.field "genreUrl", self.genre_url
- json.field "author", self.author
- json.field "authorId", self.ucid
- json.field "authorUrl", "/channel/#{self.ucid}"
+ json.field "author", self.author
+ json.field "authorId", self.ucid
+ json.field "authorUrl", "/channel/#{self.ucid}"
- json.field "authorThumbnails" do
- json.array do
- qualities = {32, 48, 76, 100, 176, 512}
+ json.field "authorThumbnails" do
+ json.array do
+ qualities = {32, 48, 76, 100, 176, 512}
- qualities.each do |quality|
- json.object do
- json.field "url", self.author_thumbnail.gsub("=s48-", "=s#{quality}-")
- json.field "width", quality
- json.field "height", quality
- end
+ qualities.each do |quality|
+ json.object do
+ json.field "url", self.author_thumbnail.gsub("=s48-", "=s#{quality}-")
+ json.field "width", quality
+ json.field "height", quality
end
end
end
+ end
- json.field "subCountText", self.sub_count_text
+ json.field "subCountText", self.sub_count_text
- json.field "lengthSeconds", self.info["length_seconds"].to_i
- json.field "allowRatings", self.allow_ratings
- json.field "rating", self.info["avg_rating"].to_f32
- json.field "isListed", self.is_listed
- json.field "liveNow", self.live_now
- json.field "isUpcoming", self.is_upcoming
+ json.field "lengthSeconds", self.info["length_seconds"].to_i
+ json.field "allowRatings", self.allow_ratings
+ json.field "rating", self.info["avg_rating"].to_f32
+ json.field "isListed", self.is_listed
+ json.field "liveNow", self.live_now
+ json.field "isUpcoming", self.is_upcoming
- if self.premiere_timestamp
- json.field "premiereTimestamp", self.premiere_timestamp.not_nil!.to_unix
- end
+ if self.premiere_timestamp
+ json.field "premiereTimestamp", self.premiere_timestamp.not_nil!.to_unix
+ end
- if self.player_response["streamingData"]?.try &.["hlsManifestUrl"]?
- host_url = make_host_url(config, kemal_config)
+ if self.player_response["streamingData"]?.try &.["hlsManifestUrl"]?
+ host_url = make_host_url(config, kemal_config)
- hlsvp = self.player_response["streamingData"]["hlsManifestUrl"].as_s
- hlsvp = hlsvp.gsub("https://manifest.googlevideo.com", host_url)
+ hlsvp = self.player_response["streamingData"]["hlsManifestUrl"].as_s
+ hlsvp = hlsvp.gsub("https://manifest.googlevideo.com", host_url)
- json.field "hlsUrl", hlsvp
- end
+ json.field "hlsUrl", hlsvp
+ end
- json.field "dashUrl", "#{make_host_url(config, kemal_config)}/api/manifest/dash/id/#{id}"
+ json.field "dashUrl", "#{make_host_url(config, kemal_config)}/api/manifest/dash/id/#{id}"
- json.field "adaptiveFormats" do
- json.array do
- self.adaptive_fmts(decrypt_function).each do |fmt|
- json.object do
- json.field "index", fmt["index"]
- json.field "bitrate", fmt["bitrate"]
- json.field "init", fmt["init"]
- json.field "url", fmt["url"]
- json.field "itag", fmt["itag"]
- json.field "type", fmt["type"]
- json.field "clen", fmt["clen"]
- json.field "lmt", fmt["lmt"]
- json.field "projectionType", fmt["projection_type"]
+ json.field "adaptiveFormats" do
+ json.array do
+ self.adaptive_fmts(decrypt_function).each do |fmt|
+ json.object do
+ json.field "index", fmt["index"]
+ json.field "bitrate", fmt["bitrate"]
+ json.field "init", fmt["init"]
+ json.field "url", fmt["url"]
+ json.field "itag", fmt["itag"]
+ json.field "type", fmt["type"]
+ json.field "clen", fmt["clen"]
+ json.field "lmt", fmt["lmt"]
+ json.field "projectionType", fmt["projection_type"]
- fmt_info = itag_to_metadata?(fmt["itag"])
- if fmt_info
- fps = fmt_info["fps"]?.try &.to_i || fmt["fps"]?.try &.to_i || 30
- json.field "fps", fps
- json.field "container", fmt_info["ext"]
- json.field "encoding", fmt_info["vcodec"]? || fmt_info["acodec"]
+ fmt_info = itag_to_metadata?(fmt["itag"])
+ if fmt_info
+ fps = fmt_info["fps"]?.try &.to_i || fmt["fps"]?.try &.to_i || 30
+ json.field "fps", fps
+ json.field "container", fmt_info["ext"]
+ json.field "encoding", fmt_info["vcodec"]? || fmt_info["acodec"]
- if fmt_info["height"]?
- json.field "resolution", "#{fmt_info["height"]}p"
+ if fmt_info["height"]?
+ json.field "resolution", "#{fmt_info["height"]}p"
- quality_label = "#{fmt_info["height"]}p"
- if fps > 30
- quality_label += "60"
- end
- json.field "qualityLabel", quality_label
+ quality_label = "#{fmt_info["height"]}p"
+ if fps > 30
+ quality_label += "60"
+ end
+ json.field "qualityLabel", quality_label
- if fmt_info["width"]?
- json.field "size", "#{fmt_info["width"]}x#{fmt_info["height"]}"
- end
+ if fmt_info["width"]?
+ json.field "size", "#{fmt_info["width"]}x#{fmt_info["height"]}"
end
end
end
end
end
end
+ end
- json.field "formatStreams" do
- json.array do
- self.fmt_stream(decrypt_function).each do |fmt|
- json.object do
- json.field "url", fmt["url"]
- json.field "itag", fmt["itag"]
- json.field "type", fmt["type"]
- json.field "quality", fmt["quality"]
+ json.field "formatStreams" do
+ json.array do
+ self.fmt_stream(decrypt_function).each do |fmt|
+ json.object do
+ json.field "url", fmt["url"]
+ json.field "itag", fmt["itag"]
+ json.field "type", fmt["type"]
+ json.field "quality", fmt["quality"]
- fmt_info = itag_to_metadata?(fmt["itag"])
- if fmt_info
- fps = fmt_info["fps"]?.try &.to_i || fmt["fps"]?.try &.to_i || 30
- json.field "fps", fps
- json.field "container", fmt_info["ext"]
- json.field "encoding", fmt_info["vcodec"]? || fmt_info["acodec"]
+ fmt_info = itag_to_metadata?(fmt["itag"])
+ if fmt_info
+ fps = fmt_info["fps"]?.try &.to_i || fmt["fps"]?.try &.to_i || 30
+ json.field "fps", fps
+ json.field "container", fmt_info["ext"]
+ json.field "encoding", fmt_info["vcodec"]? || fmt_info["acodec"]
- if fmt_info["height"]?
- json.field "resolution", "#{fmt_info["height"]}p"
+ if fmt_info["height"]?
+ json.field "resolution", "#{fmt_info["height"]}p"
- quality_label = "#{fmt_info["height"]}p"
- if fps > 30
- quality_label += "60"
- end
- json.field "qualityLabel", quality_label
+ quality_label = "#{fmt_info["height"]}p"
+ if fps > 30
+ quality_label += "60"
+ end
+ json.field "qualityLabel", quality_label
- if fmt_info["width"]?
- json.field "size", "#{fmt_info["width"]}x#{fmt_info["height"]}"
- end
+ if fmt_info["width"]?
+ json.field "size", "#{fmt_info["width"]}x#{fmt_info["height"]}"
end
end
end
end
end
end
+ end
- json.field "captions" do
- json.array do
- self.captions.each do |caption|
+ json.field "captions" do
+ json.array do
+ self.captions.each do |caption|
+ json.object do
+ json.field "label", caption.name.simpleText
+ json.field "languageCode", caption.languageCode
+ json.field "url", "/api/v1/captions/#{id}?label=#{URI.escape(caption.name.simpleText)}"
+ end
+ end
+ end
+ end
+
+ json.field "recommendedVideos" do
+ json.array do
+ self.info["rvs"]?.try &.split(",").each do |rv|
+ rv = HTTP::Params.parse(rv)
+
+ if rv["id"]?
json.object do
- json.field "label", caption.name.simpleText
- json.field "languageCode", caption.languageCode
- json.field "url", "/api/v1/captions/#{id}?label=#{URI.escape(caption.name.simpleText)}"
- end
- end
- end
- end
-
- json.field "recommendedVideos" do
- json.array do
- self.info["rvs"]?.try &.split(",").each do |rv|
- rv = HTTP::Params.parse(rv)
-
- if rv["id"]?
- json.object do
- json.field "videoId", rv["id"]
- json.field "title", rv["title"]
- json.field "videoThumbnails" do
- generate_thumbnails(json, rv["id"], config, kemal_config)
- end
- json.field "author", rv["author"]
- json.field "lengthSeconds", rv["length_seconds"].to_i
- json.field "viewCountText", rv["short_view_count_text"]
+ json.field "videoId", rv["id"]
+ json.field "title", rv["title"]
+ json.field "videoThumbnails" do
+ generate_thumbnails(json, rv["id"], config, kemal_config)
end
+ json.field "author", rv["author"]
+ json.field "lengthSeconds", rv["length_seconds"].to_i
+ json.field "viewCountText", rv["short_view_count_text"]
end
end
end
@@ -459,6 +457,16 @@ struct Video
end
end
+ def to_json(locale, config, kemal_config, decrypt_function, json : JSON::Builder | Nil = nil)
+ if json
+ to_json(locale, config, kemal_config, decrypt_function, json)
+ else
+ JSON.build do |json|
+ to_json(locale, config, kemal_config, decrypt_function, json)
+ end
+ end
+ end
+
def allow_ratings
allow_ratings = player_response["videoDetails"]?.try &.["allowRatings"]?.try &.as_bool
@@ -848,9 +856,7 @@ class VideoRedirect < Exception
end
def get_video(id, db, proxies = {} of String => Array({ip: String, port: Int32}), refresh = true, region = nil, force_refresh = false)
- if db.query_one?("SELECT EXISTS (SELECT true FROM videos WHERE id = $1)", id, as: Bool) && !region
- video = db.query_one("SELECT * FROM videos WHERE id = $1", id, as: Video)
-
+ if (video = db.query_one?("SELECT * FROM videos WHERE id = $1", id, as: Video)) && !region
# If record was last updated over 10 minutes ago, or video has since premiered,
# refresh (expire param in response lasts for 6 hours)
if (refresh &&
diff --git a/src/invidious/views/components/item.ecr b/src/invidious/views/components/item.ecr
index 780174243..28e700581 100644
--- a/src/invidious/views/components/item.ecr
+++ b/src/invidious/views/components/item.ecr
@@ -35,7 +35,7 @@
<% when MixVideo %>
-
+
<% if !env.get("preferences").as(Preferences).thin_mode %>