Live video on the AT Protocol
1package model
2
3import (
4 "encoding/json"
5 "errors"
6 "fmt"
7 "time"
8
9 "gorm.io/gorm"
10)
11
12type Recommendation struct {
13 UserDID string `gorm:"column:user_did;primaryKey"`
14 Streamers json.RawMessage `gorm:"column:streamers;type:json;not null"`
15 CreatedAt time.Time `gorm:"column:created_at"`
16 UpdatedAt time.Time `gorm:"column:updated_at"`
17}
18
19func (r *Recommendation) TableName() string {
20 return "recommendations"
21}
22
23func (r *Recommendation) GetStreamersArray() ([]string, error) {
24 var streamers []string
25 if err := json.Unmarshal(r.Streamers, &streamers); err != nil {
26 return nil, fmt.Errorf("failed to unmarshal streamers: %w", err)
27 }
28 return streamers, nil
29}
30
31// UpsertRecommendation creates or updates recommendations for a user
32func (m *DBModel) UpsertRecommendation(rec *Recommendation) error {
33 if rec.UserDID == "" {
34 return fmt.Errorf("user DID cannot be empty")
35 }
36
37 // Validate JSON contains array of max 8 DIDs
38 var streamers []string
39 if err := json.Unmarshal(rec.Streamers, &streamers); err != nil {
40 return fmt.Errorf("invalid streamers JSON: %w", err)
41 }
42 if len(streamers) > 8 {
43 return fmt.Errorf("maximum 8 recommendations allowed, got %d", len(streamers))
44 }
45
46 now := time.Now()
47 if rec.CreatedAt.IsZero() {
48 rec.CreatedAt = now
49 }
50 rec.UpdatedAt = now
51
52 // Use GORM's upsert (On Conflict Do Update)
53 result := m.DB.Save(rec)
54 if result.Error != nil {
55 return fmt.Errorf("database upsert failed: %w", result.Error)
56 }
57
58 return nil
59}
60
61// GetRecommendation retrieves a valid recommendation from a user
62func (m *DBModel) GetRecommendation(userDID string) (*Recommendation, error) {
63 if userDID == "" {
64 return nil, fmt.Errorf("user DID cannot be empty")
65 }
66
67 var rec Recommendation
68 err := m.DB.Where("user_did = ?", userDID).First(&rec).Error
69 if err != nil {
70 if errors.Is(err, gorm.ErrRecordNotFound) {
71 return nil, err
72 }
73 return nil, fmt.Errorf("database query failed: %w", err)
74 }
75 return &rec, nil
76}