From 1498e22f78438276a0ad2f5dc76a6ed36fdcf0d2 Mon Sep 17 00:00:00 2001 From: rachel-mp4 Date: Fri, 17 Oct 2025 17:23:31 -0400 Subject: [PATCH] listen for medias --- server/internal/atplistener/jetstream.go | 137 +++++++++++++++++++++++ server/internal/recordmanager/media.go | 31 +++++ 2 files changed, 168 insertions(+) diff --git a/server/internal/atplistener/jetstream.go b/server/internal/atplistener/jetstream.go index aec4d69..b7f0588 100644 --- a/server/internal/atplistener/jetstream.go +++ b/server/internal/atplistener/jetstream.go @@ -42,6 +42,7 @@ func NewConsumer(jsAddr string, l *log.Logger, db *db.Store, cli *oauth.Password "org.xcvr.feed.channel", "org.xcvr.lrc.message", "org.xcvr.lrc.signet", + "org.xcvr.lrc.media", } cfg.WantedDids = []string{} return &Consumer{ @@ -84,6 +85,8 @@ func (h *handler) HandleEvent(ctx context.Context, event *models.Event) error { return h.handleMessage(ctx, event) case "org.xcvr.lrc.signet": return h.handleSignet(ctx, event) + case "org.xcvr.lrc.media": + return h.handleMedia(ctx, event) } return nil } @@ -337,6 +340,140 @@ func parseSignetRecord(event *models.Event) (*types.Signet, error) { return &signet, nil } +func (h *handler) handleMedia(ctx context.Context, event *models.Event) error { + h.l.Deprintln("handling media") + switch event.Commit.Operation { + case "create": + return h.handleMediaCreate(ctx, event) + case "update": + return h.handleMediaUpdate(ctx, event) + case "delete": + return h.handleMediaDelete(ctx, event) + } + return errors.New("unimplemented Operation") +} + +func (h *handler) handleMediaCreate(ctx context.Context, event *models.Event) error { + mr, err := parseMediaRecord(event) + if err != nil { + h.l.Deprintln(err.Error()) + return nil + } + if mr.Image != nil { + image, err := wrangeMediaRecordIntoImage(event, mr) + if err != nil { + h.l.Deprintln(err.Error()) + return nil + } + err = h.rm.AcceptImage(image, ctx) + if err != nil { + h.l.Deprintln(err.Error()) + return nil + } + return nil + } + return nil +} + +func (h *handler) handleMediaUpdate(ctx context.Context, event *models.Event) error { + mr, err := parseMediaRecord(event) + if err != nil { + h.l.Deprintln(err.Error()) + return nil + } + if mr.Image != nil { + image, err := wrangeMediaRecordIntoImage(event, mr) + if err != nil { + h.l.Deprintln(err.Error()) + return nil + } + err = h.rm.AcceptImageUpdate(image, ctx) + if err != nil { + h.l.Deprintln(err.Error()) + return nil + } + return nil + } + return nil +} + +func (h *handler) handleMediaDelete(ctx context.Context, event *models.Event) error { + mr, err := parseMediaRecord(event) + if err != nil { + h.l.Deprintln(err.Error()) + return nil + } + if mr.Image != nil { + image, err := wrangeMediaRecordIntoImage(event, mr) + if err != nil { + h.l.Deprintln(err.Error()) + return nil + } + err = h.rm.AcceptImageDelete(image, ctx) + if err != nil { + h.l.Deprintln(err.Error()) + return nil + } + return nil + } + return nil +} + +func parseMediaRecord(event *models.Event) (*lex.MediaRecord, error) { + var mr lex.MediaRecord + err := json.Unmarshal(event.Commit.Record, &mr) + if err != nil { + return nil, errors.New("error unmarshl: " + err.Error()) + } + return &mr, nil +} + +func wrangeMediaRecordIntoImage(event *models.Event, mr *lex.MediaRecord) (*types.Image, error) { + if mr.Image != nil { + then, err := syntax.ParseDatetimeTime(mr.PostedAt) + if err != nil { + then = time.Now() + } + var color *uint32 + if mr.Color != nil { + c := uint32(*mr.Color) + color = &c + } + var blobcid *string + var blobmime *string + if mr.Image.Blob != nil { + bcid := mr.Image.Blob.Ref.String() + bmime := mr.Image.Blob.MimeType + blobcid = &bcid + blobmime = &bmime + } + var width, height *int64 + if mr.Image.AspectRatio != nil { + w := mr.Image.AspectRatio.Width + h := mr.Image.AspectRatio.Height + width = &w + height = &h + } + image := types.Image{ + URI: URI(event), + DID: event.Did, + SignetURI: mr.SignetURI, + BlobCID: blobcid, + BlobMIME: blobmime, + Alt: mr.Image.Alt, + Nick: mr.Nick, + Color: color, + CID: event.Commit.CID, + Width: width, + Height: height, + PostedAt: then, + } + return &image, nil + } + return nil, errors.New("image should be non nil") + +} + func URI(event *models.Event) string { return atputils.URI(event.Did, event.Commit.Collection, event.Commit.RKey) } diff --git a/server/internal/recordmanager/media.go b/server/internal/recordmanager/media.go index 479c64c..ab7aeb8 100644 --- a/server/internal/recordmanager/media.go +++ b/server/internal/recordmanager/media.go @@ -62,6 +62,37 @@ func (rm *RecordManager) PostMedia(cs *atoauth.ClientSession, mr *types.ParseMed } } +func (rm *RecordManager) AcceptImage(img *types.Image, ctx context.Context) error { + wasNew, err := rm.db.StoreImage(img, ctx) + if err != nil { + return err + } + if !wasNew { + return nil + } + err = rm.forwardImage(img, ctx) + if err != nil { + return errors.New("error forwarding image: " + err.Error()) + } + return nil +} + +func (rm *RecordManager) AcceptImageUpdate(img *types.Image, ctx context.Context) error { + err := rm.db.UpdateImage(img, ctx) + if err != nil { + return err + } + return nil +} + +func (rm *RecordManager) AcceptImageDelete(img *types.Image, ctx context.Context) error { + err := rm.db.DeleteImage(img.URI, ctx) + if err != nil { + return err + } + return nil +} + func (rm *RecordManager) postImageRecord(cs *atoauth.ClientSession, mr *types.ParseMediaRequest, ctx context.Context) error { imr, now, err := rm.validateImageRecord(mr, ctx) if err != nil { -- 2.51.2