////////////////////// 填充数据 ////////////////////// chrome.storage.sync.get(G.OptionLists, function (items) { if (chrome.runtime.lastError) { items = G.OptionLists; } // 确保有默认值 for (let key in G.OptionLists) { if (items[key] === undefined || items[key] === null) { items[key] = G.OptionLists[key]; } } if (items.Ext === undefined || items.Type === undefined || items.Regex === undefined) { location.reload(); } if (G.isMobile) { $(``).appendTo("head"); } $(``).appendTo("head"); const $extList = $("#extList"); for (let key in items.Ext) { $extList.append(Gethtml("Ext", { ext: items.Ext[key].ext, size: items.Ext[key].size, state: items.Ext[key].state })); } const $typeList = $("#typeList"); for (let key in items.Type) { $typeList.append(Gethtml("Type", { type: items.Type[key].type, size: items.Type[key].size, state: items.Type[key].state })); } const $regexList = $("#regexList"); for (let key in items.Regex) { $regexList.append(Gethtml("Regex", { type: items.Regex[key].type, regex: items.Regex[key].regex, ext: items.Regex[key].ext, blackList: items.Regex[key].blackList, state: items.Regex[key].state })); } const $blockUrlList = $("#blockUrlList"); for (let key in items.blockUrl) { $blockUrlList.append(Gethtml("blockUrl", { url: items.blockUrl[key].url, state: items.blockUrl[key].state })); } setTimeout(() => { for (let key in items) { if (key == "Ext" || key == "Type" || key == "Regex") { continue; } if (typeof items[key] == "boolean") { $(`#${key}`).prop("checked", items[key]); } else { $(`#${key}`).val(items[key]); } } }, 100); }); //新增格式 $("#AddExt").bind("click", function () { $("#extList").append(Gethtml("Ext", { state: true })); $("#extList [name=text]").last().focus(); }); $("#AddType").bind("click", function () { $("#typeList").append(Gethtml("Type", { state: true })); $("#typeList [name=text]").last().focus(); }); $("#AddRegex").bind("click", function () { $("#regexList").append(Gethtml("Regex", { type: "ig", state: true })); $("#regexList [name=text]").last().focus(); }); $("#blockAddUrl").bind("click", function () { $("#blockUrlList").append(Gethtml("blockUrl", { state: true })); $("#blockUrlList [name=url]").last().focus(); }); $("#version").html(i18n.catCatch + " v" + chrome.runtime.getManifest().version); // 自定义播放调用模板 playerList = new Map(); playerList.set("tips", { name: i18n.invokeProtocolTemplate, template: "" }); playerList.set("default", { name: i18n.default + " / " + i18n.disable, template: "" }); playerList.set("potplayer", { name: "PotPlayer", template: "potplayer://${url} ${referer|exists:'/referer=\"*\"'}" }); playerList.set("potplayerFix", { name: "PotPlayerFix", template: "potplayer:${url} ${referer|exists:'/referer=\"*\"'}" }); playerList.set("mxPlayerAd", { name: "Android MX Player Free", template: "intent:${url}#Intent;package=com.mxtech.videoplayer.ad;end" }); playerList.set("mxPlayerPro", { name: "Android MX Player Pro", template: "intent:${url}#Intent;package=com.mxtech.videoplayer.pro;end" }); playerList.set("vlc", { name: "Android vlc", template: "intent:${url}#Intent;package=org.videolan.vlc;end" }); playerList.set("vlcCustom", { name: i18n.customVLCProtocol + " vlc://", template: "vlc://${url}" }); playerList.set("shareApi", { name: i18n.systemShare, template: "${shareApi}" }); playerList.forEach(function (item, key) { $("#PlayerTemplate").append(``); }); // 增加后缀 类型 正则表达式 function Gethtml(Type, Param = new Object()) { let html = ""; switch (Type) { case "Ext": html = `` html += `KB` break; case "Type": html = `` html += `KB` break; case "Regex": html = `` html += `` html += `` html += `
` break; case "blockUrl": html = `` break; } html = $(` ${html}
`); html.find(".RemoveButton").click(function () { html.remove(); Save(Type); }); html.find("input").on("input", function () { Save(Type, 200); }); html.find("[name=state]").on("click", function () { Save(Type); }); if (Type == "Type") { html.find("input").blur(function () { $("#typeList tr").each(function () { let GetText = $(this).find("[name=text]").val(); if (isEmpty(GetText)) { return true; } GetText = GetText.trim(); const test = GetText.split("/"); if (test.length != 2 || isEmpty(test[0]) || isEmpty(test[1])) { alert(i18n.addTypeError); return true; } }); }); } return html; } // 预览模板 $("#PlayerTemplate").change(function () { const Value = $(this).val(); if (this.id == "PlayerTemplate" && playerList.has(Value) && Value != "tips") { const template = playerList.get(Value).template; $("#Player").val(template); chrome.storage.sync.set({ Player: template }); } }); //失去焦点 保存自动清理数 模拟手机User Agent 自定义播放调用模板 let debounce2 = undefined; $("[save='input']").on("input", function () { let val = $(this).val().trim(); if (this.type == "number") { val = parseInt(val); } clearTimeout(debounce2); debounce2 = setTimeout(() => { chrome.storage.sync.set({ [this.id]: val }); }, 300); }); // 调试模式 使用网页标题做文件名 使用PotPlayer预览 显示网站图标 刷新自动清理 $("[save='click']").bind("click", function () { chrome.storage.sync.set({ [this.id]: $(this).prop('checked') }); }); // [save='select'] 元素 储存 $("[save='select']").on("change", function () { let val = $(this).val(); if (!isNaN(val)) { val = parseInt(val); } chrome.storage.sync.set({ [this.id]: val }); }); // 一键禁用/启用 $("#allDisable, #allEnable").bind("click", function () { const state = this.id == "allEnable"; const obj = $(this).data("switch"); let query; if (obj == "Ext") { query = $("#extList [name=state]"); } else if (obj == "Type") { query = $("#typeList [name=state]"); } else if (obj == "Regex") { query = $("#regexList [name=state]"); } else if (obj == "blockUrl") { query = $("#blockUrlList [name=state]"); } query.each(function () { $(this).prop("checked", state); }); Save(obj); }); // m3u8dlArg 输出测试 function testTag() { const data = { url: $("#url").val(), requestHeaders: { referer: $("#referer").val() }, initiator: $("#initiator").val(), webUrl: $("#webUrl").val(), title: $("#title").val(), } const result = templates($("#testTextarea").val() ?? "", data); const m3u8dl = 'm3u8dl:' + (G.m3u8dl == 1 ? Base64.encode(result) : result); $("#tagTestResult").html(`${result}

${m3u8dl}`); } $("#showTestTag").bind("click", function () { testTag(); $("#testTag").slideToggle(); }); $("#testTag input, #testTextarea").on("input", function () { testTag(); }); //重置后缀 重置类型 重置正则 $("[data-reset]").bind("click", function () { if (confirm(i18n.confirmReset)) { const Option = $(this).data("reset"); chrome.storage.sync.set({ [Option]: G.OptionLists[Option] }, () => { location.reload(); }); } }); //重置设置 $(".resetOption").click(function () { if (confirm(i18n.confirmReset)) { const optionBox = $(this).closest('.optionBox'); const result = optionBox.find('[save]').toArray().reduce((acc, { id }) => { acc[id] = G.OptionLists[id]; return acc; }, {}); chrome.storage.sync.set(result, () => { location.reload(); }); } }); //清空数据 重置所有设置 $("#ClearData, #ResetAllOption").bind("click", function () { if (this.id == "ResetAllOption") { if (confirm(i18n.confirmReset)) { chrome.storage.sync.clear(); InitOptions(); } else { return; } } chrome.storage.local.clear(); chrome.storage.session.clear(); chrome.runtime.sendMessage({ Message: "ClearIcon" }); location.reload(); }); //重启扩展 $("#extensionReload").bind("click", function () { chrome.runtime.reload(); }); //正则表达式 测试 $("#testRegex, #testUrl").keyup(function () { const testUrl = $("#testUrl").val(); const testRegex = $("#testRegex").val(); const testFlag = $("#testFlag").val(); if (testUrl == "" || testRegex == "") { $("#testResult").html(i18n.noMatch); return; } let regex; try { regex = new RegExp(testRegex, testFlag); } catch (e) { $("#testResult").html(e.message); return; } const result = regex.exec(testUrl); if (result == null) { $("#testResult").html(i18n.noMatch); return; } $("#testResult").html(i18n.match) for (let i = 1; i < result.length; i++) { if (result[i] != "") { $("#testResult").append( `` ); } } }); //导出配置 $("#exportOptions").bind("click", function () { chrome.storage.sync.get(null, function (items) { let ExportData = JSON.stringify(items); ExportData = "data:text/plain," + Base64.encode(ExportData); let date = new Date(); const filename = `cat-catch-${chrome.runtime.getManifest().version}-${date.getFullYear()}${appendZero(date.getMonth() + 1)}${appendZero(date.getDate())}T${appendZero(date.getHours())}${appendZero(date.getMinutes())}.txt`; if (G.isFirefox) { downloadDataURL(ExportData, filename); return; } chrome.downloads.download({ url: ExportData, filename: filename }); }); }); //导入配置 $("#importOptionsFile").change(function () { const fileReader = new FileReader(); fileReader.onload = function () { let importData = this.result; try { importData = JSON.parse(importData); } catch (e) { importData = Base64.decode(importData); importData = JSON.parse(importData); } const keys = Object.keys(G.OptionLists); for (let item in G.OptionLists) { if (keys.includes(item) && importData[item]) { chrome.storage.sync.set({ [item]: importData[item] }); } } alert("导入完成"); location.reload(); } const file = $("#importOptionsFile").prop('files')[0]; fileReader.readAsText(file); }); $("#importOptions").bind("click", function () { $("#importOptionsFile").click(); }); // 保存 后缀 类型 正则 配置 function Save(option, sec = 0) { clearTimeout(debounce); debounce = setTimeout(() => { if (option == "Ext") { let Ext = new Array(); $("#extList tr").each(function () { const _this = $(this); let GetText = _this.find("[name=text]").val(); let GetSize = parseInt(_this.find("[name=size]").val()); let GetState = _this.find("[name=state]").prop("checked"); if (isEmpty(GetText)) { return true; } if (isEmpty(GetSize)) { GetSize = 0; } Ext.push({ ext: GetText.toLowerCase(), size: GetSize, state: GetState }); }); chrome.storage.sync.set({ Ext: Ext }); return; } if (option == "Type") { let Type = new Array(); $("#typeList tr").each(function () { const _this = $(this); let GetText = _this.find("[name=text]").val(); let GetSize = parseInt(_this.find("[name=size]").val()); let GetState = _this.find("[name=state]").prop("checked"); if (isEmpty(GetText)) { return true; } if (isEmpty(GetSize)) { GetSize = 0; } GetText = GetText.trim(); const test = GetText.split("/"); if (test.length == 2 && !isEmpty(test[0]) && !isEmpty(test[1])) { Type.push({ type: GetText.toLowerCase(), size: GetSize, state: GetState }); } }); chrome.storage.sync.set({ Type: Type }); return; } if (option == "Regex") { let Regex = new Array(); $("#regexList tr").each(function () { const _this = $(this); let GetType = _this.find("[name=type]").val(); let GetRegex = _this.find("[name=regex]").val(); let GetExt = _this.find("[name=regexExt]").val() let GetState = _this.find("[name=state]").prop("checked"); let GetBlackList = _this.find("[name=blackList]").prop("checked"); try { new RegExp("", GetType); } catch (e) { GetType = "ig"; } if (isEmpty(GetRegex)) { return true; } GetExt = GetExt ? GetExt.toLowerCase() : ""; Regex.push({ type: GetType, regex: GetRegex, ext: GetExt, blackList: GetBlackList, state: GetState }); }); chrome.storage.sync.set({ Regex: Regex }); return; } if (option == "blockUrl") { let blockUrl = new Array(); $("#blockUrlList tr").each(function () { const _this = $(this); let url = _this.find("[name=url]").val(); let GetState = _this.find("[name=state]").prop("checked"); if (isEmpty(url)) { return true; } blockUrl.push({ url: url, state: GetState }); }); chrome.storage.sync.set({ blockUrl: blockUrl }); return; } }, sec); } // 导航栏 document.querySelectorAll('nav a').forEach(anchor => { anchor.addEventListener('click', function (e) { e.preventDefault(); const targetId = this.getAttribute('href'); const targetElement = document.querySelector(targetId); if (targetElement) { targetElement.scrollIntoView({ behavior: 'smooth' }); } }); }); const adjustSidebarPosition = () => { const wrapper = document.querySelector('.wrapper'); const sidebar = document.querySelector('.sidebar'); if (wrapper && sidebar) { sidebar.style.left = `${wrapper.getBoundingClientRect().left - sidebar.offsetWidth - 20}px`; } } window.addEventListener('load', adjustSidebarPosition) window.addEventListener('resize', adjustSidebarPosition);