+18
server/internal/atputils/blob.go
+18
server/internal/atputils/blob.go
···
1
+
package atputils
2
+
3
+
import (
4
+
"context"
5
+
"net/http"
6
+
7
+
"github.com/bluesky-social/indigo/api/atproto"
8
+
"github.com/bluesky-social/indigo/atproto/client"
9
+
)
10
+
11
+
func SyncGetBlob(did string, cid string, ctx context.Context) ([]byte, error) {
12
+
host, err := GetPDSFromDid(ctx, did, http.DefaultClient)
13
+
if err != nil {
14
+
return nil, err
15
+
}
16
+
c := client.NewAPIClient(host)
17
+
return atproto.SyncGetBlob(ctx, c, cid, did)
18
+
}
+32
server/internal/db/lexicon.go
+32
server/internal/db/lexicon.go
···
398
398
image.URI = uri
399
399
return &image, nil
400
400
}
401
+
402
+
func (s *Store) GetImageDidCID(did string, cid string, ctx context.Context) (*types.Image, error) {
403
+
row := s.pool.QueryRow(ctx, `SELECT FROM images (
404
+
uri,
405
+
signet_uri,
406
+
blob_cid,
407
+
blob_mime,
408
+
alt,
409
+
height,
410
+
width,
411
+
nick,
412
+
color,
413
+
posted_at
414
+
) WHERE did = $1 AND cid = $2`, did, cid)
415
+
var image types.Image
416
+
err := row.Scan(&image.URI,
417
+
&image.SignetURI,
418
+
&image.BlobCID,
419
+
&image.BlobMIME,
420
+
&image.Alt,
421
+
&image.Height,
422
+
&image.Width,
423
+
&image.Nick,
424
+
&image.Color,
425
+
&image.PostedAt)
426
+
if err != nil {
427
+
return nil, errors.New("effor storing image: " + err.Error())
428
+
}
429
+
image.DID = did
430
+
image.CID = cid
431
+
return &image, nil
432
+
}
+1
-1
server/internal/handler/handler.go
+1
-1
server/internal/handler/handler.go
···
33
33
mux.HandleFunc("POST /lrc/message", h.oauthMiddleware(h.postMessage))
34
34
mux.HandleFunc("POST /lrc/image", h.oauthMiddleware(h.uploadImage))
35
35
mux.HandleFunc("POST /lrc/media", h.oauthMiddleware(h.postMedia))
36
-
// mux.HandleFunc("GET /lrc/image", h.getImage)
36
+
mux.HandleFunc("GET /lrc/image", h.WithCORS(h.getImage))
37
37
mux.HandleFunc("POST /lrc/mymessage", h.postMyMessage)
38
38
// xcvr handlers
39
39
mux.HandleFunc("POST /xcvr/profile", h.oauthMiddleware(h.postProfile))
+97
-30
server/internal/handler/lrcHandlers.go
+97
-30
server/internal/handler/lrcHandlers.go
···
206
206
return &mr, nil
207
207
}
208
208
209
-
// func (h *Handler) getImage(w http.ResponseWriter, r *http.Request) {
210
-
// vals := r.URL.Query()
211
-
// uri := vals.Get("uri")
212
-
// if uri == "" {
213
-
// h.badRequest(w, errors.New("must provide a did and cid"))
214
-
// return
215
-
// }
216
-
// image, err := h.db.GetImage(uri, r.Context())
217
-
// if err != nil {
218
-
// h.notFound(w, err)
219
-
// return
220
-
// }
221
-
// uploadDir := fmt.Sprintf("./uploads/%s", image.DID)
222
-
// _, err = os.Stat(uploadDir)
223
-
// if os.IsNotExist(err) {
224
-
// os.Mkdir(uploadDir, 0755)
225
-
// }
226
-
//
227
-
// imgPath := fmt.Sprintf("./uploads/%s", image.ImageCID)
228
-
// _, err = os.Stat(imgPath)
229
-
// if err != nil {
230
-
// syncGetBlob(image.DID, image.ImageCID)
231
-
// }
232
-
//
233
-
// img, err := os.Open(fmt.Sprintf("%s/%s", uploadDir, image.ImageCID))
234
-
// img.WriteTo(w)
235
-
// }
209
+
func (h *Handler) getImage(w http.ResponseWriter, r *http.Request) {
210
+
vals := r.URL.Query()
211
+
var did string
212
+
var cid string
213
+
uri := vals.Get("uri")
214
+
var image *types.Image
215
+
var err error
216
+
if uri != "" {
217
+
image, err = h.db.GetImage(uri, r.Context())
218
+
if err == nil {
219
+
did = image.DID
220
+
if image.BlobCID != nil {
221
+
cid = *image.BlobCID
222
+
}
223
+
}
224
+
}
225
+
if did == "" {
226
+
did = vals.Get("did")
227
+
if did == "" {
228
+
handle := vals.Get("handle")
229
+
if handle == "" {
230
+
h.badRequest(w, errors.New("must provide an identity"))
231
+
return
232
+
}
233
+
did, err = h.db.ResolveHandle(handle, r.Context())
234
+
if err != nil {
235
+
h.badRequest(w, errors.New("failed to resolve handle"))
236
+
return
237
+
}
238
+
}
239
+
}
240
+
if did == "" {
241
+
h.serverError(w, errors.New("empty did"))
242
+
return
243
+
}
244
+
if cid == "" {
245
+
cid = vals.Get("cid")
246
+
}
247
+
if cid == "" {
248
+
h.serverError(w, errors.New("empty cid"))
249
+
}
250
+
uploadDir := "./uploads"
251
+
_, err = os.Stat(uploadDir)
252
+
if os.IsNotExist(err) {
253
+
os.Mkdir(uploadDir, 0755)
254
+
}
255
+
256
+
imgPath := fmt.Sprintf("%s/%s%s", uploadDir, did, cid)
257
+
_, err = os.Stat(imgPath)
258
+
if err != nil {
259
+
blob, err := atputils.SyncGetBlob(did, cid, r.Context())
260
+
if err != nil {
261
+
h.serverError(w, err)
262
+
return
263
+
}
264
+
file, err := os.Create(imgPath)
265
+
if err != nil {
266
+
h.serverError(w, err)
267
+
return
268
+
}
269
+
_, err = file.Write(blob)
270
+
if err != nil {
271
+
h.serverError(w, err)
272
+
return
273
+
}
274
+
}
275
+
276
+
stats, err := os.Stat(imgPath)
277
+
if err != nil {
278
+
h.serverError(w, errors.New("yikes, file not there even though it should?: "+err.Error()))
279
+
return
280
+
}
281
+
282
+
if image == nil {
283
+
image, err = h.db.GetImageDidCID(did, cid, r.Context())
284
+
if err != nil {
285
+
h.serverError(w, err)
286
+
return
287
+
}
288
+
if image == nil {
289
+
h.serverError(w, errors.New("beep obop i didn't cache it"))
290
+
return
291
+
}
292
+
}
293
+
mime := "application/octet-stream"
294
+
if image.BlobMIME != nil {
295
+
mime = *image.BlobMIME
296
+
}
297
+
w.Header().Add("Content-Type", mime)
298
+
w.Header().Add("Content-Length", fmt.Sprintf("%d", stats.Size()))
236
299
237
-
// func syncGetBlob(did string, cid *string) {
238
-
// //TODO: impl
239
-
// }
300
+
img, err := os.Open(imgPath)
301
+
if err != nil {
302
+
h.serverError(w, err)
303
+
return
304
+
}
305
+
img.WriteTo(w)
306
+
}