Live video on the AT Protocol
1package model
2
3import (
4 "bytes"
5 "context"
6 "fmt"
7 "time"
8
9 "github.com/bluesky-social/indigo/atproto/syntax"
10 "stream.place/streamplace/pkg/spid"
11 "stream.place/streamplace/pkg/streamplace"
12)
13
14type BroadcastOrigin struct {
15 URI string `gorm:"primaryKey;column:uri"`
16 CID string `gorm:"column:cid"`
17 RepoDID string `gorm:"column:repo_did"`
18 Repo *Repo `gorm:"foreignKey:DID;references:RepoDID"`
19 StreamerRepoDID string `gorm:"column:streamer_repo_did;index:idx_streamer_repo_did_updated_at,priority:1"`
20 StreamerRepo *Repo `gorm:"foreignKey:DID;references:StreamerRepoDID"`
21 ServerRepoDID string `gorm:"column:server_repo_did;index:idx_server_repo_did_updated_at,priority:1"`
22 UpdatedAt time.Time `gorm:"column:updated_at;index:idx_streamer_repo_did_updated_at,priority:2;index:idx_server_repo_did_updated_at,priority:2"`
23 Record []byte `gorm:"column:record"`
24}
25
26func (bo *BroadcastOrigin) TableName() string {
27 return "broadcast_origins"
28}
29
30func (m *DBModel) UpdateBroadcastOrigin(ctx context.Context, origin *streamplace.BroadcastOrigin, aturi syntax.ATURI) error {
31 repoDID := aturi.Authority().String()
32 cid, err := spid.GetCID(origin)
33 if err != nil {
34 return fmt.Errorf("failed to get CID: %w", err)
35 }
36 validATURI := fmt.Sprintf("at://%s/place.stream.broadcast.origin/%s::%s", repoDID, origin.Streamer, origin.Server)
37 if validATURI != aturi.String() {
38 return fmt.Errorf("invalid ATURI: %s != %s", validATURI, aturi.String())
39 }
40 buf := bytes.Buffer{}
41 err = origin.MarshalCBOR(&buf)
42 if err != nil {
43 return fmt.Errorf("failed to marshal origin: %w", err)
44 }
45 bo := &BroadcastOrigin{
46 URI: validATURI,
47 CID: cid.String(),
48 StreamerRepoDID: origin.Streamer,
49 ServerRepoDID: origin.Server,
50 UpdatedAt: time.Now(),
51 Record: buf.Bytes(),
52 }
53 return m.DB.Save(bo).Error
54}