Greasy Fork

来自缓存

Greasy Fork is available in English.

U2显示文件校验和

为文件列表添加校验和信息

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==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/[email protected]/dist/xhook.min.js
// @require      https://cdnjs.cloudflare.com/ajax/libs/localforage/1.10.0/localforage.min.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 = $('<div></div>').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(`<style>.checksum { 
                    font-family: ui-monospace,SFMono-Regular,SF Mono,Menlo,Consolas,Liberation Mono,monospace;
                    text-align: center;
                    color: rgb(128, 128, 128);
                    border-left: none;
                    border-right: none;
                }</style>`);
                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(`<td class="rowfollow checksum">&nbsp;${hash}&nbsp;</td>`)
                });
            }
            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=(?<tid>\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(`<span id="checksum">[校验和获取失败]</a></span>`);
        return;
    }

    if (torrent_checksum.length !== 0) {
        $("#closeall").after(`<span id="checksum"><a href="javascript:void(0)">[复制校验和]</a></span>`);

        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(`<span id="checksum">[无校验和信息]</a></span>`);
    }

    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(`<tr><td style="border: none;" colspan="4"><b>文件校验和:</b>&nbsp;${checksum}</td></tr>`);
        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];
};