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.
52 lines
2.8 KiB
JavaScript
52 lines
2.8 KiB
JavaScript
// BidaAngMamamayan desk registry — single source of truth for categories.
|
|
//
|
|
// A tribute site has fewer desks than a general paper, but each one is
|
|
// deliberate: the "BAM" lead desk, his signature beats (education/college,
|
|
// energy/electricity, gaming/esports, the Senate floor), and the PH + world
|
|
// context he works inside.
|
|
|
|
export const CATEGORIES = [
|
|
{ key: "bam", label: "BAM Front", blurb: "Every story that names him" },
|
|
{ key: "education", label: "Education", blurb: "College, scholarship, the classroom" },
|
|
{ key: "energy", label: "Energy & Electricity", blurb: "The power bill fight" },
|
|
{ key: "gaming", label: "Gamer's Corner", blurb: "Esports, gaming, the 2025 runner-up" },
|
|
{ key: "politics", label: "The Senate Floor", blurb: "Bills, sessions, the chamber" },
|
|
{ key: "ph", label: "The Philippines", blurb: "Home context, region by region" },
|
|
{ key: "world", label: "World", blurb: "The rest of the wire" },
|
|
];
|
|
|
|
export const CATEGORY_KEYS = new Set(CATEGORIES.map((c) => c.key));
|
|
export const CATEGORY_LABELS = Object.fromEntries(CATEGORIES.map((c) => [c.key, c.label]));
|
|
|
|
// Anything that isn't a valid desk key falls back to the lead desk. The gate
|
|
// (lib/crawl.js) already decided the story belongs on this site, so "bam" is
|
|
// the honest default, not "world".
|
|
export function normalizeCategory(c) {
|
|
if (typeof c === "string" && CATEGORY_KEYS.has(c)) return c;
|
|
return "bam";
|
|
}
|
|
|
|
export function sectionName(c) {
|
|
return CATEGORY_LABELS[normalizeCategory(c)] || "BAM Front";
|
|
}
|
|
|
|
// The relevance gate lives in lib/crawl.js (it needs the description text);
|
|
// this is just the desk classifier for rows that pass the gate but arrive
|
|
// without a query tag.
|
|
const CLASSIFIERS = [
|
|
["gaming", /\besports?\b|\bgaming\b|\bvideo games?\b|\bsteam\b|\bplaystation\b|\bnintendo\b|\bxbox\b|\bconsole\b|\bgame (studio|developer|release)\b|\briot\b|\bvalorant\b|\blol\b|\bdota\b/i],
|
|
["education", /\beducation\b|\bschool(s|ing)?\b|\bcollege\b|\buniversity\b|\bscholarship\b|\bstudents?\b|\bclassroom\b|\bteachers?\b|\blearning\b|\bched\b|\bdeped\b/i],
|
|
["energy", /\bpower (outage|bill|rates?|grid)\b|\belectricity\b|\bbrownout\b|\bblackout\b|\bvat.*\bpower\b|\benergy\b|\bsystem loss\b|\belectric rate\b/i],
|
|
["politics", /\bsenate\b|\bbill\b|\bcongress\b|\bpresidenc?\b|\belection\b|\bparty\b|\bpolitical\b|\bimpeach\b|\bcommitte\w*\b/i],
|
|
["ph", /\bphilippines?\b|\bmanila\b|\bmarikina\b|\bquezon city\b|\bpampanga\b|\bc[eé]bu city\b|\bdavao\b|\bbaguio\b|\bpalawan\b|\bmindanao\b|\bvisayas\b|\bluzon\b|\bcalabarzon\b|\bbarangay\b|\bsenior citizen\b|\bprovincial\b|\bpeso\b/i],
|
|
];
|
|
|
|
export function classifyStory({ title, summary, source } = {}) {
|
|
const text = `${title || ""} ${summary || ""} ${source || ""}`;
|
|
if (!text.trim()) return "bam";
|
|
for (const [key, re] of CLASSIFIERS) {
|
|
if (re.test(text)) return key;
|
|
}
|
|
return "bam";
|
|
}
|