feat: add broadcast session tracking and chatlog service with database migrations
This commit is contained in:
132
broadcasters/chatlog.go
Normal file
132
broadcasters/chatlog.go
Normal file
@@ -0,0 +1,132 @@
|
||||
package broadcasters
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"encore.dev/beta/errs"
|
||||
)
|
||||
|
||||
type ChatLogEntry struct {
|
||||
ID int64 `json:"id"`
|
||||
Timestamp time.Time `json:"timestamp"`
|
||||
Room string `json:"room"`
|
||||
Type string `json:"type"`
|
||||
Data string `json:"data"`
|
||||
}
|
||||
|
||||
type AddChatLogParams struct {
|
||||
Type string `json:"type"`
|
||||
Data string `json:"data"`
|
||||
}
|
||||
|
||||
type ListChatLogParams struct {
|
||||
Limit int `json:"limit,omitempty" query:"limit"`
|
||||
Type string `json:"type,omitempty" query:"type"`
|
||||
}
|
||||
|
||||
type ListChatLogResponse struct {
|
||||
Messages []*ChatLogEntry `json:"messages"`
|
||||
}
|
||||
|
||||
// AddChatLog inserisce un nuovo evento o messaggio nella tabella chatlog.
|
||||
//
|
||||
//encore:api public method=POST path=/broadcasters/id/:id/chatlog
|
||||
func AddChatLog(ctx context.Context, id string, p *AddChatLogParams) (*ChatLogEntry, error) {
|
||||
if strings.TrimSpace(id) == "" {
|
||||
return nil, &errs.Error{Code: errs.InvalidArgument, Message: "id stanza obbligatorio"}
|
||||
}
|
||||
if p == nil || strings.TrimSpace(p.Data) == "" {
|
||||
return nil, &errs.Error{Code: errs.InvalidArgument, Message: "data obbligatorio"}
|
||||
}
|
||||
|
||||
msgType := strings.ToUpper(strings.TrimSpace(p.Type))
|
||||
if msgType == "" {
|
||||
msgType = "MESSAGE"
|
||||
} else if msgType == "ALERT" {
|
||||
msgType = "ALLERT"
|
||||
}
|
||||
switch msgType {
|
||||
case "ACTION", "MESSAGE", "ALLERT", "CMD":
|
||||
default:
|
||||
msgType = "MESSAGE"
|
||||
}
|
||||
|
||||
entry := &ChatLogEntry{
|
||||
Room: id,
|
||||
Type: msgType,
|
||||
Data: p.Data,
|
||||
}
|
||||
|
||||
err := db.QueryRow(ctx, `
|
||||
INSERT INTO chatlog (room, type, data, timestamp)
|
||||
VALUES ($1, $2, $3, NOW())
|
||||
RETURNING id, timestamp
|
||||
`, entry.Room, entry.Type, entry.Data).Scan(&entry.ID, &entry.Timestamp)
|
||||
if err != nil {
|
||||
return nil, errs.WrapCode(err, errs.Internal, "impossibile salvare il messaggio di chat")
|
||||
}
|
||||
|
||||
return entry, nil
|
||||
}
|
||||
|
||||
// ListChatLog preleva gli ultimi messaggi per la stanza (default 30) e li ordina
|
||||
// in ordine cronologico crescente (dal più vecchio al più recente), pronti per l'append nella UI.
|
||||
//
|
||||
//encore:api public method=GET path=/broadcasters/id/:id/chatlog
|
||||
func ListChatLog(ctx context.Context, id string, p *ListChatLogParams) (*ListChatLogResponse, error) {
|
||||
if strings.TrimSpace(id) == "" {
|
||||
return nil, &errs.Error{Code: errs.InvalidArgument, Message: "id stanza obbligatorio"}
|
||||
}
|
||||
|
||||
limit := 30
|
||||
filterType := ""
|
||||
if p != nil {
|
||||
if p.Limit > 0 {
|
||||
limit = p.Limit
|
||||
}
|
||||
if t := strings.TrimSpace(p.Type); t != "" {
|
||||
filterType = strings.ToUpper(t)
|
||||
}
|
||||
}
|
||||
if limit > 100 {
|
||||
limit = 100
|
||||
}
|
||||
|
||||
query := `
|
||||
SELECT id, timestamp, room, type, data
|
||||
FROM (
|
||||
SELECT id, timestamp, room, type, data
|
||||
FROM chatlog
|
||||
WHERE room = $1 AND ($3 = '' OR type = $3)
|
||||
ORDER BY timestamp DESC, id DESC
|
||||
LIMIT $2
|
||||
) sub
|
||||
ORDER BY timestamp ASC, id ASC
|
||||
`
|
||||
|
||||
rows, err := db.Query(ctx, query, id, limit, filterType)
|
||||
if err != nil {
|
||||
return nil, errs.WrapCode(err, errs.Internal, "impossibile recuperare i messaggi di chat")
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
var list []*ChatLogEntry
|
||||
for rows.Next() {
|
||||
var e ChatLogEntry
|
||||
if err := rows.Scan(&e.ID, &e.Timestamp, &e.Room, &e.Type, &e.Data); err != nil {
|
||||
return nil, errs.WrapCode(err, errs.Internal, "errore nella lettura dei messaggi")
|
||||
}
|
||||
list = append(list, &e)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, errs.WrapCode(err, errs.Internal, "errore iterazione messaggi")
|
||||
}
|
||||
|
||||
if list == nil {
|
||||
list = []*ChatLogEntry{}
|
||||
}
|
||||
|
||||
return &ListChatLogResponse{Messages: list}, nil
|
||||
}
|
||||
9
broadcasters/migrations/2_create_chatlog.up.sql
Normal file
9
broadcasters/migrations/2_create_chatlog.up.sql
Normal file
@@ -0,0 +1,9 @@
|
||||
CREATE TABLE chatlog (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
timestamp TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
room UUID NOT NULL,
|
||||
type TEXT NOT NULL CHECK (type IN ('ACTION','MESSAGE','ALLERT','CMD')),
|
||||
data TEXT NOT NULL
|
||||
);
|
||||
|
||||
CREATE INDEX idx_chatlog_room ON chatlog(room);
|
||||
@@ -6,6 +6,6 @@ ALTER TABLE broadcasters RENAME COLUMN new_id TO id;
|
||||
ALTER TABLE broadcasters ALTER COLUMN id SET NOT NULL;
|
||||
ALTER TABLE broadcasters ADD PRIMARY KEY (id);
|
||||
|
||||
ALTER TABLE broadcasters ADD COLUMN enabled BOOLEAN NOT NULL DEFAULT FALSE;
|
||||
ALTER TABLE broadcasters ADD COLUMN used BOOLEAN NOT NULL DEFAULT FALSE;
|
||||
UPDATE broadcasters SET used = TRUE, enabled = TRUE;
|
||||
-- enabled column already added in previous migration
|
||||
-- used column already added in previous migration
|
||||
-- data update for enabled/used columns moved to previous migration
|
||||
11
broadcasters/migrations/4_add_enabled_used.up.sql
Normal file
11
broadcasters/migrations/4_add_enabled_used.up.sql
Normal file
@@ -0,0 +1,11 @@
|
||||
-- 4_add_enabled_used.up.sql
|
||||
-- Aggiunge le colonne "enabled" e "used" alla tabella broadcasters.
|
||||
-- Queste colonne sono usate dal codice Go per indicare lo stato del profilo.
|
||||
|
||||
ALTER TABLE broadcasters
|
||||
ADD COLUMN enabled BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
ADD COLUMN used BOOLEAN NOT NULL DEFAULT FALSE;
|
||||
|
||||
-- Indici facoltativi per velocizzare le query su queste colonne
|
||||
CREATE INDEX idx_broadcasters_enabled ON broadcasters(enabled);
|
||||
CREATE INDEX idx_broadcasters_used ON broadcasters(used);
|
||||
4
broadcasters/migrations/5_chatlog_room_text.up.sql
Normal file
4
broadcasters/migrations/5_chatlog_room_text.up.sql
Normal file
@@ -0,0 +1,4 @@
|
||||
-- 5_chatlog_room_text.up.sql
|
||||
-- Modifica la colonna "room" da UUID a TEXT per supportare qualsiasi identificatore di stanza (es. nomi LiveKit, slug, broadcast-uuid).
|
||||
|
||||
ALTER TABLE chatlog ALTER COLUMN room TYPE TEXT;
|
||||
Reference in New Issue
Block a user