feat: Erscheinungsmeldung für Watchlist-Filme

Der Auftrag nennt sie ausdrücklich, das Profil hatte den Schalter schon —
verschickt wurde bisher nichts.

Betrachtet wird ein Zeitfenster der letzten Tage statt eines Zustandswechsels:
TMDB verschiebt Termine gelegentlich, und ein einmal verpasstes Datum soll
nicht dazu führen, dass die Meldung für immer ausbleibt. Doppelt kommt sie
trotzdem nie.

Die Meldung hängt nicht am TMDB-Abruf, sondern an den Erscheinungsdaten, die
ohnehin im Katalog stehen — sie funktioniert also auch ohne Schlüssel.
This commit is contained in:
Florian Wilde
2026-09-01 20:50:17 +02:00
parent a54e625ca8
commit 96a42594a9
2 changed files with 97 additions and 1 deletions
+37 -1
View File
@@ -8,7 +8,7 @@ import { prisma } from "../src/lib/db";
import { importMovie, importSeries } from "../src/lib/catalog";
import { addToLibrary, markMovieWatched, moveToTrash } from "../src/lib/library";
import { exportCsv, exportJson, importCsv, importTrakt, parseCsv } from "../src/lib/transfer";
import { purgeExpired, TRASH_RETENTION_DAYS } from "../src/lib/sync";
import { purgeExpired, runSync, TRASH_RETENTION_DAYS } from "../src/lib/sync";
import { notifyUser } from "../src/lib/notify";
/** Prüft Import, Export, das Aufräumen des Papierkorbs und den Doppelversandschutz. */
@@ -239,3 +239,39 @@ test("dieselbe Nachricht wird nicht zweimal verschickt", async () => {
await prisma.notificationChannel.deleteMany({ where: { userId } });
});
test("erschienene Watchlist-Filme werden gemeldet — und nur einmal", async () => {
// Der Film liegt auf der Watchlist und ist gestern erschienen.
const entry = await addToLibrary(userId, movieTitleId, "WATCHLIST");
await prisma.title.update({
where: { id: movieTitleId },
data: { releaseDate: new Date(Date.now() - 86_400_000) },
});
await prisma.user.update({ where: { id: userId }, data: { notifyRelease: true } });
await prisma.notificationChannel.create({
data: {
userId,
kind: "WEBHOOK",
name: "Test",
config: { webhookUrl: "http://127.0.0.1:9/nicht-erreichbar" },
},
});
await runSync({ limit: 0 });
const first = await prisma.notificationLog.findMany({
where: { userId, dedupeKey: `release:${movieTitleId}` },
});
assert.equal(first.length, 1, "die Meldung wird angelegt");
assert.match(first[0]?.subject ?? "", /Jetzt erschienen/);
// Ein zweiter Lauf meldet dasselbe nicht noch einmal.
await runSync({ limit: 0 });
const second = await prisma.notificationLog.count({
where: { userId, dedupeKey: `release:${movieTitleId}` },
});
assert.equal(second, 1);
await prisma.notificationChannel.deleteMany({ where: { userId } });
await prisma.libraryEntry.delete({ where: { id: entry.id } });
});