bidaangmamamayan/scripts/db-reset.cjs
Ryan 6b06e08c08 BidaAngMamayan: public supporter tribute news desk for Senator BAM Aquino
Forked from Forthena (PERSONAL/forthena) and retargeted:
- NO login, NO LLM: the edition is public and the ranking is deterministic
  (stories that name Sen. BAM lead; freshest first) — Daniel: no
  like/dislike or store profile for visitors.
- Crawler scoped to BAM: Bing news keyword queries + Inquirer/Rappler
  fallback wires, with a two-tier relevance gate (named-BAM always;
  Aquino+legislative-context only from fallback) so op-eds and non-Bam
  senators are dropped.
- Desks: BAM (lead), Gaming, Education, Politics, Energy, PH, Business.
- Community board /board: 'Thank you Senator BAM' — nickname-only posts,
  HTML-stripped, URL-only rejected, IP rate-limited (3/10min, 20/day).
- Yellow-gamer theme (Orbitron/Rajdhani/JetBrains Mono, dark + gold,
  HUD corners), supporter disclaimer in header and footer.
- Tests: category/date/relevance/text suites + Mongo board suite +
  full HTTP e2e (all passing).

Infra: 66.181.46.132 (bidaangmamamayan.com), local Mongo 7.0,
nginx + certbot TLS, PM2 bama (:3000) + 15-min crawl cron.
2026-09-15 08:37:03 +00:00

44 lines
1.9 KiB
JavaScript

// Bama scratch-DB helper: reset or peek the local database.
// node scripts/db-reset.cjs reset (wipes stories + board + rate)
// node scripts/db-reset.cjs peek (counts + newest few)
// Run on the site box (reads .env.production next to it).
const fs = require("fs");
const path = require("path");
const { MongoClient } = require("mongodb");
const envFile = path.join(__dirname, "..", ".env.production");
try {
for (const line of fs.readFileSync(envFile, "utf8").split("\n")) {
const m = line.match(/^([A-Z0-9_]+)=(.*)$/);
if (m && !process.env[m[1]]) process.env[m[1]] = m[2];
}
} catch (e) {}
const URI = process.env.MONGODB_URI || "mongodb://127.0.0.1:27017/bama";
const DB = process.env.BAMA_DB_NAME || "bama";
const CMD = process.argv[2] || "peek";
(async () => {
const c = new MongoClient(URI, { serverSelectionTimeoutMS: 8000 });
await c.connect();
const db = c.db(DB);
if (CMD === "reset") {
for (const n of ["stories", "board", "rate"]) {
const r = await db.collection(n).deleteMany({});
console.log(`${n}: removed ${r.deletedCount}`);
}
} else {
const counts = {};
for (const n of ["stories", "board", "rate"]) counts[n] = await db.collection(n).countDocuments();
console.log("counts:", counts);
const rows = await db.collection("stories").find({}).sort({ discoveredAt: -1 }).limit(6).project({ title: 1, named: 1, source: 1, published: 1 }).toArray();
for (const r of rows) console.log(` ${r.named ? "★" : " "} ${new Date(r.published).toISOString().slice(0, 16)} [${r.source}] ${String(r.title).slice(0, 70)}`);
const posts = await db.collection("board").find({}).sort({ createdAt: -1 }).limit(5).toArray();
for (const p of posts) console.log(` board/${new Date(p.createdAt).toISOString().slice(5, 16)} ${p.nick}: ${String(p.message).slice(0, 60)}`);
}
await c.close();
})().catch((e) => {
console.error("ERR", e.message);
process.exit(1);
});