您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
同步动漫网站的观看进度到bgm.tv
当前为
// ==UserScript== // @name Bgm观看进度同步 // @namespace http://tampermonkey.net/ // @version 0.1 // @description 同步动漫网站的观看进度到bgm.tv // @author HinsChou // @match https://hinschou.github.io/bangumi.html?code=* // @match https://www.bilibili.com/bangumi/play/* // @match https://www.acfun.cn/bangumi/* // @match http://www.yhdm.io/v/* // @match http://tup.yhdm.io/* // @match https://www.dilidili99.com/p* // @match https://qian.zfa.wang/m3u8.php* // @connect bgm.tv // @grant GM_openInTab // @grant GM_setValue // @grant GM_getValue // @grant GM_xmlhttpRequest // @grant GM_addValueChangeListener // @grant GM_addStyle // @grant GM_registerMenuCommand // ==/UserScript== (function() { 'use strict'; // Your code here... // 授权回调页面 let api_uri = "https://api.bgm.tv"; let token_url = 'https://bgm.tv/oauth/access_token'; let redirect_uri = "https://hinschou.github.io/bangumi.html"; // 全局参数 let bgm_id = ""; // bgm番剧id let access_token = ""; // 授权凭证 let user_id = ""; // 用户id let div_bgm; // 动态获取 let watchedEp = {}; let ep_id = ""; let is_iframe = false; if(document.URL.indexOf(redirect_uri) != -1){ let code = document.URL.replace(redirect_uri + "?code=", ""); console.log("授权页面", code); if(code.length == 40){ // 正确回调 getAccessToken(code); } }else if(getIframe() != ""){ console.log("视频页面"); is_iframe = true; window.onload = function(){ setTimeout(function(){ web_video = getVideoIframe(); listenVideo(); }, 3000); }; }else{ // 播放页面 console.log("播放页面"); initWeb(); } createSetting(); GM_registerMenuCommand("API设置", function(){ let bgm_setting = document.getElementById("bgm_setting"); bgm_setting.style.display = "block"; }, "bgm.tv"); function createSetting(){ let style_input = ".bgm_input {" + "background-color: whitesmoke;" + "border: 1px solid deepskyblue; border-radius: 2px;" + "height: 24px; width: 180px;" + "padding: 0px 5px;" + "}"; let style_button = ".bgm_button {" + "background-color: deepskyblue;" + "border: 1px solid transparent; border-radius: 2px;" + "height: 26px;" + "padding: 0px 5px; margin-top: 10px;" + "color: white;" + "}"; let style_card = ".bgm_card {" + "background-color: white;" + "border: 1px solid deepskyblue; border-radius: 2px;" + "padding: 10px; text-align: left;" + "z-index: 99; position: absolute; width: 200px; display: none;" + "}"; let style_p = ".bgm_p {" + "margin-top: 10px; margin-bottom: 10px;" + "}"; GM_addStyle(style_input); GM_addStyle(style_button); GM_addStyle(style_card); GM_addStyle(style_p); let div_setting = document.createElement("div"); div_setting.className = "bgm_card"; div_setting.id = "bgm_setting"; div_setting.style = "right: 60px; top: 60px;"; let p_app_id = document.createElement("p"); p_app_id.className = "bmg_p"; p_app_id.innerText = "App ID"; p_app_id.style = "margin-bottom: 10px;"; let input_app_id = document.createElement("input"); input_app_id.className = "bgm_input"; input_app_id.id = "input_app_id"; let p_app_secret = document.createElement("p"); p_app_secret.className = "bmg_p"; p_app_secret.innerText = "App Secret"; p_app_secret.style = "margin-top: 10px; margin-bottom: 10px;"; let input_app_secret = document.createElement("input"); input_app_secret.className = "bgm_input"; input_app_secret.id = "input_app_secret"; let button_save = document.createElement("button"); button_save.className = "bgm_button"; button_save.innerText = "保存"; button_save.onclick = function(){ let input_app_id = document.getElementById("input_app_id"); let input_app_secret = document.getElementById("input_app_secret"); if(input_app_id.value == "" || input_app_secret.value == ""){ alert("请输入"); }else{ GM_setValue("app_id", input_app_id.value); GM_setValue("app_secret", input_app_secret.value); openAccessTab(); let bgm_setting = document.getElementById("bgm_setting"); bgm_setting.style.display = "none"; } }; let button_close = document.createElement("button"); button_close.className = "bgm_button"; button_close.innerText = "取消"; button_close.style = "margin-left: 20px; background-color: gray; border: 1px solid gray"; button_close.onclick = function(){ let bgm_setting = document.getElementById("bgm_setting"); bgm_setting.style.display = "none"; }; div_setting.appendChild(p_app_id); div_setting.appendChild(input_app_id); div_setting.appendChild(p_app_secret); div_setting.appendChild(input_app_secret); div_setting.appendChild(button_save); div_setting.appendChild(button_close); document.body.appendChild(div_setting); let app_id = GM_getValue("app_id", ""); let app_secret = GM_getValue("app_secret", ""); input_app_id.value = app_id; input_app_secret.value = app_secret; } function getVideoIframe(){ switch(getIframe()){ case "yhdm": return document.querySelector("video.dplayer-video-current"); case "dilidili": return document.querySelector("video.leleplayer-video-current"); } } function getIframe(){ if(document.URL.indexOf("http://tup.yhdm.io") != -1){ return "yhdm"; }else if(document.URL.indexOf("https://qian.zfa.wang") != -1){ return "dilidili"; } return ""; } // 看过章节 function watchEp(ep_id){ if(ep_id == "" || access_token == "" || watchedEp[ep_id]){ return; } console.log("看过章节", ep_id); let url_watch = api_uri + "/ep/" + ep_id + "/status/watched?access_token=" + access_token; console.log("url_watch", url_watch); GM_xmlhttpRequest({ // 标记章节为看过 url: url_watch, method: "get", onload: function(res){ console.log("watched", res.responseText); let jsonRes = JSON.parse(res.responseText); if(jsonRes.code == 200){ let button_watched = document.getElementById("button_watched"); button_watched.innerText = "已看过"; button_watched.style.backgroundColor = "hotpink"; } } }); watchedEp[ep_id] = true; } function getEpId(subject_id){ // 预告不查询 let badge = document.querySelector(".ep-item.cursor div.badge"); if(subject_id == "" || (badge != null && badge.innerText == "预告")){ return; } console.log("查询番剧章节", subject_id); let sort = getEpSort(); let url_ep = api_uri + "/subject/" + subject_id + "/ep"; console.log("url_ep", url_ep); GM_xmlhttpRequest({ // 查询番剧所有章节 url: url_ep, method: "get", onload: function(res){ let json_eps = JSON.parse(res.responseText); if(typeof json_eps.eps == "undefined"){ return; } let eps = json_eps.eps; console.log("番剧章节数", eps.length); // 获取章节id let ep = {}; for(let i in eps){ if(eps[i].sort == (sort + 1) || i == sort){ ep = eps[i]; break; } } ep_id = ep.id; let ep_name = ep.name_cn; if(ep_name == ""){ ep_name = ep.name; } console.log("章节ID", ep_id, ep_name); let input_ep_id = document.getElementById("input_ep_id"); input_ep_id.value = ep_id; let p_ep_name = document.getElementById("p_ep_name"); p_ep_name.innerText = ep_name; let button_watched = document.getElementById("button_watched"); button_watched.innerText = "未看过"; button_watched.style.backgroundColor = "lightseagreen"; } }); } function getSubjectId(title){ if(bgm_id != ""){ return; } let title_old = title; console.log("搜索标题", title); // 提取番剧主标题 if(title.indexOf(" ") != -1){ title = title.substring(0, title.indexOf(" ")); }else if(title.indexOf(":") != -1){ title = title.substring(0, title.indexOf(":")); } // 搜索标题 var url_search = api_uri + "/search/subject/" + encodeURI(title) + "?type=2"; console.log("url_search", url_search); let input_subject_id = document.getElementById("input_subject_id"); input_subject_id.placeholder = "搜索标题中"; GM_xmlhttpRequest({ url: url_search, method: "get", onload: function(res){ let json_search = JSON.parse(res.responseText); if(typeof json_search.list != "undefined"){ let subjects = json_search.list; console.log("搜索结果个数", subjects.length, "user_id", user_id); if(json_search.list.length == 1){ // 单个结果 let id = json_search.list[0].id; let name = json_search.list[0].name_cn; if(name == ""){ name = json_search.list[0].name; } console.log("搜索标题的番剧ID", id, name); setSubject(id, name); } else if(user_id != ""){ // 多个结果 // 通过标题判断 input_subject_id.placeholder = "对比标题"; for(let i in subjects){ if(subjects[i].name_cn == title_old){ // 中文标题一致 let id = subjects[i].id; let name = subjects[i].name_cn; console.log("对比标题的番剧ID", id, name); setSubject(id, name); return; } } // 通过收藏判断 input_subject_id.placeholder = "对比收藏"; getCollection("", subjects); // 未找到 input_subject_id.placeholder = "未找到"; } } } }); } function getCollection(id, subjects){ var url_collection = api_uri + "/user/" + user_id + "/collection?cat=watching"; console.log("url_collection", url_collection); GM_xmlhttpRequest({ // 查询用户收藏 url: url_collection, method: "get", onload: function(res){ let collections = JSON.parse(res.responseText); console.log("我的收藏个数", collections.length); if(id != ""){ setCollection(id, collections); }else{ for(let i in subjects){ for(let j in collections){ // 搜索id和在看收藏id一致 if(subjects[i].id == collections[j].subject_id){ let id = subjects[i].id; let name = subjects[i].name_cn; if(name == ""){ name = subjects[i].name; } console.log("对比收藏的番剧ID", id, name); setSubject(id, name); return; } } } } } }); } function setCollection(id, collections){ let button_collect = document.getElementById("button_collect"); for(let j in collections){ if(id == collections[j].subject_id){ // 已收藏 button_collect.innerText = "已收藏"; button_collect.style.backgroundColor = "hotpink"; break; } } } function listenVideo(){ // 进度监听 console.log("web_video", web_video); if(web_video != null){ web_video.addEventListener("timeupdate", function(){ // 观看进度大于85%, 标记为看完 let progress = web_video.currentTime / web_video.duration; // console.log("addEventListener timeupdate", progress, is_iframe); if(is_iframe){ GM_setValue("timeupdate", progress); }else if(progress > 0.85){ watchEp(ep_id); } }); web_video.addEventListener("loadstart", function(){ setTimeout(function(){ getEpId(bgm_id); }, 1000); }); } console.log("is_iframe", is_iframe); if(!is_iframe){ GM_addValueChangeListener("timeupdate", function(name, old_value, new_value, remote){ // console.log("GM_addValueChangeListener timeupdate", new_value); if(new_value > 0.85){ watchEp(ep_id); } }); } } // 获取网站类型 function getWebType(){ if(document.URL.indexOf("https://www.bilibili.com") != -1){ return "bilibili"; }else if(document.URL.indexOf("https://www.acfun.cn") != -1){ return "acfun"; }else if(document.URL.indexOf("http://www.yhdm.io") != -1){ return "yhdm"; }else if(document.URL.indexOf("https://www.dilidili99.com") != -1){ return "dilidili"; } } // 网站属性 var inputDiv; // 输入框位置 var title = ""; // 番剧标题 var web_video; // 播放视频 function getWebsiteId(){ console.log("getWebsiteId"); switch(getWebType()){ case "bilibili": inputDiv = document.querySelector('#toolbar_module'); title = document.querySelector('.media-title').innerText; web_video = document.querySelector(".bilibili-player-video video"); break; case "acfun": inputDiv = document.querySelector("div.player-extend-wrap"); title = document.querySelector(".part-title").innerText; web_video = document.querySelector(".container-video video"); break; case "yhdm": title = document.querySelector(".gohome.l h1 a").innerText; inputDiv = document.querySelector("div.share.l"); break; case "dilidili": title = document.querySelector(".video_title h2.title").innerText; inputDiv = document.querySelector("div.player_detail"); break; } } // 章节序号 function getEpSort(){ let sort = 0; let ep_title = ""; switch(getWebType()){ case "bilibili": sort = parseInt(document.querySelector(".ep-item.cursor span").title) - 1; break; case "acfun": sort = parseInt(document.querySelector("li.single-p.active").attributes["data-index"].value); break; case "yhdm": ep_title = document.querySelector(".movurls ul li.sel a").innerText; sort = parseInt(ep_title.substring(1, ep_title.length - 1)) - 1; break; case "dilidili": ep_title = document.querySelector("ul.content_playlist li.active a").innerText; sort = parseInt(ep_title.substring(1, ep_title.length - 1)) - 1; break; }; console.log("章节索引", sort); return sort; } // 设置番剧ID function setSubject(id, name){ console.log("设置番剧信息", id, name); bgm_id = id; GM_setValue(title, id); let input_subject_id = document.getElementById("input_subject_id"); input_subject_id.value = id; if(name != ""){ let p_subject_name = document.getElementById("p_subject_name"); p_subject_name.innerText = name; GM_setValue(id, name); } getCollection(id, []); getEpId(id); } // 创建番剧信息板块 function createBgmDiv(){ let div_bgm = document.createElement("div"); div_bgm.style = "float: right;"; let button_show = document.createElement("button"); button_show.className = "bgm_button"; button_show.style = "margin-top: 5px; margin-right: 5px;"; button_show.onclick = function(){ let bgm_card = document.getElementById("bgm_card"); // console.log("button_show", bgm_card.style.display); if(bgm_card.style.display == "block"){ bgm_card.style.display = "none"; }else{ bgm_card.style.display = "block"; } }; button_show.innerText = "番组计划"; let bgm_card = document.createElement("div"); bgm_card.className = "bgm_card"; bgm_card.id = "bgm_card"; bgm_card.style = "margin-top: 5px;" let p_subject = document.createElement("p"); p_subject.innerText = "番剧标题"; p_subject.className = "bgm_p"; p_subject.style.marginTop = "0px"; p_subject.id = "p_subject_name"; let input_bgm = document.createElement("input"); input_bgm.placeholder = "番剧ID"; input_bgm.id = "input_subject_id"; input_bgm.className = "bgm_input" let button_bgm = document.createElement("button"); button_bgm.innerText = "保存"; button_bgm.className = "bgm_button"; button_bgm.onclick = function(){ let id = input_bgm.value; console.log("修改的番剧ID", id); setSubject(id, ""); }; let button_collect = document.createElement("button"); button_collect.className = "bgm_button"; button_collect.id = "button_collect"; button_collect.style = "background-color: lightseagreen; margin-left: 10px;"; button_collect.innerText = "未收藏"; let p_ep = document.createElement("p"); p_ep.innerText = "章节标题"; p_ep.className = "bgm_p"; p_ep.id = "p_ep_name"; let input_ep = document.createElement("input"); input_ep.placeholder = "章节ID"; input_ep.id = "input_ep_id"; input_ep.className = "bgm_input" let button_ep = document.createElement("button"); button_ep.innerText = "保存"; button_ep.className = "bgm_button"; button_ep.onclick = function(){ ep_id = input_ep.value; console.log("修改的章节ID", ep_id); }; let button_watched = document.createElement("button"); button_watched.className = "bgm_button"; button_watched.id = "button_watched"; button_watched.style = "background-color: lightseagreen; margin-left: 10px;"; button_watched.innerText = "未看过"; bgm_card.appendChild(p_subject); bgm_card.appendChild(input_bgm); bgm_card.appendChild(button_bgm); bgm_card.appendChild(button_collect); bgm_card.appendChild(p_ep); bgm_card.appendChild(input_ep); bgm_card.appendChild(button_ep); bgm_card.appendChild(button_watched); div_bgm.appendChild(button_show); div_bgm.appendChild(bgm_card); return div_bgm; } // 添加番剧信息 function insertBangumiInfo(){ let div_bgm = createBgmDiv(); setTimeout(function(){ // 获取番剧标题 getWebsiteId(); let id = GM_getValue(title, ""); let name = GM_getValue(id, ""); console.log("保存的番剧ID", id, name); listenVideo(); // 手动保存输入框 inputDiv.appendChild(div_bgm); if(id == ""){ // 查询番剧id getSubjectId(title); }else{ setSubject(id, name); } }, 3000); } // 初始化页面 function initWeb(){ // 获取token access_token = GM_getValue("access_token", ""); user_id = GM_getValue("user_id", ""); let expires_end = GM_getValue("expires_end", 0); console.log("授权凭证", access_token, user_id, expires_end); // 未授权或授权过期 if(access_token == "" || new Date().getTime() > expires_end || user_id == ""){ openAccessTab(); }else{ // 手动设置 输入框 window.onload = function(){ insertBangumiInfo(); }; } } // 打开授权页面 function openAccessTab(){ let app_id = GM_getValue("app_id", ""); if(app_id == ""){ console.log("未设置API"); return; } let access_url = "https://bgm.tv/oauth/authorize?client_id=" + app_id + "&response_type=code"; GM_openInTab(access_url, { active: true, insert: true }); setTimeout(function(){ GM_addValueChangeListener("access_token", function(name, old_value, new_value, remote){ console.log("ValueChange", name, new_value); access_token = GM_getValue("access_token", ""); user_id = GM_getValue("user_id", ""); if(access_token != ""){ insertBangumiInfo(); } }); console.log("GM_addValueChangeListener user_id"); }, 1000); } // 通过授权码获取授权凭证 function getAccessToken(code){ let app_id = GM_getValue("app_id", ""); let app_secret = GM_getValue("app_secret", ""); let body = 'grant_type=authorization_code'+ '&client_id=' + app_id + '&client_secret=' + app_secret + '&code=' + code + '&redirect_uri=' + redirect_uri; console.log(body); // 获取token GM_xmlhttpRequest({ url: token_url, method: "post", data: body, headers: { "Content-Type": "application/x-www-form-urlencoded" }, onload: function(res){ console.log("responseText", res.responseText); if(typeof res.responseText == "undefined"){ document.body.innerText = "授权失败, 请刷新此页面"; return; } let jsonToken = JSON.parse(res.responseText); // 保存token if(typeof jsonToken.access_token != undefined){ GM_setValue("expires_end", jsonToken.expires_in * 1000 + new Date().getTime()); GM_setValue("user_id", jsonToken.user_id); GM_setValue("refresh_token", jsonToken.refresh_token); // GM_setValue("token_type", res.response.token_type); // 最后设置, 触发监听器 GM_setValue("access_token", jsonToken.access_token); console.log("set access_token", jsonToken.access_token); document.body.innerText = "授权成功, 请关闭此页面"; } }, onerror: function(error){ console.log(error); } }); } })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址