feat: broadcast
This commit is contained in:
@@ -0,0 +1,40 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Broadcast is an announcement shown to every user exactly once.
|
||||
//
|
||||
// Deliberately not a notification: it creates no tray rows and no per-user
|
||||
// records until someone actually dismisses it. The modal is the delivery
|
||||
// surface; push and the realtime nudge only tell clients to go look.
|
||||
type Broadcast struct {
|
||||
ID string `json:"id"`
|
||||
Title string `json:"title"`
|
||||
Body string `json:"body"`
|
||||
// Entities are offset/length formatting spans, the same shape chat uses,
|
||||
// so no HTML is ever stored or rendered.
|
||||
Entities json.RawMessage `json:"entities"`
|
||||
// BannerURL is resolved from the stored R2 key for the client.
|
||||
BannerURL *string `json:"banner_url,omitempty"`
|
||||
CTALabel *string `json:"cta_label,omitempty"`
|
||||
CTAURL *string `json:"cta_url,omitempty"`
|
||||
|
||||
PublishedAt *time.Time `json:"published_at,omitempty"`
|
||||
ExpiresAt *time.Time `json:"expires_at,omitempty"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
|
||||
// SeenCount is filled for the admin list only — how many people have
|
||||
// dismissed it so far.
|
||||
SeenCount int64 `json:"seen_count,omitempty"`
|
||||
}
|
||||
|
||||
// Live reports whether the broadcast is currently deliverable.
|
||||
func (b *Broadcast) Live(now time.Time) bool {
|
||||
if b.PublishedAt == nil || b.PublishedAt.After(now) {
|
||||
return false
|
||||
}
|
||||
return b.ExpiresAt == nil || b.ExpiresAt.After(now)
|
||||
}
|
||||
Reference in New Issue
Block a user