Files
encore-test/broadcasters/chatlog.go

133 lines
3.3 KiB
Go

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
}