「Bad Comment Delete」のコードは、システム側の更新で動作不能になり、修復を断念しましたが、このツールの全ての目的を達成する「コメント管理 / コメントブロック機能」が、アメーバから提供されています。
従って、「Bad Comment Delete」のツールとしての存在価値はなくなりましたが、部分的なコードを参考にする場合を考慮して、記事を残しています。
削除処理数の報告機能を実装
コメントを受けると、PCユーザーは「ホーム」画面で知る事が多いと思います。
ご存知の様に、このインフォメーションから「コメント管理画面」に飛びますが、受信したコメントにブロック指定IDのコメントがあれば、「Bad Comment Delete」は即自動削除を行います。
その処理は普通は1secもかからず、慣れてしまうと処理の有無を見逃します。「ホーム」の通知件数を確かに覚えていれば、「承認待ち」のリスト件数との差で、処理の有無が判ります。
しかし、受信時にたまたま「公開済み」の画面を開いていて、そこから「承認待ち」の画面を開いた時も、ブロック対象のコメントがあれば削除機能が動作します。 そんな場合、ユーザーは状態が飲み込めず不安になるかも知れません。
そこで削除処理数を必ず報告して、ユーザーが迷う事をなくす機能を考えました。
新しい配列のフラグ
ver.3.0 から、データ記録の配列3番目を機能用フラグに予約していましたが、これに処理件数を記録する事にしました。
自動処理は、複数の削除対象があれば纏めて削除します。 リスト上の削除対象を最初にカウントして実行を判断しているので、このカウント数を3番目に記録します。
フラグは処理画面が遷移しても保存され、最後に「承認待ち」を開いた時に、このフラグが「0」以外なら、その数を「削除処理をした数」として表示します。
このフラグは「承認待ち」画面を開いた時に報告表示と同時にリセットします。 累積ではなく、ブログ上でツールが削除処理をするごとに表示する仕様です。 また、ユーザーが「承認待ち」画面から移動すると、表示は消失します。
「Bad Comment Delete」が削除処理を開始するのは「承認待ち」「公開済み」の画面のどちらかですが、処理後は必ず「承認待ち」に戻ります。 従って、削除処理が行われた時は、常にユーザーが見える上図の場所に表示される塩梅です。
表示はもっと明瞭にしても良いのですが、実際の被害者の神経に触らない適度なものにしました。
「Bad Comment Delete」ver. 0.4
このツールは Chrpme・新Edge / Firefox で動作を確認しています。
以下のコードを「Tampermonkey」の新規スクリプトの編集画面にコピー&ペーストして「保存」する事で、ツールが利用できる様になります。 ペーストの際、編集画面の初期テンプレートを完全に空白にしてから、ペーストをしてください。
〔コピー方法〕 軽量シンプルなツール「PreBox Button 」を使うと
コード枠内を「Ctrl+左Click」➔「Copy code 」を「左Click」
の操作で、掲載コードのコピーが可能になります。
〔 Bad Comment Delete 〕ver. 0.4
// ==UserScript== // @name Bad Comment Delete // @namespace http://tampermonkey.net/ // @version 0.4 // @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 path=document.location.pathname; if(path=='/ucs/comment/commentlist.do'){ // コメント管理画面の場合 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']; } comm_block_data[1]='stop'; // フラグ初期化 let announcer=document.querySelector('#announcer'); if(announcer){ if(comm_block_data[2]!=0){ announcer.textContent='Deleted: '+ comm_block_data[2]; }} // 処理数報告 comm_block_data[2]=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 announcer=document.createElement('span'); announcer.setAttribute('id', 'announcer'); 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(announcer); 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; }'+ '#announcer { position: absolute; top: 12px; right: 30px; font-size: 16px; }'; 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); } block_manage(); } function block_manage(){ 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 ... 」で始まります"); }}}); 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(); }}); } // block_manage() 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'; // 削除フラグを設定 comm_block_data[2]=count; // 削除したコメント数を保存 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'){ // 削除実行フラグがある場合 let btn_del=document.querySelector( '.actionControl .btnPrimary[value="削除"]'); if(btn_del){ btn_del.click(); }}} }}); window.addEventListener('DOMContentLoaded', function(){ let path=document.location.pathname; if(path=='/ucs/comment/commentend.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(()=>{ window.location.href= 'https://blog.ameba.jp/ucs/comment/commentlist.do?public_comment_flg=false'; }, 20); }} }});