Skip to content

Instantly share code, notes, and snippets.

@sakuro
Last active December 19, 2021 09:31
Show Gist options
  • Save sakuro/73bad1ecff74ce86b4c9fd889b129a06 to your computer and use it in GitHub Desktop.
Save sakuro/73bad1ecff74ce86b4c9fd889b129a06 to your computer and use it in GitHub Desktop.
IMASBBS Block System
// ==UserScript==
// @name IMASBBS Block System
// @namespace http://tampermonkey.net/
// @version 0.1
// @description IMASBBSのIDブロック機能を改良します。
// @author sakuro
// @match http://imasbbs.com/patio.cgi*
// @icon https://www.google.com/s2/favicons?domain=imasbbs.com
// @grant none
// ==/UserScript==
(function() {
'use strict';
// タイトル (未活用) とスレ番
const title = document.querySelector('title').textContent;
const thread = new URLSearchParams(location.search).get('read');
console.log({'title': title, 'thread': thread});
// スレ番不明 (=トップページなど) の場合は動作させない。
if ( ! thread) {
return;
}
class BlockSystem {
constructor(posts) {
this.load();
this.posts = posts;
this.posts.forEach((post) => this.isBlocked(post.id) ? post.hideComment() : post.showComment());
}
isBlocked(id) {
return this.blocks.has(id);
}
block(id) {
if (this.isBlocked(id)) {
return;
}
this.blocks.set(id, new Date());
this.save();
this.posts.filter((post) => post.id === id).forEach((post) => post.hideComment());
}
unblock(id) {
this.blocks.delete(id);
this.save();
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)) : new Map();
this.blocks.forEach((id, timestamp) => this.blocks.set(id, new TimeRanges(timestamp)));
}
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:', '');
this.comment = dom.querySelector('div.com-res, div.com-top, div.com-ng'); // com-res: 通常コメ、 com-top: 1つめのコメ、 com-ng: NGコメ
this.button = document.createElement('button');
this.button.setAttribute('type', 'button');
this.button.addEventListener('click', () => blockSystem.isBlocked(this.id) ? blockSystem.unblock(this.id) : blockSystem.block(this.id));
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
}
showComment() {
this.comment.style.display = 'block';
this.button.textContent = '\u{1F6AE}'; // Wastebucket
}
}
// 既存のNGボタンを削除
document.querySelectorAll('input.xng-btn, input.ng-btn').forEach((e) => e.remove()); // .xng-btn: OKボタン, .ng-btn: NGボタン
const posts = [...document.querySelectorAll('.tr-art')].map((dom) => new Post(dom));
const blockSystem = new BlockSystem(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', () => blockSystem.clear());
pager.appendChild(unblockAllButton);
});
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment