feat: Erinnerung zum Sichern von Story-Insights vor Ablauf
Ausgangspunkt: Instagram hält Story-Insights nach eigener Aussage nur
24 Stunden vor, auch der offizielle Datenexport enthält sie nicht mehr
danach. Der Standbild-Screenshot beim Prüfen entsteht direkt beim
Veröffentlichen, bevor nennenswerte Kennzahlen existieren — er kann
das strukturell nicht auffangen. Eine OAuth-Anbindung allein löst das
auch nicht: selbst mit API-Zugriff bräuchte es einen Abruf innerhalb
desselben 24h-Fensters.
- Migration 0007: asset.purpose ('initial' | 'insights', Default
'initial' erhält die Bedeutung aller Bestandszeilen). Ein Beitrag
kann jetzt mehrere Insights-Nachweise über die Zeit bekommen.
GetLatestAssetForSubmission berücksichtigt weiterhin nur 'initial',
damit ein späterer Insights-Upload nie den beim Archivieren
referenzierten Original-Screenshot verdrängt.
- internal/web/insights_reminder.go: computeInsightsReminder — reine,
ungetestete gegen echte Instagram-Daten, aber isoliert testbare
Logik fürs Erinnerungs-Timing (Produktentscheidung, keine Rechtsnorm,
daher nicht in rules/*.yaml).
- GET /beitraege/{id} zeigt die Erinnerung bei veröffentlichten
"story"-Beiträgen ohne existierendes insights-Asset; POST
/beitraege/{id}/insights speichert einen weiteren Screenshot (gleiche
Validierung wie das initiale Standbild, wiederverwendet über
readUploadedAsset/storeAsset mit purpose-Parameter).
- Bewusst nur In-App-Banner in dieser Ausbaustufe, kein Mail-/Push-
Versand — dafür fehlt aktuell ein SMTP-Relay/Versanddienst, siehe
CLAUDE.md-Hinweis dazu.
Volle Testsuite inkl. echter Postgres-Tests grün; End-to-End gegen
einen laufenden Server verifiziert (Story archivieren → Erinnerung
sichtbar → Insights-Upload → Erinnerung verschwindet, Nachweis
gelistet, Mandantentrennung beim Upload durchgesetzt).
This commit is contained in:
47
internal/web/insights_reminder.go
Normal file
47
internal/web/insights_reminder.go
Normal file
@@ -0,0 +1,47 @@
|
||||
package web
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
// storyInsightsWindow ist das Zeitfenster, in dem Instagram nach
|
||||
// eigener Aussage Story-Insights überhaupt vorhält — danach sind sie
|
||||
// auch über den offiziellen Datenexport nicht mehr zu bekommen. Reine
|
||||
// Produktentscheidung (Erinnerungs-Timing), keine Rechtsnorm — bewusst
|
||||
// hier als Konstante und nicht in rules/*.yaml, das ist ausschließlich
|
||||
// für die Kennzeichnungsprüfung reserviert (siehe CLAUDE.md).
|
||||
const storyInsightsWindow = 24 * time.Hour
|
||||
|
||||
// insightsReminder beschreibt, ob und wie dringend eine Erinnerung
|
||||
// angezeigt werden soll, die Kennzahlen (Insights) eines veröffentlichten
|
||||
// Beitrags per Screenshot zu sichern, bevor sie unwiederbringlich
|
||||
// verschwinden.
|
||||
type insightsReminder struct {
|
||||
Show bool
|
||||
Urgent bool // Fenster läuft noch
|
||||
Expired bool // Fenster ist wahrscheinlich schon vorbei
|
||||
Message string
|
||||
}
|
||||
|
||||
// computeInsightsReminder berechnet den Erinnerungsstatus. Nur für
|
||||
// "story"-Beiträge relevant (siehe storyInsightsWindow); alle anderen
|
||||
// Beitragstypen bekommen keine Erinnerung, da ihre Kennzahlen nicht auf
|
||||
// dieselbe Art flüchtig sind.
|
||||
func computeInsightsReminder(postType string, publishedAt time.Time, now time.Time, hasInsightsAsset bool) insightsReminder {
|
||||
if postType != "story" || hasInsightsAsset || publishedAt.IsZero() {
|
||||
return insightsReminder{}
|
||||
}
|
||||
elapsed := now.Sub(publishedAt)
|
||||
if elapsed >= storyInsightsWindow {
|
||||
return insightsReminder{
|
||||
Show: true, Expired: true,
|
||||
Message: "Das Zeitfenster für Story-Insights ist bei Instagram nach eigener Aussage abgelaufen (24 Stunden) — die Kennzahlen sind wahrscheinlich nicht mehr abrufbar.",
|
||||
}
|
||||
}
|
||||
remainingHours := int((storyInsightsWindow - elapsed).Hours()) + 1
|
||||
return insightsReminder{
|
||||
Show: true, Urgent: true,
|
||||
Message: fmt.Sprintf("Noch ca. %d Stunde(n), um die Story-Insights zu sichern, bevor sie bei Instagram verschwinden.", remainingHours),
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user