diplomail (Stage C): paid-tier broadcast + multi-game + cleanup
Closes out the producer-side of the diplomail surface. Paid-tier players can fan out one personal message to the rest of the active roster (gated on entitlement_snapshots.is_paid). Site admins gain a multi-game broadcast (POST /admin/mail/broadcast with `selected` / `all_running` scopes) and the bulk-purge endpoint that wipes diplomail rows tied to games finished more than N years ago. An admin listing (GET /admin/mail/messages) rounds out the observability surface. EntitlementReader and GameLookup are new narrow deps wired from `*user.Service` and `*lobby.Service` in cmd/backend/main; the lobby service grows a one-off `ListFinishedGamesBefore` helper for the cleanup path (the cache evicts terminal-state games so the cache walk is not enough). Stage D will swap LangUndetermined for an actual body-language detector and add the translation cache. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -278,6 +278,7 @@ func registerUserRoutes(router *gin.Engine, instruments *metrics.Instruments, de
|
||||
|
||||
userMail := userGames.Group("/:game_id/mail")
|
||||
userMail.POST("/messages", deps.UserMail.SendPersonal())
|
||||
userMail.POST("/broadcast", deps.UserMail.SendBroadcast())
|
||||
userMail.POST("/admin", deps.UserMail.SendAdmin())
|
||||
userMail.GET("/messages/:message_id", deps.UserMail.Get())
|
||||
userMail.POST("/messages/:message_id/read", deps.UserMail.MarkRead())
|
||||
@@ -339,6 +340,9 @@ func registerAdminRoutes(router *gin.Engine, instruments *metrics.Instruments, d
|
||||
mail.GET("/deliveries/:delivery_id/attempts", deps.AdminMail.ListDeliveryAttempts())
|
||||
mail.POST("/deliveries/:delivery_id/resend", deps.AdminMail.ResendDelivery())
|
||||
mail.GET("/dead-letters", deps.AdminMail.ListDeadLetters())
|
||||
mail.GET("/messages", deps.AdminDiplomail.List())
|
||||
mail.POST("/broadcast", deps.AdminDiplomail.Broadcast())
|
||||
mail.POST("/cleanup", deps.AdminDiplomail.Cleanup())
|
||||
|
||||
notifications := group.Group("/notifications")
|
||||
notifications.GET("", deps.AdminNotifications.List())
|
||||
|
||||
Reference in New Issue
Block a user