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:
1 parent
5385a4b87d
commit
b56c8abfae
6 files changed
+194
-27
No files matched your search
+24
-9
@@ -1,11 +1,11 @@
|
||||
// talkd ist der Daemon für talk 2.0: HTTP-API auf 127.0.0.1 (Default-Port
|
||||
// 7800, server.port/TALK_PORT), serialisierte Ansage-Queue mit Prioritäten
|
||||
// und now-Sprung, persistenter Mute-State (Datei mute im Config-Dir).
|
||||
//
|
||||
// Task 04: POST /speak, GET /status, POST /cancel, POST /mute, POST /unmute.
|
||||
// Rate-Limit/Ruhezeiten folgen in Task 05, CORS/MCP in Task 06 — die
|
||||
// Rate-Limit-Struktur existiert bereits (internal/queue/rate.go), ist hier
|
||||
// aber bewusst noch nicht angebunden (Task-04-Default: unbegrenzt).
|
||||
// und now-Sprung, persistenter Mute-State (Datei mute im Config-Dir) —
|
||||
// und seit Task 05 das Anti-Spam-Gesetz: Rate-Limit (queue.rate_limit,
|
||||
// Default 1 Ansage / 30 s; low über Budget wird verworfen, normal parkt,
|
||||
// high darf mit queue.allow_high_burst verstoßen) plus Ruhezeiten
|
||||
// (quiet_hours/quiet_mode; now:true bricht bewusst aus beiden aus).
|
||||
// CORS/MCP folgen in Task 06.
|
||||
package main
|
||||
|
||||
import (
|
||||
@@ -88,7 +88,21 @@ func run() error {
|
||||
return chain.Speak(ctx, item.Text, lang)
|
||||
}
|
||||
|
||||
q := queue.New(speak, lw)
|
||||
// Anti-Spam-Gesetz (Task 05): Rate-Limit + High-Burst + Ruhezeiten.
|
||||
// config.Load hat quiet_hours bereits validiert — das Parsen hier kann
|
||||
// praktisch nicht scheitern, aber ein Fehler darf nie still werden.
|
||||
quiet, err := queue.ParseQuietHours(cfg.QuietHours)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
laws := queue.Laws{
|
||||
RateLimit: cfg.Queue.RateLimit,
|
||||
AllowHighBurst: cfg.Queue.AllowHighBurst,
|
||||
Quiet: quiet,
|
||||
QuietMode: cfg.QuietMode,
|
||||
}
|
||||
|
||||
q := queue.New(laws, speak, lw)
|
||||
|
||||
// Persistenter Mute-State (Datei mute im Config-Dir). Ohne Config-Dir
|
||||
// läuft der Daemon ohne Mute weiter (dokumentierte Warnung) statt zu
|
||||
@@ -125,8 +139,9 @@ func run() error {
|
||||
srv := &http.Server{Handler: handler, ReadHeaderTimeout: 5 * time.Second}
|
||||
errCh := make(chan error, 1)
|
||||
go func() { errCh <- srv.Serve(ln) }()
|
||||
log.Printf("listening on http://%s (version %s, audio sink %s, mute=%v)",
|
||||
addr, versionString(), sink.Name(), mute.Muted())
|
||||
log.Printf("listening on http://%s (version %s, audio sink %s, mute=%v, rate-limit %s, high-burst=%v, ruhezeit=%q modus %s)",
|
||||
addr, versionString(), sink.Name(), mute.Muted(),
|
||||
cfg.Queue.RateLimit, cfg.Queue.AllowHighBurst, cfg.QuietHours, cfg.QuietMode)
|
||||
|
||||
sig := make(chan os.Signal, 1)
|
||||
signal.Notify(sig, os.Interrupt, syscall.SIGTERM)
|
||||
|
||||
Reference in new issue
Block a user