您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
IMASBBSのIDブロック機能を改良します。
// ==UserScript== // @name IMASBBS ID Blocker // @namespace https://github.com/sakuro/ // @version 1.0.7 // @description IMASBBSのIDブロック機能を改良します。 // @author sakuro // @match http://imasbbs.com/patio.cgi* // @match https://imasbbs.com/patio.cgi* // @match http://umabbs.com/patio.cgi* // @match https://umabbs.com/patio.cgi* // @icon https://www.google.com/s2/favicons?domain=imasbbs.com // @grant none // @license MIT // ==/UserScript== // jshint esversion: 6 (function () { 'use strict'; // スレ番不明 (=トップページなど) の場合は動作させない。 const thread = new URLSearchParams(location.search).get('read'); if (!thread) { return; } class Blocker { constructor(posts) { this.load(); this.posts = posts; this.posts.forEach((post) => { if (this.isBlocked(post.id)) { post.hideComment() } else { post.showComment(); } post.button.addEventListener('click', () => this.isBlocked(post.id) ? this.unblock(post.id) : this.block(post.id)); }); } isBlocked(id) { return this.blocks.has(id); } update(change) { this.load(); change(this.blocks); this.save(); } block(id) { if (this.isBlocked(id)) { return; } this.update((blocks) => blocks.set(id, new Date())); this.posts.filter((post) => post.id === id).forEach((post) => post.hideComment()); } unblock(id) { this.update((blocks) => blocks.delete(id)); this.posts.filter((post) => post.id === id).forEach((post) => post.showComment()); } save() { if (this.blocks.size === 0) { localStorage.removeItem('blocks'); } else { const data = JSON.stringify([...this.blocks]); localStorage.setItem('blocks', data); } } load() { const data = localStorage.getItem('blocks'); this.blocks = data ? new Map(JSON.parse(data).map((e) => [e[0], new Date(e[1])])) : new Map(); } clear() { this.blocks = new Map(); this.save(); this.posts.forEach((post) => post.showComment()); } } class Post { constructor(dom) { const idSpan = dom.querySelector('span'); this.id = idSpan.textContent.replace('ID:', ''); // com-res: 通常コメ、 com-top: 1つめのコメ、 com-ng: NGコメ this.comment = dom.querySelector('div.com-res, div.com-top, div.com-ng'); this.button = document.createElement('button'); this.button.setAttribute('type', 'button'); dom.insertBefore(this.button, idSpan.nextSibling); const separator = document.createTextNode(' ') dom.insertBefore(separator, idSpan.nextSibling); } hideComment() { this.comment.style.display = 'none'; this.button.textContent = '\u{267B}'; // Recycling Symbol this.button.title = this.comment.textContent; } showComment() { this.comment.style.display = 'block'; this.button.textContent = '\u{1F6AE}'; // Wastebucket this.button.title = ''; } } // 既存のNGボタンを削除 // .xng-btn: OKボタン, .ng-btn: NGボタン document.querySelectorAll('input.xng-btn, input.ng-btn').forEach((e) => e.remove()); const posts = [...document.querySelectorAll('.tr-art')].map((dom) => new Post(dom)); const blocker = new Blocker(posts); // トップとボトムにNG全クリアボタンを追加 document.querySelectorAll('.pager').forEach((pager) => { const separator = document.createTextNode('|') pager.appendChild(separator); const unblockAllButton = document.createElement('button'); unblockAllButton.setAttribute('type', 'button'); unblockAllButton.textContent = '全て \u{267B}'; unblockAllButton.addEventListener('click', () => blocker.clear()); pager.appendChild(unblockAllButton); }); })();