feat(api): /speak meldet Gesetz-Verwürfe, /status zeigt Gesetz-State

POST /speak antwortet bei Verwurf dokumentiert mit 202 {id:"",
discarded:"rate_limit"|"quiet_hours"} (+ toast:true im Toast-Modus)
— analog zum Mute-Muster, kein Fehler. GET /status ergänzt additiv
rate_limit {interval, allow_high_burst, next_slot} und quiet_hours
{window, active, mode, until} (RFC3339 bzw. null). talkd verwired die
Gesetze aus der Config und loggt sie beim Start. Die CLI meldet
'discarded: <grund>' plain (wie muted) und zeigt in talk status die
Zeilen rate-limit/ruhezeit mit Slot bzw. Fenster-Ende.
This commit is contained in:
m3ta-chiron committed 2026-10-18 17:40:46 +02:00
1 parent 5385a4b87d
commit b56c8abfae
6 files changed
+194 -27

No files matched your search

+51 -8
View File
@@ -27,10 +27,20 @@ type SpeakRequest struct {
// SpeakResponse ist die Antwort von POST /speak: 202 {"id":"…"} — bei
// aktivem Mute 202 {"id":"","muted":true} (Ansage verworfen; dokumentiertes
// Verhalten, kein Fehler).
// Verhalten, kein Fehler). Seit Task 05 meldet verworfenen Spam ebenso
// dokumentiert: 202 {"id":"","discarded":"rate_limit"|"quiet_hours"} —
// plus "toast":true, wenn die Ruhezeit-Ansage durch eine Benachrichtigung
// ersetzt wurde (quiet_mode = "toast").
type SpeakResponse struct {
ID string `json:"id"`
Muted bool `json:"muted,omitempty"`
// Discarded ist der Verwurfs-Grund ("rate_limit" | "quiet_hours");
// leer, wenn die Ansage aufgenommen wurde.
Discarded string `json:"discarded,omitempty"`
// Toast meldet die Ersetzung durch eine Benachrichtigung.
Toast bool `json:"toast,omitempty"`
}
// CurrentItem beschreibt das laufende Item in GET /status.
@@ -44,14 +54,47 @@ type CurrentItem struct {
// StatusResponse ist die Antwort von GET /status: Queue-Länge, aktuelles
// Item (null im Leerlauf), Mute-State, aktiver Provider, Daemon-Version.
// QueueIDs ist die Ergänzung der wartenden IDs in Abarbeitungs-Reihenfolge
// — die CLI braucht sie für ihr --wait-Polling.
// — die CLI braucht sie für ihr --wait-Polling. Task 05 ergänzt additiv
// den Gesetz-State (rate_limit, quiet_hours).
type StatusResponse struct {
Version string `json:"version"`
Queue int `json:"queue"`
QueueIDs []string `json:"queue_ids,omitempty"`
Current *CurrentItem `json:"current"`
Muted bool `json:"muted"`
Provider string `json:"provider"`
Version string `json:"version"`
Queue int `json:"queue"`
QueueIDs []string `json:"queue_ids,omitempty"`
Current *CurrentItem `json:"current"`
Muted bool `json:"muted"`
Provider string `json:"provider"`
RateLimit *RateLimitState `json:"rate_limit,omitempty"`
QuietHours *QuietHoursState `json:"quiet_hours,omitempty"`
}
// RateLimitState ist der Rate-Limit-State in GET /status (Task 05).
type RateLimitState struct {
// Interval ist der konfigurierte Mindestabstand als Dauer-String
// ("30s"; "0s" = unbegrenzt).
Interval string `json:"interval"`
// AllowHighBurst meldet, ob priority=high verstoßen darf.
AllowHighBurst bool `json:"allow_high_burst"`
// NextSlot ist der nächste freie Ansage-Slot als RFC3339-Zeitstempel;
// null, wenn sofort gespielt werden dürfte (oder unbegrenzt).
NextSlot *string `json:"next_slot"`
}
// QuietHoursState ist der Ruhezeit-State in GET /status (Task 05).
type QuietHoursState struct {
// Window ist das konfigurierte Fenster ("18:00-08:00"; "" = deaktiviert).
Window string `json:"window"`
// Active meldet, ob die lokale Zeit gerade im Fenster liegt.
Active bool `json:"active"`
// Mode ist der konfigurierte Ruhezeit-Modus ("discard" | "toast").
Mode string `json:"mode"`
// Until ist das Fenster-Ende als RFC3339-Zeitstempel, wenn aktiv;
// sonst null.
Until *string `json:"until"`
}
// PendingOrCurrent meldet, ob die Ansage mit der ID noch wartet oder