////////////////////// 填充数据 //////////////////////
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);