您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Loads all geeklist items into a single view simmilar to Peyo61's external tool.
当前为
// ==UserScript== // @name Board Game Geek - One page auction geeklists // @namespace http://tampermonkey.net/ // @version 0.4 // @description Loads all geeklist items into a single view simmilar to Peyo61's external tool. // @author Kempeth @ boardgamegeek // @match https://boardgamegeek.com/geeklist/* // @icon https://cf.geekdo-static.com/icons/favicon2.ico // @grant GM_setValue // @grant GM_getValue // @license MIT // ==/UserScript== const FETCHLIMIT = 20000; var nodeBtnConvert; var nodeProgressFull; var nodeProgressEmpty; var nodeItemList; var nodeFirstItem; var geeklistid; var taggedItems = []; // list of ids var items = []; // data from api (function() { 'use strict'; //console.log('root function'); init(); })(); function retry(f) { window.setTimeout(f, 500); } function init() { //console.log('init function'); var els = document.getElementsByTagName('gg-geeklist-page-ui'); //console.log(els); if (els.length == 0) { retry(init); return; } els = els[0].getElementsByTagName('header'); //console.log(els); if (els.length == 0) { retry(init); return; } els = els[0].getElementsByTagName('nav'); //console.log(els); if (els.length == 0) { retry(init); return; } var el = els[0]; nodeBtnConvert = document.createElement('button'); nodeBtnConvert.innerHTML = "One Page Auction"; nodeBtnConvert.className = "btn btn-warning"; nodeBtnConvert.onclick = convert; el.append(nodeBtnConvert); } function setProgress(done, total) { var percentage = done * 100.0 / total; nodeProgressFull.style.width = percentage + '%'; nodeProgressEmpty.style.width = (100 - percentage) + '%'; nodeProgressFull.setAttribute('aria-valuemax', total); nodeProgressFull.setAttribute('aria-valuenow', done); if (percentage > 50) { nodeProgressFull.innerHTML = done + ' / ' + total; nodeProgressEmpty.innerHTML = ''; } else { nodeProgressEmpty.innerHTML = done + ' / ' + total; nodeProgressFull.innerHTML = ''; } } function convert() { var els = document.getElementsByTagName('gg-geeklist-page-ui'); //console.log(els); if (els.length == 0) { retry(convert); return; } els = els[0].getElementsByTagName('div'); //console.log(els); if (els.length == 0) { retry(convert); return; } var footerNav = els[0].getElementsByTagName('nav'); //console.log(footerNav); if (els.length == 0) { retry(convert); return; } footerNav = footerNav[footerNav.length - 1]; els = els[0].getElementsByTagName('header'); //console.log(els); if (els.length == 0) { retry(convert); return; } els = els[0].getElementsByTagName('nav'); //console.log(els); if (els.length == 0) { retry(convert); return; } var headerNav = els[0]; els = document.getElementsByTagName('gg-geeklist-items-ui'); //console.log(els); if (els.length == 0) { retry(convert); return; } els = els[0].getElementsByTagName('div'); //console.log(els); if (els.length == 0) { retry(convert); return; } nodeItemList = els[0]; // remove header items for (var child of headerNav.childNodes) { if (child.tagName != 'GG-THUMBS-GEEKGOLD-GIVEN' && child.tagName != 'GG-SUBSCRIPTION-BUTTON') { headerNav.removeChild(child); } } // add header items var progress = document.createElement('div'); progress.className = "progress"; progress.style.height = "32px"; progress.style.width = "256px"; headerNav.appendChild(progress); nodeProgressFull = document.createElement('div'); nodeProgressFull.className = "progress-bar"; nodeProgressFull.setAttribute('role', 'progressbar'); nodeProgressFull.setAttribute('aria-valuemin', 0); nodeProgressFull.setAttribute('aria-valuemax', 0); nodeProgressFull.setAttribute('aria-valuenow', 0); nodeProgressFull.style.width = '0%'; nodeProgressFull.innerHTML = ''; progress.appendChild(nodeProgressFull); nodeProgressEmpty = document.createElement('div'); nodeProgressEmpty.className = "progress-bar bg-secondary"; nodeProgressEmpty.setAttribute('role', 'progressbar'); nodeProgressEmpty.style.width = '100%'; nodeProgressEmpty.innerHTML = '0 / ???'; progress.appendChild(nodeProgressEmpty); var btn = document.createElement('button'); btn.innerHTML = "Refresh"; btn.className = "btn btn-primary"; headerNav.appendChild(btn); // Sort Dropdown var ddSort = document.createElement('div'); ddSort.className = "dropdown"; headerNav.appendChild(ddSort); var ddSortBtn = document.createElement('button'); ddSortBtn.innerText = "Sort "; ddSortBtn.className = "btn btn-secondary dropdown-toggle"; ddSort.appendChild(ddSortBtn); var ddSortList = document.createElement('ul'); ddSortList.className = "dropdown-menu"; ddSort.appendChild(ddSortList); ddSortBtn.onclick = () => { ddSortList.style.display = (ddSortList.style.display == "block") ? "none" : "block"; }; ddSortBtn.onblur = () => { window.setTimeout(() => { ddSortList.style.display = "none"; }, 200); }; var ddSortPosted = document.createElement('li'); ddSortPosted.innerHTML = "<button type=\"button\" class=\"dropdown-item\">Posted</button>"; ddSortPosted.onclick = () => { console.log('sorting by default'); sortBy(''); }; ddSortList.appendChild(ddSortPosted); var ddSortName = document.createElement('li'); ddSortName.innerHTML = "<button type=\"button\" class=\"dropdown-item\">Name</button>"; ddSortName.onclick = () => { console.log('sorting by name'); sortBy('name'); }; ddSortList.appendChild(ddSortName); // Filter Dropdown var ddFilter = document.createElement('div'); ddFilter.className = "dropdown"; headerNav.appendChild(ddFilter); var ddFilterBtn = document.createElement('button'); ddFilterBtn.innerText = "Filter "; ddFilterBtn.className = "btn btn-secondary dropdown-toggle"; ddFilter.appendChild(ddFilterBtn); var ddFilterList = document.createElement('ul'); ddFilterList.className = "dropdown-menu"; ddFilter.appendChild(ddFilterList); ddFilterBtn.onclick = () => { ddFilterList.style.display = (ddFilterList.style.display == "block") ? "none" : "block"; }; ddFilterBtn.onblur = () => { window.setTimeout(() => { ddFilterList.style.display = "none"; }, 200); }; var ddFilterBoardgames = document.createElement('li'); ddFilterBoardgames.className = "dropdown-item"; ddFilterBoardgames.innerHTML = "<input class=\"form-check-input\" type=\"checkbox\" value=\"\" checked id=\"filterBoardgames\"> " + "<label class=\"form-check-label\" for=\"filterBoardgames\">Boardgames</label>"; ddFilterList.appendChild(ddFilterBoardgames); document.getElementById('filterBoardgames').onclick = filterList; var ddFilterExpansions = document.createElement('li'); ddFilterExpansions.className = "dropdown-item"; ddFilterExpansions.innerHTML = "<input class=\"form-check-input\" type=\"checkbox\" value=\"\" checked id=\"filterExpansions\"> " + "<label class=\"form-check-label\" for=\"filterExpansions\">Expansions</label>"; ddFilterList.appendChild(ddFilterExpansions); document.getElementById('filterExpansions').onclick = filterList; var ddFilterDivider = document.createElement('li'); ddFilterDivider.innerHTML = "<hr class=\"dropdown-divider\">"; ddFilterList.appendChild(ddFilterDivider); var ddFilterUntagged = document.createElement('li'); ddFilterUntagged.className = "dropdown-item"; ddFilterUntagged.innerHTML = "<input class=\"form-check-input\" type=\"checkbox\" value=\"\" checked id=\"filterUntagged\"> " + "<label class=\"form-check-label\" for=\"filterUntagged\">Untagged</label>"; ddFilterList.appendChild(ddFilterUntagged); document.getElementById('filterUntagged').onclick = filterList; var ddFilterTagged = document.createElement('li'); ddFilterTagged.className = "dropdown-item"; ddFilterTagged.innerHTML = "<input class=\"form-check-input\" type=\"checkbox\" value=\"\" checked id=\"filterTagged\"> " + "<label class=\"form-check-label\" for=\"filterTagged\">Tagged</label>"; ddFilterList.appendChild(ddFilterTagged); document.getElementById('filterTagged').onclick = filterList; // remove convert button nodeBtnConvert.parentNode.removeChild(nodeBtnConvert); // remove geeklist items //nodeItemList.innerHTML = ''; nodeFirstItem = nodeItemList.childNodes[0]; nodeItemList.className = "tw-grid tw-gap-2"; // remove footer nav //footerNav.parentNode.removeChild(footerNav); footerNav.innerHTML = ''; geeklistid = window.location.pathname.split('/')[2]; getTaggedItems(); items = []; fetchPage(1); } function fetchPage(page) { // https://api.geekdo.com/api/listitems?page=1&listid=301669 var url = "https://api.geekdo.com/api/listitems?page=" + page + "&listid=" + geeklistid; fetch(url) .then(response => response.json()) .then( data => { //console.log(data); var nr = (data.pagination.pageid - 1) * data.pagination.perPage; for (var item of data.data) { items[nr] = item; nr++; makeRow(nr, item); } setProgress(nr, data.pagination.total); if (data.data.length < data.pagination.perPage) { console.log("last page"); } else if (page < FETCHLIMIT) { console.log("more pages"); fetchPage(page + 1); } } ); } function makeRow(nr, item) { var row = document.createElement('span'); row.className = "tw-relative tw-flex tw-flex-wrap tw-items-center tw-gap-x-1.5 tw-gap-y-2 tw-rounded-md tw-border tw-border-gray-400 tw-bg-gray-100 tw-p-2"; const thingtype = item.item.href.split('/')[1]; const bodylower = item.body.toLowerCase(); const notsold = bodylower.includes("not sold"); const soldto = bodylower.includes("sold to"); const sold = bodylower.includes("sold"); const auctionclosed = bodylower.includes("auction closed"); var struckout = 0; var struckoutstart = bodylower.indexOf("[-]"); var struckoutend = bodylower.indexOf("[/-]"); while (struckoutstart >= 0 && struckoutend >= 0) { struckout += struckoutend - struckoutstart; struckoutstart = bodylower.indexOf("[-]", struckoutstart + 1); struckoutend = bodylower.indexOf("[/-]", struckoutend + 1); } var tagButton = document.createElement("button"); if (taggedItems.includes(item.id)) { tagButton.className = "btn btn-sm btn-primary"; tagButton.innerText = "Tagged"; } else { tagButton.className = "btn btn-sm btn-outline-primary"; tagButton.innerText = "Tag"; } tagButton.onclick = () => { toggleTaggedItem(tagButton, item.id); }; row.appendChild(tagButton); var tagGeeklistLink = document.createElement("a"); tagGeeklistLink.href = "/geeklist/" + geeklistid + "/test?itemid=" + item.id + "#" + item.id; tagGeeklistLink.target = "_blank"; tagGeeklistLink.innerText = nr + "."; row.appendChild(tagGeeklistLink); var txtThingType = document.createTextNode(thingtype == "boardgame" ? "Boardgame" : thingtype == "boardgameexpansion" ? "Expansion" : "Other"); row.appendChild(txtThingType); var tagGeeklistItemLink = document.createElement("a"); tagGeeklistItemLink.href = item.item.href; tagGeeklistItemLink.target = "_blank"; tagGeeklistItemLink.style.maxWidth = "50%"; tagGeeklistItemLink.style.textOverflow = "ellipsis"; tagGeeklistItemLink.style.overflow = "hidden"; tagGeeklistItemLink.style.whiteSpace = "nowrap"; tagGeeklistItemLink.innerText = item.item.name; row.appendChild(tagGeeklistItemLink); var tagState = document.createElement("span"); if (notsold) { tagState.innerText = "not sold"; tagState.className = "badge bg-danger"; } else if (soldto || sold) { tagState.innerText = "sold"; tagState.className = "badge bg-danger"; } else if (auctionclosed || struckout > 100) { tagState.innerText = "closed"; tagState.className = "badge bg-secondary"; } else { tagState.innerText = "open"; tagState.className = "badge bg-success"; } row.appendChild(tagState); nodeItemList.insertBefore(row, nodeFirstItem); item.node = row; } function encodeWithTextNode(htmlstring) { let textarea = document.createElement('textarea'); let text = document.createTextNode(htmlstring); textarea.appendChild(text); return textarea.innerHTML; } function getTaggedItems() { //GM_setValue("GamePage_PlayTime_" + gameid, JSON.stringify(cached)); //var cached = JSON.parse(GM_getValue("GamePage_PlayTime_" + gameid, "{}")); taggedItems = JSON.parse(GM_getValue("TaggedItems_" + geeklistid, "[]")); } function toggleTaggedItem(btn, itemid) { if (taggedItems.includes(itemid)) { taggedItems = taggedItems.filter(i => i != itemid); btn.className = "btn btn-sm btn-outline-primary"; btn.innerText = "Tag"; } else { taggedItems[taggedItems.length] = itemid; btn.className = "btn btn-sm btn-primary"; btn.innerText = "Tagged"; } GM_setValue("TaggedItems_" + geeklistid, JSON.stringify(taggedItems)); } function sortBy(type) { var sorted; if (type == null || type == '' || type == 'default') { sorted = items; } else if (type == 'name') { sorted = [...items]; sorted = sorted.sort((a,b) => { var r = a.item.name > b.item.name ? 1 : -1; //console.log(a.item.name, b.item.name, r); return r; }); } for (var i in sorted) { var item = sorted[i]; nodeItemList.removeChild(item.node); nodeItemList.insertBefore(item.node, nodeFirstItem); } } function filterList() { console.log("filtering list"); const fBg = document.getElementById('filterBoardgames').checked; const fEx = document.getElementById('filterExpansions').checked; const fUT = document.getElementById('filterUntagged').checked; const fTg = document.getElementById('filterTagged').checked; for (var i in items) { var show = true; var item = items[i]; const thingtype = item.item.href.split('/')[1]; const tagged = taggedItems.includes(item.id); if (!fBg && thingtype == 'boardgame') show = false; if (!fEx && thingtype == 'boardgameexpansion') show = false; if (!fUT && !tagged) show = false; if (!fTg && tagged) show = false; var cls = (show ? "tw-relative tw-flex tw-flex-wrap tw-items-center tw-gap-x-1.5 tw-gap-y-2 tw-rounded-md tw-border tw-border-gray-400 tw-bg-gray-100 tw-p-2" : "tw-relative d-none tw-flex-wrap tw-items-center tw-gap-x-1.5 tw-gap-y-2 tw-rounded-md tw-border tw-border-gray-400 tw-bg-gray-100 tw-p-2"); item.node.className = cls; //console.log(show); } }
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址