upnext script updated
This commit is contained in:
parent
b9ee8741e4
commit
cae8647bcc
@ -182,8 +182,10 @@
|
||||
# (not an exhaustive list of unbound commands)
|
||||
#
|
||||
|
||||
# ? add sub-scale +0.1 # increase subtitle font size
|
||||
# ? add sub-scale -0.1 # decrease subtitle font size
|
||||
+ add sub-scale +0.1 # decrease subtitle font size
|
||||
- add sub-scale -0.1 # increase subtitle font size
|
||||
Alt+= add video-zoom +0.01
|
||||
Alt+- add video-zoom -0.01
|
||||
# ? sub-step -1 # immediately display next subtitle
|
||||
# ? sub-step +1 # previous
|
||||
# ? cycle angle # switch DVD/Bluray angle
|
||||
|
@ -38,5 +38,20 @@ menu_timeout=10
|
||||
# base url for loading new urls, %s will be replaced with video id
|
||||
youtube_url=https://www.youtube.com/watch?v=%s
|
||||
|
||||
# Fallback Invidious instance. Used if "upnext" could not be retrieved from the normal youtube website
|
||||
# See https://instances.invidio.us/ for alternatives e.g. https://invidious.snopyta.org
|
||||
invidious_instance=https://invidious.xyz
|
||||
|
||||
# Keep the width of the window the same when the next video is played
|
||||
restore_window_width=no
|
||||
|
||||
# On Windows wget.exe may not be able to check SSL certificates for HTTPS, so you can disable it here
|
||||
check_certificate=yes
|
||||
|
||||
|
||||
# Use a cookies file
|
||||
# Same as youtube-dl --cookies or wget --load-cookies
|
||||
# If you don't set this, the script may create a cookie file for you
|
||||
# For example "C:\\Users\\Username\\cookies.txt"
|
||||
# Or "C:/Users/Username/cookies.txt"
|
||||
#cookies=cookies.txt
|
@ -51,13 +51,341 @@ local opts = {
|
||||
--other
|
||||
menu_timeout = 10,
|
||||
youtube_url = "https://www.youtube.com/watch?v=%s",
|
||||
|
||||
-- Fallback Invidious instance, see https://instances.invidio.us/ for alternatives e.g. https://invidious.snopyta.org
|
||||
invidious_instance = "https://invidious.xyz",
|
||||
|
||||
-- Keep the width of the window the same when the next video is played
|
||||
restore_window_width = false,
|
||||
|
||||
-- On Windows wget.exe may not be able to check SSL certificates for HTTPS, so you can disable checking here
|
||||
check_certificate = true,
|
||||
|
||||
-- Use a cookies file
|
||||
-- Same as youtube-dl --cookies or wget --load-cookies
|
||||
-- If you don't set this, the script may create a cookie file for you
|
||||
-- On Windows you need to use a double blackslash or a single fordwardslash
|
||||
-- For example "C:\\Users\\Username\\cookies.txt"
|
||||
-- Or "C:/Users/Username/cookies.txt"
|
||||
cookies = ""
|
||||
}
|
||||
(require 'mp.options').read_options(opts, "youtube-upnext")
|
||||
|
||||
-- Command line options
|
||||
if opts.cookies == nil or opts.cookies == "" then
|
||||
local raw_options = mp.get_property_native("options/ytdl-raw-options")
|
||||
for param, arg in pairs(raw_options) do
|
||||
if (param == "cookies") and (arg ~= "") then
|
||||
opts.cookies = arg
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local destroyer = nil
|
||||
upnext_cache={}
|
||||
function on_file_loaded(event)
|
||||
local upnext_cache={}
|
||||
local prefered_win_width = nil
|
||||
local last_dheight = nil
|
||||
local last_dwidth = nil
|
||||
|
||||
local function table_size(t)
|
||||
local s = 0
|
||||
for _, _ in ipairs(t) do
|
||||
s = s+1
|
||||
end
|
||||
return s
|
||||
end
|
||||
|
||||
local function exec(args)
|
||||
local ret = utils.subprocess({args = args})
|
||||
return ret.status, ret.stdout, ret
|
||||
end
|
||||
|
||||
local function url_encode(s)
|
||||
local function repl(x)
|
||||
return string.format("%%%02X", string.byte(x))
|
||||
end
|
||||
return string.gsub(s, "([^0-9a-zA-Z!'()*._~-])", repl)
|
||||
end
|
||||
|
||||
local function download_upnext(url, post_data)
|
||||
local command = {"wget", "-q", "-O", "-"}
|
||||
if not opts.check_certificate then
|
||||
table.insert(command, "--no-check-certificate")
|
||||
end
|
||||
if post_data then
|
||||
table.insert(command, "--post-data")
|
||||
table.insert(command, post_data)
|
||||
end
|
||||
if opts.cookies then
|
||||
table.insert(command, "--load-cookies")
|
||||
table.insert(command, opts.cookies)
|
||||
table.insert(command, "--save-cookies")
|
||||
table.insert(command, opts.cookies)
|
||||
table.insert(command, "--keep-session-cookies")
|
||||
end
|
||||
table.insert(command, url)
|
||||
|
||||
local es, s, _ = exec(command)
|
||||
|
||||
if (es ~= 0) or (s == nil) or (s == "") then
|
||||
if es == 5 then
|
||||
mp.osd_message("upnext failed: wget does not support HTTPS", 10)
|
||||
msg.error("wget is missing certificates, disable check-certificate in userscript options")
|
||||
elseif es == -1 or es == 127 or es == 9009 then
|
||||
mp.osd_message("upnext failed: wget not found", 10)
|
||||
msg.error("wget/ wget.exe is missing. Please install it or put an executable in your PATH")
|
||||
else
|
||||
mp.osd_message("upnext failed: error=" .. tostring(es), 10)
|
||||
msg.error("failed to get upnext list: error=" .. tostring(es))
|
||||
end
|
||||
return "{}"
|
||||
end
|
||||
|
||||
local consent_pos = s:find('action="https://consent.youtube.com/s"')
|
||||
if consent_pos ~= nil then
|
||||
-- Accept cookie consent form
|
||||
msg.debug("Need to accept cookie consent form")
|
||||
s = s:sub(s:find(">", consent_pos + 1, true), s:find("</form", consent_pos + 1, true))
|
||||
|
||||
local post_str = ""
|
||||
for k, v in string.gmatch(s, "name=\"([^\"]+)\" value=\"([^\"]*)\"") do
|
||||
msg.debug("name=" .. tostring(k) .. " value=".. tostring(v))
|
||||
post_str = post_str .. url_encode(k) .. "=" .. url_encode(v) .. "&"
|
||||
end
|
||||
msg.debug("post-data=" .. tostring(post_str))
|
||||
if opts.cookies == nil or opts.cookies == "" then
|
||||
opts.cookies = os.getenv("TEMP") .. "/youtube-upnext.cookies"
|
||||
msg.warn("Created a cookies jar file at \"" .. tostring(opts.cookies) ..
|
||||
"\". To hide this warning, set a cookies file in the script configuration")
|
||||
end
|
||||
return download_upnext("https://consent.youtube.com/s", post_str)
|
||||
end
|
||||
|
||||
local pos1 = string.find(s, "ytInitialData =", 1, true)
|
||||
if pos1 == nil then
|
||||
mp.osd_message("upnext failed, no upnext data found err01", 10)
|
||||
msg.error("failed to find json position 01: pos1=nil")
|
||||
return "{}"
|
||||
end
|
||||
local pos2 = string.find(s, ";%s*</script>", pos1 + 1)
|
||||
if pos2 ~= nil then
|
||||
s = string.sub(s, pos1 + 15, pos2 - 1)
|
||||
return s
|
||||
else
|
||||
msg.error("failed to find json position 02")
|
||||
end
|
||||
|
||||
mp.osd_message("upnext failed, no upnext data found err03", 10)
|
||||
msg.error("failed to get upnext data: pos1=" .. tostring(pos1) .. " pos2=" ..tostring(pos2))
|
||||
return "{}"
|
||||
end
|
||||
|
||||
local function get_invidious(url)
|
||||
-- convert to invidious API call
|
||||
url = string.gsub(url, "https://youtube%.com/watch%?v=", opts.invidious_instance .. "/api/v1/videos/")
|
||||
url = string.gsub(url, "https://www%.youtube%.com/watch%?v=", opts.invidious_instance .. "/api/v1/videos/")
|
||||
url = string.gsub(url, "https://youtu%.be/", opts.invidious_instance .. "/api/v1/videos/")
|
||||
msg.debug("Invidious url:" .. url)
|
||||
|
||||
local command = {"wget", "-q", "-O", "-"}
|
||||
if not opts.check_certificate then
|
||||
table.insert(command, "--no-check-certificate")
|
||||
end
|
||||
table.insert(command, url)
|
||||
|
||||
local es, s, _ = exec(command)
|
||||
|
||||
if (es ~= 0) or (s == nil) or (s == "") then
|
||||
if es == 5 then
|
||||
mp.osd_message("upnext failed: wget does not support HTTPS", 10)
|
||||
msg.error("wget is missing certificates, disable check-certificate in userscript options")
|
||||
elseif es == -1 or es == 127 or es == 9009 then
|
||||
mp.osd_message("upnext failed: wget not found", 10)
|
||||
msg.error("wget/ wget.exe is missing. Please install it or put an executable in your PATH")
|
||||
else
|
||||
mp.osd_message("upnext failed: error=" .. tostring(es), 10)
|
||||
msg.error("failed to get invidious: error=" .. tostring(es))
|
||||
end
|
||||
return {}
|
||||
end
|
||||
|
||||
local data, err = utils.parse_json(s)
|
||||
if data == nil then
|
||||
mp.osd_message("upnext fetch failed (Invidious): JSON decode failed", 10)
|
||||
msg.error("parse_json failed (Invidious): " .. err)
|
||||
return {}
|
||||
end
|
||||
|
||||
if data.recommendedVideos then
|
||||
local res = {}
|
||||
msg.verbose("wget and json decode succeeded! (Invidious)")
|
||||
for i, v in ipairs(data.recommendedVideos) do
|
||||
table.insert(res, {
|
||||
index=i,
|
||||
label=v.title .. " - " .. v.author,
|
||||
file=string.format(opts.youtube_url, v.videoId)
|
||||
})
|
||||
end
|
||||
mp.osd_message("upnext fetch from Invidious succeeded", 10)
|
||||
return res
|
||||
elseif data.error then
|
||||
mp.osd_message("upnext fetch failed (Invidious): " .. data.error, 10)
|
||||
msg.error("Invidious error: " .. data.error)
|
||||
else
|
||||
mp.osd_message("upnext: No recommended videos! (Invidious)", 10)
|
||||
msg.error("No recommended videos! (Invidious)")
|
||||
end
|
||||
|
||||
return {}
|
||||
end
|
||||
|
||||
|
||||
local function parse_upnext(json_str, current_video_url)
|
||||
if json_str == "{}" then
|
||||
return {}, 0
|
||||
end
|
||||
|
||||
local data, err = utils.parse_json(json_str)
|
||||
|
||||
if data == nil then
|
||||
mp.osd_message("upnext failed: JSON decode failed", 10)
|
||||
msg.error("parse_json failed: " .. tostring(err))
|
||||
msg.debug("Corrupted JSON:\n" .. json_str .. "\n")
|
||||
return {}, 0
|
||||
end
|
||||
|
||||
local res = {}
|
||||
msg.verbose("wget and json decode succeeded!")
|
||||
|
||||
local index = 1
|
||||
local autoplay_id = nil
|
||||
if data.playerOverlays
|
||||
and data.playerOverlays.playerOverlayRenderer
|
||||
and data.playerOverlays.playerOverlayRenderer.autoplay
|
||||
and data.playerOverlays.playerOverlayRenderer.autoplay.playerOverlayAutoplayRenderer then
|
||||
local title = data.playerOverlays.playerOverlayRenderer.autoplay.playerOverlayAutoplayRenderer.videoTitle.simpleText
|
||||
local video_id = data.playerOverlays.playerOverlayRenderer.autoplay.playerOverlayAutoplayRenderer.videoId
|
||||
autoplay_id = video_id
|
||||
msg.debug("Found autoplay video")
|
||||
table.insert(res, {
|
||||
index=index,
|
||||
label=title,
|
||||
file=string.format(opts.youtube_url, video_id)
|
||||
})
|
||||
index = index + 1
|
||||
end
|
||||
|
||||
if data.playerOverlays
|
||||
and data.playerOverlays.playerOverlayRenderer
|
||||
and data.playerOverlays.playerOverlayRenderer.endScreen
|
||||
and data.playerOverlays.playerOverlayRenderer.endScreen.watchNextEndScreenRenderer
|
||||
and data.playerOverlays.playerOverlayRenderer.endScreen.watchNextEndScreenRenderer.results
|
||||
then
|
||||
local n = table_size(data.playerOverlays.playerOverlayRenderer.endScreen.watchNextEndScreenRenderer.results)
|
||||
msg.debug("Found " .. tostring(n) .. " endScreen videos")
|
||||
for i, v in ipairs(data.playerOverlays.playerOverlayRenderer.endScreen.watchNextEndScreenRenderer.results) do
|
||||
if v.endScreenVideoRenderer
|
||||
and v.endScreenVideoRenderer.title
|
||||
and v.endScreenVideoRenderer.title.simpleText then
|
||||
local title = v.endScreenVideoRenderer.title.simpleText
|
||||
local video_id = v.endScreenVideoRenderer.videoId
|
||||
if video_id ~= autoplay_id then
|
||||
table.insert(res, {
|
||||
index=index + i,
|
||||
label=title,
|
||||
file=string.format(opts.youtube_url, video_id)
|
||||
})
|
||||
end
|
||||
end
|
||||
end
|
||||
index = index + n
|
||||
end
|
||||
|
||||
if data.contents
|
||||
and data.contents.twoColumnWatchNextResults
|
||||
and data.contents.twoColumnWatchNextResults.secondaryResults
|
||||
then
|
||||
local secondaryResults = data.contents.twoColumnWatchNextResults.secondaryResults
|
||||
if secondaryResults.secondaryResults then
|
||||
secondaryResults = secondaryResults.secondaryResults
|
||||
end
|
||||
local n = table_size(secondaryResults.results)
|
||||
msg.debug("Found " .. tostring(n) .. " watchNextResults videos")
|
||||
for i, v in ipairs(secondaryResults.results) do
|
||||
local compactVideoRenderer = nil
|
||||
local watchnextindex = index
|
||||
if v.compactAutoplayRenderer
|
||||
and v.compactAutoplayRenderer
|
||||
and v.compactAutoplayRenderer.contents
|
||||
and v.compactAutoplayRenderer.contents.compactVideoRenderer then
|
||||
compactVideoRenderer = v.compactAutoplayRenderer.contents.compactVideoRenderer
|
||||
watchnextindex = 0
|
||||
elseif v.compactVideoRenderer then
|
||||
compactVideoRenderer = v.compactVideoRenderer
|
||||
end
|
||||
if compactVideoRenderer
|
||||
and compactVideoRenderer.videoId
|
||||
and compactVideoRenderer.title
|
||||
and compactVideoRenderer.title.simpleText
|
||||
then
|
||||
local title = compactVideoRenderer.title.simpleText
|
||||
local video_id = compactVideoRenderer.videoId
|
||||
local video_url = string.format(opts.youtube_url, video_id)
|
||||
local duplicate = false
|
||||
for _, entry in ipairs(res) do
|
||||
if video_url == entry.file then
|
||||
duplicate = true
|
||||
end
|
||||
end
|
||||
if not duplicate then
|
||||
table.insert(res, {
|
||||
index=watchnextindex + i,
|
||||
label=title,
|
||||
file=video_url
|
||||
})
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
table.sort(res, function(a, b) return a.index < b.index end)
|
||||
|
||||
upnext_cache[current_video_url] = res
|
||||
return res, table_size(res)
|
||||
end
|
||||
|
||||
|
||||
local function load_upnext()
|
||||
local url = mp.get_property("path")
|
||||
|
||||
url = string.gsub(url, "ytdl://", "") -- Strip possible ytdl:// prefix.
|
||||
|
||||
if string.find(url, "//youtu.be/") == nil
|
||||
and string.find(url, "//www.youtube.co.uk/") == nil
|
||||
and string.find(url, "//youtube.com/") == nil
|
||||
and string.find(url, "//www.youtube.com/") == nil
|
||||
then
|
||||
return {}, 0
|
||||
end
|
||||
|
||||
-- don't fetch the website if it's already cached
|
||||
if upnext_cache[url] ~= nil then
|
||||
local res = upnext_cache[url]
|
||||
return res, table_size(res)
|
||||
end
|
||||
|
||||
local res, n = parse_upnext(download_upnext(url, nil), url)
|
||||
|
||||
-- Fallback to Invidious API
|
||||
if n == 0 and opts.invidious_instance and opts.invidious_instance ~= "" then
|
||||
res = get_invidious(url)
|
||||
n = table_size(res)
|
||||
end
|
||||
|
||||
return res, n
|
||||
end
|
||||
|
||||
local function on_file_loaded(_)
|
||||
local url = mp.get_property("path")
|
||||
url = string.gsub(url, "ytdl://", "") -- Strip possible ytdl:// prefix.
|
||||
if string.find(url, "youtu") ~= nil then
|
||||
@ -68,36 +396,25 @@ function on_file_loaded(event)
|
||||
end
|
||||
end
|
||||
|
||||
function show_menu()
|
||||
local function show_menu()
|
||||
mp.osd_message("fetching 'up next' with wget...", 60)
|
||||
|
||||
local upnext, num_upnext = load_upnext()
|
||||
mp.osd_message("", 1)
|
||||
if num_upnext == 0 then
|
||||
return
|
||||
end
|
||||
mp.osd_message("", 1)
|
||||
|
||||
local timeout
|
||||
local selected = 1
|
||||
function selected_move(amt)
|
||||
selected = selected + amt
|
||||
if selected < 1 then
|
||||
selected = num_upnext
|
||||
elseif selected > num_upnext then
|
||||
selected = 1
|
||||
end
|
||||
timeout:kill()
|
||||
timeout:resume()
|
||||
draw_menu()
|
||||
end
|
||||
function choose_prefix(i)
|
||||
local function choose_prefix(i)
|
||||
if i == selected then
|
||||
return opts.cursor_selected
|
||||
else
|
||||
return opts.cursor_unselected
|
||||
end
|
||||
end
|
||||
|
||||
function draw_menu()
|
||||
local function draw_menu()
|
||||
local ass = assdraw.ass_new()
|
||||
|
||||
ass:pos(opts.text_padding_x, opts.text_padding_y)
|
||||
@ -111,8 +428,19 @@ function show_menu()
|
||||
if opts.scale_playlist_by_window then w,h = 0, 0 end
|
||||
mp.set_osd_ass(w, h, ass.text)
|
||||
end
|
||||
local function selected_move(amt)
|
||||
selected = selected + amt
|
||||
if selected < 1 then
|
||||
selected = num_upnext
|
||||
elseif selected > num_upnext then
|
||||
selected = 1
|
||||
end
|
||||
timeout:kill()
|
||||
timeout:resume()
|
||||
draw_menu()
|
||||
end
|
||||
|
||||
function destroy()
|
||||
local function destroy()
|
||||
timeout:kill()
|
||||
mp.set_osd_ass(0,0,"")
|
||||
mp.remove_key_binding("move_up")
|
||||
@ -129,7 +457,6 @@ function show_menu()
|
||||
mp.add_forced_key_binding(opts.select_binding, "select", function()
|
||||
destroy()
|
||||
mp.commandv("loadfile", upnext[selected].file, "replace")
|
||||
reload_resume()
|
||||
end)
|
||||
mp.add_forced_key_binding(opts.toggle_menu_binding, "escape", destroy)
|
||||
|
||||
@ -137,124 +464,47 @@ function show_menu()
|
||||
return
|
||||
end
|
||||
|
||||
function table_size(t)
|
||||
local s = 0
|
||||
for i,v in ipairs(t) do
|
||||
s = s+1
|
||||
local function on_window_scale_changed(_, value)
|
||||
if value == nil then
|
||||
return
|
||||
end
|
||||
local dwidth = mp.get_property("dwidth")
|
||||
local dheight = mp.get_property("dheight")
|
||||
if dwidth ~= nil and dheight ~= nil and dwidth == last_dwidth and dheight == last_dheight then
|
||||
-- If video size stayed the same, then the scaling was probably done by the user to we save it
|
||||
local current_window_scale = mp.get_property("current-window-scale")
|
||||
prefered_win_width = dwidth * current_window_scale
|
||||
end
|
||||
return s
|
||||
end
|
||||
|
||||
function load_upnext()
|
||||
local url = mp.get_property("path")
|
||||
|
||||
url = string.gsub(url, "ytdl://", "") -- Strip possible ytdl:// prefix.
|
||||
|
||||
if string.find(url, "//youtu.be/") == nil
|
||||
and string.find(url, "//ww.youtu.be/") == nil
|
||||
and string.find(url, "//youtube.com/") == nil
|
||||
and string.find(url, "//www.youtube.com/") == nil
|
||||
then
|
||||
return {}, 0
|
||||
local function on_dwidth_change(_, value)
|
||||
if value == nil then
|
||||
return
|
||||
end
|
||||
local dwidth = mp.get_property("dwidth")
|
||||
local dheight = mp.get_property("dheight")
|
||||
if dwidth == nil or dheight == nil then
|
||||
return
|
||||
end
|
||||
|
||||
-- don't fetch the website if it's already cached
|
||||
if upnext_cache[url] ~= nil then
|
||||
local res = upnext_cache[url]
|
||||
return res, table_size(res)
|
||||
-- Save new video size
|
||||
last_dwidth = dwidth
|
||||
last_dheight = dheight
|
||||
|
||||
if prefered_win_width == nil then
|
||||
return
|
||||
end
|
||||
-- Scale window to prefered width
|
||||
local current_window_scale = mp.get_property("current-window-scale")
|
||||
local window_width = dwidth * current_window_scale
|
||||
local new_scale = current_window_scale
|
||||
if prefered_win_width ~= nil and math.abs(prefered_win_width - window_width) > 2 then
|
||||
new_scale = prefered_win_width / dwidth
|
||||
end
|
||||
|
||||
local res, n = parse_upnext(download_upnext(url), url)
|
||||
|
||||
return res, n
|
||||
end
|
||||
|
||||
function download_upnext(url)
|
||||
local function exec(args)
|
||||
local ret = utils.subprocess({args = args})
|
||||
return ret.status, ret.stdout, ret
|
||||
if new_scale ~= current_window_scale then
|
||||
mp.set_property("window-scale", new_scale)
|
||||
end
|
||||
|
||||
local command = {"wget", "-q", "-O", "-"}
|
||||
if not opts.check_certificate then
|
||||
table.insert(command, "--no-check-certificate")
|
||||
end
|
||||
table.insert(command, url)
|
||||
|
||||
local es, s, result = exec(command)
|
||||
|
||||
if (es ~= 0) or (s == nil) or (s == "") then
|
||||
if es == 5 then
|
||||
mp.osd_message("upnext failed: wget does not support HTTPS", 10)
|
||||
msg.error("wget is missing certificates, disable check-certificate in userscript options")
|
||||
elseif es == -1 or es == 127 or es == 9009 then
|
||||
mp.osd_message("upnext failed: wget not found", 10)
|
||||
msg.error("wget/ wget.exe is missing. Please install it or put an executable in your PATH")
|
||||
else
|
||||
mp.osd_message("upnext failed: error=" .. tostring(es), 10)
|
||||
msg.error("failed to get upnext list: error=%s" .. tostring(es))
|
||||
end
|
||||
return "{}"
|
||||
end
|
||||
|
||||
local pos1 = string.find(s, "watchNextEndScreenRenderer", 1, true)
|
||||
if pos1 == nil then
|
||||
mp.osd_message("upnext failed, no upnext data found err01", 10)
|
||||
msg.error("failed to find json position 01: pos1=nil")
|
||||
return "{}"
|
||||
end
|
||||
|
||||
local pos2 = string.find(s, "}}}],\\\"", pos1 + 1, true)
|
||||
if pos2 ~= nil then
|
||||
s = string.sub(s, pos1, pos2)
|
||||
return "{\"" .. string.gsub(s, "\\\"", "\"") .. "}}]}}"
|
||||
end
|
||||
|
||||
msg.verbose("failed to find json position 2: Trying alternative")
|
||||
pos2 = string.find(s, "}}}]}}", pos1 + 1, true)
|
||||
|
||||
if pos2 ~= nil then
|
||||
msg.verbose("Alternative found!")
|
||||
s = string.sub(s, pos1, pos2)
|
||||
return "{\"" .. string.gsub(s, "\\\"", "\"") .. "}}]}}]}}"
|
||||
end
|
||||
|
||||
mp.osd_message("upnext failed, no upnext data found err03", 10)
|
||||
msg.error("failed to get upnext data: pos1=" .. tostring(pos1) .. " pos2=" ..tostring(pos2))
|
||||
return "{}"
|
||||
end
|
||||
|
||||
function parse_upnext(json_str, url)
|
||||
if json_str == "{}" then
|
||||
return {}, 0
|
||||
end
|
||||
|
||||
local data, err = utils.parse_json(json_str)
|
||||
|
||||
if data == nil then
|
||||
mp.osd_message("upnext failed: JSON decode failed", 10)
|
||||
msg.error("parse_json failed: " .. err)
|
||||
return {}, 0
|
||||
end
|
||||
|
||||
local res = {}
|
||||
msg.verbose("wget and json decode succeeded!")
|
||||
for i, v in ipairs(data.watchNextEndScreenRenderer.results) do
|
||||
if v.endScreenVideoRenderer ~= nil and v.endScreenVideoRenderer.title ~= nil and v.endScreenVideoRenderer.title.simpleText ~= nil then
|
||||
local title = v.endScreenVideoRenderer.title.simpleText
|
||||
local video_id = v.endScreenVideoRenderer.videoId
|
||||
table.insert(res, {
|
||||
index=i,
|
||||
label=title,
|
||||
file=string.format(opts.youtube_url, video_id)
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
table.sort(res, function(a, b) return a.index < b.index end)
|
||||
|
||||
upnext_cache[url] = res
|
||||
return res, table_size(res)
|
||||
end
|
||||
|
||||
|
||||
@ -274,3 +524,8 @@ mp.add_key_binding(opts.toggle_menu_binding, "upnext-menu", show_menu)
|
||||
if opts.auto_add then
|
||||
mp.register_event("file-loaded", on_file_loaded)
|
||||
end
|
||||
|
||||
if opts.restore_window_width then
|
||||
mp.observe_property("current-window-scale", "number", on_window_scale_changed)
|
||||
mp.observe_property("dwidth", "number", on_dwidth_change)
|
||||
end
|
||||
|
Loading…
Reference in New Issue
Block a user