init (again)

This commit is contained in:
2026-05-26 15:18:17 +02:00
commit 22246060e6
270 changed files with 117698 additions and 0 deletions
+435
View File
@@ -0,0 +1,435 @@
local utils = require 'mp.utils'
local msg = require 'mp.msg'
local Source = {
["b 站"] = "bilibili1",
["腾讯"] = "qq",
["爱奇艺"] = "qiyi",
["优酷"] = "youku",
}
local function load_extra_danmaku(url, episode, number, class, id, site, title, year)
local play_url = nil
if url:match("^.-%.html") then
play_url = url:match("^(.-%.html).*")
elseif url:match("^https?://v%.youku%.com/") and url:match("[?&]vid=") then
-- 转换 youku 的短链接形式 video?vid=... 到真实播放页 v_show/id_*.html
local vid = url:match("[?&]vid=([^&]+)")
if vid then
play_url = "https://v.youku.com/v_show/id_" .. vid .. ".html"
else
play_url = url:gsub("%?bsource=360ogvys$",""):gsub("&.*$","")
end
else
play_url = url:gsub("%?bsource=360ogvys$",""):gsub("&.*$","")
end
ENABLED = true
DANMAKU.anime = title .. " (" .. year .. ")"
DANMAKU.episode = "" .. episode .. ""
DANMAKU.source = site
DANMAKU.extra = {
id = id,
site = site,
year = year,
class = class,
title = title,
number = tonumber(number),
episodenum = tonumber(episode),
}
write_history()
add_danmaku_source(play_url, true)
end
local function query_tmdb(title, class, menu)
local encoded_title = url_encode(title)
local url = string.format("https://api.tmdb.org/3/search/%s?api_key=%s&query=%s&language=zh-CN",
class, Base64.decode(options.tmdb_api_key), encoded_title)
local cmd = {
"curl",
"-s",
"-H", "accept: application/json",
url
}
if options.proxy ~= "" then
table.insert(cmd, '-x')
table.insert(cmd, options.proxy)
end
local res = mp.command_native({
name = "subprocess",
args = cmd,
capture_stdout = true,
capture_stderr = true,
})
local data = utils.parse_json(res.stdout)
if not res.status or res.status ~= 0 or not data.results or #data.results == 0 then
local message = "获取 tmdb 中文数据失败"
if uosc_available then
update_menu_uosc(menu.type, menu.title, message, menu.footnote, menu.cmd, title)
else
show_message(message, 3)
end
msg.error("获取 tmdb 中文数据失败:" .. res.stdout)
else
if class == "tv" then
return data.results[1].name
else
return data.results[1].title
end
end
end
local function get_number(cat, id, site)
local url = string.format("https://api.web.360kan.com/v1/detail?cat=%s&id=%s&site=%s",
cat, id, site)
local cmd = { "curl", "-s", url }
local res = mp.command_native({
name = "subprocess",
args = cmd,
capture_stdout = true,
capture_stderr = true,
})
if not res.status or res.status ~= 0 then
msg.error("Failed to fetch data: " .. (res.stderr or "unknown error"))
return nil
end
local result = utils.parse_json(res.stdout)
if result and result.data and result.data.allupinfo then
return tonumber(result.data.allupinfo[site])
end
return nil
end
local function get_episodes_v2(cat, id, site)
local s_param = string.format('[{"cat_id":"%s","ent_id":"%s","site":"%s"}]', tostring(cat), tostring(id), tostring(site))
local url = string.format("https://api.so.360kan.com/episodesv2?v_ap=1&s=%s", url_encode(s_param))
local cmd = { "curl", "-s", url }
local res = mp.command_native({
name = "subprocess",
args = cmd,
capture_stdout = true,
capture_stderr = true,
})
if not res.status or res.status ~= 0 then
msg.error("Failed to fetch episodesv2: " .. (res.stderr or "unknown error"))
return nil
end
local data_text = res.stdout or ""
-- 兼容 JSONP 和 纯 JSON提取最外层括号内 JSON
local json_payload = data_text
local first_paren = data_text:find('%(')
local last_paren = data_text:match('.*()%)')
if first_paren and last_paren and last_paren > first_paren then
json_payload = data_text:sub(first_paren + 1, last_paren - 1)
end
local parsed = utils.parse_json(json_payload)
if not parsed then
msg.error("episodesv2: 解析返回失败: " .. (res.stdout or ""))
return nil
end
local episodes = {}
if parsed.code == 0 and parsed.data and #parsed.data > 0 then
local seriesHTML = parsed.data[1] and parsed.data[1].seriesHTML
if seriesHTML and seriesHTML.seriesPlaylinks then
for i, ep in ipairs(seriesHTML.seriesPlaylinks) do
local episode_url = nil
if type(ep) == 'string' then
episode_url = ep
elseif type(ep) == 'table' and ep.url then
episode_url = ep.url
end
if episode_url and episode_url ~= '' then
table.insert(episodes, { index = i, url = episode_url })
end
end
end
end
if #episodes == 0 then
return nil
end
return episodes
end
function get_details(class, id, site, title, year, number, episodenum)
local message = episodenum and "查询弹幕中..." or "加载数据中..."
local menu_type = "menu_details"
local menu_title = "剧集信息"
local footnote = "使用 / 打开筛选"
if uosc_available and not episodenum then
update_menu_uosc(menu_type, menu_title, message, footnote)
else
show_message(message, 3)
end
local cat = 0
if class == "电影" then
cat = 1
elseif class == "电视剧" then
cat = 2
-- elseif class == "综艺" then
-- cat = 3
elseif class == "动漫" then
cat = 4
end
local items = {}
local episodes = nil
if cat == 2 or cat == 4 then
episodes = get_episodes_v2(cat, id, site)
end
-- 统一构建 episode_rows优先使用 episodesv2 返回的数据,否则使用 v1/detail
local episode_rows = nil
if episodes then
episode_rows = {}
for _, ep in ipairs(episodes) do
table.insert(episode_rows, { index = tostring(ep.index), url = ep.url })
end
else
if not number and cat ~= 0 then
number = get_number(cat, id, site)
end
if not number or cat == 0 then
local message = "无结果"
if uosc_available and not episodenum then
update_menu_uosc(menu_type, menu_title, message, footnote)
else
show_message(message, 3)
end
msg.verbose("无结果")
return
end
local url = string.format("https://api.web.360kan.com/v1/detail?cat=%s&id=%s&start=1&end=%s&site=%s",
cat, id, number, site)
local cmd = { "curl", "-s", url }
local res = mp.command_native({
name = "subprocess",
args = cmd,
capture_stdout = true,
capture_stderr = true,
})
if not res.status or res.status ~= 0 then
local message = "无结果"
if uosc_available and not episodenum then
update_menu_uosc(menu_type, menu_title, message, footnote)
else
show_message(message, 3)
end
msg.verbose("无结果")
return
end
local result = utils.parse_json(res.stdout)
if result and result.data and result.data.allepidetail and result.data.allepidetail[site] then
episode_rows = {}
for _, it in ipairs(result.data.allepidetail[site]) do
table.insert(episode_rows, { index = tostring(it.playlink_num), url = it.url })
end
end
end
if episode_rows and #episode_rows > 0 then
if episodenum then
for _, ep in ipairs(episode_rows) do
if tonumber(ep.index) == tonumber(episodenum) then
load_extra_danmaku(ep.url, ep.index, number, class, id, site, title, year)
return
end
end
end
table.insert(items, {
title = "← 返回搜索结果",
value = { "script-message-to", "uosc", "open-menu", latest_menu_anime },
keep_open = false,
selectable = true,
})
for _, ep in ipairs(episode_rows) do
table.insert(items, {
title = "" .. ep.index .. "",
hint = ep.index,
value = {
"script-message-to",
mp.get_script_name(),
"add-extra-event",
ep.url, ep.index, tostring(number), class, id, site, title, year
},
})
end
end
if #items > 0 then
if uosc_available and not episodenum then
update_menu_uosc(menu_type, menu_title, items, footnote)
elseif not episodenum then
show_message("", 0)
mp.add_timeout(0.1, function()
open_menu_select(items)
end)
end
else
local message = "无结果"
if uosc_available and not episodenum then
update_menu_uosc(menu_type, menu_title, message, footnote)
else
show_message(message, 3)
end
msg.verbose("无结果")
end
end
local function search_query(query, class, menu)
local url = string.format("https://api.so.360kan.com/index?force_v=1&kw=%s", query)
if class ~= nil then
url = url .. "&type=" .. class
end
local cmd = { "curl", "-s", url }
local res = mp.command_native({
name = "subprocess",
args = cmd,
capture_stdout = true,
capture_stderr = true,
})
if not res.status or res.status ~= 0 then
local message = "无结果"
if uosc_available then
update_menu_uosc(menu.type, menu.title, message, menu.footnote, menu.cmd, query)
else
show_message(message, 3)
end
msg.verbose("无结果")
return
end
local result = utils.parse_json(res.stdout)
local items = {}
if result and result.data.longData and result.data.longData.rows then
for _, item in ipairs(result.data.longData.rows) do
if item.playlinks then
for source_name, source_id in pairs(Source) do
if item.playlinks[source_id] then
table.insert(items, {
title = item.titleTxt,
hint = item.cat_name .. " | " .. item.year .. " | 来源:" .. source_name,
value = {
"script-message-to",
mp.get_script_name(),
"get-extra-event",
item.cat_name, item.en_id, item.playlinks[source_id], source_id,
item.titleTxt, item.year,
},
})
end
end
end
end
end
if #items > 0 then
if uosc_available then
latest_menu_anime = update_menu_uosc(menu.type, menu.title, items, menu.footnote, menu.cmd, query)
else
show_message("", 0)
mp.add_timeout(0.1, function()
open_menu_select(items)
end)
end
else
local message = "无结果"
if uosc_available then
update_menu_uosc(menu.type, menu.title, message, menu.footnote, menu.cmd, query)
else
show_message(message, 3)
end
msg.verbose("无结果")
end
end
function query_extra(name, class)
local name = name:gsub("%s*%(%d-%)%s*$", "")
local title = nil
local class = class and class:lower()
local message = "加载数据中..."
local menu = {
type = "menu_anime",
title = "在此处输入番剧名称",
footnote = "使用enter或ctrl+enter进行搜索"
}
menu.cmd = { "script-message-to", mp.get_script_name(), "search-anime-event" }
if uosc_available then
update_menu_uosc(menu.type, menu.title, message, menu.footnote, menu.cmd, name)
else
show_message(message, 30)
end
if is_chinese(name) then
search_query(name, class, menu)
return
end
if options.tmdb_api_key == "" or #Base64.decode(options.tmdb_api_key) < 32 then
local message = "请正确设置 tmdb_api_key 或尝试使用中文搜索"
if uosc_available then
update_menu_uosc(menu.type, menu.title, message, menu.footnote, menu.cmd, name)
else
show_message(message, 3)
end
return
end
if class == "dy" then
title = query_tmdb(name, "movie", menu)
else
title = query_tmdb(name, "tv", menu)
end
if title then
search_query(title, class, menu)
end
end
mp.register_script_message("get-extra-event", function(cat, id, playlink, source_id, title, year)
if uosc_available then
mp.commandv("script-message-to", "uosc", "close-menu", "menu_anime")
end
if cat == "电影" then
if playlink:match("^.-%.html") then
playlink = playlink:match("^(.-%.html).*")
else
playlink = playlink:gsub("%?bsource=360ogvys$","")
end
DANMAKU.anime = title .. " (" .. year .. ")"
DANMAKU.episode = "电影"
DANMAKU.source = source_id
write_history()
add_danmaku_source(playlink, true)
else
get_details(cat, id, source_id, title, year)
end
end)
mp.register_script_message("add-extra-event", function(url, episode, number, class, id, site, title, year)
if uosc_available then
mp.commandv("script-message-to", "uosc", "close-menu", "menu_details")
end
load_extra_danmaku(url, episode, number, class, id, site, title, year)
end)