Как массово удалить сообщения чата RedditJavascript

Форум по Javascript
Ответить
Anonymous
 Как массово удалить сообщения чата Reddit

Сообщение Anonymous »

Я пытаюсь написать консольный сценарий JS для вставки в консоль, когда окно чата Reddit открыто в полноэкранном режиме. Я хочу, чтобы скрипт автоматически находил все мои сообщения, наводил курсор на каждое сообщение, при этом появлялась всплывающая подсказка реакции со значком/кнопкой удаления. Нажмите на значок удаления, а затем выберите «Да, удалить» во всплывающем окне подтверждения.
Мне удалось написать сценарий, который находит мои сообщения и записывает их в консоль, но я не могу найти кнопки удаления. Я считаю, что это связано с использованием теневых домов.

Код: Выделить всё

(async () => {
console.clear();
console.log("🗂️ Reddit chat — Portal-aware auto-deleter starting...");

const sleep = ms => new Promise(r => setTimeout(r, ms));
const usernameHint = "YOUR_REDDIT_USERNAME";
const maxLoops = 50;
const scrollPause = 900;
const actionPause = 500;

let deletedCount = 0;

// --- Deep traversal helpers ---
function deepFindAll(root, predicate) {
const out = [];
const stack = [root];
while (stack.length) {
const node = stack.shift();
try {
if (predicate(node)) out.push(node);
} catch (_) {}
if (node.childNodes) node.childNodes.forEach(c => stack.push(c));
if (node.shadowRoot) stack.push(node.shadowRoot);
if (node._shadowRoot) stack.push(node._shadowRoot);
}
return out;
}

function tryClick(el) {
if (!el) return false;
try {
el.scrollIntoView({ block: "center", inline: "center", behavior: "auto" });
el.click();
return true;
} catch (e) {
try {
el.dispatchEvent(new MouseEvent("click", { bubbles: true, cancelable: true, view: window }));
return true;
} catch (e2) {
return false;
}
}
}

function getMessageContainers() {
return deepFindAll(document, el => {
if (!el.classList) return false;
return el.className.includes("room-message");
});
}

function findConfirmButton() {
const btns = deepFindAll(document, el => {
if (el.tagName !== "BUTTON") return false;
const txt = (el.textContent || "").toLowerCase();
return txt.includes("yes") && txt.includes("delete");
});
// pick the visible one
return btns.find(b => b.offsetParent !== null) || null;
}

function findVisibleDeleteButton() {
const allDeletes = deepFindAll(document, el => el.tagName?.toLowerCase() === "rs-timeline-event-delete-action");
return allDeletes.find(el => {
const rect = el.getBoundingClientRect();
return rect.width > 0 && rect.height > 0;
}) || null;
}

let loop = 0;
while (loop++ < maxLoops) {
console.log(`\n🔁 Loop ${loop} — scrolling to load messages...`);
window.scrollBy(0, 3000);
await sleep(scrollPause);

const msgs = getMessageContainers();
console.log("📬 message containers found:", msgs.length);

let madeDeletionThisLoop = false;

for (const msg of msgs) {
try {
if (msg.__autoDeleteMarked) continue;
const aria = msg.getAttribute && msg.getAttribute("aria-label") || "";
const inner = (msg.innerText || "").slice(0, 140).replace(/\s+/g, " ");
const authoredByMe = (aria.includes(usernameHint) || inner.toLowerCase().includes(usernameHint.toLowerCase()));
if (!authoredByMe) continue;

msg.__autoDeleteMarked = true;
console.log("➡ Candidate message:", inner);

// Hover to reveal menu
msg.dispatchEvent(new MouseEvent("mouseenter", { bubbles: true }));
await sleep(actionPause);

// Find the visible delete button globally
const deleteBtn = findVisibleDeleteButton();
if (!deleteBtn) {
console.log("⚠️ No visible delete button found; skipping message.");
continue;
}

console.log("🔘 Clicking delete button...");
tryClick(deleteBtn);
await sleep(actionPause);

// Click confirm
const confirmBtn = findConfirmButton();
if (!confirmBtn) {
console.warn("❌ Confirm button not found;  skipping confirmation.");
continue;
}

console.log("✅ Clicking confirm button...");
tryClick(confirmBtn);
await sleep(actionPause);

deletedCount++;
madeDeletionThisLoop = true;
console.log(`🗑️ Deleted #${deletedCount}: ${inner}`);

await sleep(300);
} catch (err) {
console.error("Error handling message:", err);
}
}

if (!madeDeletionThisLoop) {
console.log("🔚 No deletions this loop. Scrolling to try older messages...");
window.scrollBy(0, 4000);
await sleep(scrollPause);
const remaining = getMessageContainers().filter(m => {
const aria = m.getAttribute && m.getAttribute("aria-label") || "";
const inner = (m.innerText || "").toLowerCase();
return (aria.includes(usernameHint) || inner.includes(usernameHint.toLowerCase())) && !m.__autoDeleteMarked;
});
if (!remaining.length) {
console.log("✨ No more messages authored by you found. Exiting.");
break;
}
console.log("🔁 Remaining candidates:", remaining.length);
}

await sleep(500);
}

console.log("\n✅ Finished. Total messages deleted:", deletedCount);
})();
Примечание. Чтобы попробовать этот скрипт, вам нужно будет заменить YOUR_REDDIT_USERNAME своим именем пользователя.
Любая помощь или подсказки приветствуются. Спасибо.

Подробнее здесь: https://stackoverflow.com/questions/798 ... t-messages
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Javascript»