「Bad Comment Delete」のコードは、システム側の更新で動作不能になり、修復を断念しましたが、このツールの全ての目的を達成する「コメント管理 / コメントブロック機能」が、アメーバから提供されています。
従って、「Bad Comment Delete」のツールとしての存在価値はなくなりましたが、部分的なコードを参考にする場合を考慮して、記事を残しています。
ブロックIDのデータ管理機能を実装しました
これまではブロックするアメーバID(ログアウト・外部ユーザーの場合はコメントユーザー名を代用)を登録する機能しかありませんでした。 しかし、間違って無関係のIDを登録したり、削除の必要がなくなったりした場合に、ブロックの解除を行えないと困ります。 ユーザースクリプトツールは、ツールをOFFにすればブロック機能が働かなくなりますが、複数のブロックの一部を解除する操作が出来ないと不便です。
そのため、登録したブロックIDを一覧出来て、その中から不要なID登録を削除する(ブロックを解除する)機能を実装しました。
管理機能の中心はセレクトボックス
下はページタイトル上に配置したブロックIDデータの管理機能です。 データをファイルに保存する「Export」ボタン、反対にそれを読込む「Import」ボタン、ブロックIDを解除する「セレクトボックス」を並べています。 タイトル部をクリックして「設定モード」にすると、これらが表示される仕様です。
セレクトボックスをクリックすると、ブロック指定したIDがプルダウンリストで表示されます。
このリストで、ブロックを解除するIDをクリックすると、下の様な確認のダイアログが表示されます。
「OK」を押すと、指定したブロックIDが登録リストから削除され、そのIDに関するブロックが解除されます。「キャンセル」を押すと処理を中止します。
ファイル保存と読込み
登録したブロックIDはツール上で配列として扱われます。 JavaScriptは配列データを「.json」形式のファイルに保存します。 これはメモ帳等のテキストエディタで扱え、配列の一部をコピーしたり、書き換えが可能です。
「Export」 保存
「Export」ボタンを押すと、ツールに登録された配列がダウンロードフォルダーに保存されます。 Chromeや新Edgeではウインドウ下部に、そのファイルへのアクセスが表示されます。
下部の「ファイルを開く」を押すと、「.json」ファイルをメモ帳に関連付けている場合は、下の様に配列の内容がそのまま表示されます。
〔参考〕メモ帳に関連付けを行う操作は 次ページ を参照ください。
配列の [ ] の中はカンマで区切られた簡単な構造で、最初の3個はツールの機能のために使っていて、それ以降にブロックIDが書き込まれます。 なお、ver.0.2まで 最初の2個を機能用に使っていましたが、今回から予備を加えて3個にしました。 また、ブロックIDの検索対象に機能用の要素も含めていたのを、完全に後の登録IDのみを調べる様にしました。 これで「stop」「0」もヒットする事はなくなりました。
「Import」 読込み
「Import」ボタンを押すと、読込むファイルを指定するダイアログが表示されます。 Windows10の場合は「ダウンロード」フォルダの中に、それまでに保存したファイルがあります。
「Bad Comment Delete」の「Export」したファイルは「Bad_Comment_Delete」で始まるファイル名(連番付き)です。 これをクリックで指定し「開く」を押すとツールに読込まれます。
正しいファイルを読込んだ場合は、下の様なアラートが表示されます。
ツール上の配列はファイルから読込んだデータに、既に書換えられています。 プルダウンメニューを開くと、読込んだ新しいデータを確認する事が出来ます。
なお安全のために、読込んだ配列データに、このページ上のコメントを削除するIDが含まれていても、すぐには削除動作は行われません。 しかし、ページをリロードした直後から、削除動作が行われます。
ファイルバックアップの利用について
ファイル保存・読込みの機能は、基本的にブロックIDのデータをバックアップする事に使います。 通常は、PC内の記録スペース(ローカルストレージ)にデータが保存され、困る事はありません。 しかし、ブラウザのリセットや「サイトデータの削除」などの操作で、ローカルストレージのデータが削除される事があります。 Cookie削除などと一緒に誤って削除してしまう事があり、そういう場合にバックアップがあると助かります。 重要なブロックIDの登録後にだけ「Export」を押せば良いでしょう。
「Bad Comment Delete」ver. 0.3
このツールは Chrpme・新Edge / Firefox で動作を確認しています。 今回のver. 0.3 で、ほぼ実際に利用できるツールになりましたが、今後も改善を加えて行きます。
以下のコードを「Tampermonkey」の新規スクリプトの編集画面にコピー&ペーストして「保存」する事で、ツールが利用できる様になります。 ペーストの際、編集画面の初期テンプレートを完全に空白にしてから、ペーストをしてください。
〔コピー方法〕 軽量シンプルなツール「PreBox Button 」を使うと
コード枠内を「Ctrl+左Click」➔「Copy code 」を「左Click」
の操作で、掲載コードのコピーが可能になります。
〔 Bad Comment Delete 〕ver. 0.3
// ==UserScript== // @name Bad Comment Delete // @namespace http://tampermonkey.net/ // @version 0.3 // @description コメント管理画面におけるコメント自動削除機能 // @author Ameba Blog User // @match https://blog.ameba.jp/ucs/comment/comment* // @noframes // @run-at document-start // @grant none // ==/UserScript== let ua=0; let agent=window.navigator.userAgent.toLowerCase(); if(agent.indexOf('firefox') > -1){ ua=1; } // Firefoxの場合のフラッグ window.addEventListener('DOMContentLoaded', function(){ let comm_block_data=[]; // 総合ブロックデータ let block_filter_id; let block_regex_id; let edit_mode=0; disp_environ(); let read_json=localStorage.getItem('comm_id_back'); // ローカルストレージ 保存名 comm_block_data=JSON.parse(read_json); if(comm_block_data==null){ comm_block_data=['BadCommDelete','stop','0']; let write_json=JSON.stringify(comm_block_data); localStorage.setItem('comm_id_back', write_json); } // ローカルストレージ 保存 reg_set(); function reg_set(){ let comm_block_data_copy=[]; comm_block_data_copy=comm_block_data.slice(); comm_block_data_copy.splice(0, 3); block_filter_id='^('+comm_block_data_copy.join('|')+')$'; block_regex_id=new RegExp(block_filter_id); list_set(); } function list_set(){ let list_select=document.querySelector('#list_select'); if(list_select){ list_select.innerHTML=''; // リセット let option0=document.createElement("option"); option0.setAttribute('hidden', ''); option0.text='ブロック指定ID 登録解除'; option0.value=0; list_select.appendChild(option0); for(let k=3; k<comm_block_data.length; k++){ let option=document.createElement("option"); option.text=comm_block_data[k]; option.value=k; list_select.appendChild(option); }}} function disp_environ(){ let b_panel=document.createElement('li'); b_panel.setAttribute('id', 'b_panel'); let comm_set=document.querySelector('ul.commentSetting'); if(comm_set){ comm_set.appendChild(b_panel); b_panel.innerHTML= '<input id="export" type="submit" value="Export">'+ '<input id="import" type="submit" value="Import">'+ '<input id="reader" type="file" value="">'+ '<select id="list_select">'+ '</select>'; } let css= '#ucsMainLeft { position: relative; } '+ '#b_panel { position: absolute; top: 8px; right: 15px; display: none; } '+ '#list_select { width: 230px; height: 26px; padding: 1px 15px 0; '+ 'font-size: 15px !important; background: #fff; } '+ '#list_select option { font-size: 16px; } '+ '#export { font-size: 17px; padding: 2px 8px 0; margin-right: 10px; '+ 'height: 26px; vertical-align: -3px; } '+ '#import { font-size: 17px; padding: 2px 8px 0; margin-right: 15px; '+ 'height: 26px; vertical-align: -3px; } '+ '#reader{ display: none; }'; if(ua==1){ css+='#export, #import { padding: 0 8px 0; height: 27px; }'; } let style=document.createElement('style'); style.setAttribute('id', 's_list'); style.innerHTML=css; let target=document.querySelector('body'); if(!target.querySelector('#s_list')){ target.appendChild(style); } file_write_read(); permit(); } function file_write_read(){ let ex_file=document.querySelector('#export'); ex_file.onclick=function(){ let write_json=JSON.stringify(comm_block_data); let blob=new Blob([write_json], {type: 'application/json'}); let a_elem=document.createElement('a'); a_elem.href=URL.createObjectURL(blob); a_elem.download='Bad_Comment_Delete.json'; // 保存ファイル名 if(ua==1){ a_elem.target = '_blank'; document.body.appendChild(a_elem); } a_elem.click(); if(ua==1){ document.body.removeChild(a_elem); } URL.revokeObjectURL(a_elem.href); } let im_file=document.querySelector('#import'); im_file.onclick=function(){ file_read.click(); } let file_read=document.querySelector('#reader'); file_read.addEventListener("change" , function(){ if(!(file_read.value)) return; // ファイルが選択されない場合 let file_list=file_read.files; if(!file_list) return; // ファイルリストが選択されない場合 let file=file_list[0]; if(!file) return; // ファイルが無い場合 let file_reader=new FileReader(); file_reader.readAsText(file); file_reader.onload=function(){ if(file_reader.result.slice(0, 16)=='["BadCommDelete"'){ // ファイルデータの確認 comm_block_data=JSON.parse(file_reader.result); // 読出して配列を上書きする let write_json=JSON.stringify(comm_block_data); localStorage.setItem('comm_id_back', write_json); // ローカルストレージ 保存 reg_set(); alert("✅ ブロック指定IDのデータを読込みました\n"+ " 読込んだファイル名: " + file.name); } else{ alert("❌ Bad Comment Delete の Exportファイルではありません\n"+ " Importファイル名は「Bad_Comment_Delete ... 」で始まります"); }}}); } // file_write_read() function permit(){ let list_select=document.querySelector('#list_select'); list_select.addEventListener('change', (event)=>{ let sel_id=list_select.options[list_select.selectedIndex].text; let sel_index=list_select.selectedIndex+2; let ok=confirm(" ⛔ "+ sel_id +" のブロックID設定を解除しますか?"); if(ok){ comm_block_data.splice(sel_index, 1); reg_set(); let write_json=JSON.stringify(comm_block_data); localStorage.setItem('comm_id_back', write_json); } // ローカルストレージ 保存 else{ list_set(); }}); } // permit() let target=document.querySelector('body'); // 監視 target let monitor=new MutationObserver(main); monitor.observe(target, {childList: true}); // 監視開始 function main(){ comm_blocker(); checker(); let b_panel=document.querySelector('#b_panel'); let commHeader=document.querySelector('#ucsMainLeft h1'); if(commHeader){ commHeader.textContent='💛 コメント管理'; commHeader.style.paddingLeft='5px'; commHeader.onclick=function(){ if(edit_mode==0){ edit_mode=1; commHeader.style.color='#fff'; commHeader.style.background='red'; b_panel.style.display='block'; list_set(); link_prevent(); comm_blocker(); } else{ edit_mode=0; commHeader.style.color='#444'; commHeader.style.background='none'; b_panel.style.display='none'; link_prevent(); comm_blocker(); }}} } // main() function link_prevent(){ let comm_li=document.querySelectorAll('#comments li'); if(comm_li.length!=0){ for(let k=0; k<comm_li.length; k++){ if(edit_mode==1){ comm_li[k].querySelector('#comments .left h3').style.pointerEvents='none'; comm_li[k].querySelector('#comments .left h4').style.pointerEvents='none'; comm_li[k].querySelector('#comments .right').style.pointerEvents='none'; comm_li[k].querySelectorAll('#comments .right a')[0].style.pointerEvents='none'; comm_li[k].querySelectorAll('#comments .right a')[1].style.pointerEvents='none'; let public_a=comm_li[k].querySelector('#comments .right publicconfirm a'); if(public_a){ public_a.style.pointerEvents='none'; } let cmtTxt_a=comm_li[k].querySelector('#comments .cmtTxt a'); if(cmtTxt_a){ cmtTxt_a.style.pointerEvents='none'; }} if(edit_mode==0){ comm_li[k].querySelector('#comments .left h3').style.pointerEvents='auto'; comm_li[k].querySelector('#comments .left h4').style.pointerEvents='auto'; comm_li[k].querySelector('#comments .right').style.pointerEvents='auto'; comm_li[k].querySelectorAll('#comments .right a')[0].style.pointerEvents='auto'; comm_li[k].querySelectorAll('#comments .right a')[1].style.pointerEvents='auto'; let public_a=comm_li[k].querySelector('#comments .right publicconfirm a'); if(public_a){ public_a.style.pointerEvents='auto'; } let cmtTxt_a=comm_li[k].querySelector('#comments .cmtTxt a'); if(cmtTxt_a){ cmtTxt_a.style.pointerEvents='auto'; }}}}} function comm_blocker(){ let comm_name=[]; let count=0; let comm_li=document.querySelectorAll('#comments li'); if(comm_li.length!=0){ for(let k=0; k<comm_li.length; k++){ if(comm_li[k].querySelector('input[name="comment_name"]')){ comm_name[k]= comm_li[k].querySelector('input[name="comment_name"]').value; if(block_regex_id.test(comm_name[k])==true){ count+=1; comm_li[k].querySelector('input[name="del_index"]').checked=true; }}}} if(count!=0){ comm_block_data[1]='delete'; // 削除フラグを設定 let write_json=JSON.stringify(comm_block_data); localStorage.setItem('comm_id_back', write_json); // ローカルストレージ 保存 let btn_del=document.querySelector('.actionControl .btnDelete'); if(btn_del){ btn_del.click(); // alert(count); }} } // comm_blocker() function checker(){ let comm_name=[]; let comm_li=document.querySelectorAll('#comments li'); if(comm_li.length!=0){ for(let k=0; k<comm_li.length; k++){ if(comm_li[k].querySelector('input[name="comment_name"]')){ comm_name[k]= comm_li[k].querySelector('input[name="comment_name"]').value; comm_li[k].onclick=function(event){ // リストのクリックで設定 set_guard(k); }}} function set_guard(n){ if(edit_mode==1){ if(block_regex_id.test(comm_name[n])!=true){ comm_li[n].style.outline='solid 2px red'; comm_li[n].style.outlineOffset='-2px'; setTimeout(()=>{ let ok= confirm(" ⛔ "+ comm_name[n] +" をブロックIDに設定しますか?"); if(ok){ comm_block_data.push(comm_name[n]); reg_set(); let write_json=JSON.stringify(comm_block_data); localStorage.setItem('comm_id_back', write_json); // ストレージ 保存 comm_blocker(); } // 排除リストに従って削除を実行 else{ comm_li[n].style.outline='none'; } }, 20); }}} }} // checker() }) window.addEventListener('DOMContentLoaded', function(){ let path=document.location.pathname; if(path=='/ucs/comment/commentconfirm.do'){ // 削除確認画面の場合 let comm_block_data=[]; // 総合ブロックデータ let read_json=localStorage.getItem('comm_id_back'); // ローカルストレージ 保存名 comm_block_data=JSON.parse(read_json); if(comm_block_data!=null){ if(comm_block_data[1]=='delete'){ // 削除実行フラグがある場合 comm_block_data[1]='stop'; // フラグを戻す let write_json=JSON.stringify(comm_block_data); localStorage.setItem('comm_id_back', write_json); // ローカルストレージ 保存 setTimeout(()=>{ let btn_del=document.querySelector( '.actionControl .btnPrimary[value="削除"]'); if(btn_del){ btn_del.click(); }}, 50)}}} }); window.addEventListener('DOMContentLoaded', function(){ let path=document.location.pathname; if(path=='/ucs/comment/commentend.do'){ // 削除完了画面の場合 window.location.href= 'https://blog.ameba.jp/ucs/comment/commentlist.do?public_comment_flg=false'; } });