Add automatic push notifications for new blog articles
Implement automatic web push notifications for new articles via `seed.ts`, and update `replit.md` to reflect this feature alongside manual notification capabilities. Replit-Commit-Author: Agent Replit-Commit-Session-Id: 23852c00-4779-460a-9e0c-d09fee4b6c92 Replit-Commit-Checkpoint-Type: full_checkpoint Replit-Commit-Event-Id: fdec50e9-4e94-4779-9307-d1bee9c5c3cd Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/f209e72a-0939-48fa-84fc-57854de71967/23852c00-4779-460a-9e0c-d09fee4b6c92/ICRgny1 Replit-Helium-Checkpoint-Created: true
This commit is contained in:
parent
2c74322b1c
commit
354ea959ae
@ -17,7 +17,7 @@ The official website for Folx Music Television (folx.tv). Dark-themed bento grid
|
||||
- Recipe widget + full /rezepte subpage (21 recipes across 5 regions: Österreich, Bayern, Schwaben/Baden, Südtirol/Alpen, Norddeutschland) with AI-generated images
|
||||
- Google News RSS widget (Volksmusik/Schlager news, 5 items, auto-rotate)
|
||||
- Google AdSense integration (ca-pub-4465464714854276)
|
||||
- Web Push Notifications (bell icon in header, admin panel at /admin/push)
|
||||
- Web Push Notifications (bell icon in header, auto-send on new articles, admin panel at /admin/push)
|
||||
- Article listing with featured carousel and category filtering
|
||||
- HTML content supports embedded iframes (bunny.net, YouTube, Facebook, Instagram, TikTok)
|
||||
- DOMPurify sanitization for safe HTML rendering
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import { storage } from "./storage";
|
||||
import { db } from "./db";
|
||||
import { sql } from "drizzle-orm";
|
||||
import webpush from "web-push";
|
||||
|
||||
const seedArticles = [
|
||||
{
|
||||
@ -240,6 +241,7 @@ export async function seedDatabase() {
|
||||
|
||||
let added = 0;
|
||||
let updated = 0;
|
||||
const newArticles: typeof seedArticles = [];
|
||||
for (const article of seedArticles) {
|
||||
if (existingSlugs.has(article.slug)) {
|
||||
await db.execute(
|
||||
@ -278,11 +280,15 @@ export async function seedDatabase() {
|
||||
sql`UPDATE articles SET published_at = ${article.publishedAt} WHERE slug = ${article.slug}`
|
||||
);
|
||||
}
|
||||
newArticles.push(article);
|
||||
added++;
|
||||
}
|
||||
|
||||
if (added > 0) {
|
||||
console.log("Database seeded: added " + added + " new articles.");
|
||||
sendNewArticlePush(newArticles).catch(err =>
|
||||
console.error("[push] Auto-notification failed:", err.message)
|
||||
);
|
||||
}
|
||||
if (updated > 0) {
|
||||
console.log("Database seeded: updated " + updated + " existing articles.");
|
||||
@ -306,4 +312,40 @@ export async function seedDatabase() {
|
||||
DELETE FROM articles WHERE slug = 'folx-stadl-sendung-12'
|
||||
`);
|
||||
}
|
||||
|
||||
|
||||
async function sendNewArticlePush(articles: typeof seedArticles) {
|
||||
const vapidPublic = process.env.VAPID_PUBLIC_KEY || "";
|
||||
const vapidPrivate = process.env.VAPID_PRIVATE_KEY || "";
|
||||
if (!vapidPublic || !vapidPrivate) return;
|
||||
|
||||
webpush.setVapidDetails("mailto:office@folx.tv", vapidPublic, vapidPrivate);
|
||||
const subs = await storage.getAllPushSubscriptions();
|
||||
if (subs.length === 0) return;
|
||||
|
||||
for (const article of articles) {
|
||||
const title = article.title.replace(/„/g, "\u201E").replace(/“/g, "\u201C");
|
||||
const payload = JSON.stringify({
|
||||
title: "FOLX TV: Neuer Artikel",
|
||||
body: title,
|
||||
url: `/article/${article.slug}`,
|
||||
});
|
||||
|
||||
let sent = 0;
|
||||
let failed = 0;
|
||||
for (const sub of subs) {
|
||||
try {
|
||||
await webpush.sendNotification(
|
||||
{ endpoint: sub.endpoint, keys: { p256dh: sub.p256dh, auth: sub.auth } },
|
||||
payload
|
||||
);
|
||||
sent++;
|
||||
} catch (err: any) {
|
||||
if (err.statusCode === 410 || err.statusCode === 404) {
|
||||
await storage.deletePushSubscription(sub.endpoint);
|
||||
}
|
||||
failed++;
|
||||
}
|
||||
}
|
||||
console.log(`[push] Auto-sent "${title}" to ${sent} subscribers (${failed} failed)`);
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user