// ==UserScript== // @name Instagram Story Reply Deleter // @namespace http://tampermonkey.net/ // @version 1.0 // @description Automatically deletes all Instagram story replies // @author you // @match https://www.instagram.com/your_activity/interactions/story_replies* // @grant none // ==/UserScript== (function() { 'use strict'; const BATCH_SIZE = 6; const PAUSE_BETWEEN_BATCHES = 15000; const MAX_BATCHES = 10000; const STUCK_TIMEOUT = 20000; const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms)); const saveProgress = (batchCount, totalDeleted) => { sessionStorage.setItem('ig_storyreply_running', 'true'); sessionStorage.setItem('ig_storyreply_batch', batchCount); sessionStorage.setItem('ig_storyreply_total', totalDeleted); }; const loadProgress = () => { return { running: sessionStorage.getItem('ig_storyreply_running') === 'true', batchCount: parseInt(sessionStorage.getItem('ig_storyreply_batch') || '0'), totalDeleted: parseInt(sessionStorage.getItem('ig_storyreply_total') || '0') }; }; const clearProgress = () => { sessionStorage.removeItem('ig_storyreply_running'); sessionStorage.removeItem('ig_storyreply_batch'); sessionStorage.removeItem('ig_storyreply_total'); }; const humanClick = (el) => { const rect = el.getBoundingClientRect(); const x = rect.left + rect.width / 2; const y = rect.top + rect.height / 2; const eventOptions = { bubbles: true, cancelable: true, view: window, clientX: x, clientY: y, screenX: x, screenY: y, buttons: 1 }; el.dispatchEvent(new MouseEvent('mouseover', eventOptions)); el.dispatchEvent(new MouseEvent('mouseenter', eventOptions)); el.dispatchEvent(new MouseEvent('mousemove', eventOptions)); el.dispatchEvent(new MouseEvent('mousedown', eventOptions)); el.dispatchEvent(new MouseEvent('mouseup', eventOptions)); el.dispatchEvent(new MouseEvent('click', eventOptions)); }; const findSelectButton = () => { return Array.from(document.querySelectorAll('[data-bloks-name="bk.components.Flexbox"]')) .find(el => { const style = el.getAttribute('style') || ''; return el.textContent.trim() === 'Select' && style.includes('cursor: pointer'); }); }; const findDeleteButton = () => { return Array.from(document.querySelectorAll('[data-bloks-name="bk.components.Flexbox"]')) .find(el => { const style = el.getAttribute('style') || ''; return el.textContent.trim() === 'Delete' && style.includes('cursor: pointer'); }); }; const findConfirmDeleteButton = () => { const nativeBtn = Array.from(document.querySelectorAll('button')) .find(el => el.textContent.trim() === 'Delete'); if (nativeBtn) return nativeBtn; const bloksBtn = Array.from(document.querySelectorAll('[data-bloks-name="bk.components.Flexbox"]')) .find(el => { const style = el.getAttribute('style') || ''; return el.textContent.trim() === 'Delete' && style.includes('cursor: pointer'); }); if (bloksBtn) return bloksBtn; return null; }; const checkForErrorPopup = () => { const okBtn = Array.from(document.querySelectorAll('button')) .find(el => el.textContent.trim() === 'OK'); if (okBtn) { console.log('⚠️ Error popup detected! Clicking OK and continuing...'); humanClick(okBtn); return true; } return false; }; const waitForSelectButton = async () => { const startTime = Date.now(); console.log('⏳ Waiting for Select button...'); while (true) { if (checkForErrorPopup()) { await sleep(3000); } const selectBtn = findSelectButton(); if (selectBtn) return selectBtn; if (Date.now() - startTime > STUCK_TIMEOUT) { console.log('⚠️ Page stuck! Saving progress and refreshing...'); return null; } const waited = Math.round((Date.now() - startTime) / 1000); console.log(`⏳ Still waiting for Select button... ${waited}s elapsed`); await sleep(1000); } }; const getReplyRows = () => { return Array.from(document.querySelectorAll('[role="button"][data-bloks-name="bk.components.Flexbox"]')) .filter(el => { return el.getAttribute('aria-label') === 'Image with button'; }); }; (async function deleteLoop() { await sleep(5000); const progress = loadProgress(); let batchCount = progress.batchCount; let totalDeleted = progress.totalDeleted; if (progress.running) { console.log(`♻️ Resuming after page refresh — Batch ${batchCount + 1}, ${totalDeleted} deleted so far`); } else { console.log('🚀 Instagram Story Reply Deleter starting...'); } while (batchCount < MAX_BATCHES) { console.log(`\n--- Batch ${batchCount + 1} | Total deleted so far: ${totalDeleted} ---`); if (checkForErrorPopup()) { await sleep(3000); } const selectBtn = await waitForSelectButton(); if (!selectBtn) { saveProgress(batchCount, totalDeleted); console.log('Refreshing page, will auto-resume...'); await sleep(1000); window.location.reload(); return; } humanClick(selectBtn); console.log('✓ Clicked Select, waiting for UI...'); await sleep(1500); if (checkForErrorPopup()) { await sleep(3000); continue; } const rows = getReplyRows(); console.log(`📋 Found ${rows.length} reply rows in DOM`); if (rows.length === 0) { console.log('No reply rows found. All done!'); clearProgress(); break; } let selectedCount = 0; for (let row of rows) { if (selectedCount >= BATCH_SIZE) break; humanClick(row); selectedCount++; console.log(` ☑️ Selected reply ${selectedCount}/${BATCH_SIZE}`); await sleep(300); } console.log(`✓ Selected ${selectedCount} replies, looking for Delete button...`); await sleep(1000); if (checkForErrorPopup()) { await sleep(3000); continue; } const deleteBtn = findDeleteButton(); if (!deleteBtn) { console.log('Delete button not found. Dumping visible bloks buttons:'); Array.from(document.querySelectorAll('[data-bloks-name="bk.components.Flexbox"]')) .forEach(el => { const t = el.textContent.trim(); const s = el.getAttribute('style') || ''; if (t && t.length < 30) console.log(` "${t}" | style="${s.substring(0, 60)}"`); }); clearProgress(); break; } humanClick(deleteBtn); console.log('✓ Clicked Delete, waiting for confirmation popup...'); await sleep(3000); if (checkForErrorPopup()) { await sleep(3000); continue; } let confirmed = false; for (let attempt = 0; attempt < 5; attempt++) { if (checkForErrorPopup()) { await sleep(3000); confirmed = true; break; } const confirmBtn = findConfirmDeleteButton(); if (confirmBtn) { console.log(`✓ Found confirmation Delete button, clicking... (attempt ${attempt + 1})`); humanClick(confirmBtn); await sleep(2000); if (checkForErrorPopup()) { await sleep(3000); confirmed = true; break; } const stillThere = findConfirmDeleteButton(); if (!stillThere) { console.log('✓ Popup dismissed successfully!'); confirmed = true; break; } else { console.log('Popup still visible, retrying...'); } } else { console.log(`Confirmation button not found (attempt ${attempt + 1}/5). Visible buttons:`); Array.from(document.querySelectorAll('button')).forEach(el => { const t = el.textContent.trim(); if (t) console.log(` button: "${t}"`); }); await sleep(1000); } } if (!confirmed) { console.log('Could not dismiss confirmation popup. Stopping.'); clearProgress(); break; } totalDeleted += selectedCount; batchCount++; console.log(`\n✅ Batch ${batchCount} complete! Total deleted: ${totalDeleted}`); console.log(`⏳ Pausing ${PAUSE_BETWEEN_BATCHES / 1000}s before next batch...`); await sleep(PAUSE_BETWEEN_BATCHES); } console.log(`\n🎉 All done! Batches completed: ${batchCount}, Total deleted: ${totalDeleted}`); clearProgress(); })(); })();