← back to Abrams Report
scrapers/db.js
73 lines
'use strict';
const Database = require('better-sqlite3');
const path = require('path');
const DB_PATH = path.join(__dirname, '..', 'data', 'headlines.db');
let _db = null;
function getDb() {
if (_db) return _db;
_db = new Database(DB_PATH);
_db.pragma('journal_mode = WAL');
_db.pragma('foreign_keys = ON');
_db.exec(`
CREATE TABLE IF NOT EXISTS headlines (
id INTEGER PRIMARY KEY AUTOINCREMENT,
uid TEXT UNIQUE NOT NULL,
title TEXT NOT NULL,
url TEXT NOT NULL,
source TEXT NOT NULL,
category TEXT NOT NULL,
fetched_at INTEGER NOT NULL DEFAULT (unixepoch()),
pub_date INTEGER,
is_breaking INTEGER NOT NULL DEFAULT 0,
is_developing INTEGER NOT NULL DEFAULT 0,
is_top INTEGER NOT NULL DEFAULT 0
);
CREATE INDEX IF NOT EXISTS idx_headlines_category ON headlines(category);
CREATE INDEX IF NOT EXISTS idx_headlines_fetched ON headlines(fetched_at DESC);
CREATE INDEX IF NOT EXISTS idx_headlines_source ON headlines(source);
CREATE TABLE IF NOT EXISTS scrape_log (
id INTEGER PRIMARY KEY AUTOINCREMENT,
source TEXT NOT NULL,
ran_at INTEGER NOT NULL DEFAULT (unixepoch()),
count_added INTEGER NOT NULL DEFAULT 0,
error TEXT
);
`);
return _db;
}
function upsertHeadline(h) {
const db = getDb();
const stmt = db.prepare(`
INSERT OR IGNORE INTO headlines (uid, title, url, source, category, pub_date, is_breaking, is_developing, is_top)
VALUES (@uid, @title, @url, @source, @category, @pub_date, @is_breaking, @is_developing, @is_top)
`);
const info = stmt.run(h);
return info.changes;
}
function getHeadlines(opts = {}) {
const db = getDb();
const { category, limit = 200, since = 0 } = opts;
let q = 'SELECT * FROM headlines WHERE fetched_at > ?';
const params = [since];
if (category) { q += ' AND category = ?'; params.push(category); }
q += ' ORDER BY is_top DESC, fetched_at DESC LIMIT ?';
params.push(limit);
return db.prepare(q).all(...params);
}
function logScrape(source, count, error = null) {
const db = getDb();
db.prepare('INSERT INTO scrape_log (source, count_added, error) VALUES (?, ?, ?)')
.run(source, count, error);
}
module.exports = { getDb, upsertHeadline, getHeadlines, logScrape };