// ==UserScript== // @name U2历史记录 // @namespace https://u2.dmhy.org/ // @version 0.8.0 // @description 查看种子历史记录 // @author kysdm // @grant none // @match *://u2.dmhy.org/details.php?* // @match *://u2.dmhy.org/offers.php?* // @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/thenby@1.3.4/thenBy.min.js // @require https://unpkg.com/diff@5.1.0/dist/diff.js // @require https://cdn.jsdelivr.net/npm/diff2html@3.4.40/bundles/js/diff2html.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 */ 'use strict'; // 声明全局变量 var lang, torrent_id, db, user_id, topicid, key, token; (async () => { // 初始化 addGlobalStyles(`.diff-container{display:flex;align-items:flex-start;justify-content:flex-start;}.diff-cell{border:none;padding:0;margin-left:5px;flex:1;}.draw-div{box-sizing:border-box;max-width:100%;min-height:15px;max-height:600px;margin:5px;overflow:auto;border-top:1px solid #bfbfbf;border-bottom:1px solid #bfbfbf;}.diff-table{width:100%;border-left:1px solid #bfbfbf;border-right:1px solid #bfbfbf;background-color:white;}.diff-table table,.diff-table table td{background-color:transparent;border:none;vertical-align:top;}.diff-table,.diff-table table{border-collapse:collapse;box-sizing:border-box;table-layout:fixed;font-family:ui-monospace,SFMono-Regular,SF Mono,Menlo,Consolas,Liberation Mono,monospace;font-size:12px;}.diff-table tbody{vertical-align:top;}.diff-table del{text-decoration:none;background-color:#ff818266;}.diff-table ins{text-decoration:none;background-color:#abf2bc;}.diff-linenumber{text-align:right;vertical-align:top;width:3em;border:none;color:#6e7781;font-size:12px;}.diff-linenumber-delete{background-color:#ffd7d5;}.diff-linenumber-insert{background-color:#ccffd8;}.diff-line-text-delete{background-color:#ffebe9;}.diff-line-text-insert{background-color:#e6ffec;}.diff-linenumber-empty,.diff-text-cell-empty{background-color:#d0d8e080;}.diff-line-text{display:inline-block;white-space:pre-wrap;overflow-wrap:break-word;word-break:break-word;box-sizing:border-box;width:auto;font-size:12px;}.diff-line-prefix{background:none;word-wrap:break-word;display:inline;font-size:12px;box-sizing:border-box;vertical-align:top;}.diff-line-prefix-delete::before{content:" - ";}.diff-line-prefix-insert::before{content:" + ";}.diff-line-prefix-empty::before{content:" ";}.diff-text-cell,.diff-text-cell-empty{width:auto;white-space:pre;border-left:none;border-right:1px solid #bfbfbf;border-top:none;border-bottom:none;}`); lang = new lang_init($('#locale_selection').val()); // 获取当前网页语言 let em = /.*id=(?\d{3,5})/i.exec(location.search); if (em) torrent_id = em.groups.tid; else torrent_id = null; // 当前种子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(); return; }; if (torrent_id && /\/(offers|details)\.php/i.test(location.pathname) && $('#outer').find('h2').text().match(/错误|錯誤|Ошибка|error/i)) { torrentInfoHistoryReset(); torrentCommentHistoryReset(); }// 为已经删除的种子显示历史 else if (torrent_id && '/offers.php' === location.pathname && !/(cmtpage|offer_vote|vote)=(1|p)/i.test(location.href) && /off_details=1/i.test(location.href)) { torrentInfoHistory(); torrentCommentHistory(); } // 为正常种子显示历史 else if (torrent_id && '/details.php' === location.pathname && !/(cmtpage|offer_vote|vote)=(1|p)/i.test(location.href)) { torrentInfoHistory(); torrentCommentHistory(); } // 为正常种子显示历史 else if (torrent_id && /\/(offers|details)\.php/i.test(location.pathname) && /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() { $('#outer').html(`

U2种子历史记录 自动鉴权工具

点击开始按钮,将自动进行鉴权,提示完成请刷新界面。
(建议手动备份下个人说明)
`); $("#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('鉴权结束'); $("#auth_token").hide(); $("#auth_token_d").hide(); $("#auth_token_reload").show(); }; }); $("#auth_token_reload").click(function () { window.location.reload(); }); 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 = document.createElement('div'); usercp.innerHTML = 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 '
' }).replace(/\n/g, () => { return '
' }).replace(/\r/g, () => { return '
' }); // await outPutLog(`请检查准备写入个人说明的BBCODE是否正确

// // // // // // // // //
个人说明   //
`); 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); // }); 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}
`); resolve(await sleep(0)); }); }; async function sleep(interval) { return new Promise(resolve => { setTimeout(resolve, interval); }) }; $("#auth_token").click(async function () { $("#auth_token").attr('disabled', "true"); $("#auth_token_d").attr('disabled', "true"); 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('鉴权结束'); $("#auth_token").hide(); $("#auth_token_d").hide(); $("#auth_token_reload").show(); }); }); }; function forumCommentHistoryReset() { const errorstr = $('#outer').find('td.text').text(); // 正在努力加载中... $('#outer').find('td.text').html(errorstr + '        ' + lang['history_text_loading'] + ''); $.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'] + ''); return; }; const locked = __comment.some(x => x.locked === 1); // 检查帖子是否被锁定 // 计算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(`



` ); // 还原标题 $('span[id="top"]').html(`${__comment[0]['topics']}${locked ? '  [锁定]' : ''}`); __comment.forEach(x => { const bbcode_html = `
#${x.pid} ${x.username}  #${pidListSet.findIndex((a) => a == x.pid) + 1} 楼   Top  
avatar
${(() => { if (x.action === 'edit') { return `${bbcode2html(x.bbcode)} ${(() => { if ($('#locale_selection').val() === 'en_US') return `

${lang['last_edited']} ${x.username} at .



`; else if ($('#locale_selection').val() === 'ru_RU') return `

${lang['last_edited']} ${x.username} в .



`; else return `

[] ${x.username} ${lang['last_edited']}



`; })()}`; } else { return `${bbcode2html(x.bbcode)}

`; }; })()}
` 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('td:last').before(`差异对比    `); }; // 向下拉菜单写入信息 $(`#history_comment${x.pid}_select`).append(``) } else { $('#comments').append(bbcode_html); }; }); diffHistoryCommentBbcode(__comment, 'forum'); $("[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 = `${bbcode2html(x.bbcode)} ${(() => { if ($('#locale_selection').val() === 'en_US') return `

${lang['last_edited']} ${x.username} at .

`; else if ($('#locale_selection').val() === 'ru_RU') return `

${lang['last_edited']} ${x.username} в .

`; else return `

[] ${x.username} ${lang['last_edited']}

`; })()}`; } else { html = `${bbcode2html(x.bbcode)}`; }; $(this).parents('[id^=pid]').parent().next().find('.post-body').html(html); return; }; }); } else { console.log('获取论坛评论错误'); $('#outer').find('td.text').html(`${errorstr}        ${lang['history_text_error']}        ${lang['reset_token']}`); $("#apifailure").click(function () { let confirm = prompt("输入 YES 确认本次操作 (大写)"); if (confirm === 'YES') { db.removeItem('key'); db.removeItem('token'); alert("成功"); }; }); }; }, error: function (d) { }, }); }; async function forumCommentHistory() { db = localforage.createInstance({ name: "history" }); $.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: async function (d) { if (d.msg === 'success') { console.log('获取论坛评论成功'); let __comment = d.data.comment[topicid].sort((a, b) => b.self - a.self); let pid_list = __comment.map(x => x.pid); let counts = new Object(); pid_list.forEach(x => counts[x] = counts[x] ? counts[x] + 1 : 1); let pid_list_unique = Array.from(new Set(pid_list)).sort((a, b) => a - b); // 去重排序 console.log(pid_list_unique); let p = $('#outer').find('p[align="center"]:first').text().replace(/\n/g, '
'); let pg = /(?

\d+)
$/i.exec(p); let page_total = Number(pg.groups.p); // 有多少页评论 let page_now = Number($('#outer').find('p:first').find('.gray b:last').text()); console.log(`现在在评论第 ${page_now} 页 | ${page_total}`); var pid_each = await db.getItem('forum_pid_each') || 0;; // 每页最大显示楼层数量 <当数据库没有值时,pid_list_valid会是空值,> if (page_now < page_total) { // 评论完整填满一个页面时,计算单个页面最大显示评论数量 // 后期改动最大显示评论数量的数值后,直接进入帖子最后一页可能会出现不属于当前页面的评论 console.log(`页面评论数量达到最大值`); pid_each = $('table[id^=pid]').length; await db.setItem('forum_pid_each', pid_each); }; var pid_list_valid = pid_list_unique.slice(pid_each * page_now - pid_each, pid_each * page_now); // 截取属于当前页面的PID console.log(pid_list_valid); __comment.forEach(x => { let del_tag = 1; $('[id^="pid"]').each(function () { let pid = $(this).find('[class="embedded"]').children('a').first().text().replace('#', ''); // 获取网页上每个评论的PID if (x.pid == pid) { del_tag = 0; // 标记网页上有对应的PID if (counts[pid] > 1) { if ($(`#history_comment${pid}_select`).length === 0) $(this).find('td:last').before(`差异对比    `); $(`#history_comment${pid}_select`).append(``); }; }; }); if (del_tag === 1) { // console.log(`${x.pid} | 被删除`); if (!pid_list_valid.includes(x.pid)) return; // 不属于当前页面的PID直接跳出 // 只看该作者 启用时,仅还原改用户的记录 let em = /authorid=(?\d{1,5})/i.exec(location.search); if (em && x.userid != em.groups.authorid) return true; if ($('[id="pid10000000000"]').length === 0) { $('[id="outer"]').find('td.text:first').append( `

#10000000000
` ); }; $('[id^="pid"]').each(function () { let pid = $(this).find('[class="embedded"]').children('a').first().text().replace('#', ''); // 获取网页上每个评论的PID if (x.pid < Number(pid)) { const bbcode_html = `
#${x.pid} ${x.username}  Top  
avatar
${(() => { if (x.action === 'edit') { return `${bbcode2html(x.bbcode)} ${(() => { if ($('#locale_selection').val() === 'en_US') return `

${lang['last_edited']} ${x.username} at .



`; else if ($('#locale_selection').val() === 'ru_RU') return `

${lang['last_edited']} ${x.username} в .



`; else return `

[] ${x.username} ${lang['last_edited']}



`; })()}`; } else { return `${bbcode2html(x.bbcode)}

`; }; })()}
` $(`[id="pid${pid}"]`).parent().before(bbcode_html); if (counts[x.pid] > 1) { if ($(`#history_comment${x.pid}_select`).length === 0) $(`[id="pid${x.pid}"]`).find('td:last').before(`  `); $(`#history_comment${cid}_select`).append(``); }; }; }); if (del_tag === 1) { // console.log(`${x.cid} | 被删除`); if (!cid_list_valid.includes(x.cid)) return; // 不属于当前页面的评论直接跳出 if ($('[id^="cid"]').length === 0) { // 所有评论都被删除 console.log('所有评论都被删除'); $('#outer').find('table:last').hide(); $('#outer').find('table:last').prevAll('br').remove(); $('#startcomments').remove(); $('#outer').find('table:last').before('

用户评论

'); $('#outer').find('table:last').after(`
` ); } else if ($('[id="cid1000000000"]').length === 0) { $('#startcomments').nextAll('table.main:first').find('.text').append( `
#1000000000
`); }; $('[id^="cid"]').each(function () { let cid = $(this).find('[class="embedded"]').children('a').attr('name'); // 获取网页上每个评论的CID if (x.cid < Number(cid)) { if (x.userid === null && x.username === null) { var userInfo = ` ${lang['anonymous']} ` } else { var userInfo = ` ${x.username}` } const bbcode_html = `
#${x.cid} ${userInfo}   Top  
avatar
${(() => { if (x.action === 'edit') { return `${bbcode2html(x.bbcode)} ${(() => { if ($('#locale_selection').val() === 'en_US') return `

${lang['last_edited']} ${x.username} at .



`; else if ($('#locale_selection').val() === 'ru_RU') return `

${lang['last_edited']} ${x.username} в .



`; else return `

[] ${x.username} ${lang['last_edited']}



`; })()}`; } else { return `${bbcode2html(x.bbcode)}

`; }; })()}
`; $(`[id="cid${cid}"]`).parent().before(bbcode_html); // 先插入整体框架 if (counts[x.cid] > 1) { // console.log('有编辑记录 直接添加下拉菜单'); // 插入下拉菜单基本框架 if ($(`#history_comment${x.cid}_select`).length === 0) { console.log('添加下拉菜单基本框架'); $(`[id="cid${x.cid}"]`).find('td:last').before(`  `); }; // 向下拉菜单写入信息 $(`#history_comment${x.cid}_select`).append(``); }; return false; }; }); }; }); diffHistoryCommentBbcode(__comment, 'torrent'); $("[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 = `
${bbcode2html(x.bbcode)} ${(() => { if ($('#locale_selection').val() === 'en_US') return `

${lang['last_edited']} ${x.username} at .

`; else if ($('#locale_selection').val() === 'ru_RU') return `

${lang['last_edited']} ${x.username} в .

`; else return `

[] ${x.username} ${lang['last_edited']}

`; })()}`; } else { html = `
${bbcode2html(x.bbcode)} `; }; $(this).parents('[id^=cid]').parent().next().find('[class="rowfollow"]:last').html(html); return; }; }); } else { console.log('获取种子评论错误'); }; }, error: function (d) { }, }); }; async function torrentInfoHistory() { if ($('h3').length === 1) { // 插入 select 基本框架 const right = ($('#outer').width() - $('h3').next().width()) / 2 + 5; // 计算偏移量 $('#top').after('
'); $(window).resize(function () { $('#history').css("margin-right", ($('#outer').width() - $('#history').next().width()) / 2 + 5 + 'px'); }); }; $("#history_select").append(""); const __json = await getapi(); // 从 API 获取数据 if (__json.msg !== 'success') { // 加载失败时 console.log('获取历史记录失败.'); $("#history_select").empty(); // 插入前先清空 option $("#history_select").append(''); // 希望你不要看到这个 (ノДT) $("#history_select").append(``); // 删除本地授权信息 $("#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; }; let history_data = __json.data.history; for (let i = 0, len = history_data.length; i < len; i++) { // 循环插入到选择列表中 if (i === 0) { $("td[class='rowhead nowrap']:contains(" + lang['description'] + ")").closest('tr').after(` Show/Hide 代码 点击复制到剪贴板 ` ) .after(` Show/Hide 差异 `); $(`td[class='rowhead nowrap']:contains('${lang['torrent_info']}')`).next('td').find('.no_border_wide:last') .before(``) .before(``); $('#torrent_ver').html(`${lang['torrent_ver']}: ${history_data[i].torrent_ver}`); const numberOfPieces = Math.ceil(history_data[i].torrent_size / history_data[i].torrent_piece_length); $('#torrent_piece_length').html(`${lang['torrent_piece_length']}: ${numberOfPieces} (${convertBytesToAutoUnit(history_data[i].torrent_piece_length)})`); $('#ctdescr').val(history_data[i].description_info); $('#codedescr').closest('a').click(function () { $('#cdescr').toggle(); $('#codedescr').attr('class', $('#codedescr').attr('class') === 'plus' ? 'minus' : 'plus'); }); $('#diffdescr').closest('a').click(async function () { $('#diff_draw, .diff-container').toggle(); if ($('#diffdescr').attr('class') === 'plus') { $('#diffdescr').attr('class', 'minus'); await db.setItem('diff_switch', true); } else { $('#diffdescr').attr('class', 'plus'); await db.setItem('diff_switch', false); } }); // 记录上次差异按钮打开状态 if (await db.getItem('diff_switch')) $('#diffdescr').closest('a').trigger('click'); $('#codedescrcopy').click(function () { const _val = $('#ctdescr').val(); navigator.clipboard.writeText(_val).then(() => { $('#codedescrcopy_text_success').fadeIn(500); $('#codedescrcopy_text_success').fadeOut(1000); }).catch(() => { $('#codedescrcopy_text_failure').fadeIn(500); $('#codedescrcopy_text_failure').fadeOut(1000); }); }); }; $("#history_select, #history_select2, #history_select3").append(""); }; // 草 为什么会这样呢 明明原来很整齐的 $("#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 + '    [' + lang['banned'] + ']') : $('#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('' + lang['subtitle'] + ''); } 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('
' + bbcode2html(history_data[i].description_info) + '
'); // 描述 $('#ctdescr').val(history_data[i].description_info); // 描述代码 $('#torrent_ver').html(`${lang['torrent_ver']}: ${history_data[i].torrent_ver}`); // 版本 const numberOfPieces = Math.ceil(history_data[i].torrent_size / history_data[i].torrent_piece_length); $('#torrent_piece_length').html(`${lang['torrent_piece_length']}: ${numberOfPieces} (${convertBytesToAutoUnit(history_data[i].torrent_piece_length)})`); // 区块 if ($('h3').length === 1) { // 已经通过候选的种子 $("td[class='rowhead nowrap']:contains(" + lang['uploaded'] + ")").next().html(((p) => { if (p.uploader_id === null && p.uploader_name === '匿名') return '' + lang['anonymous'] + ''; // 匿名发布 if (p.uploader_id === null && p.uploader_name !== '匿名') return p.uploader_name; // 自定义署名 不带UID if (p.uploader_id !== null && p.uploader_name !== '匿名') return '' + p.uploader_name + ''; // 正常显示 || 自定义署名 带UID })(history_data[i])); // 发布人 $("td[class='rowhead nowrap']:contains(" + lang['basic_info'] + ")").next().html('' + lang['uploaded_at'] + ': ' + history_data[i].uploaded_at.replace('T', ' ') + (() => { if (history_data[i].torrent_size) { return '   ' + lang['size'] + ': ' + convert(history_data[i].torrent_size) } else { return ''; } })() + '   ' + lang['category'] + ': ' + history_data[i].category) } else { // 还在候选的种子 $("td[class='rowhead nowrap']:contains(" + lang['basic_info'] + ")").next().html('' + lang['submitted_by'] + ': ' + ((p) => { if (p.uploader_id === null && p.uploader_name === '匿名') return '' + lang['anonymous'] + ''; // 匿名发布 if (p.uploader_id !== null && p.uploader_name !== '匿名') return '' + p.uploader_name + ''; // 正常显示 })(history_data[i]) + '   ' + lang['submitted_at'] + '   ' + (() => { if (history_data[i].torrent_size) { return `${lang['size']}: ${convert(history_data[i].torrent_size)}   ` } else { return ''; } })() + lang['category'] + ': ' + history_data[i].category ); }; }; }); $("#history_select2, #history_select3").change(function () { const leftValue = Number($("#history_select2").val()); const rightValue = Number($("#history_select3").val()); drawDiffHistoryBbcode(history_data, leftValue, rightValue, 'torrent', $('#diff_draw')) }); const $historySelect2 = $("#history_select2"); const $historySelect3 = $("#history_select3"); // const firstOptionText = $historySelect2.find("option:eq(0)").text(); const historySelect2OptionsLength = $historySelect2.find("option").length; if (historySelect2OptionsLength === 1) { // 就一个记录,无法进行差异处理 $('#diff_draw_unit, #diff_unit').hide(); } else { let rightValue = 0; let leftValue = 1; let flagBreak = false; while (leftValue < historySelect2OptionsLength) { if (preCheckBbcodeDiscrepancy(history_data, leftValue, rightValue) === true) { $historySelect3.find("option").eq(rightValue).prop("selected", true); $historySelect2.find("option").eq(leftValue).prop("selected", true); $historySelect2.trigger("change"); flagBreak = true; break; } rightValue++; leftValue++; } if (!flagBreak) $('#diff_draw_unit, #diff_unit').hide(); } $("#history_select option:first").remove(); // 删除加载等待一栏 }; function torrentCommentHistoryReset() { const callback = (mutations, observer) => { mutations.forEach(function (mutation) { if (mutation.addedNodes.length === 0) return; console.log('检测到种子页面已经完成加载'); observer.disconnect(); // 停止监听 $('#description').after(`

正在加载用户评论...


`); $.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(`
` ); __comment.forEach(x => { if (x.userid === null && x.username === null) { var userInfo = ` ${lang['anonymous']} ` } else { var userInfo = ` ${x.username}` } const bbcode_html = `
#${x.cid} ${userInfo}   Top  
avatar
${(() => { if (x.action === 'edit') { return `${bbcode2html(x.bbcode)} ${(() => { if ($('#locale_selection').val() === 'en_US') return `

${lang['last_edited']} ${x.username} at .



`; else if ($('#locale_selection').val() === 'ru_RU') return `

${lang['last_edited']} ${x.username} в .



`; else return `

[] ${x.username} ${lang['last_edited']}



`; })()}`; } else { return `${bbcode2html(x.bbcode)}

`; }; })()}
`; 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(`差异对比    `); }; // 向下拉菜单写入信息 $(`#history_comment${x.cid}_select`).append(``) } else { $('#comments').append(bbcode_html); }; }); diffHistoryCommentBbcode(__comment, 'torrent'); $("[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 = `
${bbcode2html(x.bbcode)} ${(() => { if ($('#locale_selection').val() === 'en_US') return `

${lang['last_edited']} ${x.username} at .



`; else if ($('#locale_selection').val() === 'ru_RU') return `

${lang['last_edited']} ${x.username} в .



`; else return `

[] ${x.username} ${lang['last_edited']}



`; })()}`; } else { html = `
${bbcode2html(x.bbcode)}

`; }; $(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() { const errorstr = $('#outer').find('td.text').text(); // 正在努力加载中... $('#outer').find('td.text').html(errorstr + '        ' + lang['history_text_loading'] + ''); const __json = await getapi(); // 从 API 获取数据 if (__json.msg !== 'success') { // 加载失败时 console.log('获取历史记录失败.'); $('#outer').find('td.text').html(`${errorstr}        ${lang['history_text_error']}        ${lang['reset_token']}`); $("#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'] + ''); return; }; console.log('获取历史记录成功.'); let history_data = __json.data.history; // let gdListObj = JSON.parse(localStorage.getItem("u2_gd_list")); // 读取谷歌备份列表 // 还原网页 $('#outer').html('

' + (() => { return history_data[0].banned === 1 ? history_data[0].title + '    [' + lang['banned'] + ']' : history_data[0].title; })() + '

' + '
' + '
' + '

(#' + torrent_id + ')

' + '' + '' + (() => { return history_data[0].subtitle ? '' : '' })() + '' + '' + '' + '' + '' + `
' + lang['torrent_title'] + '' + '[U2].' + history_data[0].torrent_name + '.torrent
' + lang['subtitle'] + '' + history_data[0].subtitle + '
' + lang['basic_info'] + '' + lang['submitted_by'] + ': ' + ((p) => { if (p.uploader_id === null && p.uploader_name === '匿名') return '' + lang['anonymous'] + ''; // 匿名发布 if (p.uploader_id !== null && p.uploader_name !== '匿名') return '' + p.uploader_name + ''; // 正常显示 })(history_data[0]) + '   ' + lang['submitted_at'] + '' + (() => { if (history_data[0].torrent_size) { return '   大小: ' + convert(history_data[0].torrent_size) } else { return ''; } })() + '   ' + lang['category'] + ': ' + history_data[0].category // + (() => { // const r = '   ' + lang['google_backup'] + ': ' // 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}` // })() + '
' + '' + 'Show/Hide ' + lang['description'] + '' + '
' + bbcode2html(history_data[0].description_info) + '
' + lang['torrent_info'] + '



` ); $("td[class='rowhead nowrap']:contains(" + lang['description'] + ")").closest('tr').after(` Show/Hide 代码 点击复制到剪贴板 ` ).after(` Show/Hide 差异 `); $('#ctdescr').val(history_data[0].description_info); $('#codedescr').closest('a').click(function () { $('#cdescr').toggle(); $('#codedescr').attr('class', $('#codedescr').attr('class') === 'plus' ? 'minus' : 'plus'); }); $('#diffdescr').closest('a').click(async function () { $('#diff_draw, .diff-container').toggle(); if ($('#diffdescr').attr('class') === 'plus') { $('#diffdescr').attr('class', 'minus'); await db.setItem('diff_switch', true); } else { $('#diffdescr').attr('class', 'plus'); await db.setItem('diff_switch', false); } }); // 记录上次差异按钮打开状态 if (await db.getItem('diff_switch')) $('#diffdescr').closest('a').trigger('click'); $('#codedescrcopy').click(function () { const _val = $('#ctdescr').val(); navigator.clipboard.writeText(_val).then(() => { $('#codedescrcopy_text_success').fadeIn(500); $('#codedescrcopy_text_success').fadeOut(1000); }).catch(() => { $('#codedescrcopy_text_failure').fadeIn(500); $('#codedescrcopy_text_failure').fadeOut(1000); }); }); const putFileTree = (index) => { // 插入ID let counter = 0; const InsertSeq = (data) => { for (key in data) { data[key]['id'] = counter; counter++; if (data[key]['type'] == 'directory') InsertSeq(data[key]['children']); }; return data; }; // 获取文件ID const getFile = (data) => { let a = [] for (key in data) { if (data[key]['type'] == 'file') a.push(data[key]['id']); }; a = a.concat(getDirectory(data)); return a; }; // 获取文件夹ID const getDirectory = (data, directory = []) => { for (key in data) { if (data[key]['type'] == 'directory') directory.push(data[key]['id']); }; return directory; }; // 获取文件体积 const getSize = (data, size = 0) => { // console.log(data); for (key in data) { if (data[key]['type'] == 'file') { size = size + data[key]['length']; } else { size = getSize(data[key]['children'], size); }; } return size; }; // 遍历JSON const tree = (j, i) => { for (let key in j) { // console.log(j); // console.log(j['key']); if (j[key]['type'] == 'directory') { let children = j[key]['children']; let f_id_sh = getFile(children); // 获取文件夹需要的id let f_size = convert(getSize(children)) // 文件夹大小 if (f_id === 0) { f_html = f_html + `${key}[${f_size}]`; } else { f_html = f_html + `${space.repeat(i)}${key}[${f_size}]`; }; f_id++; tree(children, i + 1); } else { if (f_id === 0) { // 单文件种子 f_html = f_html + `${space.repeat(i)}${key}${convert(j[key]['length'])}`; } else { f_html = f_html + `${space.repeat(i)}${key}${convert(j[key]['length'])}`; }; f_id++; }; }; }; let torrent_tree = history_data[index].torrent_tree; const numberOfPieces = Math.ceil(history_data[0].torrent_size / history_data[0].torrent_piece_length); if (torrent_tree === null) { // console.log('tree 为空'); $('#file_tree').html( `
${lang['files']}: ${history_data[0].torrent_files_qty}
${lang['info_hash']}: ${history_data[0].torrent_hash} ${lang['torrent_ver']}: ${history_data[0].torrent_ver} ${lang['torrent_piece_length']}: ${numberOfPieces} (${convertBytesToAutoUnit(history_data[0].torrent_piece_length)})
` ); return; }; torrent_tree = stringify(torrent_tree, function (a, b) { // 对keys排序 if (typeof (a.value) !== 'object' || typeof (b.value) !== 'object') return 0; if (a.value.type === 'directory' && b.value.type === 'file') { return -1; } else if (a.value.type === 'file' && b.value.type === 'directory') { return 1; } else { return a.key.toLowerCase() < b.key.toLowerCase() ? -1 : 1; }; }); torrent_tree = JSON.parse(torrent_tree); torrent_tree = InsertSeq(torrent_tree); // console.log(__json); let f_id = 0; // 元素id let f_html = ''; // 文件列表 const space = '    '; // 缩进 tree(torrent_tree, 0); // $('#filelist').find('tr').after(f_html); $('#file_tree').html( `
${lang['files']}: ${history_data[index].torrent_files_qty}
[查看列表] ${(() => { return f_id > 1 ? ` ` : '' })()}
${lang['info_hash']}: ${history_data[index].torrent_hash} ${lang['torrent_ver']}: ${history_data[index].torrent_ver} ${lang['torrent_piece_length']}: ${numberOfPieces} (${convertBytesToAutoUnit(history_data[0].torrent_piece_length)})
` ); }; putFileTree(0); // 运行一次,生成列表 for (let i = 0, len = history_data.length; i < len; i++) { // 循环插入到选择列表中 $("#history_select, #history_select2, #history_select3").append(""); }; $("#history_select2, #history_select3").change(function () { const leftValue = Number($("#history_select2").val()); const rightValue = Number($("#history_select3").val()); drawDiffHistoryBbcode(history_data, leftValue, rightValue, 'torrent', $('#diff_draw')) }); const $historySelect2 = $("#history_select2"); const $historySelect3 = $("#history_select3"); // const firstOptionText = $historySelect2.find("option:eq(0)").text(); const historySelect2OptionsLength = $historySelect2.find("option").length; if (historySelect2OptionsLength === 1) { // 就一个记录,无法进行差异处理 $('#diff_draw_unit, #diff_unit').hide(); } else { let rightValue = 0; let leftValue = 1; let flagBreak = false; while (leftValue < historySelect2OptionsLength) { if (preCheckBbcodeDiscrepancy(history_data, leftValue, rightValue) === true) { $historySelect3.find("option").eq(rightValue).prop("selected", true); $historySelect2.find("option").eq(leftValue).prop("selected", true); $historySelect2.trigger("change"); flagBreak = true; break; } rightValue++; leftValue++; } if (!flagBreak) $('#diff_draw_unit, #diff_unit').hide(); } $("#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 + '    [' + lang['banned'] + ']') : $('#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('' + lang['subtitle'] + ''); } 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('
' + bbcode2html(history_data[i].description_info) + '
'); // 描述 $('#ctdescr').val(history_data[i].description_info); // 描述代码 $("td[class='rowhead nowrap']:contains(" + lang['basic_info'] + ")").next().html('' + lang['submitted_by'] + ': ' + ((p) => { if (p.uploader_id === null && p.uploader_name === '匿名') return '' + lang['anonymous'] + ''; // 匿名发布 if (p.uploader_id !== null && p.uploader_name !== '匿名') return '' + p.uploader_name + ''; // 正常显示 })(history_data[i]) + '   ' + lang['submitted_at'] + '' + (() => { if (history_data[i].torrent_size) { return '   ' + lang['size'] + ': ' + convert(history_data[i].torrent_size) } else { return ''; } })() + '   ' + lang['category'] + ': ' + history_data[i].category ); putFileTree(i); }; }); }; function bbcode2html(bbcodestr) { var tempCode = new Array(); var tempCodeCount = 0; let lost_tags = new Array(); function addTempCode(value) { tempCode[tempCodeCount] = value; let returnstr = ""; 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(/\r\n/g, () => { return '
' }); bbcodestr = bbcodestr.replace(/\n/g, () => { return '
' }); bbcodestr = bbcodestr.replace(/\r/g, () => { return '
' }); bbcodestr = bbcodestr.replace(/ /g, '  '); let br_end = ''; // 对结尾的换行符进行计数 let br; if (br = bbcodestr.match(/(?:
)+$/)) { br_end = br[0]; const regex = new RegExp(`${br_end}$`, ""); bbcodestr = bbcodestr.replace(regex, ''); }; const checkLostTags = (value, r_tag_start, r_tag_end) => { let state = false; let r_tag_start_exec = r_tag_start.exec(value); let index_start = r_tag_start_exec ? (r_tag_start_exec.index + r_tag_start_exec[0].length) : 0; let r_tag_end_exec = r_tag_end.exec(value.slice(index_start)); if (r_tag_start_exec && !r_tag_end_exec) { let tag_start_val = r_tag_start_exec.groups.tag;; console.log('检测到丢失的标签 => ' + `[/${tag_start_val}]`); lost_tags.push(`[/${tag_start_val}]`) // value = value + `[/${tag_start_val}]`; state = true; }; // return { "value": value, "state": state }; return { "state": state }; }; const url = (val, textarea) => { if (val === '=' || val === '="' || val === '=""') { textarea = textarea.replace(/\[url=.(?:"){0,2}\]/i, function (s) { return '[url]'; }); } if (val) { const lost = checkLostTags(textarea, /\[(?url)=[^\[]*?/i, /\[\/(?url)\]/i); if (lost.state) { return textarea.replace(/\[url=[^\[]*?/i, function (s) { return addTempCode(s); }); }; return textarea.replace(/\[url=(.+?)\](.*?)\[\/url\]/i, function (all, url, text) { if (url.match(/\s|\[/)) return addTempCode(all); let tmp = url.replace(/^(?:")?(.*?)(?:")?$/, "$1"); if (!tmp.match(/"/)) url = tmp; else { if (url.match(/"/g).length === 1) url = url.replace('"', ''); } return addTempCode('' + text + ''); }); } else { const lost = checkLostTags(textarea, /\[(?url)\]/i, /\[\/(?url)\]/i); if (lost.state) { return textarea.replace(/\[url\]/i, function (s) { return addTempCode(s); }); }; return textarea.replace(/\[url\](.+?)\[\/url\]/i, function (s, x) { if (x.match(/\s|\[/i)) return addTempCode(s); return addTempCode('' + x + ''); }); }; }; // 注释 const rt = (val, textarea) => { if (val === '=' || val === '="' || val === '=""') { return textarea.replace(/\[rt=.*?\]/i, function (s) { return addTempCode(s); }); } else if (!val) { return textarea.replace('[rt]', function (s) { return addTempCode(s); }) } else { const lost = checkLostTags(textarea, /\[(?rt)=[^\[]*?/i, /\[\/(?rt)\]/i); if (lost.state) { return textarea.replace(/\[rt=[^\[]*?/i, function (s) { return addTempCode(s); }); }; return textarea.replace(/\[rt=(.+?)\](.*?)\[\/rt\]/i, function (all, tval, text) { if (tval.match(/\[/i)) return addTempCode(all); let tmp = tval.replace(/^(?:")?(.*?)(?:")?$/, "$1"); if (!tmp.match(/"/)) tval = tmp; return addTempCode('' + text + '(' + tval + ')'); }); }; }; // 字体 const font = (val, textarea) => { if (val === '=' || val === '="' || val === '=""') { return textarea.replace(/\[font=.*?]/i, function (s) { return addTempCode(s); }); } else if (!val) { return textarea.replace('[font]', function (s) { return addTempCode(s); }) } else { const lost = checkLostTags(textarea, /\[(?font)=[^\[]*?\]/i, /\[\/(?font)\]/i); if (lost.state) { return textarea.replace(/\[font=[^\[]*?/i, function (s) { return addTempCode(s); }); }; return textarea.replace(/\[font=(.+?)\](.*?)\[\/font\]/i, function (all, tval, text) { if (tval.match(/\[/i)) return '[' + addTempCode(`font=`) + `${tval}]${text}`; let tmp = tval.replace(/^(?:")?(.*?)(?:")?$/, "$1"); if (!/"/.test(tmp)) { tval = tmp; } else { if (tval.match(/"/g).length === 1) tval = tval.replace('"', ''); }; return '' + text + ''; }); }; }; // 颜色 const color = (val, textarea) => { if (val === '=' || val === '="' || val === '=""') { return textarea.replace(/\[color=.*?\]/i, function (s) { return addTempCode(s); }); } else if (!val) { return textarea.replace('[color]', function (s) { return addTempCode(s); }) } else { const lost = checkLostTags(textarea, /\[(?color)=[^\[]*?\]/i, /\[\/(?color)\]/i); if (lost.state) { return textarea.replace(/\[color=[^\[]*?\]/i, function (s) { return addTempCode(s); }); }; return textarea.replace(/\[color=(.+?)\](.*?)\[\/color\]/i, function (all, tval, text) { if (tval.match(/\[/i)) return addTempCode(all);; let tmp = tval.replace(/^(?:")?(.*?)(?:")?$/, "$1"); if (!/"/.test(tmp)) { tval = tmp; } else { if (tval.match(/"/g).length === 1) tval = tval.replace('"', ''); }; return '' + text + ''; }); }; }; // 文字大小 const size = (val, textarea) => { if (val === '=' || val === '="' || val === '=""') { return textarea.replace(/\[size=.*?\]/i, function (s) { return addTempCode(s); }); } else if (!val) { return textarea.replace('[size]', function (s) { return addTempCode(s); }) } else { const lost = checkLostTags(textarea, /\[(?size)=[^\[]*?\]/i, /\[\/(?size)\]/i); if (lost.state) { return textarea.replace(/\[size=[^\[]*?\]/i, function (s) { return addTempCode(s); }); }; return textarea.replace(/\[size=(.+?)\](.*?)\[\/size\]/i, function (all, tval, text) { // size只允许1-9的数字 if (!tval.match(/^(?:")?[0-9](?:")?$/)) return addTempCode(all); let tmp = tval.replace(/^(?:")?(.*?)(?:")?$/, "$1"); if (!/"/.test(tmp)) { tval = tmp; } else { if (tval.match(/"/g).length === 1) tval = tval.replace('"', ''); }; return '' + text + ''; }); }; }; const pre = (val, textarea) => { if (val) { return textarea.replace(/\[pre=(.*?)\]/i, function (s, v) { return addTempCode('[pre=') + v + ']'; }); }; const lost = checkLostTags(textarea, /\[(?pre)\]/i, /\[\/(?pre)\]/i); if (lost.state) { return textarea.replace(/\[pre\]/i, function (s) { return addTempCode(s); }); }; return textarea.replace(/\[pre\](.*?)\[\/pre\]/i, function (all, text) { return '
' + text + '
'; }); }; const b = (val, textarea) => { if (val) { return textarea.replace(/\[b=(.*?)\]/i, function (s, v) { return addTempCode('[b=') + v + ']'; }); }; const lost = checkLostTags(textarea, /\[(?b)\]/i, /\[\/(?b)\]/i); if (lost.state) { return textarea.replace(/\[b\]/i, function (s) { return addTempCode(s); }); }; return textarea.replace(/\[b\](.*?)\[\/b\]/i, function (all, text) { return '' + text + ''; }); }; const i = (val, textarea) => { if (val) { return textarea.replace(/\[i=(.*?)\]/i, function (s, v) { return addTempCode('[i=') + v + ']'; }); }; const lost = checkLostTags(textarea, /\[(?i)\]/i, /\[\/(?i)\]/i); if (lost.state) { return textarea.replace(/\[i\]/i, function (s) { return addTempCode(s); }); }; return textarea.replace(/\[i\](.*?)\[\/i\]/i, function (all, text) { return '' + text + ''; }); }; const u = (val, textarea) => { if (val) { return textarea.replace(/\[u=(.*?)\]/i, function (s, v) { return addTempCode('[u=') + v + ']'; }); }; const lost = checkLostTags(textarea, /\[(?u)\]/i, /\[\/(?u)\]/i); if (lost.state) { return textarea.replace(/\[u\]/i, function (s) { return addTempCode(s); }); }; return textarea.replace(/\[u\](.*?)\[\/u\]/i, function (all, text) { return '' + text + ''; }); }; const s = (val, textarea) => { if (val) { return textarea.replace(/\[s=(.*?)\]/i, function (s, v) { return addTempCode('[s=') + v + ']'; }); }; const lost = checkLostTags(textarea, /\[(?s)\]/i, /\[\/(?s)\]/i); if (lost.state) { return textarea.replace(/\[s\]/i, function (s) { return addTempCode(s); }); }; return textarea.replace(/\[s\](.*?)\[\/s\]/i, function (all, text) { return '' + text + ''; }); }; const img = (val, textarea) => { if (val === '=' || val === '="' || val === '=""') { return textarea.replace(/\[img=.*?\]/i, function (s) { return addTempCode(s); }); } else if (val) { return textarea.replace(/\[img=(.*?)\]/i, function (all, url) { // [img=http://u2.dmhy.org/pic/logo.png] url = url.replace('&', '&'); if (/^((?!"|'|>|<|;|#).)+\.(?:png|jpg|jpeg|gif|svg|bmp|webp)$/i.test(url)) { // url 以 .png 之类结尾 return addTempCode('image'); } else { return addTempCode(all); }; }); } else { // [img]http://u2.dmhy.org/pic/logo.png[/img] const lost = checkLostTags(textarea, /\[(?img)\]/i, /\[\/(?img)\]/i); if (lost.state) { return textarea.replace(/\[img\]/i, function (s) { return addTempCode(s); }); }; return textarea.replace(/\[img\](.*?)\[\/img\]/i, function (all, url) { url = url.replace('&', '&'); if (/^((?!"|'|>|<|;|#).)+\.(?:png|jpg|jpeg|gif|svg|bmp|webp)$/i.test(url)) { // url 以 .png 之类结尾 return addTempCode('image'); } else { return addTempCode(all); }; }); }; }; const imglnk = (val, textarea) => { if (val === '=' || val === '="' || val === '=""') { return textarea.replace(/\[imglnk=.*?\]/i, function (s) { return addTempCode(s); }); } else if (val) { return textarea.replace(/\[imglnk=(.*?)\]/i, function (all, url) { return addTempCode('[imglnk=') + url + ']'; }); } else { // [img]http://u2.dmhy.org/pic/logo.png[/img] const lost = checkLostTags(textarea, /\[(?imglnk)\]/i, /\[\/(?imglnk)\]/i); if (lost.state) { return textarea.replace(/\[imglnk\]/i, function (s) { return addTempCode(s); }); }; return textarea.replace(/\[imglnk\](.*?)\[\/imglnk\]/i, function (all, url) { url = url.replace('&', '&'); if (/^((?!"|'|>|<|;|#).)+\.(?:png|jpg|jpeg|gif|svg|bmp|webp)$/i.test(url)) { // url 以 .png 之类结尾 return addTempCode(`image`); } else { return addTempCode(all); }; }); }; }; const code = (val, textarea) => { if (val === '=' || val === '="' || val === '=""') { textarea = textarea.replace(/\[code=(?:"){0,2}/, '[code]'); }; if (val) { textarea = textarea.replace(/\[code=(.*?)\]/i, function (s, v) { return addTempCode('[code=') + v + ']'; }); }; const lost = checkLostTags(textarea, /\[(?code)\]/i, /\[\/(?code)\]/i); if (lost.state) { return textarea.replace(/\[code\]/i, function (s) { return addTempCode(s); }); }; return textarea.replace(/\[code\](.*?)\[\/code\]/i, function (all, text) { return addTempCode(`
${lang['code']}
${text.replace(/  /g, ' ')}

`); }); }; const info = (val, textarea) => { if (val === '=' || val === '="' || val === '=""') { textarea = textarea.replace(/\[info=(?:"){0,2}/, '[info]'); }; if (val) { textarea = textarea.replace(/\[info=(.*?)\]/i, function (s, v) { return addTempCode('[info=') + v + ']'; }); }; const lost = checkLostTags(textarea, /\[(?info)\]/i, /\[\/(?info)\]/i); if (lost.state) { return textarea.replace(/\[info\]/i, function (s) { return addTempCode(s); }); }; return textarea.replace(/\[info\](.*?)\[\/info\]/i, function (all, text) { return addTempCode(`
${lang['info']}${text.replace(/  /g, ' ')}
`); }); }; const mediainfo = (val, textarea) => { if (val === '=' || val === '="' || val === '=""') { textarea = textarea.replace(/\[mediainfo=(?:"){0,2}/, '[mediainfo]'); }; if (val) { textarea = textarea.replace(/\[mediainfo=(.*?)\]/i, function (s, v) { return addTempCode('[mediainfo=') + v + ']'; }); }; const lost = checkLostTags(textarea, /\[(?mediainfo)\]/i, /\[\/(?mediainfo)\]/i); if (lost.state) { return textarea.replace(/\[mediainfo\]/i, function (s) { return addTempCode(s); }); }; return textarea.replace(/\[mediainfo\](.*?)\[\/mediainfo\]/i, function (all, text) { return addTempCode(`
${lang['mediainfo']}${text.replace(/  /g, ' ')}
`); }); }; const quote = (val, textarea) => { if (!val) { // [quote]我爱U2分享園@動漫花園。[/quote] const lost = checkLostTags(textarea, /\[(?quote)]/i, /\[\/(?quote)\]/i); if (lost.state) { return textarea.replace(/\[quote\]/i, function (s) { return addTempCode(s); }); }; return textarea.replace(/\[quote\](.*?)\[\/quote\]/i, function (s, x) { return '
' + lang['quote'] + '' + x.replace(/(
)*$/, '') + '
'; }); } else if (val === '=' || val === '="' || val === '=""') { // [quote=""]我爱U2分享園@動漫花園。[/quote] const lost = checkLostTags(textarea, /\[(?quote)=[^\[]*?\]/i, /\[\/(?quote)\]/i); if (lost.state) { return textarea.replace(/\[quote=[^\[]*?\]/i, function (s) { return addTempCode(s); }); }; return textarea.replace(/\[quote=[^\[]*?\](.*?)\[\/quote\]/i, function (s, x) { return '
' + lang['quote'] + '' + x.replace(/(
)*$/, '') + '
'; }); } else { // [quote="ABC"]我爱U2分享園@動漫花園。[/quote] const lost = checkLostTags(textarea, /\[(?quote)=[^\[]*?\]/i, /\[\/(?quote)\]/i); if (lost.state) { return textarea.replace(/\[quote=[^\[]*?\]/i, function (s) { return addTempCode(s); }); }; return textarea.replace(/\[quote=([^\[]*?)\](.*?)\[\/quote\]/i, function (all, tval, text) { if (tval.match(/\[/i)) return addTempCode(all);; let tmp = tval.replace(/^(?:")?(.*?)(?:")?$/, "$1"); if (!/"/.test(tmp)) { tval = tmp; }; return '
' + lang['quote'] + ': ' + tval + '' + text.replace(/(
)*$/, '') + '
'; }); }; }; const spoiler = (val, textarea) => { if (!val) { // [spoiler]我要剧透了![/spoiler] const lost = checkLostTags(textarea, /\[(?spoiler)]/i, /\[\/(?spoiler)\]/i); if (lost.state) { return textarea.replace(/\[spoiler\]/i, function (s) { return addTempCode(s); }); }; return textarea.replace(/\[spoiler\](.*?)\[\/spoiler\]/i, function (s, x) { return `` + `` + `` + `
${lang['spoiler']}  ` + `
`; }); } else if (val === '=' || val === '="' || val === '=""') { // [spoiler=""]真的![/spoiler] const lost = checkLostTags(textarea, /\[(?spoiler)=.+?\]/i, /\[\/(?spoiler)\]/i); if (lost.state) { return textarea.replace(/\[spoiler=[^\[]*?\]/i, function (s) { return addTempCode(s); }); }; return textarea.replace(/\[spoiler=.*?\](.*?)\[\/spoiler\]/i, function (s, x) { return `` + `` + `` + `
${lang['spoiler']}  ` + `
`; }); } else { // [spoiler="剧透是不可能的!"]真的![/spoiler] const lost = checkLostTags(textarea, /\[(?spoiler)=.+?\]/i, /\[\/(?spoiler)\]/i); if (lost.state) { return textarea.replace(/\[spoiler=[^\[]*?\]/i, function (s) { return addTempCode(s); }); }; return textarea.replace(/\[spoiler=(.*?)\](.*?)\[\/spoiler\]/i, function (all, tval, text) { if (tval.match(/\[/i)) return addTempCode(all);; let tmp = tval.replace(/^(?:")?(.*?)(?:")?$/, "$1"); if (!/"/.test(tmp)) tval = tmp; return `` + `` + `` + `
${tval}  ` + `
`; }); }; }; const localConvert = (textarea) => { let convert_count = 0; let index = 0; let _textarea = textarea; let bbcode_tag; while (bbcode_tag = /\[(?b|i|u|s|color|size|font|rt|mediainfo|info|code|url|img|imglnk|quote|pre|spoiler)(?=[^\[]*?)?\]/gi.exec(_textarea)) { let t; let tag = bbcode_tag.groups.tag; let val = bbcode_tag.groups.val; index = bbcode_tag.index; _textarea = _textarea.slice(index); // console.log(_textarea); // console.log(`当前标签:` + tag + ' | ' + val); switch (tag.toLowerCase()) { case 'b': t = b(val, _textarea); break; case 'i': t = i(val, _textarea); break; case 'u': t = u(val, _textarea); break; case 's': t = s(val, _textarea); break; case 'color': t = color(val, _textarea); break; case 'size': t = size(val, _textarea); break; case 'font': t = font(val, _textarea); break; case 'rt': t = rt(val, _textarea); break; case 'mediainfo': t = mediainfo(val, _textarea); break; case 'info': t = info(val, _textarea); break; case 'code': t = code(val, _textarea); break; case 'url': t = url(val, _textarea); break; case 'img': t = img(val, _textarea); break; case 'imglnk': t = imglnk(val, _textarea); break; case 'quote': t = quote(val, _textarea); break; case 'pre': t = pre(val, _textarea); break; case 'spoiler': t = spoiler(val, _textarea); break; default: break;; }; textarea = textarea.replace(_textarea, t); _textarea = t; if (++convert_count > 5000) break; // console.log('发生次数: ' + convert_count); // console.log(textarea); }; return textarea; }; bbcodestr = localConvert(bbcodestr); // 没有bbcode包裹的超链接 bbcodestr = bbcodestr.replace(/((?:https?|ftp|gopher|news|telnet|mms|rtsp):\/\/((?!<|>|\s|"|>|'|<|\(|\)|\[|\]).)+)/gi, function (s, x) { return '' + s + ''; }); // 单个标签 不带参 const o_reg = new RegExp("\\[(\\*|siteurl|site)\\]", "gi"); bbcodestr = bbcodestr.replace(o_reg, function (s, x, y) { switch (x) { case '*': return 'list'; case 'site': return 'U2分享園@動漫花園'; case 'siteurl': return 'https://u2.dmhy.org'; default: return s; }; }); // 表情 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 '[' + x + ']'; default: return s; }; }); for (let i = 0, len = tempCode.length; i < len; i++) { bbcodestr = bbcodestr.replace("", tempCode[i]); }; bbcodestr = bbcodestr + br_end; if (/(
)$/.test(bbcodestr)) { bbcodestr = bbcodestr + '
' }; // lost_tags // if (lost_tags.length !== 0) { // $('#preview_bbcode').html(`⚠ ${lang['preview']}`); // $('#preview_bbcode').attr('title', [...new Set(lost_tags)].join('\n')) // } else { // $('#preview_bbcode').html(lang['preview']); // $('#preview_bbcode').attr('title', '') // }; let htmlobj = document.createElement('div'); htmlobj.innerHTML = bbcodestr; $(htmlobj).children('fieldset').children('fieldset').children('fieldset').children('fieldset').each(function () { $(this).html($(this).html().replace(/(^[^<]*?<\/legend>)(.*)/i, function (s, x, y) { return x + '' + '
' + lang['auto_fold'] + '  ' + '' + '' + '
'; })); }); return $(htmlobj).html(); }; function getapi() { 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_id=' + 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) { const 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": "种子信息", "torrent_ver": "种子版本", "torrent_piece_length": "种子区块", "files": "文件数", "info_hash": "种子散列值", "show_or_hide": "显示 / 隐藏", "KiB": " KiB", "MiB": " MiB", "GiB": " GiB", "TiB": " TiB", "current_time": " 当前时间", "anonymous_user": " 匿名用户", "system": " 系统", "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": "種子訊息", "torrent_ver": "種子版本", "torrent_piece_length": "種子區塊", "files": "文件數", "info_hash": "種子散列值", "show_or_hide": "顯示 / 隱藏", "KiB": " KiB", "MiB": " MiB", "GiB": " GiB", "TiB": " TiB", "current_time": " 當前時間", "anonymous_user": " 匿名用戶", "system": " 系統", "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": "種子訊息", "torrent_ver": "種子版本", "torrent_piece_length": "種子區塊", "files": "文件數", "info_hash": "種子散列值", "show_or_hide": "顯示 / 隱藏", "KiB": " KiB", "MiB": " MiB", "GiB": " GiB", "TiB": " TiB", "current_time": " 當前時間", "anonymous_user": " 匿名用戶", "system": " 系統", "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", "torrent_ver": "Torrent Ver", "torrent_piece_length": "Torrent Piece Length", "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", "system": " 系統", "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": "Информация о торренте", "torrent_ver": "Торрент Вер", "torrent_piece_length": "Длина куска торрента", "files": "Файлов в торренте", "info_hash": "Информация о ХЕШЕ", "show_or_hide": "Показать / Скрыть", "KiB": " KiБ", "MiB": " MiБ", "GiB": " GiБ", "TiB": " TiБ", "current_time": " Текущее время", "anonymous_user": " Анонимный пользователь", "system": " система", "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'] }; // 生成种子评论cid定位url 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 '/' }; }; // 对JSON进行排序 // https://github.com/substack/json-stable-stringify const stringify = function (obj, opts) { if (!opts) opts = {}; if (typeof opts === 'function') opts = { cmp: opts }; var space = opts.space || ''; if (typeof space === 'number') space = Array(space + 1).join(' '); var cycles = (typeof opts.cycles === 'boolean') ? opts.cycles : false; var replacer = opts.replacer || function (key, value) { return value; }; var cmp = opts.cmp && (function (f) { return function (node) { return function (a, b) { var aobj = { key: a, value: node[a] }; var bobj = { key: b, value: node[b] }; return f(aobj, bobj); }; }; })(opts.cmp); var seen = []; return (function stringify(parent, key, node, level) { var indent = space ? ('\n' + new Array(level + 1).join(space)) : ''; var colonSeparator = space ? ': ' : ':'; if (node && node.toJSON && typeof node.toJSON === 'function') { node = node.toJSON(); } node = replacer.call(parent, key, node); if (node === undefined) { return; } if (typeof node !== 'object' || node === null) { return JSON.stringify(node); } if (isArray(node)) { var out = []; for (var i = 0; i < node.length; i++) { var item = stringify(node, i, node[i], level + 1) || JSON.stringify(null); out.push(indent + space + item); } return '[' + out.join(',') + indent + ']'; } else { if (seen.indexOf(node) !== -1) { if (cycles) return JSON.stringify('__cycle__'); throw new TypeError('Converting circular structure to JSON'); } else seen.push(node); var keys = objectKeys(node).sort(cmp && cmp(node)); var out = []; for (var i = 0; i < keys.length; i++) { var key = keys[i]; var value = stringify(node, key, node[key], level + 1); if (!value) continue; var keyValue = JSON.stringify(key) + colonSeparator + value; ; out.push(indent + space + keyValue); } seen.splice(seen.indexOf(node), 1); return '{' + out.join(',') + indent + '}'; } })({ '': obj }, '', obj, 0); }; const isArray = Array.isArray || function (x) { return {}.toString.call(x) === '[object Array]'; }; const objectKeys = Object.keys || function (obj) { var has = Object.prototype.hasOwnProperty || function () { return true }; var keys = []; for (var key in obj) { if (has.call(obj, key)) keys.push(key); } return keys; }; function convertBytesToAutoUnit(bytes) { var units = ['B', 'KiB', 'MiB']; var unitIndex = 0; while (bytes >= 1024 && unitIndex < units.length - 1) { bytes >>= 10; unitIndex++; }; return bytes + units[unitIndex]; }; async function loadExternalCssAsync(url) { return new Promise((resolve) => { const link = document.createElement("link"); link.rel = "stylesheet"; link.type = "text/css"; link.href = url; link.onload = resolve; link.onerror = resolve; document.head.appendChild(link); }); } function addGlobalStyles(cssRules) { const styleElement = document.createElement('style'); styleElement.appendChild(document.createTextNode(cssRules)); document.head.appendChild(styleElement); } function diffHistoryCommentBbcode(comments, type) { const elementId = type === 'torrent' ? '[id^=cid]' : '[id^=pid]'; $('.diff_comment_button_close').click(function () { $(this).hide(); $(this).next().show(); type === 'torrent' ? $(this).parents(elementId).parent().next().find('[class="rowfollow"]:last').show() : $(this).parents(elementId).parent().next().find('.post-body').parent().show(); $(this).parents(elementId).parent().next().find('.diff_comment_body').hide(); }) $('.diff_comment_button_open').click(function () { $(this).hide(); $(this).prev().show(); const options = $(this).next().html(); const post = type === 'torrent' ? $(this).parents(elementId).parent().next().find('[class="rowfollow"]:last') : $(this).parents(elementId).parent().next().find('.post-body').parent(); // 文字部分 post.hide() if ($(this).parents(elementId).parent().next().find('.draw-div').length !== 0) { // 已插入过的 $(this).parents(elementId).parent().next().find('.diff_comment_body').show(); return; } post.after(`
 
`); const leftSelect = $(this).parents(elementId).parent().next().find('.diff_comment_left_select'); const rightSelect = $(this).parents(elementId).parent().next().find('.diff_comment_right_select'); const drawElement = $(this).parents(elementId).parent().next().find('.draw-div'); leftSelect.add(rightSelect).change(function () { const leftValue = Number(leftSelect.val()); const rightValue = Number(rightSelect.val()); console.log(`${leftValue} | ${rightValue}`); drawDiffHistoryBbcode(comments, leftValue, rightValue, 'comment', drawElement); }); let leftEq = 1; let rightValue = Number(rightSelect.find('option:eq(0)').val()); var optionCount = rightSelect.find('option').length; let leftBbcode, rightBbcode; let flagBreak = false; while (leftEq < optionCount) { let leftValue = Number(leftSelect.find(`option:eq(${leftEq})`).val()); for (let i = 0, len = comments.length; i < len; i++) { if (comments[i].self === leftValue) { leftBbcode = comments[i].bbcode; } else if (comments[i].self === rightValue) { rightBbcode = comments[i].bbcode; } if (leftBbcode !== undefined && leftBbcode !== "" && rightBbcode !== undefined && rightBbcode !== "") break; } if (leftBbcode !== rightBbcode) { leftSelect.find(`option:eq(${leftEq})`).prop("selected", true); leftSelect.trigger("change"); flagBreak = true; break; } leftBbcode = ''; leftEq++; } if (!flagBreak) { // 如果修改记录的BBCODE都一样 leftSelect.find(`option:eq(1)`).prop("selected", true); rightSelect.find(`option:eq(0)`).prop("selected", true); leftSelect.trigger("change"); } }); } function preCheckBbcodeDiscrepancy(data, left, right) { // 预检测两边BBCODE是否存在差异 let leftBbcode = generateBbcode(data[left]); let rightBbcode = generateBbcode(data[right]); return !(leftBbcode === rightBbcode || typeof leftBbcode === 'undefined' || typeof rightBbcode === 'undefined'); } function generateBbcode(data) { return `Title: ${data.title} Subtitle: ${data.subtitle || 'N/A'} Uploader Name: ${data.uploader_name} Category: ${data.category} Anidb: ${data.anidb || 'N/A'} *此变动不精准,仅供参考。 Description: ${data.description_info}`; } function drawDiffHistoryBbcode(data, leftValue, rightValue, type, drawElement) { /* addGlobalStyles(`.diff-container{ display: flex; align-items: flex-start; justify-content: flex-start; } .diff-cell{ border: none; padding: 0; margin-left: 5px; flex: 1; } .draw-div{ box-sizing: border-box; max-width: 100%; min-height: 15px; max-height: 600px; margin: 5px; overflow: auto; border-top: 1px solid #bfbfbf; border-bottom: 1px solid #bfbfbf; } .diff-table { width: 100%; border-left: 1px solid #bfbfbf; border-right: 1px solid #bfbfbf; background-color: white; } .diff-table table, .diff-table table td{ background-color: transparent; border: none; vertical-align: top; } .diff-table, .diff-table table { border-collapse: collapse; box-sizing: border-box; table-layout: fixed; font-family: ui-monospace,SFMono-Regular,SF Mono,Menlo,Consolas,Liberation Mono,monospace; font-size: 12px; } .diff-table tbody { vertical-align: top; } .diff-table del { text-decoration: none; background-color: #ff818266; } .diff-table ins { text-decoration: none; background-color: #abf2bc; } .diff-linenumber { text-align: right; vertical-align: top; width: 3em; border: none; color: #6e7781; font-size: 12px; } .diff-linenumber-delete { background-color: #ffd7d5; } .diff-linenumber-insert { background-color: #ccffd8; } .diff-line-text-delete { background-color: #ffebe9; } .diff-line-text-insert { background-color: #e6ffec; } .diff-linenumber-empty, .diff-text-cell-empty { background-color: #d0d8e080; } .diff-line-text { display: inline-block; white-space: pre-wrap; overflow-wrap: break-word; word-break: break-word; box-sizing: border-box; width: auto; font-size: 12px; } .diff-line-prefix { background: none; word-wrap: break-word; display: inline; font-size: 12px; box-sizing: border-box; vertical-align: top; } .diff-line-prefix-delete::before { content: " - "; } .diff-line-prefix-insert::before { content: " + "; } .diff-line-prefix-empty::before { content: " "; } .diff-text-cell, .diff-text-cell-empty { width: auto; white-space: pre; border-left: none; border-right: 1px solid #bfbfbf; border-top: none; border-bottom: none; }`); */ // 生成BBCODE内容 for (let i = 0, len = data.length; i < len; i++) { if (data[i].self === leftValue) { var leftBbcode = type === 'torrent' ? generateBbcode(data[i]) : data[i].bbcode; } else if (data[i].self === rightValue) { var rightBbcode = type === 'torrent' ? generateBbcode(data[i]) : data[i].bbcode; } } if (leftBbcode === rightBbcode || typeof leftBbcode === 'undefined' || typeof rightBbcode === 'undefined') { drawElement.html(`
bbcode without changes
`); return; } const configuration = { drawFileList: false, fileListToggle: false, fileListStartVisible: false, fileContentToggle: false, matching: 'lines', outputFormat: 'side-by-side', // line-by-line or side-by-side synchronisedScroll: true, highlight: false, renderNothingWhenEmpty: false, wordWrap: true, stickyFileHeaders: false, }; let $diffHtml = $(Diff2Html.html(Diff.createTwoFilesPatch("a", "b", leftBbcode, rightBbcode), configuration)); let $diffTbody = $diffHtml.find('tbody.d2h-diff-tbody'); const processTr = ($tr) => { let list = []; $tr.each(function () { let obj; if ($(this).find('td.d2h-code-side-linenumber.d2h-info').length == 1) { // 行信息 const header = $(this).text().trim(); list.push({ "type": 'header', "content": header }); } else { const number = $(this).find("td[class^='d2h-code-side-linenumber']").text().trim(); const prefix = $(this).find('span.d2h-code-line-prefix').text(); let content = $(this).find('span.d2h-code-line-ctn').html(); content = content === '
' ? '' : content; const state = (prefix === '+') ? 'add' : ((prefix === '-') ? 'del' : 'no'); list.push({ "type": 'content', "content": content, "prefix": prefix, "line": number }); } }); return list; } let oldList = processTr($diffTbody.eq(0).children('tr')); let newList = processTr($diffTbody.eq(1).children('tr')); let $html = $(`
`); const $tbody = $html.find('#diff-tbody'); for (let index = 0; index < oldList.length; index++) { if (oldList[index].type === 'header') { $tbody.append(`` + `${oldList[index].content}` + `` + ``); continue; } const oldPrefix = oldList[index].prefix; const oldContent = oldList[index].content; const oldLine = oldList[index].line; const newPrefix = newList[index].prefix; const newContent = newList[index].content; const newLine = newList[index].line; if (oldPrefix === ' ' && newPrefix === ' ') { // 两边都没有修改 $tbody.append(`` + `${oldLine} ` + `` + `
${oldContent}
` + `` + `${newLine} ` + `` + `
${newContent}
` + `` + ``); } else if (oldPrefix === '-' && newPrefix === '+') { $tbody.append(`` + `${oldLine} ` + `` + `
${oldContent}
` + `` + `${newLine} ` + `` + `
${newContent}
` + `` + ``); } else if (oldPrefix === '-' && newPrefix === ' ') { $tbody.append(`` + `${oldLine} ` + `` + `
${oldContent}
` + `` + `` + `` + ``); } else if (oldPrefix === ' ' && newPrefix === '+') { $tbody.append(`` + `` + `` + `${newLine} ` + `` + `
${newContent}
` + `` + ``); } } drawElement.html($html); }