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.
44 lines
1.9 KiB
JavaScript
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);
|
|
});
|