// ==UserScript==
// @name SmartStrm助手 - 转存触发任务
// @namespace https://github.com/Cp0204/SmartStrm
// @license AGPL
// @icon https://raw.githubusercontent.com/Cp0204/SmartStrm/refs/heads/main/img/icon.svg
// @version 1.0
// @description 监听天翼云盘、夸克网盘和115网盘转存成功事件,根据转存路径触发 SmartStrm 任务
// @author Cp0204
// @match https://cloud.189.cn/web/share?code=*
// @match https://pan.quark.cn/s/*
// @match https://115cdn.com/s/*
// @grant GM_xmlhttpRequest
// @grant GM_setValue
// @grant GM_getValue
// @grant GM_registerMenuCommand
// @connect *
// ==/UserScript==
(function () {
'use strict';
// 设置webhook URL的函数
function setWebhookUrl() {
const inputUrl = prompt('请输入 SmartStrm Webhook 地址: ', GM_getValue('webhook', ''));
if (inputUrl !== null) {
GM_setValue('webhook', inputUrl);
alert('已保存 Webhook 地址: \n' + inputUrl + '\n\n如填错可在油猴菜单中重新设置');
}
}
// 注册菜单命令,用于设置webhook URL
GM_registerMenuCommand('设置Webhook地址', setWebhookUrl);
// 获取已保存的webhook URL
let webhook = GM_getValue('webhook', '');
// 如果没有设置webhook,则提示用户设置
if (!webhook) {
setWebhookUrl();
webhook = GM_getValue('webhook', '');
if (!webhook) {
return;
}
}
// 根据当前域名判断处理逻辑
if (window.location.hostname === 'cloud.189.cn') {
initCloud189();
} else if (window.location.hostname === 'pan.quark.cn') {
initQuark();
} else if (window.location.hostname === '115cdn.com') {
init115();
}
// 天翼云盘处理逻辑
function initCloud189() {
let saveSuccess = false;
const originalOpen = XMLHttpRequest.prototype.open;
const originalSend = XMLHttpRequest.prototype.send;
XMLHttpRequest.prototype.open = function (method, url, async, user, password) {
this._url = url;
originalOpen.apply(this, arguments);
};
XMLHttpRequest.prototype.send = function (body) {
this.addEventListener('load', function () {
try {
if (this._url.includes('api/open/batch/checkBatchTask.action')) {
const response = JSON.parse(this.responseText);
// taskStatus=4 任务成功
if (response.taskStatus === 4) {
saveSuccess = true;
console.log('检测到天翼云盘转存成功');
}
}
// 监听系统发出的 getLastSavePath.action 请求,但仅在转存成功后才处理
else if (this._url.includes('api/open/getLastSavePath.action') && saveSuccess) {
const response = JSON.parse(this.responseText);
if (response.code === 'success') {
const savepath = response.data.filePath;
sendWebhook(savepath, 'cloud189');
saveSuccess = false;
}
}
} catch (e) {
console.error('SmartStrm助手解析响应出错:', e);
}
});
originalSend.apply(this, arguments);
};
}
// 夸克网盘处理逻辑
function initQuark() {
const originalOpen = XMLHttpRequest.prototype.open;
const originalSend = XMLHttpRequest.prototype.send;
XMLHttpRequest.prototype.open = function (method, url, async, user, password) {
this._url = url;
originalOpen.apply(this, arguments);
};
XMLHttpRequest.prototype.send = function (body) {
this.addEventListener('load', function () {
try {
if (this._url.includes('drive-pc.quark.cn/1/clouddrive/task')) {
const response = JSON.parse(this.responseText);
// status=2 任务成功
if (response.data && response.data.status === 2) {
console.log('检测到夸克网盘转存成功');
let pathElement = document.querySelector('.path-name');
const savepath = pathElement ? pathElement.title.replace('全部文件', '').trim() : "";
sendWebhook(savepath, 'quark');
}
}
} catch (e) {
console.error('SmartStrm助手解析响应出错:', e);
}
});
originalSend.apply(this, arguments);
};
}
// 115网盘处理逻辑
function init115() {
const originalOpen = XMLHttpRequest.prototype.open;
const originalSend = XMLHttpRequest.prototype.send;
XMLHttpRequest.prototype.open = function (method, url, async, user, password) {
this._url = url;
originalOpen.apply(this, arguments);
};
XMLHttpRequest.prototype.send = function (body) {
this.addEventListener('load', function () {
try {
if (this._url.includes('webapi/share/receive')) {
const response = JSON.parse(this.responseText);
// state=true 任务成功
if (response.state === true) {
const cid = localStorage.getItem('SEL_F_DIR').split('|')[1];
GM_xmlhttpRequest({
method: 'GET',
url: `https://115cdn.com/webapi/files?aid=1&cid=${cid}&max_size=&offset=0&limit=50&show_dir=1&nf=1&qid=0&natsort=1&source=&format=json&type=`,
onload: function (response) {
try {
const data = JSON.parse(response.responseText);
if (data.errNo == 20130827) {
console.error('获取115网盘保存路径失败', '堆屎山的 115 API');
return;
} else if (data.errNo != 0) {
console.error('获取115网盘保存路径失败', response.responseText);
return;
}
// console.log('获取115网盘保存路径成功', response.responseText);
let savepath = '';
if (data.path && data.path.length > 1) {
// 构建路径,从第二个元素开始(第一个是根目录)
for (let i = 1; i < data.path.length; i++) {
savepath += '/' + data.path[i].name;
}
console.log('保存路径:', savepath);
sendWebhook(savepath, 'open115');
}
} catch (e) {
console.error('解析115网盘路径出错:', e);
}
},
onerror: function (error) {
console.error('获取115网盘路径失败:', error);
}
});
}
}
} catch (e) {
console.error('SmartStrm助手解析响应出错:', e);
}
});
originalSend.apply(this, arguments);
};
}
// 发送webhook通知
function sendWebhook(savepath, driver) {
const webhook = GM_getValue('webhook', '');
if (!webhook) {
console.error('Webhook地址未设置');
return;
}
GM_xmlhttpRequest({
method: 'POST',
url: webhook,
headers: {
'Content-Type': 'application/json'
},
data: JSON.stringify({
event: 'web_save',
data: {
driver: driver,
savepath: savepath
},
}),
onload: function (response) {
const data = JSON.parse(response.responseText);
if (data.success) {
console.log('Webhook发送成功:', data.message, data.task);
} else {
console.error('Webhook发送成功,但触发失败:', data.message);
}
},
onerror: function (error) {
console.error('Webhook发送失败:', error);
}
});
}
console.log('SmartStrm助手已启动');
})();