backend for xcvr appview
1package recordmanager
2
3import (
4 "context"
5 "errors"
6 "fmt"
7 atoauth "github.com/bluesky-social/indigo/atproto/auth/oauth"
8 "github.com/bluesky-social/indigo/atproto/syntax"
9 lexutil "github.com/bluesky-social/indigo/lex/util"
10 "mime/multipart"
11 "os"
12 "rvcx/internal/atputils"
13 "rvcx/internal/lex"
14 "rvcx/internal/oauth"
15 "rvcx/internal/types"
16 "time"
17)
18
19func (rm *RecordManager) PostImage(cs *atoauth.ClientSession, file multipart.File, fileHeader *multipart.FileHeader, ctx context.Context) (*lexutil.BlobSchema, error) {
20 return oauth.UploadBLOB(cs, file, fileHeader, ctx)
21}
22
23func (rm *RecordManager) AddImageToCache(did string, cid string, ctx context.Context) (string, error) {
24 ib, err := rm.db.IsBanned(did, ctx)
25 if err != nil {
26 return "", err
27 }
28 if ib {
29 return "", errors.New("user banned")
30 }
31 uploadDir := "./uploads"
32 _, err = os.Stat(uploadDir)
33 if os.IsNotExist(err) {
34 os.Mkdir(uploadDir, 0755)
35 }
36
37 imgPath := fmt.Sprintf("%s/%s%s", uploadDir, did, cid)
38 _, err = os.Stat(imgPath)
39 if err != nil {
40 blob, err := atputils.SyncGetBlob(did, cid, ctx)
41 if err != nil {
42 return "", err
43 }
44 file, err := os.Create(imgPath)
45 if err != nil {
46 return "", err
47 }
48 _, err = file.Write(blob)
49 if err != nil {
50 return "", err
51 }
52 }
53 return imgPath, nil
54}
55
56func (rm *RecordManager) PostMedia(cs *atoauth.ClientSession, mr *types.ParseMediaRequest, ctx context.Context) error {
57 switch mr.Type {
58 case "image":
59 return rm.postImageRecord(cs, mr, ctx)
60 default:
61 return nil
62 }
63}
64
65func (rm *RecordManager) AcceptImage(img *types.Image, ctx context.Context) error {
66 wasNew, err := rm.db.StoreImage(img, ctx)
67 if err != nil {
68 return err
69 }
70 if !wasNew {
71 return nil
72 }
73 err = rm.forwardImage(img, ctx)
74 if err != nil {
75 return errors.New("error forwarding image: " + err.Error())
76 }
77 return nil
78}
79
80func (rm *RecordManager) AcceptImageUpdate(img *types.Image, ctx context.Context) error {
81 err := rm.db.UpdateImage(img, ctx)
82 if err != nil {
83 return err
84 }
85 return nil
86}
87
88func (rm *RecordManager) AcceptImageDelete(img *types.Image, ctx context.Context) error {
89 err := rm.db.DeleteImage(img.URI, ctx)
90 if err != nil {
91 return err
92 }
93 return nil
94}
95
96func (rm *RecordManager) postImageRecord(cs *atoauth.ClientSession, mr *types.ParseMediaRequest, ctx context.Context) error {
97 imr, now, err := rm.validateImageRecord(mr, ctx)
98 if err != nil {
99 return errors.New("coudlnt validate media record: " + err.Error())
100 }
101 img, err := rm.createImageRecord(cs, imr, now, ctx)
102 if err != nil {
103 return errors.New("coudlnt validate media record: " + err.Error())
104 }
105 wasNew, err := rm.db.StoreImage(img, ctx)
106 if err != nil {
107 return errors.New("beeped that up!: " + err.Error())
108 }
109 if !wasNew {
110 return nil
111 }
112 err = rm.forwardImage(img, ctx)
113 if err != nil {
114 return errors.New("YIEKRSa, " + err.Error())
115 }
116 return nil
117}
118
119func (rm *RecordManager) forwardImage(i *types.Image, ctx context.Context) error {
120 curi, err := rm.db.GetMsgChannelURI(i.SignetURI, ctx)
121 if err != nil {
122 return errors.New("failed to get curi: " + err.Error())
123 }
124 return rm.broadcaster.BroadcastImage(curi, i)
125}
126
127func (rm *RecordManager) validateImageRecord(mr *types.ParseMediaRequest, ctx context.Context) (*lex.MediaRecord, *time.Time, error) {
128 var imr lex.MediaRecord
129 if mr.SignetURI == nil {
130 if mr.ChannelURI == nil || mr.MessageID == nil {
131 return nil, nil, errors.New("not enough info!")
132 }
133 suri, _, err := rm.db.QuerySignet(*mr.ChannelURI, *mr.MessageID, ctx)
134 if err != nil {
135 return nil, nil, errors.New("failed to get signet!")
136 }
137 mr.SignetURI = &suri
138 }
139 imr.SignetURI = *mr.SignetURI
140 imr.Nick = mr.Nick
141 cptr := mr.Color
142 if cptr != nil {
143 cnum := uint64(*cptr)
144 imr.Color = &cnum
145 }
146 imr.Image = mr.Image
147 nowsyn := syntax.DatetimeNow()
148 imr.PostedAt = nowsyn.String()
149 nt := nowsyn.Time()
150 now := &nt
151 return &imr, now, nil
152}
153
154func (rm *RecordManager) createImageRecord(cs *atoauth.ClientSession, imr *lex.MediaRecord, now *time.Time, ctx context.Context) (*types.Image, error) {
155 uri, cid, err := oauth.CreateXCVRMedia(cs, imr, ctx)
156 if err != nil {
157 return nil, errors.New("beeped up: " + err.Error())
158 }
159 var img types.Image
160 img.URI = uri
161 img.DID = cs.Data.AccountDID.String()
162 img.SignetURI = imr.SignetURI
163 if imr.Image != nil {
164 img.Alt = imr.Image.Alt
165 if imr.Image.Blob != nil {
166 img.BlobMIME = &imr.Image.Blob.MimeType
167 icid := imr.Image.Blob.Ref.String()
168 img.BlobCID = &icid
169 }
170 }
171 img.Nick = imr.Nick
172 img.CID = cid
173 if imr.Color != nil {
174 c := uint32(*imr.Color)
175 img.Color = &c
176 }
177 if now != nil {
178 img.PostedAt = *now
179 } else {
180 img.PostedAt = time.Now()
181 }
182 return &img, nil
183}