import { email } from "https://esm.town/v/std/email";
import { sqlite } from "https://esm.town/v/stevekrouse/sqlite";
const KEY = new URL(import.meta.url).pathname.split("/").at(-1);
const TABLE_NAME = `${KEY}_notified_stories`;
async function initializeDatabase() {
await sqlite.execute(`
CREATE TABLE IF NOT EXISTS ${TABLE_NAME} (
id INTEGER PRIMARY KEY,
story_id INTEGER UNIQUE,
notified_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)
`);
}
async function checkHackerNewsForPatreon() {
await initializeDatabase();
const response = await fetch("https://hacker-news.firebaseio.com/v0/newstories.json");
const storyIds = await response.json();
const keywordRegex = /(patreon|buymeacoffee|ko-fi)/i;
const patreonStories = [];
for (let i = 0; i < Math.min(100, storyIds.length); i++) {
const storyResponse = await fetch(`https://hacker-news.firebaseio.com/v0/item/${storyIds[i]}.json`);
const story = await storyResponse.json();
if (
story && story.id && story.title
&& (keywordRegex.test(story.title) || (story.text && keywordRegex.test(story.text)))
) {
const result = await sqlite.execute(`SELECT * FROM ${TABLE_NAME} WHERE story_id = ?`, [story.id]);
if (result.rows.length === 0) {
patreonStories.push(story);
await sqlite.execute(`INSERT INTO ${TABLE_NAME} (story_id) VALUES (?)`, [story.id]);
}
}
}
if (patreonStories.length > 0) {
const emailContent = patreonStories.map(story =>
`<p><strong>${story.title}</strong><br>
${story.url ? `URL: <a href="${story.url}">${story.url}</a><br>` : ""}
Comments: <a href="https://news.ycombinator.com/item?id=${story.id}">https://news.ycombinator.com/item?id=${story.id}</a></p>`
).join("");
await email({
subject: `Hacker News Alert: ${patreonStories.length} new stories about Patreon, Buy Me A Coffee, or Ko-fi`,
html: `<h1>New Stories about Patreon, Buy Me A Coffee, or Ko-fi on Hacker News</h1>${emailContent}`,
});
} else {
console.log("No new stories found.");
}
await sqlite.execute(`DELETE FROM ${TABLE_NAME} WHERE notified_at < datetime('now', '-7 days')`);
}
export const main = async () => {
await checkHackerNewsForPatreon();
};