Advertisement
brandizzi

Script to mass-delete Threads posts

Mar 23rd, 2025 (edited)
573
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
JavaScript 4.56 KB | Source Code | 0 0
  1. (async function deleteOldReplies() {
  2.     const ONE_YEAR_AGO = new Date();
  3.     ONE_YEAR_AGO.setFullYear(ONE_YEAR_AGO.getFullYear() - 1);
  4.     const MORE = "Mais"; // Aria label of the three-dots menu button at each post
  5.     const DELETE = "Excluir"; // Text of the delete buttons
  6.     const REPLYING = 'Respondendo'; // Text marking every post that is a reply
  7.  
  8.     console.log(`🟢 Script started. Deleting replies older than ${ONE_YEAR_AGO.toISOString().split('T')[0]}...`);
  9.  
  10.     function wait(ms) {
  11.         return new Promise(resolve => setTimeout(resolve, ms));
  12.     }
  13.  
  14.     async function deleteReply(replyElement) {
  15.         try {
  16.             const timeElement = replyElement.querySelector('time');
  17.             if (!timeElement || !timeElement.hasAttribute("datetime")) {
  18.                 console.warn("⚠️ Could not find time element for a reply. Skipping deletion.");
  19.                 return 0;
  20.             }
  21.  
  22.             const postDate = new Date(timeElement.getAttribute("datetime"));
  23.             console.log(`🟡 Attempting to delete reply from ${postDate.toISOString().split('T')[0]}...`);
  24.  
  25.             // Find the "More options" button (which is a div with a title inside)
  26.             const optionsSvg = replyElement.querySelector(`svg[aria-label="${MORE}"]`);
  27.  
  28.             if (!optionsSvg) {
  29.                 console.warn("⚠️ 'More options' button (div with title 'Mais') not found. Skipping.");
  30.                 return 0;
  31.             }
  32.  
  33.             optionsSvg.parentNode.click();
  34.             await wait(5000);
  35.             const spansDel = [...document.querySelectorAll('span')];
  36.             const deleteButton = spansDel.find(btn => btn.textContent.includes(DELETE));
  37.             if (!deleteButton) {
  38.                 console.warn("⚠️ Delete button not found. Skipping.");
  39.                 return 0;
  40.             }
  41.  
  42.             deleteButton.parentNode.click();
  43.             await wait(5000);
  44.             const confirmButton = [...document.querySelectorAll('span')].find(btn => btn.textContent.includes(DELETE)).parentNode;
  45.             if (!confirmButton) {
  46.                 console.warn("⚠️ Confirm button not found. Skipping.");
  47.                 return 0;
  48.             }
  49.  
  50.             confirmButton.click();
  51.             await wait(2000);
  52.  
  53.             console.log("✅ Reply deleted successfully.");
  54.             return 1;
  55.         } catch (error) {
  56.             console.error("❌ Error deleting a reply:", error);
  57.         }
  58.         return 0;
  59.     }
  60.  
  61.     async function processReplies() {
  62.         let deleted = 0;
  63.         let cycle = 0;
  64.  
  65.         console.log(`🔄 Scanning for replies...`);
  66.  
  67.         const times = [...document.querySelectorAll('time')];
  68.         console.log(`🟠 Found ${times.length} time elements.`);
  69.  
  70.         const posts = times.map(time => {
  71.             let ancestor = time.parentNode;
  72.             while (ancestor) {
  73.                 if (ancestor.querySelector(`svg[aria-label="${MORE}"]`)) {
  74.                     return ancestor;
  75.                 }
  76.                 ancestor = ancestor.parentNode;
  77.             }
  78.             console.warn("⚠️ No ancestor with a <time> tag found. Skipping.");
  79.             return null;
  80.         }).filter(Boolean); // Remove null values
  81.  
  82.         console.log(`🔍 Found ${posts.length} reply posts.`);
  83.  
  84.         if (posts.length === 0) {
  85.             console.log("🚫 No more posts found. Exiting loop.");
  86.             return;
  87.         }
  88.  
  89.         let checked = 0;
  90.         for (const post of posts) {
  91.             const timeElement = post.querySelector('time');
  92.             if (!timeElement || !timeElement.hasAttribute("datetime")) {
  93.                 console.warn("⚠️ Post has no valid time element. Skipping.");
  94.                 continue;
  95.             }
  96.  
  97.             const postDate = new Date(timeElement.getAttribute("datetime"));
  98.             checked++;
  99.  
  100.             if (postDate >= ONE_YEAR_AGO) {
  101.                 console.log(`➡️ Skipping reply from ${postDate.toISOString().split('T')[0]} (less than a year old).`);
  102.                 continue;
  103.             }
  104.  
  105.             deleted += await deleteReply(post);
  106.             console.log(`✅ Deleted: ${deleted}`);
  107.         }
  108.  
  109.         console.log(`📊 Checked ${checked} replies in this cycle. Deleted so far: ${deleted}.`);
  110.  
  111.         // Scroll down to load more replies
  112.         // window.scrollTo(0, document.body.scrollHeight);
  113.         // console.log("⬇️ Scrolling down to load more replies...");
  114.         await wait(2000);
  115.  
  116.         console.log(`🏁 Finished! Total replies deleted: ${deleted}.`);
  117.     }
  118.  
  119.     processReplies();
  120. })();
  121.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement