Add 'to_json' into respective structs

This commit is contained in:
Omar Roth 2019-06-08 13:31:41 -05:00
parent 1c9085556c
commit 12b2ab5da8
No known key found for this signature in database
GPG key ID: B8254FB7EC3D37F2
7 changed files with 307 additions and 451 deletions

View file

@ -3405,31 +3405,10 @@ get "/api/v1/trending" do |env|
videos = JSON.build do |json| videos = JSON.build do |json|
json.array do json.array do
trending.each do |video| trending.each do |video|
json.object do video.to_json(locale, config, Kemal.config, json)
json.field "title", video.title
json.field "videoId", video.id
json.field "videoThumbnails" do
generate_thumbnails(json, video.id, config, Kemal.config)
end 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
end
end
videos videos
end end
@ -3459,9 +3438,12 @@ get "/api/v1/top" do |env|
next error_message next error_message
end end
videos = JSON.build do |json| JSON.build do |json|
json.array do json.array do
top_videos.each do |video| 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.object do
json.field "title", video.title json.field "title", video.title
json.field "videoId", video.id json.field "videoId", video.id
@ -3487,8 +3469,6 @@ get "/api/v1/top" do |env|
end end
end end
end end
videos
end end
get "/api/v1/channels/:ucid" do |env| get "/api/v1/channels/:ucid" do |env|
@ -3577,6 +3557,7 @@ get "/api/v1/channels/:ucid" do |env|
end end
channel_info = JSON.build do |json| channel_info = JSON.build do |json|
# TODO: Refactor into `to_json` for InvidiousChannel
json.object do json.object do
json.field "author", author json.field "author", author
json.field "authorId", ucid json.field "authorId", ucid
@ -3634,35 +3615,7 @@ get "/api/v1/channels/:ucid" do |env|
json.field "latestVideos" do json.field "latestVideos" do
json.array do json.array do
videos.each do |video| videos.each do |video|
json.object do video.to_json(locale, config, Kemal.config, json)
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
end end
end end
end end
@ -3727,45 +3680,15 @@ end
next error_message next error_message
end end
result = JSON.build do |json| JSON.build do |json|
json.array do json.array do
videos.each do |video| videos.each do |video|
json.object do video.to_json(locale, config, Kemal.config, json)
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 end
json.field "videoThumbnails" do
generate_thumbnails(json, video.id, config, Kemal.config)
end 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
end
result
end
end
{"/api/v1/channels/:ucid/latest", "/api/v1/channels/latest/:ucid"}.each do |route| {"/api/v1/channels/:ucid/latest", "/api/v1/channels/latest/:ucid"}.each do |route|
get route do |env| get route do |env|
@ -3786,33 +3709,12 @@ end
JSON.build do |json| JSON.build do |json|
json.array do json.array do
videos.each do |video| videos.each do |video|
json.object do video.to_json(locale, config, Kemal.config, json)
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)
end 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
end end
end
end
{"/api/v1/channels/:ucid/playlists", "/api/v1/channels/playlists/:ucid"}.each do |route| {"/api/v1/channels/:ucid/playlists", "/api/v1/channels/playlists/:ucid"}.each do |route|
get route do |env| get route do |env|
@ -3841,32 +3743,8 @@ end
json.field "playlists" do json.field "playlists" do
json.array do json.array do
items.each do |item| items.each do |item|
json.object do if item.is_a?(SearchPlaylist)
if item.is_a?(SearchPlaylist) item.to_json(locale, config, Kemal.config, json)
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
end end
end end
end end
@ -3894,90 +3772,13 @@ get "/api/v1/channels/search/:ucid" do |env|
page ||= 1 page ||= 1
count, search_results = channel_search(query, page, ucid) count, search_results = channel_search(query, page, ucid)
response = JSON.build do |json| JSON.build do |json|
json.array do json.array do
search_results.each do |item| search_results.each do |item|
json.object do item.to_json(locale, config, Kemal.config, json)
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
end end
end end
end end
response
end end
get "/api/v1/search" do |env| get "/api/v1/search" do |env|
@ -4019,90 +3820,13 @@ get "/api/v1/search" do |env|
end end
count, search_results = search(query, page, search_params, proxies, region).as(Tuple) count, search_results = search(query, page, search_params, proxies, region).as(Tuple)
response = JSON.build do |json| JSON.build do |json|
json.array do json.array do
search_results.each do |item| search_results.each do |item|
json.object do item.to_json(locale, config, Kemal.config, json)
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
end end
end end
end end
response
end end
get "/api/v1/playlists/:plid" do |env| get "/api/v1/playlists/:plid" do |env|
@ -4170,26 +3894,12 @@ get "/api/v1/playlists/:plid" do |env|
json.field "videos" do json.field "videos" do
json.array do json.array do
videos.each do |video| videos.each do |video|
json.object do video.to_json(locale, config, Kemal.config, json)
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
end end
end end
end end
end end
end end
end
if format == "html" if format == "html"
response = JSON.parse(response) response = JSON.parse(response)

View file

@ -135,9 +135,7 @@ def get_batch_channels(channels, db, refresh = false, pull_all_videos = true, ma
end end
def get_channel(id, db, refresh = true, pull_all_videos = true) 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) if channel = db.query_one?("SELECT * FROM channels WHERE id = $1", id, as: InvidiousChannel)
channel = db.query_one("SELECT * FROM channels WHERE id = $1", id, as: InvidiousChannel)
if refresh && Time.utc - channel.updated > 10.minutes if refresh && Time.utc - channel.updated > 10.minutes
channel = fetch_channel(id, db, pull_all_videos: pull_all_videos) channel = fetch_channel(id, db, pull_all_videos: pull_all_videos)
channel_array = channel.to_a channel_array = channel.to_a

View file

@ -6,7 +6,7 @@ struct MixVideo
ucid: String, ucid: String,
length_seconds: Int32, length_seconds: Int32,
index: Int32, index: Int32,
mixes: Array(String), rdid: String,
}) })
end end
@ -70,7 +70,7 @@ def fetch_mix(rdid, video_id, cookies = nil, locale = nil)
ucid, ucid,
length_seconds, length_seconds,
index, index,
[rdid] rdid
) )
end end

View file

@ -1,4 +1,32 @@
struct PlaylistVideo 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({ db_mapping({
title: String, title: String,
id: String, id: String,

View file

@ -50,6 +50,43 @@ struct SearchVideo
end end
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({ db_mapping({
title: String, title: String,
id: String, id: String,
@ -76,6 +113,45 @@ struct SearchPlaylistVideo
end end
struct SearchPlaylist 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({ db_mapping({
title: String, title: String,
id: String, id: String,
@ -88,6 +164,44 @@ struct SearchPlaylist
end end
struct SearchChannel 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({ db_mapping({
author: String, author: String,
ucid: String, ucid: String,

View file

@ -273,184 +273,182 @@ struct Video
end end
end end
def to_json(locale, config, kemal_config, decrypt_function) def to_json(locale, config, kemal_config, decrypt_function, json : JSON::Builder)
JSON.build do |json| json.object do
json.object do json.field "type", "video"
json.field "type", "video"
json.field "title", self.title json.field "title", self.title
json.field "videoId", self.id json.field "videoId", self.id
json.field "videoThumbnails" do json.field "videoThumbnails" do
generate_thumbnails(json, self.id, config, kemal_config) generate_thumbnails(json, self.id, config, kemal_config)
end end
json.field "storyboards" do json.field "storyboards" do
generate_storyboards(json, self.id, self.storyboards, config, kemal_config) generate_storyboards(json, self.id, self.storyboards, config, kemal_config)
end end
description_html, description = html_to_content(self.description) description_html, description = html_to_content(self.description)
json.field "description", description json.field "description", description
json.field "descriptionHtml", description_html json.field "descriptionHtml", description_html
json.field "published", self.published.to_unix json.field "published", self.published.to_unix
json.field "publishedText", translate(locale, "`x` ago", recode_date(self.published, locale)) json.field "publishedText", translate(locale, "`x` ago", recode_date(self.published, locale))
json.field "keywords", self.keywords json.field "keywords", self.keywords
json.field "viewCount", self.views json.field "viewCount", self.views
json.field "likeCount", self.likes json.field "likeCount", self.likes
json.field "dislikeCount", self.dislikes json.field "dislikeCount", self.dislikes
json.field "paid", self.paid json.field "paid", self.paid
json.field "premium", self.premium json.field "premium", self.premium
json.field "isFamilyFriendly", self.is_family_friendly json.field "isFamilyFriendly", self.is_family_friendly
json.field "allowedRegions", self.allowed_regions json.field "allowedRegions", self.allowed_regions
json.field "genre", self.genre json.field "genre", self.genre
json.field "genreUrl", self.genre_url json.field "genreUrl", self.genre_url
json.field "author", self.author json.field "author", self.author
json.field "authorId", self.ucid json.field "authorId", self.ucid
json.field "authorUrl", "/channel/#{self.ucid}" json.field "authorUrl", "/channel/#{self.ucid}"
json.field "authorThumbnails" do json.field "authorThumbnails" do
json.array do json.array do
qualities = {32, 48, 76, 100, 176, 512} qualities = {32, 48, 76, 100, 176, 512}
qualities.each do |quality| qualities.each do |quality|
json.object do json.object do
json.field "url", self.author_thumbnail.gsub("=s48-", "=s#{quality}-") json.field "url", self.author_thumbnail.gsub("=s48-", "=s#{quality}-")
json.field "width", quality json.field "width", quality
json.field "height", quality json.field "height", quality
end
end end
end 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 "lengthSeconds", self.info["length_seconds"].to_i
json.field "allowRatings", self.allow_ratings json.field "allowRatings", self.allow_ratings
json.field "rating", self.info["avg_rating"].to_f32 json.field "rating", self.info["avg_rating"].to_f32
json.field "isListed", self.is_listed json.field "isListed", self.is_listed
json.field "liveNow", self.live_now json.field "liveNow", self.live_now
json.field "isUpcoming", self.is_upcoming json.field "isUpcoming", self.is_upcoming
if self.premiere_timestamp if self.premiere_timestamp
json.field "premiereTimestamp", self.premiere_timestamp.not_nil!.to_unix json.field "premiereTimestamp", self.premiere_timestamp.not_nil!.to_unix
end end
if self.player_response["streamingData"]?.try &.["hlsManifestUrl"]? if self.player_response["streamingData"]?.try &.["hlsManifestUrl"]?
host_url = make_host_url(config, kemal_config) host_url = make_host_url(config, kemal_config)
hlsvp = self.player_response["streamingData"]["hlsManifestUrl"].as_s hlsvp = self.player_response["streamingData"]["hlsManifestUrl"].as_s
hlsvp = hlsvp.gsub("https://manifest.googlevideo.com", host_url) hlsvp = hlsvp.gsub("https://manifest.googlevideo.com", host_url)
json.field "hlsUrl", hlsvp json.field "hlsUrl", hlsvp
end 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.field "adaptiveFormats" do
json.array do json.array do
self.adaptive_fmts(decrypt_function).each do |fmt| self.adaptive_fmts(decrypt_function).each do |fmt|
json.object do json.object do
json.field "index", fmt["index"] json.field "index", fmt["index"]
json.field "bitrate", fmt["bitrate"] json.field "bitrate", fmt["bitrate"]
json.field "init", fmt["init"] json.field "init", fmt["init"]
json.field "url", fmt["url"] json.field "url", fmt["url"]
json.field "itag", fmt["itag"] json.field "itag", fmt["itag"]
json.field "type", fmt["type"] json.field "type", fmt["type"]
json.field "clen", fmt["clen"] json.field "clen", fmt["clen"]
json.field "lmt", fmt["lmt"] json.field "lmt", fmt["lmt"]
json.field "projectionType", fmt["projection_type"] json.field "projectionType", fmt["projection_type"]
fmt_info = itag_to_metadata?(fmt["itag"]) fmt_info = itag_to_metadata?(fmt["itag"])
if fmt_info if fmt_info
fps = fmt_info["fps"]?.try &.to_i || fmt["fps"]?.try &.to_i || 30 fps = fmt_info["fps"]?.try &.to_i || fmt["fps"]?.try &.to_i || 30
json.field "fps", fps json.field "fps", fps
json.field "container", fmt_info["ext"] json.field "container", fmt_info["ext"]
json.field "encoding", fmt_info["vcodec"]? || fmt_info["acodec"] json.field "encoding", fmt_info["vcodec"]? || fmt_info["acodec"]
if fmt_info["height"]? if fmt_info["height"]?
json.field "resolution", "#{fmt_info["height"]}p" json.field "resolution", "#{fmt_info["height"]}p"
quality_label = "#{fmt_info["height"]}p" quality_label = "#{fmt_info["height"]}p"
if fps > 30 if fps > 30
quality_label += "60" quality_label += "60"
end end
json.field "qualityLabel", quality_label json.field "qualityLabel", quality_label
if fmt_info["width"]? if fmt_info["width"]?
json.field "size", "#{fmt_info["width"]}x#{fmt_info["height"]}" json.field "size", "#{fmt_info["width"]}x#{fmt_info["height"]}"
end
end end
end end
end end
end end
end end
end end
end
json.field "formatStreams" do json.field "formatStreams" do
json.array do json.array do
self.fmt_stream(decrypt_function).each do |fmt| self.fmt_stream(decrypt_function).each do |fmt|
json.object do json.object do
json.field "url", fmt["url"] json.field "url", fmt["url"]
json.field "itag", fmt["itag"] json.field "itag", fmt["itag"]
json.field "type", fmt["type"] json.field "type", fmt["type"]
json.field "quality", fmt["quality"] json.field "quality", fmt["quality"]
fmt_info = itag_to_metadata?(fmt["itag"]) fmt_info = itag_to_metadata?(fmt["itag"])
if fmt_info if fmt_info
fps = fmt_info["fps"]?.try &.to_i || fmt["fps"]?.try &.to_i || 30 fps = fmt_info["fps"]?.try &.to_i || fmt["fps"]?.try &.to_i || 30
json.field "fps", fps json.field "fps", fps
json.field "container", fmt_info["ext"] json.field "container", fmt_info["ext"]
json.field "encoding", fmt_info["vcodec"]? || fmt_info["acodec"] json.field "encoding", fmt_info["vcodec"]? || fmt_info["acodec"]
if fmt_info["height"]? if fmt_info["height"]?
json.field "resolution", "#{fmt_info["height"]}p" json.field "resolution", "#{fmt_info["height"]}p"
quality_label = "#{fmt_info["height"]}p" quality_label = "#{fmt_info["height"]}p"
if fps > 30 if fps > 30
quality_label += "60" quality_label += "60"
end end
json.field "qualityLabel", quality_label json.field "qualityLabel", quality_label
if fmt_info["width"]? if fmt_info["width"]?
json.field "size", "#{fmt_info["width"]}x#{fmt_info["height"]}" json.field "size", "#{fmt_info["width"]}x#{fmt_info["height"]}"
end
end end
end end
end end
end end
end end
end end
end
json.field "captions" do json.field "captions" do
json.array do json.array do
self.captions.each do |caption| 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.object do
json.field "label", caption.name.simpleText json.field "videoId", rv["id"]
json.field "languageCode", caption.languageCode json.field "title", rv["title"]
json.field "url", "/api/v1/captions/#{id}?label=#{URI.escape(caption.name.simpleText)}" json.field "videoThumbnails" do
end generate_thumbnails(json, rv["id"], config, kemal_config)
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"]
end 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 end
end end
@ -459,6 +457,16 @@ struct Video
end end
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 def allow_ratings
allow_ratings = player_response["videoDetails"]?.try &.["allowRatings"]?.try &.as_bool allow_ratings = player_response["videoDetails"]?.try &.["allowRatings"]?.try &.as_bool
@ -848,9 +856,7 @@ class VideoRedirect < Exception
end end
def get_video(id, db, proxies = {} of String => Array({ip: String, port: Int32}), refresh = true, region = nil, force_refresh = false) 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 if (video = db.query_one?("SELECT * FROM videos WHERE id = $1", id, as: Video)) && !region
video = db.query_one("SELECT * FROM videos WHERE id = $1", id, as: Video)
# If record was last updated over 10 minutes ago, or video has since premiered, # If record was last updated over 10 minutes ago, or video has since premiered,
# refresh (expire param in response lasts for 6 hours) # refresh (expire param in response lasts for 6 hours)
if (refresh && if (refresh &&

View file

@ -35,7 +35,7 @@
</b> </b>
</p> </p>
<% when MixVideo %> <% when MixVideo %>
<a style="width:100%" href="/watch?v=<%= item.id %>&list=<%= item.mixes[0] %>"> <a style="width:100%" href="/watch?v=<%= item.id %>&list=<%= item.rdid %>">
<% if !env.get("preferences").as(Preferences).thin_mode %> <% if !env.get("preferences").as(Preferences).thin_mode %>
<div class="thumbnail"> <div class="thumbnail">
<img class="thumbnail" src="/vi/<%= item.id %>/mqdefault.jpg"/> <img class="thumbnail" src="/vi/<%= item.id %>/mqdefault.jpg"/>