コピペレス検出用ブックマークレット20251226 ☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★ ☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★ このツールは見た目だけでは安全かどうか分かりません 使う前に中身をChatGPTなどに見せて 勝手に何かを送信したり悪さをする内容が含まれていないか 自分で確認してから使用してくださいね ☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★ ☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★ ──────────────────────── 使い方 ──────────────────────── ・ブックマークレット用のコードが下部に2種類あります  特定スレ用か通常スレ用を選び  ブックマークレットにして使用してください ・1 ブラウザのブックマークを新しく作成する ・2 ブックマークのURL欄にコードを貼り付けて保存する ・3 掲示板のスレッドページを開く ・4 作成したブックマークをクリックする ・5 ページ内のレスが自動で解析される ・6 色が付いたレスが過去と似ている内容 ・7 delボタンは押すと削除依頼が送信される ・delボタンが表示されない場合は  ページを再起動してから使用してください ──────────────────────── 動作環境 ──────────────────────── ・PC用ブラウザ推奨  Chrome Edge Firefoxなど ・スマートフォン環境では正常に動作しない場合があります  スマートフォン用Firefoxでは動作を確認しました  スマートフォン用Chrome系ブラウザでは動作しませんでした ──────────────────────── 重要な注意と免責 ──────────────────────── ・このブックマークレットは掲示板の表示内容を解析し  レス本文を強調表示するユーザー補助ツールです ・本ツールの使用はすべて自己責任です  使用によって発生した不利益やトラブル  アクセス制限や削除依頼に関する問題  利用規約違反などについて配布者は一切の責任を負いません ・本ツールには削除依頼を送信する機能が含まれています  delボタンを押すと実際に掲示板へ削除依頼の通信が行われます ・削除依頼は実行者の環境に基づいて送信されます  誤操作や連続使用によって警告や制限を受ける可能性があります ・ツールの判定結果は管理人や運営の判断を代行するものではありません ・内容が理解できない場合や動作が不安に感じられる場合は使用しないでください ──────────────────────── 概要 ──────────────────────── ・このブックマークレットは掲示板のレス本文を監視し  過去に出現した文章と一致または部分一致するレスを  自動で強調表示します ・完全一致した文章は赤色  部分一致した文章はオレンジ色で表示されます ・コピペ投稿や定型文の再投稿を  視覚的に把握することを目的としています ──────────────────────── 主な機能 ──────────────────────── ・レス本文の取得と解析 ・HTMLタグの除去と文字列の正規化 ・過去に検出した文章との比較 ・完全一致と部分一致の色分け表示 ・検出件数を画面右下に表示 ・追加で読み込まれたレスにも自動対応 ・このツールは荒らしかどうかを判断するものではありません  文字列が一致しているかどうかのみを検出します ──────────────────────── del機能について ──────────────────────── ・各レスの横にdelボタンが表示されます  delボタンを押すと掲示板の公式削除依頼先へ通信が行われます ・delは取り消しできません  誤って押した場合でも送信されます  短時間での連続使用は制限の原因になる場合があります ・削除依頼を行うかどうかは必ず自分で判断してください ──────────────────────── 判定仕様の注意 ──────────────────────── ・短い文章や定型文も検出されることがあります  並列化したレスも検出されます  自分の書き込みが一致扱いされることもあります  判定結果は参考情報です 例)デカパイ感謝 と既にレスされているスレで   デカパイ感謝 とレスをすると完全一致で検出されます ──────────────────────── 過去の変更点 ──────────────────────── 20251226 ・書き込みをした人によって削除されました を判定対象から除外 ・ふたクロで引用元を表示した際に検出件数が増えてしまう問題を修正 ・delボタン押下時にダイアログ表示を行わず  ボタン横に結果を表示する方式へ変更 ・同じIPアドレスからの削除依頼があります  と表示された場合  delボタンを灰色にして再操作できないよう修正 ──────────────────────── 再配布と改変について ──────────────────────── ・再配布や改変は自己責任で行ってください ・内容が変更されている可能性がある場合は  利用者に分かるようにしてください ・安全性を断言する表現は避けてください ──────────────────────── 最後に ──────────────────────── ・便利な機能を持つツールですが  扱いを誤るとトラブルにつながります ・内容と注意点を理解した上で  節度を持って使用してくださいね ──────────────────────── ブックマークレットのコード(特定スレ用) ──────────────────────── ↓↓↓↓↓↓↓↓↓↓ここから↓↓↓↓↓↓↓↓↓↓ javascript:(()=>{if(window.__cpRunningForTab)return;window.__cpRunningForTab=1;let red=0,yel=0;const badge=document.createElement("div"),upd=()=>{badge.textContent=(red||yel)?"🟥"+red+" 🟨"+yel:"🔍 コピペ監視中"};Object.assign(badge.style,{position:"fixed",right:"8px",bottom:"8px",padding:"6px 10px",fontSize:"12px",background:"rgba(0,0,0,0.75)",color:"#fff",borderRadius:"6px",zIndex:999999,pointerEvents:"none"});upd();document.body.appendChild(badge);const seen={},NGP=["スレッドを立てた人によって削除されました","削除依頼によって隔離されました","書き込みをした人によって削除されました","キタ━━━━━━(゚∀゚)━━━━━━"],norm=s=>s.replace(/<[^>]+>/g,"").replace(/\s+/g," ").trim(),isNG=s=>NGP.some(p=>s.includes(p)),split=b=>b.innerHTML.split(//i),mark=(r,t)=>{r.style.background=t=="full"?"rgba(255,0,0,0.2)":"rgba(255,165,0,0.25)";r.style.border=t=="full"?"2px solid red":"2px solid orange"};const showMsg=(btn,msg,mode)=>{let s=document.createElement("span");s.textContent=msg;let bg="#fff",fg="#000",bd="#000";if(mode==="ok"){bg="#0a0";fg="#fff"}else if(mode==="ip"){bg="#ccc";fg="#000";bd="#888"}Object.assign(s.style,{marginLeft:"4px",fontSize:"11px",padding:"2px 4px",border:"1px solid "+bd,borderRadius:"3px",background:bg,color:fg,opacity:"1",transition:"opacity 1s"});btn.after(s);setTimeout(()=>{s.style.opacity="0"},2000);setTimeout(()=>{s.remove()},3000)};const addDel=r=>{if(r.dataset.delbtn)return;r.dataset.delbtn=1;const sod=r.querySelector(".sod"),cno=r.querySelector(".cno");if(!sod||!cno)return;const m=cno.textContent.match(/No\.(\d+)/);if(!m)return;const no=m[1];const d=document.createElement("button");d.textContent="del";Object.assign(d.style,{marginLeft:"4px",cursor:"pointer",fontSize:"12px",color:"#000",background:"#fff",border:"1px solid #000",borderRadius:"3px",padding:"1px 4px"});d.onclick=e=>{e.stopPropagation();fetch("https://img.2chan.net/del.php",{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:new URLSearchParams({mode:"post",b:"b",d:no,reason:"110",responsemode:"ajax"}),credentials:"include"}).then(r=>r.arrayBuffer()).then(buf=>{const t=new TextDecoder("shift_jis").decode(buf).trim();if(t=="ok"){d.style.background="#0a0";d.style.color="#fff";d.disabled=true;showMsg(d,"登録しました","ok")}else if(t.includes("同じIPアドレス")){d.style.background="#ccc";d.style.color="#000";d.disabled=true;showMsg(d,t,"ip")}else{showMsg(d,t,"ng")}}).catch(_=>{showMsg(d,"del送信失敗","ng")})};sod.after(d)};const proc=r=>{if(!r||r.dataset.cp)return;if(r.closest("#respopup_area,.fvw_respop"))return;r.dataset.cp=1;addDel(r);const b=r.querySelector("blockquote");if(!b)return;let raw=split(b),lines=raw.map(norm).filter(l=>l&&!isNG(l)),fk=null,pk=null;lines.forEach(l=>{if(l.length>=6&&seen[l])fk=l});if(!fk){lines.forEach(l=>{if(l.length>=6)for(const k in seen)if(k.length>=6&&l.includes(k)){pk=k;break}})}if(fk||pk){raw=raw.map(h=>{const t=norm(h);if(isNG(t))return h;if(fk&&t===fk)return""+h+"";if(pk&&t.includes(pk))return h.replace(pk,""+pk+"");return h});b.innerHTML=raw.join("
");mark(r,fk?"full":"part");fk?red++:yel++;upd()}lines.forEach(l=>{if(l.length>=6&&!isNG(l))seen[l]=1})};document.querySelectorAll(".rtd").forEach(proc);const t=document.querySelector(".thre");t&&new MutationObserver(m=>{m.forEach(x=>x.addedNodes.forEach(n=>{if(n.nodeType==1){n.matches&&n.matches(".rtd")&&proc(n);n.querySelectorAll&&n.querySelectorAll(".rtd").forEach(proc)}}))}).observe(t,{childList:true,subtree:true});console.log("copipe watcher started")})(); ↑↑↑↑↑↑↑↑↑↑ここまで↑↑↑↑↑↑↑↑↑↑ ──────────────────────── ブックマークレットのコード(通常スレ用) ──────────────────────── ↓↓↓↓↓↓↓↓↓↓ここから↓↓↓↓↓↓↓↓↓↓ javascript:(()=>{if(window.__cpRunningForTab)return;window.__cpRunningForTab=1;let red=0,yel=0;const badge=document.createElement("div"),upd=()=>{badge.textContent=(red||yel)?"🟥"+red+" 🟨"+yel:"🔍 コピペ監視中"};Object.assign(badge.style,{position:"fixed",right:"8px",bottom:"8px",padding:"6px 10px",fontSize:"12px",background:"rgba(0,0,0,0.75)",color:"#fff",borderRadius:"6px",zIndex:999999,pointerEvents:"none"});upd();document.body.appendChild(badge);const seen={},NGP=["スレッドを立てた人によって削除されました","削除依頼によって隔離されました","書き込みをした人によって削除されました","キタ━━━━━━(゚∀゚)━━━━━━"],isQuote=s=>/^\s*(?:>|>|>)+/.test(s),norm=s=>s.replace(/<[^>]+>/g,"").replace(/>/g,">").replace(/\s+/g," ").trim(),isNG=s=>NGP.some(p=>s.includes(p)),split=b=>b.innerHTML.split(//i),mark=(r,t)=>{r.style.background=t=="full"?"rgba(255,0,0,0.2)":"rgba(255,165,0,0.25)";r.style.border=t=="full"?"2px solid red":"2px solid orange"};const showMsg=(btn,msg,mode)=>{let s=document.createElement("span");s.textContent=msg;let bg="#fff",fg="#000",bd="#000";if(mode==="ok"){bg="#0a0";fg="#fff"}else if(mode==="ip"){bg="#ccc";fg="#000";bd="#888"}Object.assign(s.style,{marginLeft:"4px",fontSize:"11px",padding:"2px 4px",border:"1px solid "+bd,borderRadius:"3px",background:bg,color:fg,opacity:"1",transition:"opacity 1s"});btn.after(s);setTimeout(()=>{s.style.opacity="0"},2000);setTimeout(()=>{s.remove()},3000)};const addDel=r=>{if(r.dataset.delbtn)return;r.dataset.delbtn=1;const sod=r.querySelector(".sod"),cno=r.querySelector(".cno");if(!sod||!cno)return;const m=cno.textContent.match(/No\.(\d+)/);if(!m)return;const no=m[1];const d=document.createElement("button");d.textContent="del";Object.assign(d.style,{marginLeft:"4px",cursor:"pointer",fontSize:"12px",color:"#000",background:"#fff",border:"1px solid #000",borderRadius:"3px",padding:"1px 4px"});d.onclick=e=>{e.stopPropagation();fetch("https://img.2chan.net/del.php",{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:new URLSearchParams({mode:"post",b:"b",d:no,reason:"110",responsemode:"ajax"}),credentials:"include"}).then(r=>r.arrayBuffer()).then(buf=>{const t=new TextDecoder("shift_jis").decode(buf).trim();if(t=="ok"){d.style.background="#0a0";d.style.color="#fff";d.disabled=true;showMsg(d,"登録しました","ok")}else if(t.includes("同じIPアドレス")){d.style.background="#ccc";d.style.color="#000";d.disabled=true;showMsg(d,t,"ip")}else{showMsg(d,t,"ng")}}).catch(_=>{showMsg(d,"del送信失敗","ng")})};sod.after(d)};const proc=r=>{if(!r||r.dataset.cp)return;if(r.closest("#respopup_area,.fvw_respop"))return;r.dataset.cp=1;addDel(r);const b=r.querySelector("blockquote");if(!b)return;let raw=split(b),lines=raw.map(norm).filter(l=>l&&!isNG(l)&&!isQuote(l)),fk=null,pk=null;lines.forEach(l=>{if(l.length>=6&&seen[l])fk=l});if(!fk){lines.forEach(l=>{if(l.length>=6)for(const k in seen)if(k.length>=6&&l.includes(k)){pk=k;break}})}if(fk||pk){raw=raw.map(h=>{const t=norm(h);if(isNG(t)||isQuote(t))return h;if(fk&&t===fk)return""+h+"";if(pk&&t.includes(pk))return h.replace(pk,""+pk+"");return h});b.innerHTML=raw.join("
");mark(r,fk?"full":"part");fk?red++:yel++;upd()}lines.forEach(l=>{if(l.length>=6&&!isNG(l)&&!isQuote(l))seen[l]=1})};document.querySelectorAll(".rtd").forEach(proc);const t=document.querySelector(".thre");t&&new MutationObserver(m=>{m.forEach(x=>x.addedNodes.forEach(n=>{if(n.nodeType==1){n.matches&&n.matches(".rtd")&&proc(n);n.querySelectorAll&&n.querySelectorAll(".rtd").forEach(proc)}}))}).observe(t,{childList:true,subtree:true});console.log("copipe watcher started (quote ignored)")})(); ↑↑↑↑↑↑↑↑↑↑ここまで↑↑↑↑↑↑↑↑↑↑