invidious-copy-2023-06-08/src/invidious/mixes.cr

123 lines
3.2 KiB
Crystal
Raw Normal View History

2019-03-29 21:30:02 +00:00
struct MixVideo
db_mapping({
2018-09-29 04:12:35 +00:00
title: String,
id: String,
author: String,
ucid: String,
length_seconds: Int32,
index: Int32,
mixes: Array(String),
2018-09-29 04:12:35 +00:00
})
end
2019-03-29 21:30:02 +00:00
struct Mix
db_mapping({
2018-09-29 04:12:35 +00:00
title: String,
id: String,
videos: Array(MixVideo),
})
end
2018-12-20 21:32:09 +00:00
def fetch_mix(rdid, video_id, cookies = nil, locale = nil)
2018-09-29 04:12:35 +00:00
client = make_client(YT_URL)
headers = HTTP::Headers.new
headers["User-Agent"] = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36"
if cookies
headers = cookies.add_request_headers(headers)
end
2018-11-10 16:50:09 +00:00
response = client.get("/watch?v=#{video_id}&list=#{rdid}&gl=US&hl=en&has_verified=1&bpctr=9999999999", headers)
2018-09-29 04:12:35 +00:00
yt_data = response.body.match(/window\["ytInitialData"\] = (?<data>.*);/)
if yt_data
yt_data = JSON.parse(yt_data["data"].rchop(";"))
else
2018-12-20 21:32:09 +00:00
raise translate(locale, "Could not create mix.")
2018-09-29 04:12:35 +00:00
end
2018-10-08 22:52:55 +00:00
if !yt_data["contents"]["twoColumnWatchNextResults"]["playlist"]?
2018-12-20 21:32:09 +00:00
raise translate(locale, "Could not create mix.")
2018-10-08 02:11:33 +00:00
end
2018-09-29 04:12:35 +00:00
playlist = yt_data["contents"]["twoColumnWatchNextResults"]["playlist"]["playlist"]
mix_title = playlist["title"].as_s
contents = playlist["contents"].as_a
if contents.map { |video| video["playlistPanelVideoRenderer"]["videoId"] }.includes? video_id
until contents[0]["playlistPanelVideoRenderer"]["videoId"].as_s == video_id
contents.shift
end
2018-09-29 04:12:35 +00:00
end
videos = [] of MixVideo
contents.each do |item|
item = item["playlistPanelVideoRenderer"]
id = item["videoId"].as_s
2019-02-15 23:28:54 +00:00
title = item["title"]?.try &.["simpleText"].as_s
if !title
next
end
2018-09-29 04:12:35 +00:00
author = item["longBylineText"]["runs"][0]["text"].as_s
ucid = item["longBylineText"]["runs"][0]["navigationEndpoint"]["browseEndpoint"]["browseId"].as_s
length_seconds = decode_length_seconds(item["lengthText"]["simpleText"].as_s)
index = item["navigationEndpoint"]["watchEndpoint"]["index"].as_i
videos << MixVideo.new(
title,
id,
author,
ucid,
length_seconds,
index,
[rdid]
2018-09-29 04:12:35 +00:00
)
end
if !cookies
2018-12-20 21:32:09 +00:00
next_page = fetch_mix(rdid, videos[-1].id, response.cookies, locale)
2018-09-29 04:12:35 +00:00
videos += next_page.videos
end
videos.uniq! { |video| video.id }
videos = videos.first(50)
return Mix.new(mix_title, rdid, videos)
end
2018-10-08 02:11:33 +00:00
def template_mix(mix)
html = <<-END_HTML
<h3>
<a href="/mix?list=#{mix["mixId"]}">
#{mix["title"]}
</a>
</h3>
<div class="pure-menu pure-menu-scrollable playlist-restricted">
<ol class="pure-menu-list">
END_HTML
mix["videos"].as_a.each do |video|
html += <<-END_HTML
<li class="pure-menu-item">
<a href="/watch?v=#{video["videoId"]}&list=#{mix["mixId"]}">
<div class="thumbnail">
<img class="thumbnail" src="/vi/#{video["videoId"]}/mqdefault.jpg">
<p class="length">#{recode_length_seconds(video["lengthSeconds"].as_i)}</p>
</div>
2018-10-08 02:11:33 +00:00
<p style="width:100%">#{video["title"]}</p>
<p>
2019-05-02 01:03:39 +00:00
<b style="width:100%">#{video["author"]}</b>
2018-10-08 02:11:33 +00:00
</p>
</a>
</li>
END_HTML
end
html += <<-END_HTML
</ol>
</div>
<hr>
END_HTML
html
end