// ==UserScript==
// @name U2显示文件校验和
// @namespace U2显示文件校验和
// @version 0.0.4
// @description 为文件列表添加校验和信息
// @author kysdm
// @match *://u2.dmhy.org/details.php?id=*
// @grant none
// @license MIT
// @icon https://u2.dmhy.org/favicon.ico
// @require https://unpkg.com/xhook@1.6.2/dist/xhook.min.js
// @require https://cdnjs.cloudflare.com/ajax/libs/localforage/1.10.0/localforage.min.js
// @downloadURL https://update.greasyfork.icu/scripts/495220/U2%E6%98%BE%E7%A4%BA%E6%96%87%E4%BB%B6%E6%A0%A1%E9%AA%8C%E5%92%8C.user.js
// @updateURL https://update.greasyfork.icu/scripts/495220/U2%E6%98%BE%E7%A4%BA%E6%96%87%E4%BB%B6%E6%A0%A1%E9%AA%8C%E5%92%8C.meta.js
// ==/UserScript==
(async () => {
'use strict';
xhook.before(async (request, callback) => {
if (request.url.match(/viewfilelist\.php\?id=\d+/)) { await checkTorrentChecksum(); }
callback();
})
xhook.after(function (request, response) {
if (request.url.match(/viewfilelist\.php\?id=\d+/)) {
if (torrent_checksum === 'null') return;
const resp = response.text;
const doc = $('
').html(resp);
const f_ids = doc.find('[id^=f_id_]');
const f_obj = new Object();
const f_tmp = [];
let f_id = '';
f_ids.each(function () {
const f_name = $(this).find('td').first().text();
const f_name_trim = f_name.trimStart();
const leadingSpaceCount = countLeadingSpaces(f_name);
const _depth = leadingSpaceCount / 4;
const f_depth = f_tmp.length - 1;
if (_depth === f_depth + 1) {
// root
} else if (_depth === f_depth) {
if (f_tmp.length !== 0) f_obj[f_tmp.join('/')] = f_id;
f_tmp.pop();
} else {
f_obj[f_tmp.join('/')] = f_id;
f_tmp.splice(-(f_depth - _depth + 1));
}
f_tmp.push(f_name_trim);
f_id = $(this).attr("id");
});
f_obj[f_tmp.join('/')] = f_id;
if (torrent_checksum.length !== 0) {
doc.append(``);
doc.find("td.rowfollow.dir_size").attr("colspan", "2");
doc.find("tr:first").find("td.colhead:last").attr("colspan", "2");
torrent_checksum[0].torrent_files_info.files.forEach(function (item) {
const path = item.path.split("/").slice(1).join("/");
const hash = item.hash;
const f_id = f_obj[path];
const td2 = doc.find(`#${f_id}`).find('td:last');
td2.css({ "border-left": "none" });
td2.before(` ${hash} | `)
});
}
response.text = doc.html();
}
})
var checkTorrentChecksumPromise, uid, tid, torrent_checksum;
function checkTorrentChecksum() {
return new Promise((resolve, reject) => {
if (typeof torrent_checksum !== 'undefined') { resolve(); } else { checkTorrentChecksumPromise = resolve; }
});
}
function assignTorrentChecksum() {
if (checkTorrentChecksumPromise) checkTorrentChecksumPromise();
}
let em = /.*id=(?\d{3,5})/i.exec(location.search); if (em) tid = em.groups.tid; else tid = null; // 当前种子ID
uid = $('#info_block').find('a:first').attr('href').match(/\.php\?id=(\d{3,5})/i) || ['', '']; if (uid[1] !== '') uid = uid[1]; // 当前用户ID
const lang = new lang_init($('#locale_selection').val()); // 获取当前网页语言
const db = localforage.createInstance({ name: "history" });
const token = await db.getItem('token');
if (token === null || token.length !== 96) { window.alert('未找到有效 API Token,将无法使用此脚本。') };
torrent_checksum = await getApi(uid, token, tid);
assignTorrentChecksum();
if (torrent_checksum === 'null') {
$("#closeall").after(`[校验和获取失败]`);
return;
}
if (torrent_checksum.length !== 0) {
$("#closeall").after(`[复制校验和]`);
const __checksum = [];
torrent_checksum[0].torrent_files_info.files.forEach(function (item) { __checksum.push(`${item.hash} *${item.path}`); });
$("#checksum").click(function () {
navigator.clipboard.writeText(__checksum.join('\n')).then(() => {
window.alert('成功')
}).catch(() => {
window.alert('失败 - 可能是你的浏览器太古老了')
});
});
} else {
$("#closeall").after(`[无校验和信息]`);
}
if ($('#showfl').length === 0) {
// 单文件种子
const checksum = torrent_checksum.length !== 0 ? torrent_checksum[0].torrent_files_info.files[0].hash : '---';
$(`td[class='rowhead nowrap']:contains('${lang['torrent_info']}')`).next('td').find('tr:first')
.after(`文件校验和: ${checksum} |
`);
return;
}
})();
async function getApi(uid, token, tid) {
return new Promise(async (resolve) => {
$.ajax({
type: 'post',
url: 'https://u2.kysdm.com/api/v1/torrent_checksum/',
contentType: "application/json",
dataType: 'json',
data: JSON.stringify({ "uid": uid, "token": token, "torrent_id": tid }),
success: async function (d) {
if (d.msg === 'success') {
return resolve(d.data.torrent);
} else {
window.alert('checksum 获取失败')
return resolve('null');
};
},
error: async function (d) {
window.alert('checksum 获取失败')
return resolve('null');
},
})
})
};
function countLeadingSpaces(s) {
return s.length - s.trimStart().length;
}
function lang_init(lang) {
const lang_json = {
"zh_CN": {
"torrent_info": "种子信息",
},
"zh_TW": {
"torrent_info": "種子訊息",
},
"zh_HK": {
"torrent_info": "種子訊息",
},
"en_US": {
"torrent_info": "Torrent Info",
},
"ru_RU": {
"torrent_info": "Информация о торренте",
}
};
return lang_json[lang];
};