おーぷん2ch無視設定変更スクリプト
@@ -3,56 +3,321 @@
* @include http://*.open2ch.net/test/read.cgi/*
* @license MIT License
*/
-//スレッド書き込み欄の下にボタンとテキストエリアが出てきます。
-//IDを好きに設定してください。完全一致のみです。
-//なお、ツイッターID「tw@~」を設定すると、@は消えますが使用であり問題なく設定できます。
-//
-// ==UserScript==
-// @name ローカルストレージ勉強
-// @namespace open
-// @include http://*.open2ch.net/test/read.cgi/*
-// @version 1
-// @grant none
-// ==/UserScript==
-function Manual_GetStorage() {
- var mes = ''
- try {
- var ignArray = localStorage.getItem('ign:' + bbs).slice(1, - 1).split(',')
- for (var i = 0; i < ignArray.length; i++) {
- mes += ignArray[i].slice(0, ignArray[i].indexOf(':')).slice(1, - 1) + '\n'
- }
- }
- catch (e) {
- console.log('無視対象がありません')
- }
- return mes
-}
-var musiid = 'musi_upd_ta'
-function Manual_SetStorage() {
- var setMes = '';
- var at = '@'
- //document.getElementById(musiid);
- var setMesArray = Ta.value.split('\n');
- localStorage.setItem('ign:' + bbs, '')
- for (var i = 0; i < setMesArray.length; i++) {
- console.log('■' + setMesArray[i] + '■')
- if (setMesArray[i] !== '' && setMesArray[i] !== '\n') {
- setMes += '"' + setMesArray[i].replace(at, '') + '"' + ':1,'
- }
- }
- setMes = '{' + setMes.slice(0, - 1) + '}' //var ignArray =
- localStorage.setItem('ign:' + bbs, setMes)
- window.location.reload();
-}
-var Frm = document.getElementById('form1');
-var Botan = document.createElement('input');
-Botan.type = 'button';
-Botan.value = '無視設定配列更新ボタン';
-Botan.id = 'musi_upd_btn';
-Botan.onclick = Manual_SetStorage;
-Frm.appendChild(Botan);
-var Ta = document.createElement('textarea');
-Ta.value = Manual_GetStorage();
-Ta.id = musiid;
-Ta.rows = 3
-Frm.appendChild(Ta);
+//作った人 Awn
+//Forked from && Inspired by http://let.hatelabo.jp/TimeFires/let/hJmesYHtkMte
+
+(function (d) {
+ //note:「Hatena::Let」の@includeが効かないようなので、
+ // URLが「http://*.open2ch.net/test/read.cgi/*」を満たさ無い場合、スクリプト内部で弾く
+ let REGEXP_OPEN2CHREADCGI = new RegExp(/http:\/\/.*\.open2ch\.net\/test\/read\.cgi\/.*/);
+ if (!REGEXP_OPEN2CHREADCGI.test(location.href)) {
+ console.warn("available only under http://*.open2ch.net/test/read.cgi/*");
+ return;
+ }
+
+ //member
+ let appName = 'ignoreManager';
+ let _ignores = ignores;
+
+
+ //initializer
+ _init();
+
+
+ //function
+ function _init() {
+ _embedHTML();
+ _assignEventListener();
+ }
+
+ function _embedHTML() {
+ _embedBackgroundElm();
+ _embedMainElm();
+ _setIgnores();
+ }
+
+ function _assignEventListener() {
+ AddBtnEventListener();
+ DeleteAllBtnEventListener();
+ DeleteWithoutTwitterBtnEventListener();
+ DeleteSelectedBtnEventListener();
+ CloseIgnoreManager();
+ }
+
+ function _embedBackgroundElm() {
+ let bg = d.createElement('div');
+ bg.id = `${appName}_bg`;
+ bg.style = `
+ background:black;
+ position:fixed;
+ top:0;
+ left:0;
+ width:100%;
+ height:100%;
+ opacity:0.5;
+ z-index:30;
+ `;
+ d.body.appendChild(bg);
+ }
+
+ function _embedMainElm() {
+ let main = d.createElement('div');
+ main.id = `${appName}_main`;
+ main.style = `
+ background:#EFEFEF;
+ position:fixed;
+ top:30px;
+ left:30px;
+ width:calc(100% - 80px);
+ height:calc(100% - 80px);
+ z-index:31;
+ border:solid black 1px;
+ padding:10px;
+ `;
+ main.innerHTML = `
+ <h1>無視id編集画面</h1>
+ <hr>
+ <form name="ign_form" style="width:500px" onsubmit="return false;">
+ <fieldset>
+ <legend>一括削除</legend>
+ <input type="button" value="全て削除" id="b_deleteAll">
+ <input type="button" value="TwitterID以外を削除" id="b_deleteWithoutTwitter">
+ </fieldset>
+ <fieldset>
+ <legend>個別追加</legend>
+ <label>
+ 追加するid <input type="text" id="t_input">
+ </label>
+ <input type="button" value="追加する" id="b_add">
+ </fieldset>
+ </form>
+ <h2>無視id ↓</h2>
+ <hr>
+ <div id="ignoresView" style="height:200px;overflow:scroll;">
+ </div>
+ <hr>
+ <input type="button" value="選択したidを削除する" id="b_deleteSelected">
+ <span id="s_messageArea"></span>
+ `;
+ d.body.appendChild(main);
+ }
+
+ function _setIgnores() {
+ let keys = Object.keys(_ignores);
+ let arr = [];
+ let id;
+ for (key of keys) {
+ [id, key] = _transformID(key);
+ arr.push(`<label style="display: block;"><input type="checkbox" value="${key}">${id}</label>`);
+ }
+ let div = d.querySelector('#ignoresView');
+ div.innerHTML = arr.join('');
+ }
+
+ function _transformID(key) {
+ let id;
+ if (key.length > 3 && key.startsWith('tw@')) {
+ id = key;
+ key.replace(/^tw@/, 'tw');
+ return [id, key];
+ }
+ if (key.length > 3 && key.startsWith('tw')) {
+ id = key.replace(/^tw/, 'tw@');
+ return [id, key];
+ }
+ if (key.length > 3 && key.startsWith('@')) {
+ id = key.replace(/^@/, 'tw@');
+ key = key.replace(/^@/, 'tw');
+ return [id, key];
+ }
+ id = key;
+ return [id, key];
+ }
+
+ function _addIgnore(key) {
+ let elm = d.createElement('label');
+ elm.style = 'display:block';
+ id = key;
+ id = id.length > 3 && id.startsWith('tw') ? id.replace(/^tw/, 'tw@') : id;
+ elm.innerHTML = `<input type="checkbox" value="${key}">${id}`;
+ let div = d.querySelector('#ignoresView');
+ div.appendChild(elm);
+ }
+
+ function _validateID(id) {
+ return new Promise((resolve, reject) => {
+ if (id.length < 3) {
+ reject();
+ }
+
+ //note: idで利用できない文字は弾く
+ if (/[^A-Za-z0-9@_]/.test(id)) {
+ reject();
+ }
+
+ //note: @が2つ以上現れるidは存在しないので弾く
+ if (id.includes('@') && id.match(/@/g).length > 1) {
+ reject();
+ }
+
+ if (id.length === 3) {
+ //note: 3文字の時はtwitterアカウント連携のidではないと「見做す」
+ // 理論上(?)[1-3]文字のtwitterアカウントも存在しうるが、そんなレアな人が書き込む可能性は皆無であろう。
+ if (id.includes('@') || id.includes('_')) {
+ reject();
+ }
+ resolve(id);
+ }
+
+ //note: 3文字より大きい場合 -> twitterIDと見做す
+ // idが[10,9,8,7,6,5,4]桁の過去スレは諦めよう
+ /*
+ # 正常ケース
+ tw@aidee_42 -> twaidee_42
+ @aidee_42 -> twaidee_42
+ aidee_42 -> twaidee_42
+ # エラーケース
+ 正常ケース以外
+ */
+ if (id.length > 3) {
+ if (id.includes('@')) {
+ if (id.startsWith('tw@')) {
+ id = id.replace(/^tw@/, 'tw');
+ resolve(id);
+ } else if (id.startsWith('@')) {
+ id = id.replace(/@/, 'tw');
+ resolve(id);
+ } else {
+ reject();
+ }
+ } else {
+ id = 'tw' + id;
+ resolve(id);
+ }
+ }
+ });
+ }
+
+ //deleter
+ function _deleteAll() {
+ delStorage(cachekey);
+ _ignores = new Object();
+ ignores = _ignores;
+ return;
+ }
+
+ function _deleteAllFromView() {
+ let div = d.querySelector('#ignoresView');
+ while (div.firstChild) {
+ div.removeChild(div.firstChild);
+ }
+ }
+
+
+ function _deleteWithoutTwitter() {
+ let keys = Object.keys(_ignores);
+ for (let key of keys) {
+ if (key.length === 3) {
+ delete _ignores[key];
+ }
+ }
+ setStorage(cachekey, JSON.stringify(_ignores));
+ ignores = _ignores;
+ }
+
+ function _deleteWithoutTwitterFromView() {
+ let div = d.querySelector('#ignoresView');
+ let elms = div.querySelectorAll('input[type="checkbox"]');
+ for (let elm of elms) {
+ if (elm.value.length === 3) {
+ div.removeChild(elm.parentElement);
+ }
+ }
+ }
+
+ function _deleteSelected() {
+ let div = d.querySelector('#ignoresView');
+ let elms = div.querySelectorAll('input[type="checkbox"]');
+ let obj = {};
+ for (let elm of elms) {
+ obj[elm.value] = 1;
+ }
+ _ignores = obj;
+ ignores = _ignores;
+ setStorage(cachekey, JSON.stringify(ignores));
+ return;
+ }
+
+ function _deleteSelectedFromView() {
+ let div = d.querySelector('#ignoresView');
+ let elms = div.querySelectorAll('input[type="checkbox"]:checked');
+ for (let elm of elms) {
+ div.removeChild(elm.parentElement);
+ }
+ return;
+ }
+
+ //EventListener
+ function AddBtnEventListener() {
+ let elm = d.querySelector('#b_add');
+ elm.addEventListener('click', function (ev) {
+ ev.preventDefault();
+ let id = d.querySelector('#t_input').value;
+ id = id.trim();
+ _validateID(id)
+ .then((key) => {
+ _ignores[key] = 1;
+ _addIgnore(key);
+ setStorage(cachekey, JSON.stringify(_ignores));
+ console.dir(_ignores);
+ }, () => { alert(`${id}はidっぽくないみたい。。`); });
+ });
+ }
+
+ function DeleteAllBtnEventListener() {
+ let elm = d.querySelector('#b_deleteAll');
+ elm.addEventListener('click', function (ev) {
+ ev.preventDefault();
+ if (confirm('消しますか?')) {
+ _deleteAll();
+ _deleteAllFromView();
+ }
+ });
+ }
+
+ function DeleteWithoutTwitterBtnEventListener() {
+ let elm = d.querySelector('#b_deleteWithoutTwitter');
+ elm.addEventListener('click', function (ev) {
+ ev.preventDefault();
+ if (confirm('消しますか?')) {
+ _deleteWithoutTwitter();
+ _deleteWithoutTwitterFromView();
+ }
+ });
+ }
+
+ function DeleteSelectedBtnEventListener() {
+ let elm = d.querySelector('#b_deleteSelected');
+ elm.addEventListener('click', function (ev) {
+ ev.preventDefault();
+ if (confirm('消しますか?')) {
+ _deleteSelectedFromView();
+ _deleteSelected();
+ }
+ })
+ }
+
+ function CloseIgnoreManager() {
+ let elm = document.querySelector('#ignoreManager_bg');
+ elm.addEventListener('click', function (ev) {
+ if (confirm('閉じますか?')) {
+ let main = d.querySelector(`#${appName}_main`);
+ let bg = d.querySelector(`#${appName}_bg`);
+ d.body.removeChild(main);
+ d.body.removeChild(bg);
+ }
+ });
+ }
+
+ return;
+})(document);
/*
* @title おーぷん2ch無視設定変更スクリプト
* @include http://*.open2ch.net/test/read.cgi/*
* @license MIT License
*/
//作った人 Awn
//Forked from && Inspired by http://let.hatelabo.jp/TimeFires/let/hJmesYHtkMte
(function (d) {
//note:「Hatena::Let」の@includeが効かないようなので、
// URLが「http://*.open2ch.net/test/read.cgi/*」を満たさ無い場合、スクリプト内部で弾く
let REGEXP_OPEN2CHREADCGI = new RegExp(/http:\/\/.*\.open2ch\.net\/test\/read\.cgi\/.*/);
if (!REGEXP_OPEN2CHREADCGI.test(location.href)) {
console.warn("available only under http://*.open2ch.net/test/read.cgi/*");
return;
}
//member
let appName = 'ignoreManager';
let _ignores = ignores;
//initializer
_init();
//function
function _init() {
_embedHTML();
_assignEventListener();
}
function _embedHTML() {
_embedBackgroundElm();
_embedMainElm();
_setIgnores();
}
function _assignEventListener() {
AddBtnEventListener();
DeleteAllBtnEventListener();
DeleteWithoutTwitterBtnEventListener();
DeleteSelectedBtnEventListener();
CloseIgnoreManager();
}
function _embedBackgroundElm() {
let bg = d.createElement('div');
bg.id = `${appName}_bg`;
bg.style = `
background:black;
position:fixed;
top:0;
left:0;
width:100%;
height:100%;
opacity:0.5;
z-index:30;
`;
d.body.appendChild(bg);
}
function _embedMainElm() {
let main = d.createElement('div');
main.id = `${appName}_main`;
main.style = `
background:#EFEFEF;
position:fixed;
top:30px;
left:30px;
width:calc(100% - 80px);
height:calc(100% - 80px);
z-index:31;
border:solid black 1px;
padding:10px;
`;
main.innerHTML = `
<h1>無視id編集画面</h1>
<hr>
<form name="ign_form" style="width:500px" onsubmit="return false;">
<fieldset>
<legend>一括削除</legend>
<input type="button" value="全て削除" id="b_deleteAll">
<input type="button" value="TwitterID以外を削除" id="b_deleteWithoutTwitter">
</fieldset>
<fieldset>
<legend>個別追加</legend>
<label>
追加するid <input type="text" id="t_input">
</label>
<input type="button" value="追加する" id="b_add">
</fieldset>
</form>
<h2>無視id ↓</h2>
<hr>
<div id="ignoresView" style="height:200px;overflow:scroll;">
</div>
<hr>
<input type="button" value="選択したidを削除する" id="b_deleteSelected">
<span id="s_messageArea"></span>
`;
d.body.appendChild(main);
}
function _setIgnores() {
let keys = Object.keys(_ignores);
let arr = [];
let id;
for (key of keys) {
[id, key] = _transformID(key);
arr.push(`<label style="display: block;"><input type="checkbox" value="${key}">${id}</label>`);
}
let div = d.querySelector('#ignoresView');
div.innerHTML = arr.join('');
}
function _transformID(key) {
let id;
if (key.length > 3 && key.startsWith('tw@')) {
id = key;
key.replace(/^tw@/, 'tw');
return [id, key];
}
if (key.length > 3 && key.startsWith('tw')) {
id = key.replace(/^tw/, 'tw@');
return [id, key];
}
if (key.length > 3 && key.startsWith('@')) {
id = key.replace(/^@/, 'tw@');
key = key.replace(/^@/, 'tw');
return [id, key];
}
id = key;
return [id, key];
}
function _addIgnore(key) {
let elm = d.createElement('label');
elm.style = 'display:block';
id = key;
id = id.length > 3 && id.startsWith('tw') ? id.replace(/^tw/, 'tw@') : id;
elm.innerHTML = `<input type="checkbox" value="${key}">${id}`;
let div = d.querySelector('#ignoresView');
div.appendChild(elm);
}
function _validateID(id) {
return new Promise((resolve, reject) => {
if (id.length < 3) {
reject();
}
//note: idで利用できない文字は弾く
if (/[^A-Za-z0-9@_]/.test(id)) {
reject();
}
//note: @が2つ以上現れるidは存在しないので弾く
if (id.includes('@') && id.match(/@/g).length > 1) {
reject();
}
if (id.length === 3) {
//note: 3文字の時はtwitterアカウント連携のidではないと「見做す」
// 理論上(?)[1-3]文字のtwitterアカウントも存在しうるが、そんなレアな人が書き込む可能性は皆無であろう。
if (id.includes('@') || id.includes('_')) {
reject();
}
resolve(id);
}
//note: 3文字より大きい場合 -> twitterIDと見做す
// idが[10,9,8,7,6,5,4]桁の過去スレは諦めよう
/*
# 正常ケース
tw@aidee_42 -> twaidee_42
@aidee_42 -> twaidee_42
aidee_42 -> twaidee_42
# エラーケース
正常ケース以外
*/
if (id.length > 3) {
if (id.includes('@')) {
if (id.startsWith('tw@')) {
id = id.replace(/^tw@/, 'tw');
resolve(id);
} else if (id.startsWith('@')) {
id = id.replace(/@/, 'tw');
resolve(id);
} else {
reject();
}
} else {
id = 'tw' + id;
resolve(id);
}
}
});
}
//deleter
function _deleteAll() {
delStorage(cachekey);
_ignores = new Object();
ignores = _ignores;
return;
}
function _deleteAllFromView() {
let div = d.querySelector('#ignoresView');
while (div.firstChild) {
div.removeChild(div.firstChild);
}
}
function _deleteWithoutTwitter() {
let keys = Object.keys(_ignores);
for (let key of keys) {
if (key.length === 3) {
delete _ignores[key];
}
}
setStorage(cachekey, JSON.stringify(_ignores));
ignores = _ignores;
}
function _deleteWithoutTwitterFromView() {
let div = d.querySelector('#ignoresView');
let elms = div.querySelectorAll('input[type="checkbox"]');
for (let elm of elms) {
if (elm.value.length === 3) {
div.removeChild(elm.parentElement);
}
}
}
function _deleteSelected() {
let div = d.querySelector('#ignoresView');
let elms = div.querySelectorAll('input[type="checkbox"]');
let obj = {};
for (let elm of elms) {
obj[elm.value] = 1;
}
_ignores = obj;
ignores = _ignores;
setStorage(cachekey, JSON.stringify(ignores));
return;
}
function _deleteSelectedFromView() {
let div = d.querySelector('#ignoresView');
let elms = div.querySelectorAll('input[type="checkbox"]:checked');
for (let elm of elms) {
div.removeChild(elm.parentElement);
}
return;
}
//EventListener
function AddBtnEventListener() {
let elm = d.querySelector('#b_add');
elm.addEventListener('click', function (ev) {
ev.preventDefault();
let id = d.querySelector('#t_input').value;
id = id.trim();
_validateID(id)
.then((key) => {
_ignores[key] = 1;
_addIgnore(key);
setStorage(cachekey, JSON.stringify(_ignores));
console.dir(_ignores);
}, () => { alert(`${id}はidっぽくないみたい。。`); });
});
}
function DeleteAllBtnEventListener() {
let elm = d.querySelector('#b_deleteAll');
elm.addEventListener('click', function (ev) {
ev.preventDefault();
if (confirm('消しますか?')) {
_deleteAll();
_deleteAllFromView();
}
});
}
function DeleteWithoutTwitterBtnEventListener() {
let elm = d.querySelector('#b_deleteWithoutTwitter');
elm.addEventListener('click', function (ev) {
ev.preventDefault();
if (confirm('消しますか?')) {
_deleteWithoutTwitter();
_deleteWithoutTwitterFromView();
}
});
}
function DeleteSelectedBtnEventListener() {
let elm = d.querySelector('#b_deleteSelected');
elm.addEventListener('click', function (ev) {
ev.preventDefault();
if (confirm('消しますか?')) {
_deleteSelectedFromView();
_deleteSelected();
}
})
}
function CloseIgnoreManager() {
let elm = document.querySelector('#ignoreManager_bg');
elm.addEventListener('click', function (ev) {
if (confirm('閉じますか?')) {
let main = d.querySelector(`#${appName}_main`);
let bg = d.querySelector(`#${appName}_bg`);
d.body.removeChild(main);
d.body.removeChild(bg);
}
});
}
return;
})(document);
- Permalink
- このページへの個別リンクです。
- RAW
- 書かれたコードへの直接のリンクです。
- Packed
- 文字列が圧縮された書かれたコードへのリンクです。
- Userscript
- Greasemonkey 等で利用する場合の .user.js へのリンクです。
- Loader
- @require やソースコードが長い場合に多段ロードする Loader コミのコードへのリンクです。
- Metadata
- コード中にコメントで @xxx と書かれたメタデータの JSON です。