From b5863ca511165882af8f3168988d912ac6e19ad1 Mon Sep 17 00:00:00 2001 From: Cho Young-Hwi Date: Tue, 24 Mar 2026 15:57:37 +0000 Subject: [PATCH 1/2] [#499] Add notifyNewStoryline() notification trigger Add a dedicated notification for new storylines with "New story published" title and "{title} by {author}" body. Called from the backfill cron when a StorylineCreated event is first indexed. Fixes #499 Co-Authored-By: Claude Opus 4.6 (1M context) --- lib/notifications.server.ts | 26 ++++++++++++++++++++++++++ src/app/api/cron/backfill/route.ts | 8 ++++---- 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/lib/notifications.server.ts b/lib/notifications.server.ts index afcee5d8..5d4c2719 100644 --- a/lib/notifications.server.ts +++ b/lib/notifications.server.ts @@ -160,6 +160,32 @@ export async function sendNotification(params: { const appUrl = process.env.NEXT_PUBLIC_APP_URL ?? "https://plotlink.xyz"; +/** + * Notify all users with enabled notifications about a new storyline. + * Called from the backfill cron when a new storyline is first indexed. + */ +export async function notifyNewStoryline( + storylineId: number, + title: string, + author: string, +): Promise { + const tokens = await getEnabledTokens(); + if (tokens.length === 0) return; + + const displayAuthor = + author.length > 10 + ? `${author.slice(0, 6)}…${author.slice(-4)}` + : author; + + await sendNotification({ + notificationId: `pl-new-storyline-${storylineId}`, + title: "New story published", + body: `"${title.slice(0, 40)}" by ${displayAuthor} is now on PlotLink`, + targetUrl: `${appUrl}/story/${storylineId}`, + tokens, + }); +} + /** * Notify all users with enabled notifications about a new plot. * Called from the backfill cron when a new plot is indexed. diff --git a/src/app/api/cron/backfill/route.ts b/src/app/api/cron/backfill/route.ts index 22ff0ff1..72e34282 100644 --- a/src/app/api/cron/backfill/route.ts +++ b/src/app/api/cron/backfill/route.ts @@ -7,7 +7,7 @@ import { STORY_FACTORY } from "../../../../../lib/contracts/constants"; import { hashContent } from "../../../../../lib/content"; import { detectWriterType } from "../../../../../lib/contracts/erc8004"; import { reconcileStorylinePlotCount } from "../../../../../lib/reconcile"; -import { notifyNewPlot } from "../../../../../lib/notifications.server"; +import { notifyNewPlot, notifyNewStoryline } from "../../../../../lib/notifications.server"; import type { Database } from "../../../../../lib/supabase"; const IPFS_GATEWAY = "https://ipfs.filebase.io/ipfs/"; @@ -164,9 +164,9 @@ export async function GET(req: Request) { storylinesInserted++; if (result.genesisPlotFailed) failures++; else { - // Notify users about the new story - const args = decoded.args as { storylineId: bigint; title: string }; - notifyNewPlot(Number(args.storylineId), args.title, 0).catch(() => {}); + // Notify users about the new storyline + const args = decoded.args as { storylineId: bigint; title: string; writer: `0x${string}` }; + notifyNewStoryline(Number(args.storylineId), args.title, args.writer).catch(() => {}); } } else if (decoded.eventName === "PlotChained") { const failed = await processPlotChained( From 5d8e4bca483d0874945ea73db8b461e08e91eaec Mon Sep 17 00:00:00 2001 From: Cho Young-Hwi Date: Tue, 24 Mar 2026 16:02:29 +0000 Subject: [PATCH 2/2] [#499] Remove title/author truncation to match ticket spec MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Send the exact body from the requirement: "{title}" by {author} is now on PlotLink — without truncating either value. Co-Authored-By: Claude Opus 4.6 (1M context) --- lib/notifications.server.ts | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/lib/notifications.server.ts b/lib/notifications.server.ts index 5d4c2719..a64a7a43 100644 --- a/lib/notifications.server.ts +++ b/lib/notifications.server.ts @@ -172,15 +172,10 @@ export async function notifyNewStoryline( const tokens = await getEnabledTokens(); if (tokens.length === 0) return; - const displayAuthor = - author.length > 10 - ? `${author.slice(0, 6)}…${author.slice(-4)}` - : author; - await sendNotification({ notificationId: `pl-new-storyline-${storylineId}`, title: "New story published", - body: `"${title.slice(0, 40)}" by ${displayAuthor} is now on PlotLink`, + body: `"${title}" by ${author} is now on PlotLink`, targetUrl: `${appUrl}/story/${storylineId}`, tokens, });