您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
查看种子历史记录
当前为
// ==UserScript== // @name U2历史记录 // @namespace https://u2.dmhy.org/ // @version 0.3.3 // @description 查看种子历史记录 // @author kysdm // @grant none // @match *://u2.dmhy.org/details.php?id=* // @match *://u2.dmhy.org/offers.php?id=* // @match *://u2.dmhy.org/forums.php?action=viewtopic* // @icon https://u2.dmhy.org/favicon.ico // @require https://cdnjs.cloudflare.com/ajax/libs/localforage/1.10.0/localforage.min.js // @require https://unpkg.com/[email protected]/thenBy.min.js // @license Apache-2.0 // ==/UserScript== /* 本脚本基于 Bamboo Green 界面风格进行修改 /* /* GreasyFork 地址 https://greasyfork.org/zh-CN/scripts/428545 */ /* 使用说明 https://u2.dmhy.org/forums.php?action=viewtopic&topicid=13495&page=p150133#pid150133 */ /* 更新日志 https://github.com/kysdm/u2_share/commits/main/u2share_history.user.js */ // 声明全局变量 var lang, torrent_id, db, user_id, topicid, key, token; (async () => { 'use strict'; // 初始化 lang = new lang_init($('#locale_selection').val()); // 获取当前网页语言 torrent_id = location.href.match(/\.php\?id=(\d{3,5})/i) || ['', '']; if (torrent_id[1] !== '') torrent_id = torrent_id[1]; // 当前种子ID topicid = location.href.match(/topicid=(\d+)/i) || ['', '']; if (topicid[1] !== '') topicid = topicid[1]; user_id = $('#info_block').find('a:first').attr('href').match(/\.php\?id=(\d{3,5})/i) || ['', '']; if (user_id[1] !== '') user_id = user_id[1]; // 当前用户ID db = localforage.createInstance({ name: "history" }); key = await db.getItem('key'); token = await db.getItem('token'); if (token === null || token.length !== 96) { new auth(key); return; }; if (/\/(offers|details)\.php\?id=\d{3,5}/i.test(location.href) && $('#outer').find('h2').text().match(/错误|錯誤|Ошибка|error/i)) { torrentInfoHistoryReset(); torrentCommentHistoryReset(); }// 为已经删除的种子显示历史 else if (/\/(offers|details)\.php\?id=\d{3,5}/i.test(location.href) && !/(cmtpage|offer_vote|vote)=(1|p)/i.test(location.href)) { torrentInfoHistory(); torrentCommentHistory(); } // 为正常种子显示历史 else if (/\/(offers|details)\.php\?id=\d{3,5}/i.test(location.href) && /cmtpage=1/i.test(location.href)) { torrentCommentHistory(); } // 为正常种子显示历史 <仅评论> else if (/\/forums\.php\?action=viewtopic/i.test(location.href) && $('#outer').find('h2').text().match(/错误|錯誤|Ошибка|error/i)) { forumCommentHistoryReset(); } // 为被删除的论坛帖子显示历史 else if (/\/forums\.php\?action=viewtopic/i.test(location.href)) { forumCommentHistory(); }; // 为论坛帖子显示历史 })(); function auth() { 'use strict'; $('#outer').html(`<h1 align="center">U2种子历史记录 自动鉴权工具</h1> <table border="0" align="center" cellspacing="0" cellpadding="5"> <tbody> <tr> <td valign="top" width="500" align="center"><span style="word-break: break-all; word-wrap: break-word;"> <bdo dir="ltr">点击开始按钮,将自动进行鉴权,提示完成请刷新界面。<br>(建议手动备份下个人说明)<br></bdo></span></td> </tr> <tr> <td valign="top" align="left"><span style="word-break: break-all; word-wrap: break-word;"> <bdo id="auth_log" dir="ltr"></bdo></span></td> </tr> <tr> <td align="center"> <button id="auth_token" class="codebuttons" style="font-size:11px;margin-right:3px;" type="button">开始鉴权</button> <button id="auth_token_d" class="codebuttons" style="font-size:11px;margin-right:3px;" type="button">已有TOKEN</button> </td> </tr> </tbody> </table>`); $("#auth_token_d").click(async function () { let __token = window.prompt("请输入Token"); // 弹窗提示输入Token if (__token === null || __token.length === 0) return; // 没有任何输入时 无视本次操作 else if (__token.length !== 96) { await outPutLog(`Token: ${__token}`); await outPutLog(`Token长度不正确`); return; } // TOKEN长度不正确时 无视本次操作 else { await db.setItem('token', __token); await outPutLog(`Token: ${__token}`); await outPutLog('鉴权结束'); }; }); function getProfile() { return new Promise(async (resolve, reject) => { $.ajax({ type: 'get', url: 'https://u2.dmhy.org/usercp.php?action=personal', cache: false, success: async r => { const usercp = $.parseHTML(r) // const profile = $(usercp).find('[name="info"]').text(); // 获取用户信息 const profile = { "action": "personal", "type": "save", "acceptpms": $(usercp).find('[name="acceptpms"]:checked').val(), // 接受以下短讯 // 如果不需要开启对应功能,则不发送该参数 "deletepms": $(usercp).find('[name="deletepms"]').is(':checked') ? 'on' : '', // 回复后删除短讯 "savepms": $(usercp).find('[name="savepms"]').is(':checked') ? 'on' : '', // 保存短讯至发件箱 "commentpm": $(usercp).find('[name="commentpm"]').is(':checked') ? 'yes' : '', // 我发布的种子有新评论时通知我 "atpm": $(usercp).find('[name="atpm"]').is(':checked') ? '1' : '',// 有人在群聊区@我时通知 "quotepm": $(usercp).find('[name="quotepm"]').is(':checked') ? '1' : '',// 有人在论坛、种子评论或候选评论引用我时通知。 // 如果不需要开启对应功能,则不发送该参数 "country": $(usercp).find('[name="country"]').val(), // 国家/地区 "download": $(usercp).find('[name="download"]').val(),// 下行带宽 "upload": $(usercp).find('[name="upload"]').val(),// 上行带宽 "isp": $(usercp).find('[name="isp"]').val(),// 互联网服务提供商 "savatar": $(usercp).find('[name="savatar"]').val(), // 选择头像 "avatar": $(usercp).find('[name="avatar"]').val(), // 自定义头像 "info": $(usercp).find('[name="info"]').text() // 个人说明 }; let profileAuth = { ...profile }; // 复制 profileAuth.info = `-----BEGIN API KEY-----\n${key}\n-----END API KEY-----\n\n${profile.info}`; // 在个人说明加入鉴权信息 const p = profileAuth.info.replace(/\r\n/g, () => { return '<br>' }).replace(/\n/g, () => { return '<br>' }).replace(/\r/g, () => { return '<br>' }); await outPutLog(`请检查准备写入个人说明的BBCODE是否正确<br><br><table class="spoiler" width="100%"> <tbody> <tr> <td class="colhead">个人说明 <button class="spoiler-button-show" style="">检查一下</button> <button id="auth_profile_check" class="spoiler-button-hide" style="display: none;">检查完成</button></td> </tr> <tr> <td><span class="spoiler-content" style="display: none;">${p}</span></td> </tr> </tbody> </table>`); await db.setItem('profile', profile); // 存储用户信息 $("#auth_profile_check").click(async function (ev) { $(this).hide(); $(this).siblings(".spoiler-button-show").show(); $(this).parentsUntil(".spoiler").find("span.spoiler-content:first").hide(); ev.preventDefault(); return resolve(profileAuth); }); }, error: async d => { await outPutLog('获取个人说明BBCODE失败'); await outPutLog(`错误信息: ${d.responseText}`); return reject(Error(d.responseText)); }, }); }); }; function postProfile(data) { return new Promise(async (resolve, reject) => { $.ajax({ type: 'post', url: 'https://u2.dmhy.org/usercp.php', cache: false, contentType: "application/x-www-form-urlencoded", data: data, success: async r => { await outPutLog('修改个人说明BBCODE成功'); return resolve(key); }, error: async d => { await outPutLog('修改个人说明BBCODE失败'); await outPutLog(`错误信息: ${d.responseText}`); return reject(Error(d.responseText)); }, }); }); }; function getAuthKey() { return new Promise(async (resolve, reject) => { $.ajax({ type: 'post', url: 'https://u2.kysdm.com/api/v1/token', contentType: "application/json", dataType: 'json', // async: false, data: JSON.stringify({ "uid": user_id }), success: async function (d) { if (d.msg === 'success') { key = d.data.key db.setItem('key', key); await outPutLog('获取Key成功'); await outPutLog(`Key: ${key}`); return resolve(key); } else { await outPutLog('获取Key失败'); await outPutLog(`错误信息: ${JSON.stringify(d)}`); return reject(Error('获取Key失败')); }; }, error: async function (d) { await outPutLog('获取Key失败'); await outPutLog(`错误信息: ${d.responseText}`); return reject(Error('获取Key失败')); }, }); }); }; function getToken() { return new Promise(async (resolve, reject) => { $.ajax({ type: 'post', url: 'https://u2.kysdm.com/api/v1/token', contentType: "application/json", dataType: 'json', data: JSON.stringify({ "uid": user_id, "key": key }), success: async function (d) { if (d.msg === 'success') { let __token = d.data.token await outPutLog('获取Token成功'); await outPutLog(`Token: ${__token}`); await db.setItem('token', __token); return resolve(__token); } else { await outPutLog('获取Token失败'); await outPutLog(`错误信息: ${JSON.stringify(d)}`); return reject(Error('获取Token失败')); }; }, error: async function (d) { await outPutLog('获取Token失败'); await outPutLog(`错误信息: ${d.responseText}`); return reject(Error('获取Token失败')); }, }); }); }; function outPutLog(text) { return new Promise(async (resolve, reject) => { const log = $('#auth_log').html(); $('#auth_log').html(`${log}${getDateString()} - ${text}<br>`); resolve(await sleep(0)); }); }; async function sleep(interval) { return new Promise(resolve => { setTimeout(resolve, interval); }) }; $("#auth_token").click(async function () { await outPutLog('鉴权开始'); await outPutLog('获取鉴权所需的Key'); getAuthKey() .then(async () => { await outPutLog('获取个人说明BBCODE'); return getProfile(); }) .then(async data => { await outPutLog('修改个人说明BBCODE'); await postProfile(data); }) .then(async () => { await outPutLog('获取鉴权所需的Token'); await getToken(); }) .then(async () => { await outPutLog('还原个人说明BBCODE'); await postProfile(await db.getItem('profile')); }) .catch(async err => { await outPutLog(err); }) .finally(async () => { await outPutLog('鉴权结束'); }); }); }; async function forumCommentHistoryReset() { 'use strict'; const errorstr = $('#outer').find('td.text').text(); // 正在努力加载中... $('#outer').find('td.text').html(errorstr + ' <i>' + lang['history_text_loading'] + '</i>'); $.ajax({ type: 'post', url: 'https://u2.kysdm.com/api/v1/comment', contentType: "application/json", dataType: 'json', data: JSON.stringify({ "uid": user_id, "token": token, "topicid": topicid, "type": "forum" }), success: function (d) { if (d.msg === 'success') { console.log('获取论坛评论成功'); let __comment = d.data.comment[topicid].sort(firstBy((a, b) => a.pid - b.pid).thenBy((a, b) => b.self - a.self)); // 如果用self排序,消息顺序不正确,则改用编辑日期排序 if (__comment.length === 0) { // 没有评论 可以说不会出现这种情况 console.log('没有历史记录.'); $('#outer').find('td.text').html(errorstr + ' ' + lang['history_text_empty'] + '</i>'); return; }; // 计算pid出现次数 let pidList = __comment.map(x => x.pid); let counts = new Object(); pidList.forEach(x => counts[x] = counts[x] ? counts[x] + 1 : 1); const pidListSet = [...new Set(pidList)]; // 去重 // 还原网页 $('#outer').html(` <table class="main" width="940" border="0" cellspacing="0" cellpadding="0"> <tbody> <tr> <td class="embedded" align="center"> <h1 align="center"><span id="top"></span></h1><br><br> </td> </tr> </tbody> </table> <table class="main" width="940" border="0" cellspacing="0" cellpadding="0"> <tbody> <tr> <td class="embedded"> <table width="100%" border="1" cellspacing="0" cellpadding="10"> <tbody> <tr> <td id="comments" class="text"> </td> </tr> </tbody> </table> </td> </tr> </tbody> </table>` ); // 还原标题 $('span[id="top"]').html(__comment[0]['topics']); __comment.forEach(x => { const bbcode_html = `<div style="margin-top: 8pt; margin-bottom: 8pt;"> <table id="pid${x.pid}" border="0" cellspacing="0" cellpadding="0" width="100%"> <tbody> <tr> <td class="embedded" width="99%"> <a href="forums.php?action=viewtopic&${x.topicid}=14068&page=p${x.pid}#pid${x.pid}">#${x.pid}</a> <!-- 论坛应该不能匿名发帖吧 --> <span class="nowrap"><a href="userdetails.php?id=${x.userid}"><b> <bdo dir="ltr">${x.username}</bdo></b></a></span> <time>${x.edit_time.replace('T', ' ')}</time> </td> <td class="embedded nowrap" width="1%"> <font class="big">#<b>${pidListSet.findIndex((a) => a == x.pid) + 1}</b> 楼 </font> <a href="#top"><img class="top" src="pic/trans.gif" alt="Top" title="${lang['back_to_top']}"></a> </td> </tr> </tbody> </table> </div> <table class="main-inner" border="1" cellspacing="0" cellpadding="5"> <tbody> <tr> <td class="rowfollow" width="150" valign="top" align="left" style="padding: 0px"> <img src="//u2.dmhy.org/pic/default_avatar.png" alt="avatar" width="150px"> </td> <td class="rowfollow" valign="top"><br> <div class="post-body" id="pid${x.pid}body"> <span style="word-break: break-all; word-wrap: break-word;"><bdo dir="ltr"> ${(() => { if (x.action === 'edit') { return `${bbcode2html(x.bbcode)}</bdo></span> ${(() => { if ($('#locale_selection').val() === 'en_US') return `<p class="small">${lang['last_edited']} <span class="nowrap"><a href="userdetails.php?id=${x.user_id}"><b><bdo dir="ltr">${x.username}</bdo></b></a></span> at <time>${x.edit_time.replace('T', ' ')}</time>.</p><br><br>`; else if ($('#locale_selection').val() === 'ru_RU') return `<p class="small">${lang['last_edited']} <span class="nowrap"><a href="userdetails.php?id=${x.user_id}"><b><bdo dir="ltr">${x.username}</bdo></b></a></span> в <time>${x.edit_time.replace('T', ' ')}</time>.</p><br><br>`; else return `<p class="small">[<time>${x.edit_time.replace('T', ' ')}</time>] <span class="nowrap"><a href="userdetails.php?id=${x.user_id}"><b><bdo dir="ltr">${x.username}</bdo></b></a></span> ${lang['last_edited']} </p><br><br>`; })()}`; } else { return `${bbcode2html(x.bbcode)}<br><br></bdo></span>`; }; })()} </div> </td> </tr> </tbody> </table>` if (counts[x.pid] > 1) { console.log('有编辑记录 直接添加下拉菜单'); // 插入下拉菜单基本框架 if ($(`#history_comment${x.pid}_select`).length === 0) { $('#comments').append(bbcode_html); // 先插入整体框架 console.log('添加下拉菜单基本框架'); $(`[id="pid${x.pid}"]`).find('[class="embedded nowrap"]').before(` <div id="hsty" style="position: relative;"> <div id="history_comment" style="position: absolute; right:10px; margin-top: 0px;"> <select name="type" id="history_comment${x.pid}_select"> </div> /div>` ); }; // 向下拉菜单写入信息 $(`#history_comment${x.pid}_select`).append(`<option value="${x.self}">${x.edit_time.replace('T', ' ')} ${(() => { return x.action === 'edit' ? ' E' : x.action === 'reply' ? ' R' : ' N' })()} ${(() => { return x.username === null && x.userid === null ? lang['anonymous_user'] : ` ${x.username}(${x.userid})` })()} </option>`) } else { $('#comments').append(bbcode_html); }; }); $("[id^=history_comment]").change(function () { // 监听菜单选择 let self = $(this).val(); for (let i = 0, len = __comment.length; i < len; i++) { if (self != __comment[i].self) continue; let html; let x = __comment[i]; if (x.action === 'edit') { html = `<span style="word-break: break-all; word-wrap: break-word;"><bdo dir="ltr">${bbcode2html(x.bbcode)}</bdo></span> ${(() => { if ($('#locale_selection').val() === 'en_US') return `<p><font class="small">${lang['last_edited']} <span class="nowrap"><a href="userdetails.php?id=${x.user_id}"><b><bdo dir="ltr">${x.username}</bdo></b></a></span> at <time>${x.edit_time.replace('T', ' ')}</time>.</font></p>`; else if ($('#locale_selection').val() === 'ru_RU') return `<p><font class="small">${lang['last_edited']} <span class="nowrap"><a href="userdetails.php?id=${x.user_id}"><b><bdo dir="ltr">${x.username}</bdo></b></a></span> в <time>${x.edit_time.replace('T', ' ')}</time>.</font></p>`; else return `<br><p><font class="small">[<time>${x.edit_time.replace('T', ' ')}</time>] <span class="nowrap"><a href="userdetails.php?id=${x.user_id}"><b><bdo dir="ltr">${x.username}</bdo></b></a></span> ${lang['last_edited']} </font></p>`; })()}`; } else { html = `<span style="word-break: break-all; word-wrap: break-word;"><bdo dir="ltr">${bbcode2html(x.bbcode)}</bdo></span>`; }; $(this).parents('[id^=pid]').parent().next().find('.post-body').html(html); return; }; }); } else { console.log('获取论坛评论错误'); $('#outer').find('td.text').html(`${errorstr} <i>${lang['history_text_error']} <a id="apifailure" href="javascript:void(0);" style="color:#FF1212">${lang['reset_token']}</a></i>`); $("#apifailure").click(function () { let confirm = prompt("输入 YES 确认本次操作 (大写)"); if (confirm === 'YES') { db.removeItem('key'); db.removeItem('token'); alert("成功"); }; }); }; }, error: function (d) { }, }); }; async function forumCommentHistory() { 'use strict'; $.ajax({ type: 'post', url: 'https://u2.kysdm.com/api/v1/comment', contentType: "application/json", dataType: 'json', data: JSON.stringify({ "uid": user_id, "token": token, "topicid": topicid, "type": "forum" }), success: function (d) { if (d.msg === 'success') { console.log('获取论坛评论成功'); let __comment = d.data.comment[topicid].sort((a, b) => b.self - a.self); let pidList = __comment.map(x => x.pid); let counts = new Object(); pidList.forEach(x => counts[x] = counts[x] ? counts[x] + 1 : 1) $('[id^="pid"]').each(function () { let pid = $(this).find('[class="embedded"]').children('a').first().text().replace('#', ''); __comment.forEach(x => { if (x.pid == pid && counts[pid] > 1) { if ($(`#history_comment${pid}_select`).length === 0) $(this).find('[class="embedded nowrap"]').before(`<div id="hsty" style="position: relative;"><div id="history_comment" style="position: absolute; right:10px; margin-top: 1px;"><select name="type" id="history_comment${pid}_select"></div></div>`); $(`#history_comment${pid}_select`).append(`<option value="${x.self}">${x.edit_time.replace('T', ' ')} ${(() => { return x.action === 'edit' ? ' E' : x.action === 'reply' ? ' R' : ' N' })()} ${(() => { return x.username === null && x.userid === null ? lang['anonymous_user'] : ` ${x.username}(${x.userid})` })()} </option>`); }; }); }); $("[id^=history_comment]").change(function () { // 监听菜单选择 let self = $(this).val(); for (let i = 0, len = __comment.length; i < len; i++) { if (self != __comment[i].self) continue; let html; let x = __comment[i]; if (x.action === 'edit') { html = `<span style="word-break: break-all; word-wrap: break-word;"><bdo dir="ltr">${bbcode2html(x.bbcode)}</bdo></span> ${(() => { if ($('#locale_selection').val() === 'en_US') return `<p><font class="small">${lang['last_edited']} <span class="nowrap"><a href="userdetails.php?id=${x.user_id}"><b><bdo dir="ltr">${x.username}</bdo></b></a></span> at <time>${x.edit_time.replace('T', ' ')}</time>.</font></p>`; else if ($('#locale_selection').val() === 'ru_RU') return `<p><font class="small">${lang['last_edited']} <span class="nowrap"><a href="userdetails.php?id=${x.user_id}"><b><bdo dir="ltr">${x.username}</bdo></b></a></span> в <time>${x.edit_time.replace('T', ' ')}</time>.</font></p>`; else return `<br><p><font class="small">[<time>${x.edit_time.replace('T', ' ')}</time>] <span class="nowrap"><a href="userdetails.php?id=${x.user_id}"><b><bdo dir="ltr">${x.username}</bdo></b></a></span> ${lang['last_edited']} </font></p>`; })()}`; } else { html = `<span style="word-break: break-all; word-wrap: break-word;"><bdo dir="ltr">${bbcode2html(x.bbcode)}</bdo></span>`; }; $(this).parents('[id^=pid]').parent().next().find('.post-body').html(html); return; }; }); } else { console.log('获取论坛评论错误'); }; }, error: function (d) { }, }); }; async function torrentCommentHistory() { 'use strict'; $.ajax({ type: 'post', url: 'https://u2.kysdm.com/api/v1/comment', contentType: "application/json", dataType: 'json', data: JSON.stringify({ "uid": user_id, "token": token, "torrent_id": torrent_id, "type": "torrent" }), success: function (d) { if (d.msg === 'success') { console.log('获取种子评论成功'); let __comment = d.data.comment[torrent_id].sort((a, b) => b.self - a.self); let cidList = __comment.map(x => x.cid); let counts = new Object(); cidList.forEach(x => counts[x] = counts[x] ? counts[x] + 1 : 1) $('[id^="cid"]').each(function () { let cid = $(this).find('[class="embedded"]').children('a').attr('name'); __comment.forEach(x => { if (x.cid == cid && counts[cid] > 1) { if ($(`#history_comment${cid}_select`).length === 0) $(this).find('[class="embedded nowrap"]').before(`<div id="hsty" style="position: relative;"><div id="history_comment" style="position: absolute; right:10px; margin-top: -2px;"><select name="type" id="history_comment${cid}_select"></div></div>`); $(`#history_comment${cid}_select`).append(`<option value="${x.self}">${x.edit_time.replace('T', ' ')} ${(() => { return x.action === 'edit' ? ' E' : x.action === 'reply' ? ' R' : ' N' })()} ${(() => { return x.username === null && x.userid === null ? lang['anonymous_user'] : ` ${x.username}(${x.userid})` })()} </option>`); }; }); }); $("[id^=history_comment]").change(function () { // 监听菜单选择 let self = $(this).val(); for (let i = 0, len = __comment.length; i < len; i++) { if (self != __comment[i].self) continue; let html; let x = __comment[i]; if (x.action === 'edit') { html = `<br> <span style="word-break: break-all; word-wrap: break-word;"> <bdo dir="ltr">${bbcode2html(x.bbcode)}</bdo> </span> ${(() => { if ($('#locale_selection').val() === 'en_US') return `<p class="small">${lang['last_edited']} <span class="nowrap"><a href="userdetails.php?id=${x.user_id}"><b><bdo dir="ltr">${x.username}</bdo></b></a></span> at <time>${x.edit_time.replace('T', ' ')}</time>.</p>`; else if ($('#locale_selection').val() === 'ru_RU') return `<p class="small">${lang['last_edited']} <span class="nowrap"><a href="userdetails.php?id=${x.user_id}"><b><bdo dir="ltr">${x.username}</bdo></b></a></span> в <time>${x.edit_time.replace('T', ' ')}</time>.</p>`; else return `<br><p class="small">[<time>${x.edit_time.replace('T', ' ')}</time>] <span class="nowrap"><a href="userdetails.php?id=${x.user_id}"><b><bdo dir="ltr">${x.username}</bdo></b></a></span> ${lang['last_edited']} </p>`; })()}`; } else { html = `<br> <span style="word-break: break-all; word-wrap: break-word;"> <bdo dir="ltr">${bbcode2html(x.bbcode)}</bdo> </span>`; }; $(this).parents('[id^=cid]').parent().next().find('[class="rowfollow"]:last').html(html); return; }; }); } else { console.log('获取种子评论错误'); }; }, error: function (d) { }, }); }; async function torrentInfoHistory() { 'use strict'; if ($('h3').length === 1) { // 插入 select 基本框架 const right = ($('#outer').width() - $('h3').next().width()) / 2 + 5; // 计算偏移量 $('#top').after('<div id="hsty" style="position: relative;"><div id="history" style="position: absolute; right:' + right + 'px; margin-top: 4px;"><select name="type" id="history_select"></div></div>'); $(window).resize(function () { $('#history').css("right", ($('#outer').width() - $('h3').next().width()) / 2 + 5); }); } else { const right = ($('#outer').width() - $('#top').next().width()) / 2 + 5; // 计算偏移量 $('#top').after('<div id="history" style="position: relative; float: right; margin-bottom: 10px; margin-right: ' + right + 'px"><select name="type" id="history_select"></div>'); $(window).resize(function () { $('#history').css("margin-right", ($('#outer').width() - $('#history').next().width()) / 2 + 5 + 'px'); }); }; $("#history_select").append("<option>" + lang['history_select_loading'] + "</option>"); const __json = await getapi(); // 从 API 获取数据 if (__json.msg !== 'success') { // 加载失败时 console.log('获取历史记录失败.'); $("#history_select").empty(); // 插入前先清空 option $("#history_select").append('<option value="80000">' + lang['history_select_error'] + '</option>'); // 希望你不要看到这个 (ノДT) $("#history_select").append(`<option value="90000">${lang['reset_token']}</option>`); // 删除本地授权信息 $("#history_select").change(function () { // 监听菜单选择 let self = Number($(this).val()); if (self === 90000) { let confirm = prompt("输入 YES 确认本次操作 (大写)"); if (confirm === 'YES') { db.removeItem('key'); db.removeItem('token'); $('#history_select').val(80000); // 将焦点设置到 80000 $('#history_select').change(); // 手动触发列表更改事件 alert("成功"); } else { $('#history_select').val(80000); // 将焦点设置到 80000 $('#history_select').change(); // 手动触发列表更改事件 }; }; }); return; }; console.log('获取历史记录成功.'); let history_data = __json.data.history; $("#history_select").empty(); // 插入前先清空 option for (let i = 0, len = history_data.length; i < len; i++) { // 循环插入到选择列表中 $("#history_select").append("<option value='" + history_data[i].self + "'>" + history_data[i].get_time.replace('T', ' ') + (() => { return history_data[i].self === 0 ? ' N' : history_data[i].offer === 1 ? ' H' : ' T' })() + (() => { if (history_data[i].self === 0) return lang['current_time'] else if (history_data[i].edited_name === null && history_data[i].edited_id === null) return '' else if (history_data[i].edited_name === 'Anonymous' && history_data[i].edited_id === null) return lang['anonymous_user'] else if (history_data[i].edited_name !== null && history_data[i].edited_id !== null) return ' ' + history_data[i].edited_name + '(' + history_data[i].edited_id + ')' else return ' @BUG@' })() + "</option>"); }; // 草 为什么会这样呢 明明原来很整齐的 $("#history_select").change(function () { // 监听菜单选择 let self = Number($(this).val()); for (let i = 0, len = history_data.length; i < len; i++) { if (self !== history_data[i].self) continue; history_data[i].banned === 1 ? $('#top').html(history_data[i].title + ' <b>[<font class="striking">' + lang['banned'] + '</font>]</b>') : $('#top').text(history_data[i].title); // 检查副标题一栏是否存在 if ($("td[class='rowhead nowrap']:contains(" + lang['subtitle'] + ")").length === 0 && history_data[i].subtitle !== null) { $("td[class='rowhead nowrap']:contains(" + lang['uploaded'] + ")").parent().before('<tr><td class="rowhead nowrap" valign="top" align="right">' + lang['subtitle'] + '</td><td class="rowfollow" valign="top" align="left"></td></tr>'); } else if ($("td[class='rowhead nowrap']:contains(" + lang['subtitle'] + ")").length === 1 && history_data[i].subtitle === null) { $("td[class='rowhead nowrap']:contains(" + lang['subtitle'] + ")").parent().remove(); }; $("td[class='rowhead nowrap']:contains(" + lang['subtitle'] + ")").next().text(history_data[i].subtitle); // 副标题 $("td[class='rowhead nowrap']:contains(" + lang['description'] + ")").last().next().html('<span style="word-break: break-all; word-wrap: break-word;"><bdo dir="ltr">' + bbcode2html(history_data[i].description_info) + '</bdo></span>'); // 描述 if ($('h3').length === 1) { // 已经通过候选的种子 $("td[class='rowhead nowrap']:contains(" + lang['uploaded'] + ")").next().html(((p) => { if (p.uploader_id === null && p.uploader_name === '匿名') return '<i>' + lang['anonymous'] + '</i>'; // 匿名发布 if (p.uploader_id === null && p.uploader_name !== '匿名') return p.uploader_name; // 自定义署名 不带UID if (p.uploader_id !== null && p.uploader_name !== '匿名') return '<a href="userdetails.php?id=' + p.uploader_id + '"><b>' + p.uploader_name + '</b></a>'; // 正常显示 || 自定义署名 带UID })(history_data[i])); // 发布人 $("td[class='rowhead nowrap']:contains(" + lang['basic_info'] + ")").next().html('<b>' + lang['uploaded_at'] + ':</b> ' + history_data[i].uploaded_at.replace('T', ' ') + (() => { if (history_data[i].torrent_size) { return ' <b>' + lang['size'] + ':</b> ' + convert(history_data[i].torrent_size) } else { return ''; } })() + ' <b>' + lang['category'] + ':</b> ' + history_data[i].category) } else { // 还在候选的种子 $("td[class='rowhead nowrap']:contains(" + lang['basic_info'] + ")").next().html('<b>' + lang['submitted_by'] + '</b>: ' + ((p) => { if (p.uploader_id === null && p.uploader_name === '匿名') return '<i>' + lang['anonymous'] + '</i>'; // 匿名发布 if (p.uploader_id !== null && p.uploader_name !== '匿名') return '<a href="userdetails.php?id=' + p.uploader_id + '"><b>' + p.uploader_name + '</b></a>'; // 正常显示 })(history_data[i]) + ' <b>' + lang['submitted_at'] + '</b>: <time>' + history_data[i].uploaded_at.replace('T', ' ') + '</time> <b>' + (() => { if (history_data[i].torrent_size) { return `${lang['size']}</b>: ${convert(history_data[i].torrent_size)} <b>` } else { return ''; } })() + lang['category'] + '</b>: ' + history_data[i].category ); }; }; }); }; async function torrentCommentHistoryReset() { 'use strict'; const cidUrl = (t, c) => { if (/\/offers\.php/i.test(location.href)) { return `offers.php?id=${t}&off_details=1#cid${c}` } else if (/\/details\.php/i.test(location.href)) return `details.php?id=${t}#cid${c}` else { return '/' }; }; const callback = (mutations, observer) => { mutations.forEach(function (mutation) { if (mutation.addedNodes.length === 0) return; console.log('检测到种子页面已经完成加载'); observer.disconnect(); // 停止监听 $('#description').after(`<br><br><h1 align="center" id="startcomments" style="font-weight:normal; font-style: italic">正在加载用户评论...</h1><br>`); $.ajax({ type: 'post', url: 'https://u2.kysdm.com/api/v1/comment', contentType: "application/json", dataType: 'json', data: JSON.stringify({ "uid": user_id, "token": token, "torrent_id": torrent_id, "type": "torrent" }), success: function (d) { if (d.msg !== 'success') { console.log('获取种子评论错误'); } else { console.log('获取种子评论成功'); let __comment = d.data.comment[torrent_id].sort(firstBy((a, b) => a.cid - b.cid).thenBy((a, b) => b.self - a.self)); // 如果用self排序,消息顺序不正确,则改用编辑日期排序 if (__comment.length === 0) { // 没有评论 $('#startcomments').text('没有评论'); $('#startcomments').removeAttr("style"); return; } else { $('#startcomments').text('用户评论'); $('#startcomments').removeAttr("style"); }; let cidList = __comment.map(x => x.cid); let counts = new Object(); cidList.forEach(x => counts[x] = counts[x] ? counts[x] + 1 : 1); $('#startcomments').after(`<br> <table class="main" width="940" border="0" cellspacing="0" cellpadding="0"> <tbody> <tr> <td class="embedded"> <table width="100%" border="1" cellspacing="0" cellpadding="10"> <tbody> <tr> <td id="comments" class="text"></td> </tr> </tbody> </table> </td> </tr> </tbody> </table>` ); __comment.forEach(x => { if (x.userid === null && x.username === null) { var userInfo = `<span style="color: gray"> <i>${lang['anonymous']}</i> </span>` } else { var userInfo = `<span style="color: gray"> <span class="nowrap"><a href="userdetails.php?id=${x.userid}"><b><bdo dir="ltr">${x.username}</bdo></b></a></span>` } const bbcode_html = `<div style="margin-top: 8pt; margin-bottom: 8pt;"> <table id="cid${x.cid}" border="0" cellspacing="0" cellpadding="0" width="100%"> <tbody> <tr> <td class="embedded" width="99%"> <a href="${cidUrl(x.torrent_id, x.cid)}" name="${x.cid}">#${x.cid}</a> ${userInfo} <span style="color: gray"> <time>${x.edit_time.replace('T', ' ')}</time></span></span> </td> <td class="embedded nowrap" width="1%"> <a href="#top"><img class="top" src="pic/trans.gif" alt="Top" title="Top"></a> </td> </tr> </tbody> </table> </div> <table class="main-inner" width="100%" border="0" cellspacing="0" cellpadding="5"> <tbody> <tr> <td class="rowfollow" width="150" valign="top" style="padding: 0"> <img src="//u2.dmhy.org/pic/default_avatar.png" alt="avatar" width="150px"></td> <td class="rowfollow" valign="top"><br> ${(() => { if (x.action === 'edit') { return `<span style="word-break: break-all; word-wrap: break-word;"><bdo dir="ltr">${bbcode2html(x.bbcode)}</bdo></span> ${(() => { if ($('#locale_selection').val() === 'en_US') return `<p class="small">${lang['last_edited']} <span class="nowrap"><a href="userdetails.php?id=${x.user_id}"><b><bdo dir="ltr">${x.username}</bdo></b></a></span> at <time>${x.edit_time.replace('T', ' ')}</time>.</p><br><br>`; else if ($('#locale_selection').val() === 'ru_RU') return `<p class="small">${lang['last_edited']} <span class="nowrap"><a href="userdetails.php?id=${x.user_id}"><b><bdo dir="ltr">${x.username}</bdo></b></a></span> в <time>${x.edit_time.replace('T', ' ')}</time>.</p><br><br>`; else return `<p class="small">[<time>${x.edit_time.replace('T', ' ')}</time>] <span class="nowrap"><a href="userdetails.php?id=${x.user_id}"><b><bdo dir="ltr">${x.username}</bdo></b></a></span> ${lang['last_edited']} </p><br><br>`; })()}`; } else { return `<span style="word-break: break-all; word-wrap: break-word;"><bdo dir="ltr">${bbcode2html(x.bbcode)}<br><br></bdo></span>`; }; })()} </td> </tr> </tbody> </table>`; if (counts[x.cid] > 1) { console.log('有编辑记录 直接添加下拉菜单'); // 插入下拉菜单基本框架 if ($(`#history_comment${x.cid}_select`).length === 0) { $('#comments').append(bbcode_html); // 先插入整体框架 console.log('添加下拉菜单基本框架'); $(`[id="cid${x.cid}"]`).find('[class="embedded nowrap"]').before(`<div id="hsty" style="position: relative;"> <div id="history_comment" style="position: absolute; right:10px; margin-top: -2px;"> <select name="type" id="history_comment${x.cid}_select"> </div> </div>`); }; // 向下拉菜单写入信息 $(`#history_comment${x.cid}_select`).append(`<option value="${x.self}">${x.edit_time.replace('T', ' ')} ${(() => { return x.action === 'edit' ? ' E' : x.action === 'reply' ? ' R' : ' N' })()} ${(() => { return x.username === null && x.userid === null ? lang['anonymous_user'] : ` ${x.username}(${x.userid})` })()} </option>`) } else { $('#comments').append(bbcode_html); }; }); $("[id^=history_comment]").change(function () { // 监听菜单选择 let self = $(this).val(); for (let i = 0, len = __comment.length; i < len; i++) { if (self != __comment[i].self) continue; let html; let x = __comment[i]; if (x.action === 'edit') { html = `<br> <span style="word-break: break-all; word-wrap: break-word;"> <bdo dir="ltr">${bbcode2html(x.bbcode)}</bdo> </span> ${(() => { if ($('#locale_selection').val() === 'en_US') return `<p class="small">${lang['last_edited']} <span class="nowrap"><a href="userdetails.php?id=${x.user_id}"><b><bdo dir="ltr">${x.username}</bdo></b></a></span> at <time>${x.edit_time.replace('T', ' ')}</time>.</p><br><br>`; else if ($('#locale_selection').val() === 'ru_RU') return `<p class="small">${lang['last_edited']} <span class="nowrap"><a href="userdetails.php?id=${x.user_id}"><b><bdo dir="ltr">${x.username}</bdo></b></a></span> в <time>${x.edit_time.replace('T', ' ')}</time>.</p><br><br>`; else return `<br><p class="small">[<time>${x.edit_time.replace('T', ' ')}</time>] <span class="nowrap"><a href="userdetails.php?id=${x.user_id}"><b><bdo dir="ltr">${x.username}</bdo></b></a></span> ${lang['last_edited']} </p><br><br>`; })()}`; } else { html = `<br> <span style="word-break: break-all; word-wrap: break-word;"> <bdo dir="ltr">${bbcode2html(x.bbcode)}<br><br></bdo> </span>`; }; $(this).parents('[id^=cid]').parent().next().find('[class="rowfollow"]:last').html(html); return; }; }); }; }, error: function (d) { }, }); }) }; const MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver; const element = document.getElementById("outer"); var observer = new MutationObserver(callback); observer.observe(element, { childList: true }); }; async function torrentInfoHistoryReset() { 'use strict'; const errorstr = $('#outer').find('td.text').text(); // 正在努力加载中... $('#outer').find('td.text').html(errorstr + ' <i>' + lang['history_text_loading'] + '</i>'); const __json = await getapi(); // 从 API 获取数据 if (__json.msg !== 'success') { // 加载失败时 console.log('获取历史记录失败.'); $('#outer').find('td.text').html(`${errorstr} <i>${lang['history_text_error']} <a id="apifailure" href="javascript:void(0);" style="color:#FF1212">${lang['reset_token']}</a></i>`); $("#apifailure").click(function () { let confirm = prompt("输入 YES 确认本次操作 (大写)"); if (confirm === 'YES') { db.removeItem('key'); db.removeItem('token'); alert("成功"); }; }); return; } else if (__json.data.history.length === 0) { // 获取成功 但没有历史记录时 console.log('没有历史记录.'); $('#outer').find('td.text').html(errorstr + ' ' + lang['history_text_empty'] + '</i>'); return; }; console.log('获取历史记录成功.'); let history_data = __json.data.history; // let gdListObj = JSON.parse(localStorage.getItem("u2_gd_list")); // 读取谷歌备份列表 // 还原网页 $('#outer').html('<h1 align="center" id="top">' + (() => { return history_data[0].banned === 1 ? history_data[0].title + ' <b>[<font class="striking">' + lang['banned'] + '</font>]</b>' : history_data[0].title; })() + '</h1>' + '<div id="hsty" style="position: relative;"><div id="history" style="position: absolute; right:56px; margin-top: 4px;">' + '<select name="type" id="history_select" style="visibility: visible;"></select></div></div>' + '<h3>(#' + torrent_id + ')</h3>' + '<table id="description" width="90%" min-width="940px" cellspacing="0" cellpadding="5"><tbody><tr><td class="rowhead" width="13%">' + lang['torrent_title'] + '</td>' + '<td class="rowfollow" width="87%" align="left">' + '<b>[U2].' + history_data[0].torrent_name + '.torrent</b></td></tr>' + (() => { return history_data[0].subtitle ? '<tr><td class="rowhead nowrap" valign="top" align="right">' + lang['subtitle'] + '</td><td class="rowfollow" valign="top" align="left">' + history_data[0].subtitle + '</td></tr></td></tr>' : '' })() + '<tr><td class="rowhead nowrap" valign="top" align="right">' + lang['basic_info'] + '</td>' + '<td class="rowfollow" valign="top" align="left"><b>' + lang['submitted_by'] + '</b>: ' + ((p) => { if (p.uploader_id === null && p.uploader_name === '匿名') return '<i>' + lang['anonymous'] + '</i>'; // 匿名发布 if (p.uploader_id !== null && p.uploader_name !== '匿名') return '<a href="userdetails.php?id=' + p.uploader_id + '"><b>' + p.uploader_name + '</b></a>'; // 正常显示 })(history_data[0]) + ' <b>' + lang['submitted_at'] + '</b>: <time>' + history_data[0].uploaded_at.replace('T', ' ') + '</time>' + (() => { if (history_data[0].torrent_size) { return ' <b>大小:</b> ' + convert(history_data[0].torrent_size) } else { return ''; } })() + ' <b>' + lang['category'] + '</b>: ' + history_data[0].category // + (() => { // const r = ' <b>' + lang['google_backup'] + '</b>: ' // if (gdListObj === null) return ``; // 列表不存在时,直接返回 // const gdList = gdListObj.list; // 载入种子列表 // let d = gdList.findIndex((value) => value == Number(torrent_id)); // 查找数据库中是否有备份,没有返回-1 // if (d === -1) return r + `×`; // 没有备份时 // return `${r}<a href="sendmessage.php?receiver=45940#${torrent_id}" target="_blank" title="${lang['google_send']}">√</a>` // })() + '</td></tr>' + '<tr><td class="rowhead nowrap" valign="top" align="right">' + '<a href="javascript: klappe_news(\'descr\')"><span class="nowrap">' + '<img class="minus" src="pic/trans.gif" alt="Show/Hide" id="picdescr" title="' + lang['show_or_hide'] + '"> ' + lang['description'] + '</span></a></td>' + '<td class="rowfollow" valign="top" align="left">' + '<div id="kdescr"><span style="word-break: break-all; word-wrap: break-word;"><bdo dir="ltr">' + bbcode2html(history_data[0].description_info) + '</bdo></span></div></td></tr><tr>' + '<td class="rowhead nowrap" valign="top" align="right">' + lang['torrent_info'] + '</td>' + '<td class="rowfollow" valign="top" align="left"><table><tbody><tr>' + '<td class="no_border_wide"><b>' + lang['files'] + '</b>: ' + history_data[0].torrent_files_qty + '<br></td><td class="no_border_wide"><b>' + lang['info_hash'] + ':</b> ' + history_data[0].torrent_hash + '</td></tr></tbody></table></td></tr></tbody></table><br><br></br>' ); for (let i = 0, len = history_data.length; i < len; i++) { // 循环插入到选择列表中 $("#history_select").append("<option value='" + history_data[i].self + "'>" + history_data[i].get_time.replace('T', ' ') + (() => { return history_data[i].self === 0 ? ' N' : history_data[i].offer === 1 ? ' H' : ' T' })() + (() => { if (history_data[i].self === 0) return lang['current_time'] else if (history_data[i].edited_name === null && history_data[i].edited_id === null) return '' else if (history_data[i].edited_name === 'Anonymous' && history_data[i].edited_id === null) return lang['anonymous_user'] else if (history_data[i].edited_name !== null && history_data[i].edited_id !== null) return ' ' + history_data[i].edited_name + '(' + history_data[i].edited_id + ')' else return ' @BUG@' })() + "</option>"); }; $("#history_select").change(function () { // 监听菜单选择 let self = Number($(this).val()); for (let i = 0, len = history_data.length; i < len; i++) { if (self !== history_data[i].self) continue; history_data[i].banned === 1 ? $('#top').html(history_data[i].title + ' <b>[<font class="striking">' + lang['banned'] + '</font>]</b>') : $('#top').text(history_data[i].title); // 检查副标题一栏是否存在 if ($("td[class='rowhead nowrap']:contains(" + lang['subtitle'] + ")").length === 0 && history_data[i].subtitle !== null) { $("td[class='rowhead nowrap']:contains(" + lang['uploaded'] + ")").parent().before('<tr><td class="rowhead nowrap" valign="top" align="right">' + lang['subtitle'] + '</td><td class="rowfollow" valign="top" align="left"></td></tr>'); } else if ($("td[class='rowhead nowrap']:contains(" + lang['subtitle'] + ")").length === 1 && history_data[i].subtitle === null) { $("td[class='rowhead nowrap']:contains(" + lang['subtitle'] + ")").parent().remove(); }; $("td[class='rowhead nowrap']:contains(" + lang['subtitle'] + ")").next().text(history_data[i].subtitle); // 副标题 $("td[class='rowhead nowrap']:contains(" + lang['description'] + ")").last().next().html('<span style="word-break: break-all; word-wrap: break-word;"><bdo dir="ltr">' + bbcode2html(history_data[i].description_info) + '</bdo></span>'); // 描述 $("td[class='rowhead nowrap']:contains(" + lang['basic_info'] + ")").next().html('<b>' + lang['submitted_by'] + '</b>: ' + ((p) => { if (p.uploader_id === null && p.uploader_name === '匿名') return '<i>' + lang['anonymous'] + '</i>'; // 匿名发布 if (p.uploader_id !== null && p.uploader_name !== '匿名') return '<a href="userdetails.php?id=' + p.uploader_id + '"><b>' + p.uploader_name + '</b></a>'; // 正常显示 })(history_data[i]) + ' <b>' + lang['submitted_at'] + '</b>: <time>' + history_data[i].uploaded_at.replace('T', ' ') + '</time>' + (() => { if (history_data[i].torrent_size) { return ' <b>' + lang['size'] + ':</b> ' + convert(history_data[i].torrent_size) } else { return ''; } })() + ' <b>' + lang['category'] + '</b>: ' + history_data[i].category ); }; }); }; function bbcode2html(bbcodestr) { 'use strict'; const f_reg = new RegExp("^\"?\"?$|^(?:")?(?:")?$"); var tempCode = new Array(); var tempCodeCount = 0; function addTempCode(value) { tempCode[tempCodeCount] = value; let returnstr = "<tempCode_" + tempCodeCount + ">"; tempCodeCount++; return returnstr; } const escape_reg = new RegExp("[&\"\'<>]", "g"); bbcodestr = bbcodestr.replace(escape_reg, function (s, x) { switch (s) { case '&': return '&'; case '"': return '"'; case "'": return '''; case '<': return '<'; case '>': return '>'; default: return s; } }); bbcodestr = bbcodestr.replace(/ /g, () => { return ' ' }); bbcodestr = bbcodestr.replace(/\r\n/g, () => { return '<br>' }); bbcodestr = bbcodestr.replace(/\n/g, () => { return '<br>' }); bbcodestr = bbcodestr.replace(/\r/g, () => { return '<br>' }); // info/code 标签 const info_reg = new RegExp("\\[(mediainfo|info|code)\\](.+?)\\[\\/(\\1)\\]", "gis"); bbcodestr = bbcodestr.replace(info_reg, function (s, x, y) { switch (x) { case 'info': return addTempCode('<fieldset class="codemain" style="background-color: transparent; word-break: break-all"><legend><b><span style="color: blue">' + lang['info'] + '</span></b></legend>' + y + '</fieldset>'); case 'mediainfo': return addTempCode('<fieldset class="codemain" style="background-color: transparent; word-break: break-all"><legend><b><span style="color: red">' + lang['mediainfo'] + '</span></b></legend>' + y + '</fieldset>'); case 'code': return addTempCode(`<br><div class="codetop">${lang['code']}</div><div class="codemain">${y}</div><br />`); default: return s; } }); // 超链接 (绝对) bbcodestr = bbcodestr.replace(/\[url=((?:https?|ftp|gopher|news|telnet|mms|rtsp):\/\/((?!<|>|\s|"|>|'|<|\(|\)|\[|\]).)+)\](.+?)\[\/url\]/gis, function (s, x, y, z) { return addTempCode('<a class="faqlink" rel="nofollow noopener noreferer" href="' + x + '">' + z + '</a>'); }); bbcodestr = bbcodestr.replace(/\[url\]((?:https?|ftp|gopher|news|telnet|mms|rtsp):\/\/((?!<|>|\s|"|>|'|<|\(|\)|\[|\]).)+)\[\/url\]/gis, function (s, x) { return addTempCode('<a class="faqlink" rel="nofollow noopener noreferer" href="' + x + '">' + x + '</a>') }); // 超链接 (相对) bbcodestr = bbcodestr.replace(/\[url=(((?!<|>|\s|"|>|'|<|\(|\)|\[|\]).)+)\](.+?)\[\/url\]/gis, function (s, x, y, z) { return addTempCode('<a class="faqlink" rel="nofollow noopener noreferer" href="' + x + '">' + z + '</a>'); }); bbcodestr = bbcodestr.replace(/\[url\](((?!<|>|\s|"|>|'|<|\(|\)|\[|\]).)+)\[\/url\]/gis, function (s, x) { return addTempCode('<a class="faqlink" rel="nofollow noopener noreferer" href="' + x + '">' + x + '</a>') }); // 单个标签 不带参 const o_reg = new RegExp("\\[(\\*|siteurl|site)\\]", "gi"); bbcodestr = bbcodestr.replace(o_reg, function (s, x, y) { switch (x) { case '*': return '<img class="listicon listitem" src="pic/trans.gif" alt="list">'; case 'site': return 'U2分享園@動漫花園'; case 'siteurl': return 'https://u2.dmhy.org'; default: return s; } }); // 成对标签 带参 const d_reg = new RegExp("\\[(rt|font)=([^\\]]+)\\](.*?)\\[(/\\1)\\]", "gis"); while (d_reg.test(bbcodestr)) { bbcodestr = bbcodestr.replace(d_reg, function (s, w, x, y, z) { switch (w) { case 'rt': if (f_reg.test(x)) { return '[' + addTempCode('p3F#oW2@cEn_JHstp-&37DgD' + w) + '=' + x + ']' + y + '[' + addTempCode('p3F#oW2@cEn_JHstp-&37DgD' + z) + ']' } else { return addTempCode('<ruby>' + y + '<rp>(</rp><rt>' + x.replace(/^(?:")?(.*?)(?:")?$/, "$1") + '</rt><rp>)</rp></ruby>'); } case 'font': if (f_reg.test(x)) { return '[' + addTempCode('p3F#oW2@cEn_JHstp-&37DgD' + w) + '=' + x + ']' + y + '[' + addTempCode('p3F#oW2@cEn_JHstp-&37DgD' + z) + ']'; } else { return '<span style="font-family: ' + x.replace(/^(?:")?(.*?)(?:")?$/, "$1") + '">' + y + '</span>'; } default: return s; } }) }; // 成对标签 不带参 const a_reg = new RegExp("\\[(pre|b|i|u|s)\\](.*?)\\[/(\\1)\\]", "gs"); while (a_reg.test(bbcodestr)) { bbcodestr = bbcodestr.replace(a_reg, function (s, x, y, z) { switch (x) { case 'b': return '<b>' + y + '</b>'; case 'i': return '<em>' + y + '</em>'; case 'u': return '<u>' + y + '</u>'; case 's': return '<s>' + y + '</s>'; case 'pre': return '<pre>' + y + '</pre>'; default: return s; } }) }; // 颜色 const color_reg = new RegExp("\\[color=(?:")?([#0-9a-z]{1,15}|[a-z]+?)(?:")?\\](.*?)\\[/color\\]", "gis"); while (color_reg.test(bbcodestr)) { bbcodestr = bbcodestr.replace(color_reg, function (s, x, y) { return '<span style="color: ' + x + '">' + y + '</span>'; }) }; // 文字大小 const size_reg = new RegExp("\\[size=(?:")?([1-7])(?:")?\\](.*?)\\[/size\\]", "gis"); while (size_reg.test(bbcodestr)) { bbcodestr = bbcodestr.replace(size_reg, function (s, x, y) { return '<font size="' + x + '">' + y + '</font>'; }) }; // 图片 bbcodestr = bbcodestr.replace(/\[(img|imglnk)\]([^\]]+)\[\/(?:\1)\]/gi, function (s, x, y) { if (/^((?!<|>|"|>|'|<|;|\(|\)|\[|\]|#).)+\.(?:png|jpg|jpeg|gif|svg|bmp)$/i.test(y)) { // url 以 .png 之类结尾 switch (x) { case 'img': return addTempCode('<img alt="image" src="' + y + '" style="height: auto; width: auto; max-width: 100%;">'); case 'imglnk': return addTempCode('<a class="faqlink" rel="nofollow noopener noreferer" href="' + y + '"><img alt="image" src="' + y + '" style="height: auto; width: auto; max-width: 100%;"></a>'); }; }; return addTempCode(s); }); bbcodestr = bbcodestr.replace(/\[img=([^\]]+)\]/gi, function (s, x) { if (/^((?!<|>|"|>|'|<|;|\(|\)|\[|\]|#).)+\.(?:png|jpg|jpeg|gif|svg|bmp)$/i.test(x)) { // url 以 .png 之类结尾 return addTempCode('<img alt="image" src="' + x + '" style="height: auto; width: auto; max-width: 100%;">'); }; return s; }); // 没有bbcode包裹的超链接 bbcodestr = bbcodestr.replace(/((?:https?|ftp|gopher|news|telnet|mms|rtsp):\/\/((?!<|>|\s|"|>|'|<|\(|\)|\[|\]).)+)/gi, function (s, x) { return '<a class="faqlink" rel="nofollow noopener noreferer" href="' + s + '">' + s + '</a>'; }); // 引用 const quote_reg1 = new RegExp("\\[quote\\](.*?)\\[/quote\\]", "gsi"); while (quote_reg1.test(bbcodestr)) { bbcodestr = bbcodestr.replace(quote_reg1, function (s, x) { return '<fieldset><legend>' + lang['quote'] + '</legend>' + x + '</fieldset>'; }); }; const quote_reg2 = new RegExp("\\[quote=([^\\[\\]]*)\\](.*?)\\[/quote\\]", "gsi"); while (quote_reg2.test(bbcodestr)) { bbcodestr = bbcodestr.replace(quote_reg2, function (s, x, y) { if (f_reg.test(x)) { return '<fieldset><legend>' + lang['quote'] + '</legend>' + y + '</fieldset>'; } else { return '<fieldset><legend>' + lang['quote'] + ': ' + x.replace(/^(?:")?(.*?)(?:")?$/, "$1") + '</legend>' + y + '</fieldset>'; } }); }; // spoiler const spoiler_reg1 = new RegExp("\\[spoiler\\](.*?)\\[/spoiler\\]", "gsi"); const spoiler_reg2 = new RegExp("\\[spoiler=([^\\]]+)\\](.*?)\\[/spoiler\\]", "gsi"); while (spoiler_reg1.test(bbcodestr)) { bbcodestr = bbcodestr.replace(spoiler_reg1, function (s, x) { return '<table class="spoiler" width="100%"><tbody><tr><td class="colhead">' + lang['spoiler'] + ' ' + '<button class="spoiler-button-show">' + lang['spoiler_button_1'] + '</button>' + '<button class="spoiler-button-hide" style="display: none;">' + lang['spoiler_button_2'] + '</button>' + '</td></tr><tr><td><span class="spoiler-content">' + x + '</span></td></tr></tbody></table>'; }); }; while (spoiler_reg2.test(bbcodestr)) { bbcodestr = bbcodestr.replace(spoiler_reg2, function (s, x, y) { if (f_reg.test(x)) { return '<table class="spoiler" width="100%"><tbody><tr><td class="colhead">' + lang['spoiler'] + ' ' + '<button class="spoiler-button-show">' + lang['spoiler_button_1'] + '</button>' + '<button class="spoiler-button-hide" style="display: none;">' + lang['spoiler_button_2'] + '</button>' + '</td></tr><tr><td><span class="spoiler-content">' + y + '</span></td></tr></tbody></table>'; } else { return '<table class="spoiler" width="100%"><tbody><tr><td class="colhead">' + x.replace(/^(?:")?(.*?)(?:")?$/, "$1") + ' ' + '<button class="spoiler-button-show">' + lang['spoiler_button_1'] + '</button>' + '<button class="spoiler-button-hide" style="display: none;">' + lang['spoiler_button_2'] + '</button>' + '</td></tr><tr><td><span class="spoiler-content">' + y + '</span></td></tr></tbody></table>'; } }); }; // 表情 const em_reg = new RegExp("\\[(em[1-9][0-9]*)\\]", "gi"); bbcodestr = bbcodestr.replace(em_reg, function (s, x) { switch (x) { case (x.match(/^em[1-9][0-9]*/i) || {}).input: return '<img src="pic/smilies/' + x.replace("em", "") + '.gif" alt="[' + x + ']">'; default: return s; } }) for (let i = 0, len = tempCode.length; i < len; i++) { // console.log(i + " : " + tempCode[i]); bbcodestr = bbcodestr.replace("<tempCode_" + i + ">", tempCode[i]); } bbcodestr = bbcodestr.replace(/p3F#oW2@cEn_JHstp-&37DgD/g, ""); if (/(<br>)$/.test(bbcodestr)) { bbcodestr = bbcodestr + '<br>' }; var htmlobj = $.parseHTML('<div>' + bbcodestr + '</div>'); $(htmlobj).children('fieldset').children('fieldset').children('fieldset').children('fieldset').each(function () { $(this).html($(this).html().replace(/(^<legend>[^<]*?<\/legend>)(.*)/i, function (s, x, y) { return x + '<table class="spoiler" width="100%"><tbody>' + '<tr><td class="colhead">' + lang['auto_fold'] + ' ' + '<button class="spoiler-button-show">' + lang['spoiler_button_1'] + '</button>' + '<button class="spoiler-button-hide" style="display: none;">' + lang['spoiler_button_2'] + '</button>' + '</td></tr><tr><td><span class="spoiler-content">' + y + '</span></td></tr></tbody></table>'; })) }); return $(htmlobj).html(); }; function getapi() { 'use strict'; return new Promise((resolve, reject) => { // https://www.w3school.com.cn/jquery/ajax_ajax.asp $.ajax({ type: 'get', url: 'https://u2.kysdm.com/api/v1/history?token=' + token + '&maximum=50&uid=' + user_id + '&torrent=' + torrent_id, contentType: 'application/json', dataType: 'json', cache: true, success: r => resolve(r), error: r => { console.log('发生错误,HTTP状态码[' + r.status + ']。'); reject(r.status) }, }); }).catch(() => { return { "state": "404", "msg": "failure", "data": { "history": [] } }; }); }; function lang_init(lang) { 'use strict'; var lang_json = { "zh_CN": { "quote": "引用", "info": "发布信息", "mediainfo": "媒体信息", "code": "代码", "spoiler": "警告!下列文字很可能泄露剧情,请谨慎选择是否观看。", "spoiler_button_1": "我就是手贱", "spoiler_button_2": "我真是手贱", "main_title": "主标题", "rt_text": "请输入上标", "main_body": "请输入正文", "main_body_prefix": "请输入标题", "url_name": "请输入网址名称", "url_link": "请输入网址链接", "select_type": "请选择分类...", "preview": "预览", "auto_fold": "过深引用自动折叠", "subtitle": "副标题", "uploaded": "发布人", "basic_info": "基本信息", "description": "描述", "history_select_loading": "正在努力加载中...", "history_select_error": "加载失败啦 (ノДT)", "anonymous": "匿名", "uploaded_at": "发布时间", "size": "大小", "category": "类型", "submitted_by": "提供者", "submitted_at": "提交时间", "history_text_loading": "~~正在检查历史数据中~~", "history_text_error": "加载失败啦 (ノДT) %%", "history_text_empty": "半条历史记录都没有 (ノДT) @@", "torrent_title": "种子标题", "torrent_info": "种子信息", "files": "文件数", "info_hash": "种子散列值", "show_or_hide": "显示 / 隐藏", "KiB": " KiB", "MiB": " MiB", "GiB": " GiB", "TiB": " TiB", "current_time": " 当前时间", "anonymous_user": " 匿名用户", "banned": "已屏蔽", "google_backup": "谷歌备份", "google_send": "发送请求", "last_edited": "最后编辑", "back_to_top": "返回顶部", "reset_token": "重置Token (・_・)ヾ", }, "zh_TW": { "quote": "引用", "info": "發佈訊息", "mediainfo": "媒體訊息", "code": "代碼", "spoiler": "警告!下列文字很可能洩露劇情,請謹慎選擇是否觀看。", "spoiler_button_1": "我就是手賤", "spoiler_button_2": "我真是手賤", "main_title": "主標題", "rt_text": "請輸入上標", "main_body": "請輸入正文", "main_body_prefix": "請輸入標題", "url_name": "請輸入網址名稱", "url_link": "請輸入網址連結", "select_type": "請選擇分類...", "preview": "預覽", "auto_fold": "過深引用自動摺疊", "subtitle": "副標題", "uploaded": "發布人", "basic_info": "基本訊息", "description": "描述", "history_select_loading": "正在努力載入中...", "history_select_error": "載入失敗啦 (ノДT)", "anonymous": "匿名", "uploaded_at": "發布時間", "size": "大小", "category": "類型", "submitted_by": "提供者", "submitted_at": "提交時間", "history_text_loading": "~~正在檢查歷史數據中~~", "history_text_error": "載入失敗啦 (ノДT) %%", "history_text_empty": "半條歷史記錄都沒有 (ノДT) @@", "torrent_title": "種子標題", "torrent_info": "種子訊息", "files": "文件數", "info_hash": "種子散列值", "show_or_hide": "顯示 / 隱藏", "KiB": " KiB", "MiB": " MiB", "GiB": " GiB", "TiB": " TiB", "current_time": " 當前時間", "anonymous_user": " 匿名用戶", "banned": "已屏蔽", "google_backup": "Google備份", "google_send": "發送請求", "last_edited": "最後編輯", "back_to_top": "返回頂部", "reset_token": "重設Token (・_・)ヾ", }, "zh_HK": { "quote": "引用", "info": "發佈訊息", "mediainfo": "媒體訊息", "code": "代碼", "spoiler": "警告!下列文字很可能洩露劇情,請謹慎選擇是否觀看。", "spoiler_button_1": "我就是手賤", "spoiler_button_2": "我真是手賤", "main_title": "主標題", "rt_text": "請輸入上標", "main_body": "請輸入正文", "main_body_prefix": "請輸入標題", "url_name": "請輸入網址名稱", "url_link": "請輸入網址鏈接", "select_type": "請選擇分類...", "preview": "預覽", "auto_fold": "過深引用自動摺疊", "subtitle": "副標題", "uploaded": "發布人", "basic_info": "基本訊息", "description": "描述", "history_select_loading": "正在努力加載中...", "history_select_error": "加載失敗啦 (ノДT)", "anonymous": "匿名", "uploaded_at": "發佈時間", "size": "大小", "category": "類型", "submitted_by": "提供者", "submitted_at": "提交時間", "history_text_loading": "~~正在檢查歷史數據中~~", "history_text_error": "加載失敗啦 (ノДT) %%", "history_text_empty": "半條歷史記錄都沒有 (ノДT) @@", "torrent_title": "種子標題", "torrent_info": "種子訊息", "files": "文件數", "info_hash": "種子散列值", "show_or_hide": "顯示 / 隱藏", "KiB": " KiB", "MiB": " MiB", "GiB": " GiB", "TiB": " TiB", "current_time": " 當前時間", "anonymous_user": " 匿名用戶", "banned": "已屏蔽", "google_backup": "Google備份", "google_send": "發送請求", "last_edited": "最後編輯", "back_to_top": "返回頂部", "reset_token": "重置Token (・_・)ヾ", }, "en_US": { "quote": "Quote", "info": "Infobox", "mediainfo": "Media Info", "code": "CODE", "spoiler": "Warning! This section contains spoiler!", "spoiler_button_1": "I agree to view this.", "spoiler_button_2": "Hide this.", "main_title": "Main Title", "rt_text": "Please enter superscript", "main_body": "Please enter the text", "main_body_prefix": "Please enter a title", "url_name": "Please enter the URL name", "url_link": "Please enter the URL link", "select_type": "Please select a type.", "preview": "Preview", "auto_fold": "Over quote auto fold", "subtitle": "Small Description", "uploaded": "Uploader", "basic_info": "Basic Info", "description": "Description", "history_select_loading": "Trying to load now ...", "history_select_error": "Load failure (ノДT)", "anonymous": "Anonymous", "uploaded_at": "Uploaded at", "size": "Size", "category": "Category", "submitted_by": "Submitted by", "submitted_at": "Submitted at", "history_text_loading": "~~Checking historical data now~~", "history_text_error": "Load failure (ノДT) %%", "history_text_empty": "Half of the history is missing (ノДT) @@", "torrent_title": "Torrent Title", "torrent_info": "Torrent Info", "files": "Files", "info_hash": "Info hash", "show_or_hide": "Show or Hide", "KiB": " KiB", "MiB": " MiB", "GiB": " GiB", "TiB": " TiB", "current_time": " CurrentTime", "anonymous_user": " AnonymousUser", "banned": "Banned", "google_backup": "Google Backup", "google_send": "Send request", "last_edited": "Last edited by", "back_to_top": "Back to top", "reset_token": "Reset Token (・_・)ヾ", }, "ru_RU": { "quote": "Цитата", "info": "Отправленные", "mediainfo": "Данные о Медиа", "code": "CODE", "spoiler": "Предупреждение! Данный раздел содержит СПОЙЛЕРЫ!", "spoiler_button_1": "I agree to view this.", "spoiler_button_2": "Hide this.", "main_title": "Основное название", "rt_text": "Пожалуйста, введите надстрочный индекс", "main_body": "Пожалуйста, введите текст", "main_body_prefix": "Пожалуйста, введите название", "url_name": "Пожалуйста, введите имя URL", "url_link": "Пожалуйста, введите URL-ссылку", "select_type": "выберите тип ...", "preview": "Предварительный просмотр", "auto_fold": "Автоматическое складывание для более глубоких ссылок", "subtitle": "Краткое Описание", "uploaded": "Загрузил", "basic_info": "Базовая инф.", "description": "Описание", "history_select_loading": "Пытаюсь загрузить сейчас ...", "history_select_error": "Отказ нагрузки (ノДT)", "anonymous": "Анонимно", "uploaded_at": "Загружен", "size": "Размер", "category": "Категория", "submitted_by": "Разместивший Запрос", "submitted_at": "Дата размещения", "history_text_loading": "~~Проверка исторических данных сейчас~~", "history_text_error": "Отказ нагрузки (ノДT) %%", "history_text_empty": "Половина истории отсутствует (ノДT) @@", "torrent_title": "Имя торрента", "torrent_info": "Информация о торренте ", "files": "Файлов в торренте", "info_hash": "Информация о ХЕШЕ", "show_or_hide": "Показать / Скрыть", "KiB": " KiБ", "MiB": " MiБ", "GiB": " GiБ", "TiB": " TiБ", "current_time": " Текущее время", "anonymous_user": " Анонимный пользователь", "banned": "Забанен", "google_backup": "Резервное копирование Google", "google_send": "послать запрос", "last_edited": "Последний раз редактировалось", "back_to_top": "На главную", "reset_token": "Токен сброса (・_・)ヾ", } }; return lang_json[lang]; }; // 当前时间 字符串格式 function getDateString() { function zero(obj) { return obj < 10 ? '0' + obj : obj }; const time = new Date(); return time.getFullYear().toString() + '-' + zero(time.getMonth() + 1).toString() + '-' + zero(time.getDate()).toString() + ' ' + zero(time.getHours()) + ':' + zero(time.getMinutes()) + ':' + zero(time.getSeconds()) }; function convert(s) { if (s / 1024 < 1024) return (s / 1024).toFixed(3) + lang['KiB'] if (s / 1024 / 1024 < 1024) return (s / 1024 / 1024).toFixed(3) + lang['MiB'] if (s / 1024 / 1024 / 1024 < 1024) return (s / 1024 / 1024 / 1024).toFixed(3) + lang['GiB'] if (s / 1024 / 1024 / 1024 / 1024 < 1024) return (s / 1024 / 1024 / 1024 / 1024).toFixed(3) + lang['TiB'] };