您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
This script provides buttons to block MODs and MOD authors on the MOD portal
当前为
// ==UserScript== // @name Factorio: Block MODs and MOD authors // @name:ja Factirio: MODおよびMOD作者をブロック // @namespace https://2238.club/ // @version 1.0.1 // @description This script provides buttons to block MODs and MOD authors on the MOD portal // @description:ja MODポータルに個々のMODや特定の作者のMODを一式ブロックするボタンを追加します // @author sakuro // @match https://mods.factorio.com/* // @icon https://www.google.com/s2/favicons?sz=64&domain=factorio.com // @license MIT // ==/UserScript== (function() { 'use strict'; const uniq = (array) => [...new Set(array)]; class BlockList { constructor(key) { this.key = key; this.load(); } load() { const rawData = localStorage.getItem(this.key); this.list = rawData ? JSON.parse(rawData) : []; } save() { localStorage.setItem(this.key, JSON.stringify(this.list)); } add(item) { this.list = uniq([item, ...this.list]); this.save(); } isBlocked(item) { return this.list.includes(item); } clear() { this.list = []; localStorage.removeItem(this.key); } }; const getNames = (anchor, prefix) => { try { if (!(anchor instanceof HTMLAnchorElement)) { throw new Error('anchor must be an HTMLAnchorElement'); } if (!prefix.startsWith('/') || !prefix.endsWith('/')) { throw new Error('prefix must start and end with /'); } const textContent = anchor.textContent.trim() || ''; const href = anchor.getAttribute('href') || ''; const pathname = new URL(href, document.location).pathname; const strippedHref = pathname.startsWith(prefix) ? pathname.substring(prefix.length) : pathname; return [textContent, strippedHref]; } catch (error) { console.error({anchor, prefix, error}); return []; } } const getMod = (mod) => getNames(mod.querySelector('a[href^="/mod/"]'), '/mod/'); const getAuthor = (mod) => getNames(mod.querySelector('a[href^="/user/"]'), '/user/'); const blockedMods = new BlockList('blocked mods'); const blockedAuthors = new BlockList('blocked authors'); const modList = document.querySelector('.mod-list'); const onBlockMod = (mod) => { return (evt) => { const [name, id] = getMod(mod, '/mod/'); blockedMods.add(id); refresh(modList); }; }; const onBlockAuthor = (mod) => { return (evt) => { const [name, id] = getAuthor(mod, '/user/'); blockedAuthors.add(id); refresh(modList); }; }; const onUnblockAll = (evt) => { blockedAuthors.clear(); blockedMods.clear(); refresh(modList); }; const createButton = (iconName, tooltip, handler) => { const div = document.createElement('div'); div.classList.add('mr12'); const button = document.createElement('button'); button.classList.add('button'); button.style = 'min-width: 44px; line-height: 1; text-align: center;'; button.title = tooltip; button.ariaLabel = tooltip; button.addEventListener('click', handler); const icon = document.createElement('i'); icon.classList.add('fa'); icon.classList.add(iconName); button.append(icon); div.append(button); return div; }; const refresh = (list) => { list.querySelectorAll('.panel-inset-lighter.flex-column.p0').forEach((e) => { const [authorName, authorId] = getAuthor(e); if (! authorId) { console.log("author not found"); return; } const [modName, modId] = getMod(e); if (! modId) { console.log("mod not found"); return; } if (blockedAuthors.isBlocked(authorId)) { e.style.display = 'none'; console.log(`Blocked: ${modId} by ${authorId}`); } else if (blockedMods.isBlocked(modId)) { e.style.display = 'none'; console.log(`Blocked: ${modId}`); } else { e.style.display = 'block'; const section = e.querySelector('.mod-download-section'); const lastElement = section.lastElementChild; if (section.querySelectorAll('.mr12').length < 4) { const blockModButton = createButton('fa-circle-xmark', 'Block this mod', onBlockMod(e)); lastElement.insertAdjacentElement('beforebegin', blockModButton); const blockAuthorButton = createButton('fa-person-circle-xmark', 'Block this author', onBlockAuthor(e)); lastElement.insertAdjacentElement('beforebegin', blockAuthorButton); } } }); }; const unblockAllButton = createButton('fa-recycle', 'Unblock all blocked MODs and MOD authors', onUnblockAll); document.querySelector('.header-links').appendChild(unblockAllButton); refresh(modList); }());