This commit is contained in:
ChuXun
2025-10-19 20:55:27 +08:00
parent e879ccefb3
commit 53f9554f38
99 changed files with 22308 additions and 2 deletions

232
js/pupup-utils.js Normal file
View File

@@ -0,0 +1,232 @@
// 复制选项
function copyLink(data) {
let text = data.url;
if (data.parsing == "m3u8") {
text = G.copyM3U8;
} else if (data.parsing == "mpd") {
text = G.copyMPD;
} else {
text = G.copyOther;
}
return templates(text, data);
}
function isM3U8(data) {
return (
data.ext == "m3u8" ||
data.ext == "m3u" ||
data.type?.endsWith("/vnd.apple.mpegurl") ||
data.type?.endsWith("/x-mpegurl") ||
data.type?.endsWith("/mpegurl") ||
data.type?.endsWith("/octet-stream-m3u8")
)
}
function isMPD(data) {
return (data.ext == "mpd" ||
data.type == "application/dash+xml"
)
}
function isJSON(data) {
return (data.ext == "json" ||
data.type == "application/json" ||
data.type == "text/json"
)
}
function isPicture(data) {
return (data.type?.startsWith("image/") ||
data.ext == "jpg" ||
data.ext == "png" ||
data.ext == "jpeg" ||
data.ext == "bmp" ||
data.ext == "gif" ||
data.ext == "webp" ||
data.ext == "svg"
)
}
function isMediaExt(ext) {
return ['ogg', 'ogv', 'mp4', 'webm', 'mp3', 'wav', 'm4a', '3gp', 'mpeg', 'mov', 'm4s', 'aac'].includes(ext);
}
function isMedia(data) {
return isMediaExt(data.ext) || data.type?.startsWith("video/") || data.type?.startsWith("audio/");
}
/**
* ari2a RPC发送一套资源
* @param {object} data 资源对象
* @param {Function} success 成功运行函数
* @param {Function} error 失败运行函数
*/
function aria2AddUri(data, success, error) {
const json = {
"jsonrpc": "2.0",
"id": "cat-catch-" + data.requestId,
"method": "aria2.addUri",
"params": []
};
if (G.aria2RpcToken) {
json.params.push(`token:${G.aria2RpcToken}`);
}
const params = { out: data.downFileName };
if (G.enableAria2RpcReferer) {
params.header = [];
params.header.push(G.userAgent ? G.userAgent : navigator.userAgent);
if (data.requestHeaders?.referer) {
params.header.push("Referer: " + data.requestHeaders.referer);
}
if (data.cookie) {
params.header.push("Cookie: " + data.cookie);
}
if (data.requestHeaders?.authorization) {
params.header.push("Authorization: " + data.requestHeaders.authorization);
}
}
json.params.push([data.url], params);
fetch(G.aria2Rpc, {
method: "POST",
headers: {
"Content-Type": "application/json; charset=utf-8"
},
body: JSON.stringify(json)
}).then(response => {
return response.json();
}).then(data => {
success && success(data);
}).catch(errMsg => {
error && error(errMsg);
});
}
// MQTT 相关功能
/**
* 发送数据到 MQTT 服务器
* @param {Object} data - 要发送的媒体数据
* @returns {Promise} - 返回发送结果的 Promise
*/
function sendToMQTT(data, config) {
return new Promise((resolve, reject) => {
if (!G.mqttEnable) {
reject("MQTT is not enabled");
return;
}
// 使用配置的标题长度如果未设置则默认为100
const titleLength = G.mqttTitleLength || 100;
data.title = data.title.slice(0, titleLength) || "";
data.action = "media_found";
data = trimData(data);
// 创建 MQTT 连接并发送数据
connectAndSendMQTT(data, config)
.then(() => {
resolve(true);
})
.catch((error) => {
console.error("MQTT send error:", error);
reject("MQTT send failed: " + error.message);
});
});
}
/**
* 连接到 MQTT 服务器并发送消息
* @param {Object} data - 要发送的数据
* @returns {Promise} - 连接和发送的 Promise
*/
function connectAndSendMQTT(data, config) {
return new Promise((resolve, reject) => {
try {
// 构建 MQTT 连接 URL
const protocol = G.mqttProtocol;
const broker = G.mqttBroker;
const port = G.mqttPort;
const path = G.mqttPath;
if (!protocol || !broker || !port || !path) {
throw new Error("MQTT connection parameters are missing");
}
const mqttUrl = `${protocol}://${broker}:${port}${path}`;
// 创建 MQTT 客户端选项
const options = {
clientId: `${G.mqttClientId || "cat-catch-client"}-${Math.random().toString(16).slice(2)}`,
clean: true,
connectTimeout: 10000,
reconnectPeriod: 0 // 不自动重连,用完即断
};
// 添加用户名和密码(如果有)
if (G.mqttUser) {
options.username = G.mqttUser;
}
if (G.mqttPassword) {
options.password = G.mqttPassword;
}
const mqttLib = window.mqtt || (typeof mqtt !== 'undefined' ? mqtt : null);
if (!mqttLib) {
throw new Error("MQTT library not found. Please check if lib/mqtt.min.js is loaded correctly.");
}
if (!mqttLib.connect) {
throw new Error("MQTT.connect method not found. Available methods: " + Object.keys(mqttLib));
}
// 如果提供了提示回调函数,则使用它
if (typeof config?.alert === 'function') {
Tips = config.alert;
}
// 2. 创建连接阶段提示:正在连接 MQTT 服务器
Tips(i18n.connectingToMQTT || "Connecting to MQTT server...", 2000);
const client = mqttLib.connect(mqttUrl, options);
// 连接成功
client.on('connect', () => {
const topic = G.mqttTopic || "cat-catch/media";
const qos = parseInt(G.mqttQos) || 2;
// 处理自定义数据格式
let message;
if (G.mqttDataFormat?.trim()) {
message = templates(G.mqttDataFormat, data);
} else {
// 使用默认JSON格式
message = JSON.stringify(data);
}
// 3. 正在发送消息到 MQTT 服务器
Tips(i18n.sendingMessageToMQTT || "Sending message to MQTT server...", 2000);
// 发送消息
client.publish(topic, message, { qos: qos }, (error) => {
if (error) {
console.error("MQTT publish error:", error);
reject(error);
} else {
resolve();
}
});
});
// 连接错误
client.on('error', (error) => {
console.error("MQTT connection error:", error);
reject(error);
});
// 连接超时
setTimeout(() => {
if (!client.connected) {
client.end();
reject(new Error("MQTT connection timeout"));
}
}, 6000);
// client.on('close', () => {
// console.log('MQTT connection closed');
// });
} catch (error) {
console.error("MQTT setup error:", error);
reject(error);
}
});
}