bidaangmamamayan/scripts/cron-crawl.cjs
Ryan 70a23bbd46 BidaAngMamayan: verified-publisher gate + In Pictures + standalone board band
Three changes per Daniel (2026-09-15):

1. VERIFIED PUBLISHERS ONLY — lib/sources.js gains VERIFIED_HOSTS
   (established PH newsrooms + state wire + international) and
   publisherVerified(url); lib/crawl.js now drops any story whose
   article URL host is not on the allowlist BEFORE the relevance gate
   (skippedUnverified counter surfaces in the crawl result + cron log).
   Tabloids/blogs/radio (bomboradyo, unboxph, bnc.bilyonaryo, dzrh,
   thechronicle, …) can no longer reach the desk. Quiet-day fallback
   wires expanded to Inquirer/Rappler/GMA/ABS-CBN/Interaksyon/Manila
   Bulletin (all verified).

2. IN PICTURES — a new prominent full-width band on the front page:
   7 real public-domain photos of Sen. BAM (official Senate/Facebook
   pages via Wikimedia Commons), each credited to its source with a
   link out to the Commons file page. lib/photos.js holds the curated,
   URL-verified set.

3. BOARD AS ITS OWN AREA — the 'Thank You, Senator BAM' community board
   is now a distinct gold-edged full-width band (front page + its own
   view), clearly separate from the news desks. The nav 'Thank You
   Board' button is gold (not a category tab) and jumps to the band.

Tests: publisher-gate unit checks (22/22), ui-check.mjs updated to
verify the In Pictures band (>=5 credited photos) + front-page board
band posting; e2e + board suites still green.
2026-09-16 15:04:10 +00:00

37 lines
1.4 KiB
JavaScript

// Bama crawl trigger — fires the server's /api/crawl every 15 min via PM2
// cron_restart. The web app itself never crawls on page load.
const fs = require("fs");
const path = require("path");
// Load .env.production (KEY=VALUE lines) so the cron process has the real
// secret + port.
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 SECRET = process.env.CRON_SECRET || "bama-cron";
const PORT = process.env.PORT || "3000";
let run = async () => {
const res = await fetch(`http://127.0.0.1:${PORT}/api/crawl`, {
method: "POST",
headers: { "x-bama-cron": SECRET },
signal: AbortSignal.timeout(280000),
});
const j = await res.json().catch(() => ({}));
const c = (j && j.crawl) || {};
console.log(
`[bama-crawl] ${res.status} added=${c.added} named=${c.named} fallback=${c.usedFallback ? "yes" : "no"} gated=${c.gatedOut} unverified=${c.skippedUnverified} imgs=${c.withImage} articles=${c.articles ? c.articles.ok + "/" + c.articles.fetched : "?"} ${c.errors && c.errors.length ? "errs=" + c.errors.length : ""}`
);
process.exit(res.ok ? 0 : 1);
};
run().catch((e) => {
console.error("[bama-crawl] FAILED", e && e.message);
process.exit(1);
});