← back to George Gmail
trash-redfin-zillow.js
71 lines
const fs=require("fs");const {google}=require("googleapis");
const env={};fs.readFileSync("/root/Projects/Designer-Wallcoverings/DW-MCP/.env","utf8").split("\n").forEach(l=>{const m=l.match(/^([^#=]+)=(.+)/);if(m)env[m[1].trim()]=m[2].trim()});
const accts=[
{k:"steve-office",l:"steve@designerwallcoverings.com",r:env.GMAIL_REFRESH_TOKEN},
{k:"info",l:"info@designerwallcoverings.com",r:env.INFO_REFRESH_TOKEN},
{k:"steve-personal",l:"steveabramsdesigns@gmail.com",r:env.PERSONAL_REFRESH_TOKEN},
];
const QUERY = "redfin OR zillow";
const totals = { collected: 0, trashed: 0, byAccount: {} };
const auditPath = "/root/DW-Agents/logs/george-workspace-audit.log";
(async()=>{
for(const a of accts){
const oc=new google.auth.OAuth2(env.GMAIL_CLIENT_ID,env.GMAIL_CLIENT_SECRET,"http://localhost:9850/oauth2callback");
oc.setCredentials({refresh_token:a.r});
const gm=google.gmail({version:"v1",auth:oc});
console.log(`\n=== ${a.l} ===`);
// 1. Collect all message IDs matching the query
const ids=[];let pageToken=null,pages=0;
const t0=Date.now();
do{
const r=await gm.users.messages.list({userId:"me",q:QUERY,maxResults:500,pageToken:pageToken||undefined});
(r.data.messages||[]).forEach(m=>ids.push(m.id));
pageToken=r.data.nextPageToken||null;
pages++;
if(pages%20===0) process.stdout.write(` collecting... ${ids.length} IDs so far\n`);
}while(pageToken);
console.log(` collected ${ids.length} message IDs in ${((Date.now()-t0)/1000).toFixed(1)}s (${pages} pages)`);
totals.collected += ids.length;
totals.byAccount[a.l] = { collected: ids.length, trashed: 0 };
if(ids.length === 0) continue;
// 2. Batch-modify: add TRASH label (remove INBOX for cleanliness)
const BATCH = 1000;
const t1=Date.now();
for(let i=0; i<ids.length; i+=BATCH){
const chunk = ids.slice(i, i+BATCH);
try {
await gm.users.messages.batchModify({
userId:"me",
requestBody:{
ids: chunk,
addLabelIds: ["TRASH"],
removeLabelIds: ["INBOX"]
}
});
totals.trashed += chunk.length;
totals.byAccount[a.l].trashed += chunk.length;
process.stdout.write(` trashed ${i+chunk.length}/${ids.length}\n`);
} catch(e) {
console.log(` batch ${Math.floor(i/BATCH)+1} failed: ${e.message.slice(0,120)}`);
}
}
const elapsed = ((Date.now()-t1)/1000).toFixed(1);
console.log(` trashed ${totals.byAccount[a.l].trashed} in ${elapsed}s`);
// Audit log
try {
fs.appendFileSync(auditPath, `${new Date().toISOString()}\t${a.k}\tgmail.batchTrash\t${JSON.stringify({query:QUERY, count: totals.byAccount[a.l].trashed})}\n`);
} catch {}
}
console.log("\n=== FINAL ===");
for(const [email,v] of Object.entries(totals.byAccount)){
console.log(` ${email}: ${v.trashed}/${v.collected} trashed`);
}
console.log(` TOTAL: ${totals.trashed}/${totals.collected} trashed`);
})();