您需要先安装一个扩展,例如 篡改猴、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.8 // @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 var progressData = { done: 0, total: 0}; (function() { 'use strict'; //console.log('root function'); UT_extractEndDate(); init(); })(); function retry(f) { window.setTimeout(f, 500); } function init() { var els = document.getElementsByTagName('gg-geeklist-page-ui'); if (els.length == 0) { retry(init); return; } els = els[0].getElementsByTagName('header'); if (els.length == 0) { retry(init); return; } els = els[0].getElementsByTagName('nav'); 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 updateProgressUI() { // This should ensure that the values are not changed during the execution of this method var copy = progressData; var percentage = copy.total > 0 ? (copy.done * 100.0 / copy.total) : 0; nodeProgressFull.style.width = percentage + '%'; nodeProgressEmpty.style.width = (100 - percentage) + '%'; nodeProgressFull.setAttribute('aria-valuemax', copy.total); nodeProgressFull.setAttribute('aria-valuenow', copy.done); if (percentage > 50) { nodeProgressFull.innerHTML = copy.done + ' / ' + copy.total; nodeProgressEmpty.innerHTML = ''; } else { nodeProgressEmpty.innerHTML = copy.done + ' / ' + copy.total; nodeProgressFull.innerHTML = ''; } } function setProgress(done, total) { progressData = { done: done, total: total }; } function setProgressAsync(done, total) { return new Promise(res => { setProgress(done, total); // res(); window.setTimeout(() => { res(); }, 0); }); } function convert() { var els = document.getElementsByTagName('gg-geeklist-page-ui'); if (els.length == 0) { retry(convert); return; } els = els[0].getElementsByTagName('div'); if (els.length == 0) { retry(convert); return; } var footerNav = els[0].getElementsByTagName('nav'); if (els.length == 0) { retry(convert); return; } footerNav = footerNav[footerNav.length - 1]; els = els[0].getElementsByTagName('header'); if (els.length == 0) { retry(convert); return; } els = els[0].getElementsByTagName('nav'); if (els.length == 0) { retry(convert); return; } var headerNav = els[0]; els = document.getElementsByTagName('gg-geeklist-items-ui'); if (els.length == 0) { retry(convert); return; } els = els[0].getElementsByTagName('div'); 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', new Date()); 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', new Date()); sortBy('name'); }; ddSortList.appendChild(ddSortName); var ddSortDate = document.createElement('li'); ddSortDate.innerHTML = "<button type=\"button\" class=\"dropdown-item\">Closing Date</button>"; ddSortDate.onclick = () => { console.log('sorting by closing date', new Date()); sortBy('closing'); }; ddSortList.appendChild(ddSortDate); // 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 = () => { window.setTimeout(() => { filterList(); }, 400); }; 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 = () => { window.setTimeout(() => { filterList(); }, 400); }; 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 = () => { window.setTimeout(() => { filterList(); }, 400); }; 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 = () => { window.setTimeout(() => { filterList(); }, 400); }; ddFilterDivider = document.createElement('li'); ddFilterDivider.innerHTML = "<hr class=\"dropdown-divider\">"; ddFilterList.appendChild(ddFilterDivider); var ddFilterClosed = document.createElement('li'); ddFilterClosed.className = "dropdown-item"; ddFilterClosed.innerHTML = "<input class=\"form-check-input\" type=\"checkbox\" value=\"\" checked id=\"filterClosed\"> " + "<label class=\"form-check-label\" for=\"filterClosed\">Closed</label>"; ddFilterList.appendChild(ddFilterClosed); document.getElementById('filterClosed').onclick = () => { window.setTimeout(() => { filterList(); }, 400); }; var ddFilterSold = document.createElement('li'); ddFilterSold.className = "dropdown-item"; ddFilterSold.innerHTML = "<input class=\"form-check-input\" type=\"checkbox\" value=\"\" checked id=\"filterSold\"> " + "<label class=\"form-check-label\" for=\"filterSold\">Sold</label>"; ddFilterList.appendChild(ddFilterSold); document.getElementById('filterSold').onclick = () => { window.setTimeout(() => { filterList(); }, 400); }; var ddFilterNotSold = document.createElement('li'); ddFilterNotSold.className = "dropdown-item"; ddFilterNotSold.innerHTML = "<input class=\"form-check-input\" type=\"checkbox\" value=\"\" checked id=\"filterNotSold\"> " + "<label class=\"form-check-label\" for=\"filterNotSold\">Not Sold</label>"; ddFilterList.appendChild(ddFilterNotSold); document.getElementById('filterNotSold').onclick = () => { window.setTimeout(() => { filterList(); }, 400); }; var ddFilterOpen = document.createElement('li'); ddFilterOpen.className = "dropdown-item"; ddFilterOpen.innerHTML = "<input class=\"form-check-input\" type=\"checkbox\" value=\"\" checked id=\"filterOpen\"> " + "<label class=\"form-check-label\" for=\"filterOpen\">Open</label>"; ddFilterList.appendChild(ddFilterOpen); document.getElementById('filterOpen').onclick = () => { window.setTimeout(() => { filterList(); }, 400); }; // 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]; window.setInterval(updateProgressUI, 250); 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 => { 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 unsold = bodylower.includes("unsold"); const soldto = bodylower.includes("sold to"); const sold = bodylower.includes("sold"); const auctionclosed = bodylower.includes("auction closed"); var today = new Date(); today.setHours(23, 59, 59, 999); const auctionends = extractEndDate(item, false); if (!auctionends) console.warn(item.body); item.auctionends = auctionends; var struckout = getStruckoutTextLength(item, false); 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 || unsold) { item.state = "not sold"; tagState.innerText = "not sold"; tagState.className = "badge bg-danger"; } else if (soldto || (sold && struckout > 100)) { item.state = "sold"; tagState.innerText = "sold"; tagState.className = "badge bg-danger"; } else if (auctionclosed || (auctionends && auctionends < today) || struckout > 150) { item.state = "closed"; tagState.innerText = "closed"; tagState.className = "badge bg-secondary"; } else { item.state = "open"; tagState.innerText = "open"; tagState.className = "badge bg-success"; } row.appendChild(tagState); if (auctionends) { var tagClosing = document.createElement("span"); tagClosing.style.color = "gray"; tagClosing.innerHTML = "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 448 512\" style=\"height: 1em; vertical-align: -0.125em;\" fill=\"currentColor\">"+ "<!--! Font Awesome Pro 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. -->"+ "<path d=\"M152 64H296V24C296 10.75 306.7 0 320 0C333.3 0 344 10.75 344 24V64H384C419.3 64 448 92.65 448 128V448C448 483.3 419.3 512 384 512H64C28.65 512 0 483.3 0 448V128C0 92.65 28.65 64 64 64H104V24C104 10.75 114.7 0 128 0C141.3 0 152 10.75 152 24V64zM48 448C48 456.8 55.16 464 64 464H384C392.8 464 400 456.8 400 448V192H48V448z\"></path></svg>"+ " " + auctionends.toLocaleDateString(undefined, { weekday: 'short', month: 'short', day: 'numeric' }); row.appendChild(tagClosing); } var spanRight = document.createElement('span'); spanRight.className = "tw-ml-auto tw-hidden tw-pr-0.5 tw-text-sm tw-text-muted md:tw-inline"; row.appendChild(spanRight); var btnPreview = document.createElement('button'); btnPreview.className = "btn btn-sm text-bg-secondary"; btnPreview.innerText = "Preview"; btnPreview.onclick = () => { if (btnPreview.data != null) { btnPreview.data.parentNode.removeChild(btnPreview.data); btnPreview.data = null; } else { makePreview(item, btnPreview); } }; spanRight.appendChild(btnPreview); nodeItemList.insertBefore(row, nodeFirstItem); item.node = row; } function makePreview(item, btn) { var gli = document.createElement('div'); gli.className = "geeklist-item tw-grid tw-items-start tw-gap-2.5 sm:tw-grid-cols-[minmax(auto,_185px)_minmax(65%,_1fr)] lg:tw-gap-3 lg:tw-gap-x-4"; if (item.node.nextSibling) { item.node.parentNode.insertBefore(gli, item.node.nextSibling); } else { item.node.parentNode.appendChild(gli); } btn.data = gli; const gliImg = makeItemImage(item); gli.appendChild(gliImg); var gliDiv = document.createElement('div'); gliDiv.className = "tw-min-w-0 sm:tw-mt-0"; gli.appendChild(gliDiv); const gliDivBody = makeItemBody(item); gliDiv.appendChild(gliDivBody); } function makeItemUser(item) { } function makeItemBody(item) { var body = document.createElement('div'); var parser = new DOMParser(); var xmlDoc = parser.parseFromString(item.bodyXml, "text/xml"); for (var child of xmlDoc.firstChild.childNodes) { console.log(child); if (child.nodeName == 'safehtml') { var safehtml = document.createElement('div'); safehtml.innerHTML = child.firstChild.data; body.appendChild(safehtml); } else { var other = document.createElement('div'); other.className = "alert alert-warning"; other.innerText = "displaying " + child.nodeName + " is not yet supported by one page auction userscript."; body.appendChild(other); } } return body; } function makeItemImage(item) { var gliImg = document.createElement('a'); gliImg.className = "geeklist-item__img-link tw-relative tw-block tw-overflow-hidden tw-rounded-md tw-bg-gray-100"; gliImg.href = item.linkedImage.href; var gliImgDiv = document.createElement('div'); gliImgDiv.className = "tw-h-44 tw-w-full sm:tw-aspect-w-1 sm:tw-aspect-h-1"; gliImg.appendChild(gliImgDiv); var gliImgDivImg = document.createElement('img'); gliImgDivImg.className = "img-fluid geeklist-item__img tw-absolute tw-w-full tw-h-full tw-p-2.5 md:tw-p-3.5 tw-object-contain tw-z-10"; gliImgDivImg.loading = "lazy"; gliImgDivImg.style.display = "inherit"; gliImgDivImg.src = item.item.imageSets.square100.src; gliImgDivImg.srcset = item.item.imageSets.square100.src + " 1x," + item.item.imageSets.square100["src@2x"] + " 2x"; gliImgDivImg.alt = item.linkedImage.alt; gliImgDivImg.sizes = ""; gliImgDiv.appendChild(gliImgDivImg); gliImgDivImg = document.createElement('img'); gliImgDivImg.className = "img-fluid tw-absolute tw-w-full tw-h-full tw-object-cover tw-scale-125 tw-opacity-30 tw-blur-xl tw-bg-white"; gliImgDivImg.loading = "lazy"; gliImgDivImg.style.display = "inherit"; gliImgDivImg.src = item.item.imageSets.square100.src; gliImgDivImg.srcset = item.item.imageSets.square100.src + " 1x," + item.item.imageSets.square100["src@2x"] + " 2x"; gliImgDivImg.sizes = ""; gliImgDiv.appendChild(gliImgDivImg); if (item.stats) { gliImgDiv = document.createElement('div'); gliImgDiv.className = "tw-absolute tw-right-2 tw-bottom-2 tw-z-20"; gliImgDiv.innerHTML = "<gg-rating-indicator tooltip=\"Avg. Rating\" shape=\"hex\" size=\"md\">" + "<span container=\"body\" class=\"hex rating--" + Math.floor(item.stats.average) + " tw-flex tw-font-semibold tw-h-[var(--hex-h)] tw-items-center tw-justify-center tw-text-white tw-text-xs tw-w-[var(--hex-w)]\"" + " style=\"background:" + getColorFromRating(item.stats.average) + "; --hex-w: 1.625rem; --hex-h: 1.875rem; -webkit-clip-path: polygon(50% 0,100% 25%,100% 75%,50% 100%,0 75%,0 25%); clip-path: polygon(50% 0,100% 25%,100% 75%,50% 100%,0 75%,0 25%);\">" + "<span class=\"tw-pb-px\"> " + (Math.round(item.stats.average * 10) / 10) + " </span>" + "</span>" + "</gg-rating-indicator>"; gliImg.appendChild(gliImgDiv); } return gliImg; } function encodeWithTextNode(htmlstring) { let textarea = document.createElement('textarea'); let text = document.createTextNode(htmlstring); textarea.appendChild(text); return textarea.innerHTML; } function getTaggedItems() { 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)); } async function sortBy(type) { await setProgressAsync(0, items.length); 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; return r; }); } else if (type == 'closing') { sorted = [...items]; sorted = sorted.sort((a,b) => { var r = a.auctionends > b.auctionends ? 1 : -1; return r; }); } nodeItemList.innerHTML = ''; sortChunks(sorted, 0); } function sortChunks(sorted, start) { sortAChunk(sorted, start) .then(async data => { //console.log(data.next, data.sorted.length); await setProgressAsync(data.next, data.sorted.length); if (data.next >= data.sorted.length) { console.log("sorting finished", new Date()); } else { sortChunks(data.sorted, data.next); } } ); } function sortAChunk(sorted, start) { const chunk = 250; return new Promise(res => { window.setTimeout(() => { //console.log(start); for (var i = 0; i < chunk && start + i < sorted.length; i++) { var item = sorted[start + i]; //nodeItemList.removeChild(item.node); nodeItemList.insertBefore(item.node, nodeFirstItem); } res({ sorted: sorted, next: start + i }); }, 0); }); } 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; const fCl = document.getElementById('filterClosed').checked; const fSo = document.getElementById('filterSold').checked; const fNS = document.getElementById('filterNotSold').checked; const fOp = document.getElementById('filterOpen').checked; for (var i = 0; i < items.length; i++) { 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; if (!fCl && item.state == 'closed') show = false; if (!fSo && item.state == 'sold') show = false; if (!fNS && item.state == 'not sold') show = false; if (!fOp && item.state == 'open') 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; if ((i + 1) % 100 == 0 || i == items.length - 1) { setProgress(i+1, items.length); } } } function getColorFromRating(rating) { const i = Math.floor(rating); switch (i) { case 1: case 2: return "#b2151f"; case 3: case 4: return "#d71925"; case 5: case 6: return "#5369a2"; case 7: return "#1978b3"; case 8: return "#1d804c"; case 9: case 10: return "#186b40"; default: return "#666e75"; } } function UT_extractEndDate() { const september = 8; const october = 9; const cases = [ { expected: new Date(2022, september, 25), item: { postdate: "2022-08-31T13:03:45+00:00", body: "Bar\n\nAuction ends: Sunday 25th September, random time\n\nFoo." } }, { expected: new Date(2022, september, 30), item: { postdate: "2022-08-31T13:03:45+00:00", body: "Bar\n\n[b]Auction ends:[/b] [b][COLOR=#0066FF]September 30 at random time[/COLOR][/b]\nFoo" } }, { expected: new Date(2022, october, 2), item: { postdate: "2022-08-31T13:03:45+00:00", body: "Bar\n\nAuction ends: Sun 2 Oct, \nFoo" } }, { expected: new Date(2022, september, 30), item: { postdate: "2022-08-31T13:03:45+00:00", body: "Bar\n\n[size=12][b]Auction ends[/b]: [COLOR=#FF0000]Fri 30 Sept[/COLOR] [-][COLOR=#6699FF][b]Wed 5 Oct[/b][/COLOR][/-], random time.[/size]\nFoo" } }, { expected: new Date(2022, september, 18), item: { postdate: "2022-08-31T13:03:45+00:00", body: "Bar\n\n[b]End of Auction: 18.09.2022\n[/b]\nFoo" } }, { expected: new Date(2022, september, 30), item: { postdate: "2022-08-31T13:03:45+00:00", body: "Bar\n\n[-][size=12][b]Auction ends[/b]: [COLOR=#6699FF][b]Fry 30 Sep, random time[/b][/COLOR][/size][/-]\nFoo" } }, { expected: new Date(2022, october, 1), item: { postdate: "2022-08-31T13:03:45+00:00", body: "Bar\n\nAuction ends: 1 of Okt, random time\nFoo" } } ]; for (var test of cases) { var res = extractEndDate(test.item, false); if ((res instanceof Date && res.getTime() != test.expected.getTime()) || ( !(res instanceof Date) && res != test.expected)) { console.warn("Expected|Actual|Data", test.expected, res, test.item); extractEndDate(test.item, true); } } console.info("Unit Test for extractEndDate are complete"); } function extractEndDate(item, debug) { var auctionends = false; var parsed; const posted = new Date(item.postdate); const bodytext = item.body.toLowerCase() //.replaceAll(/\[-\].*?\[\/-\]/gi, '') // remove all struck out information .replaceAll(/\[[^\]]+\]/gi, ''); // remove all tags if (debug) console.log(bodytext); // find and extract the line of the auction end date var linematch = /(?:auction ends|end of auction)(?: (?:on|at))?(?:\:)?(.+)/i.exec(bodytext); if (debug) console.log(linematch); if (linematch && linematch.length > 1) { var line = linematch[1] .replaceAll(/\[-\].*?\[\/-\]/gi, ''); // remove all struck out information. We do this only now in case the whole line was struck out. Otherwise we would lose the information //try obvious formats var datematch; datematch = /(\d\d)\.(\d\d)\.(\d\d\d\d)/.exec(line); if (datematch) { if (debug) console.log(datematch); return new Date(parseInt(datematch[3]), parseInt(datematch[2])-1, parseInt(datematch[1])); } // (Mon) 1 Jan datematch = /\d\d? (of )?\w{3}/.exec(line); if (datematch) { if (debug) console.log(datematch); var datetext = datematch[0] .replace(/of/i, '') .replace(/Okt/i, 'Oct'); // Subbing year from post parsed = Date.parse(datetext + " " + posted.getFullYear()); if (!isNaN(parsed)) { // It's possible the end date is something like january X and the item is posted december Y if (new Date(parsed) < posted) { // so we need to increment the supplied year parsed = Date.parse(datetext + " " + (posted.getFullYear() + 1)); } if (debug) console.log(parsed); return new Date(parsed); } } line = line.replace(/(\.|,)/gi, ''); // don't need these line = line.replaceAll(/(\d+)(th|nd|rd|st)/g, '$1'); // Cannot parse days like 25th, numbers only! line = line.replaceAll(/(Monday|Tuesday|Wednesday|Thursday|Friday|Saturday|Sunday|Mon|Tue|Wed|Thu|Fri|Sat|Sun|Fry)/gi, ''); // Don't need the weekday line = line.replaceAll(/Okt(ober)?/gi, 'October'); // german line = line.replaceAll(/(at )?random time/gi, ''); // remove random time line = line.replaceAll(/at .+/gi, ''); // remove specific time line = line.replaceAll(/\d\d?(:\d\d)?\s*(am|pm)(\s+\w{3,4})?/gi, ''); // remove time without leading words line = line.replaceAll(/\d\d?:\d\d(\s+\w{3,4})?/gi, ''); // remove time without leading words if (debug) console.log(line); var ms = Date.parse(line); if (isNaN(ms)) { // There probably isn't a year supplied. Subbing year from post ms = Date.parse(line + " " + posted.getFullYear()); if (!isNaN(ms)) { // It's possible the end date is something like january X and the item is posted december Y if (new Date(ms) < posted) { // so we need to increment the supplied year ms = Date.parse(line + " " + (posted.getFullYear() + 1)); } auctionends = new Date(ms); } } else { auctionends = new Date(ms); } } return auctionends; } function getStruckoutTextLength(item, debug) { var bodytext = item.body.toLowerCase(); var struckout = 0; var struckoutstart = bodytext.indexOf("[-]"); var struckoutend = bodytext.indexOf("[/-]"); while (struckoutstart >= 0 && struckoutend >= 0) { var text = bodytext.substring(struckoutstart+3, struckoutend) .replaceAll(/\[[^\]]+\]/gi, ''); // remove tags struckout += text.length; struckoutstart = bodytext.indexOf("[-]", struckoutstart + 1); struckoutend = bodytext.indexOf("[/-]", struckoutend + 1); } return struckout; }
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址