← back to Handbag Auth Nextjs
scripts/reportCrawlComplete.ts
90 lines
// Report crawl completion to Slack channel claude-to-steve
import fs from "fs";
import path from "path";
async function reportComplete() {
const slackWebhook = process.env.SLACK_WEBHOOK_URL;
if (!slackWebhook) {
console.log("No Slack webhook configured. Skipping notification.");
return;
}
// Load crawl results
const file = path.resolve("data/crawled_affiliate_listings.json");
const listings = fs.existsSync(file) ? JSON.parse(fs.readFileSync(file, "utf8")) : [];
// Calculate stats
const brandCounts = listings.reduce((acc: any, item: any) => {
acc[item.brand] = (acc[item.brand] || 0) + 1;
return acc;
}, {});
const merchantCounts = listings.reduce((acc: any, item: any) => {
acc[item.merchant] = (acc[item.merchant] || 0) + 1;
return acc;
}, {});
const message = {
channel: "#claude-to-steve",
username: "Handbag Crawler Bot",
icon_emoji: ":handbag:",
text: "Affiliate site crawl complete!",
attachments: [
{
color: "#36a64f",
title: "Crawl Summary",
fields: [
{
title: "Total Listings",
value: listings.length.toLocaleString(),
short: true
},
{
title: "Brands Found",
value: Object.keys(brandCounts).length.toString(),
short: true
},
{
title: "Top Brand",
value: Object.entries(brandCounts).sort((a: any, b: any) => b[1] - a[1])[0]?.[0] || "N/A",
short: true
},
{
title: "Merchants Crawled",
value: Object.keys(merchantCounts).length.toString(),
short: true
}
],
footer: "Handbag Auth Crawler",
ts: Math.floor(Date.now() / 1000)
}
]
};
try {
const response = await fetch(slackWebhook, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(message)
});
if (response.ok) {
console.log("✅ Slack notification sent to #claude-to-steve");
} else {
console.error("❌ Failed to send Slack notification:", response.statusText);
}
} catch (error) {
console.error("❌ Error sending Slack notification:", error);
}
}
const isMainModule = import.meta.url === `file://${process.argv[1]}`;
if (isMainModule) {
reportComplete().catch(console.error);
}
export { reportComplete };