在购买心得 #####play 和 2Game 板块的帖子一楼开始位置添加折扣表格,折后价和史低可排序。
// ==UserScript== // @name Keylol #####play 2Game Table // @namespace https://greasyfork.org/users/34380 // @version 20240918 // @description 在购买心得 #####play 和 2Game 板块的帖子一楼开始位置添加折扣表格,折后价和史低可排序。 // @supportURL https://keylol.com/t920709-1-1 // @match https://keylol.com/t* // @match https://keylol.com/forum.php?mod=viewthread&tid=* // @connect gitee.com // @connect raw.githubusercontent.com // @grant GM_xmlhttpRequest // ==/UserScript== (function () { 'use strict'; if (document.querySelector('.subforum_left_title_left_up').innerText.match(/#####play/)) { document.querySelector('head').insertAdjacentHTML('beforeend', `<style> .td-wide-80 { width:80px; } .td-wide-50 { width:50px; } .hidden1,.hidden2,.hidden3,.hidden4 { display:none; }</style>`); const html_table = `<br><div class="sff_collapse"><div class="sff_collapse_b" onclick="var s = this.parentNode; while (!s.classList.contains('sff_collapse')) {s = s.parentNode;} if (s.classList.contains('sff_collapsed')) {s.classList.remove('sff_collapsed');} else {s.classList.add('sff_collapsed');}"><span class="sff_collapse_t">></span> 折扣表格</div><div class="sff_collapse_d"> <span id="checkbox-rows"><label><input id="cb-tr-higher" type="checkbox" value="tr-higher"></input>高于史低</label><label><input id="cb-tr-old" type="checkbox" value="tr-old"></input>高于史低CP</label><label><input id="cb-tr-not-wish" type="checkbox" value="tr-not-wish"></input>非愿望单</label><label><input id="cb-tr-own" type="checkbox" value="tr-own"></input>已拥有</label></span> <table id="table-#####play" class="t_table"><thead><tr><td data-col="index" data-reverse="1">游戏名</td><td class="td-wide-80" data-col="coupon" data-reverse="-1">折后价</td><td class="td-wide-80" data-col="hist-cp" data-reverse="-1">史低CP</td><td class="td-wide-80" data-col="hist" data-reverse="-1">史低</td><td>区域</td><td class="td-wide-50">截止</td><td>折扣码</td><td class="td-wide-50">加购</td></tr></thead><tbody></tbody></table> <div><a href="javascript:;" onclick="var s = this.parentNode; while (!s.classList.contains('sff_collapse')) {s = s.parentNode;} s.scrollIntoView(true); if (s.classList.contains('sff_collapsed')) {s.classList.remove('sff_collapsed');} else {s.classList.add('sff_collapsed');}">点击隐藏</a></div></div></div>`; const floor1 = document.querySelector('.t_f'); const anchor = floor1.querySelector('.t_f .pstatus') || floor1.querySelector('.original_text_style1'); if (anchor) { anchor.insertAdjacentHTML('afterend', '' + html_table); } else { floor1.insertAdjacentHTML('afterbegin', html_table); } const cb_rows = floor1.querySelector('#checkbox-rows'); cb_rows.querySelectorAll('input').forEach((cb) => { cb.checked = true; }); const tbody = floor1.querySelector('#table-#####play > tbody'); // table col > name discount hist region expire code cart steam let name; let discount = 0; let hist = 0; let region; let expire; let code = ''; let steam; let is_code4down let trs = []; let i_start = 0; let i_end = 0; let is_hist_fill = true; const vnode = document.createElement('div'); vnode.innerHTML = floor1.innerHTML.replace(/<\/?span[^>]*>/g, '').replace(/<\/?strong[^>]*>/g, ''); const nodes = vnode.childNodes; nodes.forEach((node) => { readNode(node); }); GM_xmlhttpRequest({ method: "GET", url: 'https://gitee.com/mouse040429/keylol-#####play-table/raw/main/datacp.json', timeout: 9100, onload: (res) => { try { const data = JSON.parse(res.responseText); newTable(data); } catch (e) { console.log('可能是 Gitee 屏蔽关键字导致出错,正在连接 Github。'); GM_xmlhttpRequest({ method: "GET", url: 'https://raw.githubusercontent.com/mouse040429/Keylol-#####play-Table/refs/heads/main/datacp.json', timeout: 9100, onload: (res) => { const data = JSON.parse(res.responseText); console.log('成功连接到 Github。'); newTable(data); } }); } } }); setTimeout(() => { tbody.querySelectorAll('tr > td:nth-child(1) > a').forEach((node) => { if (!node.classList.contains('steam-info-wish')) { if (node.classList.contains('steam-info-own')) { node.parentNode.parentNode.classList.add('tr-own', 'tr-not-wish'); } else { node.parentNode.parentNode.classList.add('tr-not-wish'); } } }); }, 5000); function newTable(data) { let html = ''; trs.forEach((tds, i) => { // tds [name, parseFloat(discount), parseFloat(hist), region, expire, code, cart, steam]; const is_lower = tds[1] <= tds[2]; const cur = data[tds[6]]; let td_hist; let is_newlow = false; if (cur) { const _low = cur.low; is_newlow = tds[1] <= _low[0]; let tit = padEnsp(_low[0]) + _low[1] + ' '; cur.hist.forEach((item) => { tit = tit + ' ' + padEnsp(item[0]) + item[1]; }); td_hist = `<td data-hist-cp="${_low[0]}" title="${tit}">${is_newlow ? '<span style="background-color:LightBlue">' + _low[0] + '</span>' : _low[0]}</td>`; } else { td_hist = `<td data-hist-cp="0">0</td>`; } html = html + `<tr class="${is_lower ? '' : 'tr-higher '}${is_newlow ? '' : 'tr-old'}"><td data-index="${i}"><a href="https://store.steampowered.com/${tds[7]}/" target="_blank">${tds[0]}</a></td><td data-coupon="${tds[1]}">${is_lower ? '<span style="background-color:Wheat">' + tds[1] + '</span>' : tds[1]}</td>${td_hist}<td data-hist="${tds[2]}">${tds[2]}</td><td>${tds[3]}</td><td>${tds[4]}</td><td>${tds[5]}</td><td><a href="https://#####play.store/detail/${tds[6]}/" target="_blank">加购</a></td></tr>`; }); tbody.innerHTML = html; function padEnsp(para) { for (let i = para.toString().length; i < 8; i++) { para += ' '; } return para; } } function readNode(node) { if (node.nodeName == 'H1') { expire = ''; region = '-'; const matched1 = node.innerText.match(/((\d+\.\d+)?)(.*)((.*))/); if (matched1) { expire = matched1[1]; region = matched1[4]; i_end = trs.length; for (; i_start < i_end; i_start++) { trs[i_start][5] = code; } const matched2 = matched1[3].match(/.*《(.*)》/); if (matched2) { name = matched2[1]; } if (!is_hist_fill) { trs[i_end - 1][2] = hist; } } } else if (node.nodeName == 'A') { if (node.href.match(/https:\/\/store\.steampowered\.com\/(app|sub|bundle)\/\d+\//)) { name = node.innerText; steam = node.href.match(/https:\/\/store\.steampowered\.com\/((app|sub|bundle)\/\d+)\//)[1]; } else if (node.href.match(/https:\/\/#####play\.store\/detail\/[\w-]+\/?/)) { const cart = node.href.match(/https:\/\/#####play\.store\/detail\/([\w-]+)\/?/)[1]; if (!name) { name = cart.replace(/-/g, ' ').replace(' ', ' - '); } trs.push([name, parseFloat(discount), parseFloat(hist), region, expire, code, cart, steam]); if (is_code4down) { i_start++; } name = null; hist = 0; is_hist_fill = true; } } else if (node.nodeName == '#text') { const content = node.textContent; if (content.match(/史低:?(\d+(\.\d+)?)/)) { hist = content.match(/史低:?(\d+(\.\d+)?)/)[1]; is_hist_fill = false; } else if (content.match(/(\d+(\.\d+)?)元/)) { discount = content.match(/(\d+(\.\d+)?)元/)[1]; } else if (content.match(/适用折扣码:/)) { code = content.match(/折扣码:(\S+)/)[1]; is_code4down = true; } else if (content.match(/对应折扣码:/)) { code = content.match(/折扣码:(\S+)/)[1]; } } } cb_rows.addEventListener('click', (event) => { if (event.target.nodeName == 'INPUT') { const hidden = { 'tr-higher': 'hidden1', 'tr-old': 'hidden2', 'tr-not-wish': 'hidden3', 'tr-own': 'hidden4' } const value = event.target.value; tbody.querySelectorAll('.' + value).forEach((node) => { node.classList.toggle(hidden[value]); }); } }); floor1.querySelector('#table-#####play > thead > tr').addEventListener('click', function (event) { const target = event.target; if (target.nodeName == 'TD' && target.hasAttribute('data-reverse')) { const col = target.getAttribute('data-col'); let reverse = target.getAttribute('data-reverse'); let sorted; if (reverse == 0) { sorted = Array.from(tbody.querySelectorAll('tr')).sort((a, b) => { return b.querySelector('td[data-' + col + ']').getAttribute('data-' + col) - a.querySelector('td[data-' + col + ']').getAttribute('data-' + col); }); const siblings = this.querySelectorAll('[data-reverse="1"]'); target.setAttribute('data-reverse', '1'); siblings.forEach((node) => { node.setAttribute('data-reverse', '0'); }); } else { sorted = Array.from(tbody.querySelectorAll('tr')).sort((a, b) => { return a.querySelector('td[data-' + col + ']').getAttribute('data-' + col) - b.querySelector('td[data-' + col + ']').getAttribute('data-' + col); }); const siblings = this.querySelectorAll('[data-reverse="0"]'); target.setAttribute('data-reverse', '0'); siblings.forEach((node) => { node.setAttribute('data-reverse', '1'); }); } sorted.forEach((node) => { tbody.insertAdjacentElement('beforeend', node); }); } }); } else if (document.querySelector('.subforum_left_title_left_up').innerText.match(/2Game/)) { document.querySelector('head').insertAdjacentHTML('beforeend', `<style> .td-wide-80 { width:80px; } .td-wide-50 { width:50px; } .hidden1,.hidden2,.hidden3,.hidden4 { display:none; }</style>`); const html_table = `<br><div class="sff_collapse"><div class="sff_collapse_b" onclick="var s = this.parentNode; while (!s.classList.contains('sff_collapse')) {s = s.parentNode;} if (s.classList.contains('sff_collapsed')) {s.classList.remove('sff_collapsed');} else {s.classList.add('sff_collapsed');}"><span class="sff_collapse_t">></span> 折扣表格</div><div class="sff_collapse_d"> <span id="checkbox-rows"><label><input id="cb-tr-old" type="checkbox" value="tr-old"></input>高于史低2G</label><label><input id="cb-tr-not-wish" type="checkbox" value="tr-not-wish"></input>非愿望单</label><label><input id="cb-tr-own" type="checkbox" value="tr-own"></input>已拥有</label></span> <table id="table-#####play" class="t_table" style="width:80%"><thead><tr><td data-col="index" data-reverse="1">游戏名</td><td class="td-wide-80" data-col="coupon" data-reverse="-1">折后价</td><td class="td-wide-80" data-col="hist-cp" data-reverse="-1">史低2G</td><td class="td-wide-50">加购</td></tr></thead><tbody></tbody></table> <div><a href="javascript:;" onclick="var s = this.parentNode; while (!s.classList.contains('sff_collapse')) {s = s.parentNode;} s.scrollIntoView(true); if (s.classList.contains('sff_collapsed')) {s.classList.remove('sff_collapsed');} else {s.classList.add('sff_collapsed');}">点击隐藏</a></div></div></div>`; const floor1 = document.querySelector('.t_f'); const anchor = floor1.querySelector('.t_f .pstatus') || floor1.querySelector('.original_text_style1'); if (anchor) { anchor.insertAdjacentHTML('afterend', '' + html_table); } else { floor1.insertAdjacentHTML('afterbegin', html_table); } const cb_rows = floor1.querySelector('#checkbox-rows'); cb_rows.querySelectorAll('input').forEach((cb) => { cb.checked = true; }); const tbody = floor1.querySelector('#table-#####play > tbody'); // table col > name discount hist region expire code cart steam let name; let version; let discount = 0; let hist = 0; let region; let expire; let code = ''; let steam; let trs = []; let i_start = 0; let i_end = 0; let is_hist_fill = true; const vnode = document.createElement('div'); vnode.innerHTML = floor1.innerHTML.replace(/<\/?span[^>]*>/g, '').replace(/<\/?strong[^>]*>/g, ''); const nodes = vnode.childNodes; nodes.forEach((node) => { readNode(node); }); GM_xmlhttpRequest({ method: "GET", url: 'https://gitee.com/mouse040429/keylol-#####play-table/raw/main/data2g.json', timeout: 9100, onload: (res) => { try { const data = JSON.parse(res.responseText); newTable(data); } catch (e) { console.log('可能是 Gitee 屏蔽关键字导致出错,正在连接 Github。'); GM_xmlhttpRequest({ method: "GET", url: 'https://raw.githubusercontent.com/mouse040429/Keylol-#####play-Table/refs/heads/main/data2g.json', timeout: 9100, onload: (res) => { const data = JSON.parse(res.responseText); console.log('成功连接到 Github。'); newTable(data); } }); } } }); setTimeout(() => { tbody.querySelectorAll('tr > td:nth-child(1) > a').forEach((node) => { if (!node.classList.contains('steam-info-wish')) { if (node.classList.contains('steam-info-own')) { node.parentNode.parentNode.classList.add('tr-own', 'tr-not-wish'); } else { node.parentNode.parentNode.classList.add('tr-not-wish'); } } }); }, 5000); function newTable(data) { let html = ''; trs.forEach((tds, i) => { // tds [name, parseFloat(discount), parseFloat(hist), region, expire, code, cart, steam]; const cur = data[tds[2]]; let td_hist; let is_newlow = false; if (cur) { const _low = cur.low; is_newlow = tds[1] <= _low[0]; let tit = _low[0] + ' ' + _low[1] + ' '; cur.hist.forEach((item) => { tit = tit + ' ' + item[0] + ' ' + item[1]; }); td_hist = `<td data-hist-2g="${_low[0]}" title="${tit}">${is_newlow ? '<span style="background-color:LightBlue">' + _low[0] + '</span>' : _low[0]}</td>`; } else { td_hist = `<td data-hist-2g="0">0</td>`; } html = html + `<tr class="${is_newlow ? '' : 'tr-old'}"><td data-index="${i}"><a href="https://store.steampowered.com/${tds[3]}/" target="_blank">${tds[0]}</a></td><td data-coupon="${tds[1]}">${tds[1]}</td>${td_hist}<td><a href="https://#####play.store/detail/${tds[2]}/" target="_blank">加购</a></td></tr>`; }); tbody.innerHTML = html; } function readNode(node) { if (node.nodeName == 'A') { console.log('a'); if (node.href.match(/https?:\/\/store\.steampowered\.com\/(app|sub|bundle)\/\d+\//)) { name = node.innerText; steam = node.href.match(/https?:\/\/store\.steampowered\.com\/((app|sub|bundle)\/\d+)\//)[1]; } else if (node.href.match(/https:\/\/2game\.hk\/cn\/[\w-]+\/?/)) { const cart = node.href.match(/https:\/\/2game\.hk\/cn\/([\w-]+)/)[1]; trs.push([name + version, parseFloat(discount), cart, steam]); hist = 0; is_hist_fill = true; } } else if (node.nodeName == '#text') { const content = node.textContent; if (content.match(/价格:\d+(\.\d+)?/)) { version = content.match(/(.*)叠加折扣码价格:/)[1]; discount = content.match(/价格:(\d+(\.\d+)?)/)[1]; } } else if (node.nodeName == 'DIV') { node.childNodes.forEach((_node) => { readNode(_node); }); } } cb_rows.addEventListener('click', (event) => { if (event.target.nodeName == 'INPUT') { const hidden = { 'tr-higher': 'hidden1', 'tr-old': 'hidden2', 'tr-not-wish': 'hidden3', 'tr-own': 'hidden4' } const value = event.target.value; tbody.querySelectorAll('.' + value).forEach((node) => { node.classList.toggle(hidden[value]); }); } }); floor1.querySelector('#table-#####play > thead > tr').addEventListener('click', function (event) { const target = event.target; if (target.nodeName == 'TD' && target.hasAttribute('data-reverse')) { const col = target.getAttribute('data-col'); let reverse = target.getAttribute('data-reverse'); let sorted; if (reverse == 0) { sorted = Array.from(tbody.querySelectorAll('tr')).sort((a, b) => { return b.querySelector('td[data-' + col + ']').getAttribute('data-' + col) - a.querySelector('td[data-' + col + ']').getAttribute('data-' + col); }); const siblings = this.querySelectorAll('[data-reverse="1"]'); target.setAttribute('data-reverse', '1'); siblings.forEach((node) => { node.setAttribute('data-reverse', '0'); }); } else { sorted = Array.from(tbody.querySelectorAll('tr')).sort((a, b) => { return a.querySelector('td[data-' + col + ']').getAttribute('data-' + col) - b.querySelector('td[data-' + col + ']').getAttribute('data-' + col); }); const siblings = this.querySelectorAll('[data-reverse="0"]'); target.setAttribute('data-reverse', '0'); siblings.forEach((node) => { node.setAttribute('data-reverse', '1'); }); } sorted.forEach((node) => { tbody.insertAdjacentElement('beforeend', node); }); } }); } })();