Live video on the AT Protocol
1package model
2
3import (
4 "context"
5 "errors"
6 "fmt"
7 "time"
8
9 "github.com/bluesky-social/indigo/api/bsky"
10 lexutil "github.com/bluesky-social/indigo/lex/util"
11 "gorm.io/gorm"
12 "stream.place/streamplace/pkg/streamplace"
13)
14
15type Block struct {
16 RKey string `gorm:"primaryKey;column:rkey"`
17 CID string `gorm:"column:cid"`
18 RepoDID string `json:"repoDID" gorm:"column:repo_did;index:idx_repo_did_subject_did,priority:1"`
19 Repo *Repo `json:"repo,omitempty" gorm:"foreignKey:DID;references:RepoDID"`
20 SubjectDID string `gorm:"column:subject_did;index:idx_repo_did_subject_did,priority:2"`
21 Record []byte
22 CreatedAt time.Time
23}
24
25func (b *Block) ToStreamplaceBlock() (*streamplace.Defs_BlockView, error) {
26 if b == nil {
27 return nil, fmt.Errorf("block is nil")
28 }
29 if b.Repo == nil {
30 return nil, fmt.Errorf("block repo is nil")
31 }
32 if b.Record == nil {
33 return nil, fmt.Errorf("block record is nil")
34 }
35 rec, err := lexutil.CborDecodeValue(b.Record)
36 if err != nil {
37 return nil, fmt.Errorf("error decoding feed post: %w", err)
38 }
39 block, ok := rec.(*bsky.GraphBlock)
40 if !ok {
41 return nil, fmt.Errorf("record is not a GraphBlock")
42 }
43 return &streamplace.Defs_BlockView{
44 LexiconTypeID: "place.stream.defs#blockView",
45 Blocker: &bsky.ActorDefs_ProfileViewBasic{
46 Did: b.RepoDID,
47 Handle: b.Repo.Handle,
48 },
49 Cid: b.CID,
50 IndexedAt: b.CreatedAt.Format(time.RFC3339),
51 Record: block,
52 Uri: fmt.Sprintf(`at://%s/app.bsky.graph.block/%s`, b.RepoDID, b.RKey),
53 }, nil
54}
55
56func (m *DBModel) CreateBlock(ctx context.Context, block *Block) error {
57 return m.DB.Create(block).Error
58}
59
60func (m *DBModel) DeleteBlock(ctx context.Context, rkey string) error {
61 return m.DB.Where("rkey = ?", rkey).Delete(&Block{}).Error
62}
63
64func (m *DBModel) GetBlock(ctx context.Context, rkey string) (*Block, error) {
65 var block Block
66 err := m.DB.Preload("Repo").Where("rkey = ?", rkey).First(&block).Error
67 if errors.Is(err, gorm.ErrRecordNotFound) {
68 return nil, nil
69 }
70 if err != nil {
71 return nil, err
72 }
73 return &block, nil
74}
75
76func (m *DBModel) GetBlockedDIDs(ctx context.Context, blockerDID string) ([]string, error) {
77 var dids []string
78 err := m.DB.Model(&Block{}).Where("repo_did = ?", blockerDID).Pluck("subject_did", &dids).Error
79 if err != nil {
80 return nil, err
81 }
82 return dids, nil
83}
84
85func (m *DBModel) GetUserBlock(ctx context.Context, userDID, subjectDID string) (*Block, error) {
86 var block Block
87 err := m.DB.Where("repo_did = ? AND subject_did = ?", userDID, subjectDID).First(&block).Error
88 if errors.Is(err, gorm.ErrRecordNotFound) {
89 return nil, nil
90 }
91 if err != nil {
92 return nil, err
93 }
94 return &block, nil
95}