diff --git a/migrations/005_initimages.up.sql b/migrations/005_initimages.up.sql index 24993cb..d636f78 100644 --- a/migrations/005_initimages.up.sql +++ b/migrations/005_initimages.up.sql @@ -1,11 +1,13 @@ -CREATE TABLE medias ( +CREATE TABLE iamges ( uri TEXT PRIMARY KEY, did TEXT NOT NULL, signet_uri TEXT NOT NULL, FOREIGN KEY (signet_uri) REFERENCES signets(uri) ON DELETE CASCADE, - media_cid TEXT, - media_mime TEXT, + blob_cid TEXT, + blob_mime TEXT, alt TEXT, + height INTEGER, + width INTEGER, nick TEXT NOT NULL, color INTEGER CHECK (color BETWEEN 0 AND 16777215), cid TEXT NOT NULL, @@ -13,4 +15,4 @@ CREATE TABLE medias ( indexed_at TIMESTAMPTZ NOT NULL DEFAULT now() ); -CREATE INDEX ON medias (signet_uri); +CREATE INDEX ON images (signet_uri); diff --git a/server/gen/main.go b/server/gen/main.go index c70df1c..e609a16 100644 --- a/server/gen/main.go +++ b/server/gen/main.go @@ -10,7 +10,10 @@ func main() { lex.ProfileRecord{}, lex.ChannelRecord{}, lex.MessageRecord{}, - lex.SignetRecord{}); err != nil { + lex.SignetRecord{}, + lex.AspectRatio{}, + lex.Image{}, + lex.MediaRecord{}); err != nil { panic(err) } } diff --git a/server/go.sum b/server/go.sum index fe88fbe..5afdc62 100644 --- a/server/go.sum +++ b/server/go.sum @@ -117,8 +117,6 @@ github.com/prometheus/common v0.54.0 h1:ZlZy0BgJhTwVZUn7dLOkwCZHUkrAqd3WYtcFCWnM github.com/prometheus/common v0.54.0/go.mod h1:/TQgMJP5CuVYveyT7n/0Ix8yLNNXy9yRSkhnLTHPDIQ= github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= -github.com/rachel-mp4/lrcd v0.0.0-20250906202657-38adb092ac1a h1:AWXrdTM1ew/J6mup1xBKkmg/nC6xx6BkL4wT6INdAWI= -github.com/rachel-mp4/lrcd v0.0.0-20250906202657-38adb092ac1a/go.mod h1:aWUVglSyrLf2RGpQdqTucX498b434yWBFJkD6Yzr0OE= github.com/rachel-mp4/lrcd v0.0.1 h1:9d5if0HJ/+TLKdupd7Zu9dISA5fF3QRtI/yr+gYVqXM= github.com/rachel-mp4/lrcd v0.0.1/go.mod h1:aWUVglSyrLf2RGpQdqTucX498b434yWBFJkD6Yzr0OE= github.com/rachel-mp4/lrcproto v0.0.0-20250905154858-2ddb78e31d0c h1:t33xVlfSwvB80nj1jroRXUaq/RTgjWwD4l7p/ISatUQ= diff --git a/server/internal/db/lexicon.go b/server/internal/db/lexicon.go index afcf39c..78bf2b3 100644 --- a/server/internal/db/lexicon.go +++ b/server/internal/db/lexicon.go @@ -293,22 +293,26 @@ func (s *Store) StoreImage(image *types.Image, ctx context.Context) error { uri, did, signet_uri, - image_cid, - image_mime, + blob_cid, + blob_mime, alt, + height, + width, nick, color, cid, posted_at ) VALUES ( - $1, $2, $3, $4, $5, $6, $7, $8, $9, $10 + $1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12 ) ON CONFLICT (uri) DO NOTHING`, image.URI, image.DID, image.SignetURI, - image.ImageCID, - image.ImageMIME, + image.BlobCID, + image.BlobMIME, image.Alt, + image.Height, + image.Width, image.Nick, image.Color, image.CID, @@ -320,26 +324,30 @@ func (s *Store) StoreImage(image *types.Image, ctx context.Context) error { } func (s *Store) UpdateImage(image *types.Image, ctx context.Context) error { - _, err := s.pool.Exec(ctx, `INSERT INTO medias ( + _, err := s.pool.Exec(ctx, `INSERT INTO images ( uri, did, signet_uri, - image_cid, - image_mime, + blob_cid, + blob_mime, alt, + height, + width, nick, color, cid, posted_at ) VALUES ( - $1, $2, $3, $4, $5, $6, $7, $8, $9, $10 + $1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12 )`, image.URI, image.DID, image.SignetURI, - image.ImageCID, - image.ImageMIME, + image.BlobCID, + image.BlobMIME, image.Alt, + image.Height, + image.Width, image.Nick, image.Color, image.CID, @@ -351,7 +359,7 @@ func (s *Store) UpdateImage(image *types.Image, ctx context.Context) error { } func (s *Store) DeleteImage(uri string, ctx context.Context) error { - _, err := s.pool.Exec(ctx, `DELETE from medias m WHERE m.uri = $1`, uri) + _, err := s.pool.Exec(ctx, `DELETE from images i WHERE i.uri = $1`, uri) if err != nil { return errors.New("bep bep bop: " + err.Error()) } @@ -362,9 +370,11 @@ func (s *Store) GetImage(uri string, ctx context.Context) (*types.Image, error) row := s.pool.QueryRow(ctx, `SELECT FROM medias ( did, signet_uri, - media_cid, - media_mime, + blob_cid, + blob_mime, alt, + height, + width, nick, color, cid, @@ -373,9 +383,11 @@ func (s *Store) GetImage(uri string, ctx context.Context) (*types.Image, error) var image types.Image err := row.Scan(&image.DID, &image.SignetURI, - &image.ImageCID, - &image.ImageMIME, + &image.BlobCID, + &image.BlobMIME, &image.Alt, + &image.Height, + &image.Width, &image.Nick, &image.Color, &image.CID, diff --git a/server/internal/handler/handler.go b/server/internal/handler/handler.go index dbd1158..064b566 100644 --- a/server/internal/handler/handler.go +++ b/server/internal/handler/handler.go @@ -34,7 +34,6 @@ func New(db *db.Store, logger *log.Logger, oauthserv *oauth.Service, model *mode mux.HandleFunc("POST /lrc/image", h.oauthMiddleware(h.uploadImage)) mux.HandleFunc("POST /lrc/media", h.oauthMiddleware(h.postMedia)) // mux.HandleFunc("GET /lrc/image", h.getImage) - mux.HandleFunc("POST /lrc/imagePub", h.oauthMiddleware(h.postImagePub)) mux.HandleFunc("POST /lrc/mymessage", h.postMyMessage) // xcvr handlers mux.HandleFunc("POST /xcvr/profile", h.oauthMiddleware(h.postProfile)) diff --git a/server/internal/handler/lrcHandlers.go b/server/internal/handler/lrcHandlers.go index 464928c..2e88d10 100644 --- a/server/internal/handler/lrcHandlers.go +++ b/server/internal/handler/lrcHandlers.go @@ -181,7 +181,12 @@ func (h *Handler) postMedia(cs *atoauth.ClientSession, w http.ResponseWriter, r h.badRequest(w, err) return } - h.rm.PostMedia(cs, mr, r.Context()) + err = h.rm.PostMedia(cs, mr, r.Context()) + if err != nil { + h.serverError(w, errors.New("failing to post the media :c")) + return + } + w.Write(nil) } func parseMediaRequest(r *http.Request) (*types.ParseMediaRequest, error) { @@ -225,7 +230,3 @@ func parseMediaRequest(r *http.Request) (*types.ParseMediaRequest, error) { // func syncGetBlob(did string, cid *string) { // //TODO: impl // } - -func (h *Handler) postImagePub(cs *atoauth.ClientSession, w http.ResponseWriter, r *http.Request) { - -} diff --git a/server/internal/lex/lexicons_cbor.go b/server/internal/lex/lexicons_cbor.go index a628c6f..1360194 100644 --- a/server/internal/lex/lexicons_cbor.go +++ b/server/internal/lex/lexicons_cbor.go @@ -969,29 +969,6 @@ func (t *SignetRecord) MarshalCBOR(w io.Writer) error { return err } - // t.Author (string) (string) - if len("nick") > 8192 { - return xerrors.Errorf("Value in field \"nick\" was too long") - } - - if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("nick"))); err != nil { - return err - } - if _, err := cw.WriteString(string("nick")); err != nil { - return err - } - - if len(t.AuthorHandle) > 8192 { - return xerrors.Errorf("Value in field t.Author was too long") - } - - if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(t.AuthorHandle))); err != nil { - return err - } - if _, err := cw.WriteString(string(t.AuthorHandle)); err != nil { - return err - } - // t.LexiconTypeID (string) (string) if len("$type") > 8192 { return xerrors.Errorf("Value in field \"$type\" was too long") @@ -1081,6 +1058,29 @@ func (t *SignetRecord) MarshalCBOR(w io.Writer) error { if _, err := cw.WriteString(string(t.ChannelURI)); err != nil { return err } + + // t.AuthorHandle (string) (string) + if len("authorHandle") > 8192 { + return xerrors.Errorf("Value in field \"authorHandle\" was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("authorHandle"))); err != nil { + return err + } + if _, err := cw.WriteString(string("authorHandle")); err != nil { + return err + } + + if len(t.AuthorHandle) > 8192 { + return xerrors.Errorf("Value in field t.AuthorHandle was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(t.AuthorHandle))); err != nil { + return err + } + if _, err := cw.WriteString(string(t.AuthorHandle)); err != nil { + return err + } return nil } @@ -1109,7 +1109,7 @@ func (t *SignetRecord) UnmarshalCBOR(r io.Reader) (err error) { n := extra - nameBuf := make([]byte, 10) + nameBuf := make([]byte, 12) for i := uint64(0); i < n; i++ { nameLen, ok, err := cbg.ReadFullStringIntoBuf(cr, nameBuf, 8192) if err != nil { @@ -1125,18 +1125,7 @@ func (t *SignetRecord) UnmarshalCBOR(r io.Reader) (err error) { } switch string(nameBuf[:nameLen]) { - // t.Author (string) (string) - case "authorHandle": - - { - sval, err := cbg.ReadStringWithMax(cr, 8192) - if err != nil { - return err - } - - t.AuthorHandle = string(sval) - } - // t.LexiconTypeID (string) (string) + // t.LexiconTypeID (string) (string) case "$type": { @@ -1194,6 +1183,717 @@ func (t *SignetRecord) UnmarshalCBOR(r io.Reader) (err error) { t.ChannelURI = string(sval) } + // t.AuthorHandle (string) (string) + case "authorHandle": + + { + sval, err := cbg.ReadStringWithMax(cr, 8192) + if err != nil { + return err + } + + t.AuthorHandle = string(sval) + } + + default: + // Field doesn't exist on this type, so ignore it + if err := cbg.ScanForLinks(r, func(cid.Cid) {}); err != nil { + return err + } + } + } + + return nil +} +func (t *AspectRatio) MarshalCBOR(w io.Writer) error { + if t == nil { + _, err := w.Write(cbg.CborNull) + return err + } + + cw := cbg.NewCborWriter(w) + + if _, err := cw.Write([]byte{162}); err != nil { + return err + } + + // t.Width (int64) (int64) + if len("width") > 8192 { + return xerrors.Errorf("Value in field \"width\" was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("width"))); err != nil { + return err + } + if _, err := cw.WriteString(string("width")); err != nil { + return err + } + + if t.Width >= 0 { + if err := cw.WriteMajorTypeHeader(cbg.MajUnsignedInt, uint64(t.Width)); err != nil { + return err + } + } else { + if err := cw.WriteMajorTypeHeader(cbg.MajNegativeInt, uint64(-t.Width-1)); err != nil { + return err + } + } + + // t.Height (int64) (int64) + if len("height") > 8192 { + return xerrors.Errorf("Value in field \"height\" was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("height"))); err != nil { + return err + } + if _, err := cw.WriteString(string("height")); err != nil { + return err + } + + if t.Height >= 0 { + if err := cw.WriteMajorTypeHeader(cbg.MajUnsignedInt, uint64(t.Height)); err != nil { + return err + } + } else { + if err := cw.WriteMajorTypeHeader(cbg.MajNegativeInt, uint64(-t.Height-1)); err != nil { + return err + } + } + + return nil +} + +func (t *AspectRatio) UnmarshalCBOR(r io.Reader) (err error) { + *t = AspectRatio{} + + cr := cbg.NewCborReader(r) + + maj, extra, err := cr.ReadHeader() + if err != nil { + return err + } + defer func() { + if err == io.EOF { + err = io.ErrUnexpectedEOF + } + }() + + if maj != cbg.MajMap { + return fmt.Errorf("cbor input should be of type map") + } + + if extra > cbg.MaxLength { + return fmt.Errorf("AspectRatio: map struct too large (%d)", extra) + } + + n := extra + + nameBuf := make([]byte, 6) + for i := uint64(0); i < n; i++ { + nameLen, ok, err := cbg.ReadFullStringIntoBuf(cr, nameBuf, 8192) + if err != nil { + return err + } + + if !ok { + // Field doesn't exist on this type, so ignore it + if err := cbg.ScanForLinks(cr, func(cid.Cid) {}); err != nil { + return err + } + continue + } + + switch string(nameBuf[:nameLen]) { + // t.Width (int64) (int64) + case "width": + { + maj, extra, err := cr.ReadHeader() + if err != nil { + return err + } + var extraI int64 + switch maj { + case cbg.MajUnsignedInt: + extraI = int64(extra) + if extraI < 0 { + return fmt.Errorf("int64 positive overflow") + } + case cbg.MajNegativeInt: + extraI = int64(extra) + if extraI < 0 { + return fmt.Errorf("int64 negative overflow") + } + extraI = -1 - extraI + default: + return fmt.Errorf("wrong type for int64 field: %d", maj) + } + + t.Width = int64(extraI) + } + // t.Height (int64) (int64) + case "height": + { + maj, extra, err := cr.ReadHeader() + if err != nil { + return err + } + var extraI int64 + switch maj { + case cbg.MajUnsignedInt: + extraI = int64(extra) + if extraI < 0 { + return fmt.Errorf("int64 positive overflow") + } + case cbg.MajNegativeInt: + extraI = int64(extra) + if extraI < 0 { + return fmt.Errorf("int64 negative overflow") + } + extraI = -1 - extraI + default: + return fmt.Errorf("wrong type for int64 field: %d", maj) + } + + t.Height = int64(extraI) + } + + default: + // Field doesn't exist on this type, so ignore it + if err := cbg.ScanForLinks(r, func(cid.Cid) {}); err != nil { + return err + } + } + } + + return nil +} +func (t *Image) MarshalCBOR(w io.Writer) error { + if t == nil { + _, err := w.Write(cbg.CborNull) + return err + } + + cw := cbg.NewCborWriter(w) + fieldCount := 4 + + if t.AspectRatio == nil { + fieldCount-- + } + + if t.Blob == nil { + fieldCount-- + } + + if _, err := cw.Write(cbg.CborEncodeMajorType(cbg.MajMap, uint64(fieldCount))); err != nil { + return err + } + + // t.Alt (string) (string) + if len("alt") > 8192 { + return xerrors.Errorf("Value in field \"alt\" was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("alt"))); err != nil { + return err + } + if _, err := cw.WriteString(string("alt")); err != nil { + return err + } + + if len(t.Alt) > 8192 { + return xerrors.Errorf("Value in field t.Alt was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(t.Alt))); err != nil { + return err + } + if _, err := cw.WriteString(string(t.Alt)); err != nil { + return err + } + + // t.Blob (util.BlobSchema) (struct) + if t.Blob != nil { + + if len("blob") > 8192 { + return xerrors.Errorf("Value in field \"blob\" was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("blob"))); err != nil { + return err + } + if _, err := cw.WriteString(string("blob")); err != nil { + return err + } + + if err := t.Blob.MarshalCBOR(cw); err != nil { + return err + } + } + + // t.LexiconTypeID (string) (string) + if len("$type") > 8192 { + return xerrors.Errorf("Value in field \"$type\" was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("$type"))); err != nil { + return err + } + if _, err := cw.WriteString(string("$type")); err != nil { + return err + } + + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("org.xcvr.lrc.image"))); err != nil { + return err + } + if _, err := cw.WriteString(string("org.xcvr.lrc.image")); err != nil { + return err + } + + // t.AspectRatio (lex.AspectRatio) (struct) + if t.AspectRatio != nil { + + if len("aspectRatio") > 8192 { + return xerrors.Errorf("Value in field \"aspectRatio\" was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("aspectRatio"))); err != nil { + return err + } + if _, err := cw.WriteString(string("aspectRatio")); err != nil { + return err + } + + if err := t.AspectRatio.MarshalCBOR(cw); err != nil { + return err + } + } + return nil +} + +func (t *Image) UnmarshalCBOR(r io.Reader) (err error) { + *t = Image{} + + cr := cbg.NewCborReader(r) + + maj, extra, err := cr.ReadHeader() + if err != nil { + return err + } + defer func() { + if err == io.EOF { + err = io.ErrUnexpectedEOF + } + }() + + if maj != cbg.MajMap { + return fmt.Errorf("cbor input should be of type map") + } + + if extra > cbg.MaxLength { + return fmt.Errorf("Image: map struct too large (%d)", extra) + } + + n := extra + + nameBuf := make([]byte, 11) + for i := uint64(0); i < n; i++ { + nameLen, ok, err := cbg.ReadFullStringIntoBuf(cr, nameBuf, 8192) + if err != nil { + return err + } + + if !ok { + // Field doesn't exist on this type, so ignore it + if err := cbg.ScanForLinks(cr, func(cid.Cid) {}); err != nil { + return err + } + continue + } + + switch string(nameBuf[:nameLen]) { + // t.Alt (string) (string) + case "alt": + + { + sval, err := cbg.ReadStringWithMax(cr, 8192) + if err != nil { + return err + } + + t.Alt = string(sval) + } + // t.Blob (util.BlobSchema) (struct) + case "blob": + + { + + b, err := cr.ReadByte() + if err != nil { + return err + } + if b != cbg.CborNull[0] { + if err := cr.UnreadByte(); err != nil { + return err + } + t.Blob = new(util.BlobSchema) + if err := t.Blob.UnmarshalCBOR(cr); err != nil { + return xerrors.Errorf("unmarshaling t.Blob pointer: %w", err) + } + } + + } + // t.LexiconTypeID (string) (string) + case "$type": + + { + sval, err := cbg.ReadStringWithMax(cr, 8192) + if err != nil { + return err + } + + t.LexiconTypeID = string(sval) + } + // t.AspectRatio (lex.AspectRatio) (struct) + case "aspectRatio": + + { + + b, err := cr.ReadByte() + if err != nil { + return err + } + if b != cbg.CborNull[0] { + if err := cr.UnreadByte(); err != nil { + return err + } + t.AspectRatio = new(AspectRatio) + if err := t.AspectRatio.UnmarshalCBOR(cr); err != nil { + return xerrors.Errorf("unmarshaling t.AspectRatio pointer: %w", err) + } + } + + } + + default: + // Field doesn't exist on this type, so ignore it + if err := cbg.ScanForLinks(r, func(cid.Cid) {}); err != nil { + return err + } + } + } + + return nil +} +func (t *MediaRecord) MarshalCBOR(w io.Writer) error { + if t == nil { + _, err := w.Write(cbg.CborNull) + return err + } + + cw := cbg.NewCborWriter(w) + fieldCount := 6 + + if t.Image == nil { + fieldCount-- + } + + if t.Nick == nil { + fieldCount-- + } + + if t.Color == nil { + fieldCount-- + } + + if _, err := cw.Write(cbg.CborEncodeMajorType(cbg.MajMap, uint64(fieldCount))); err != nil { + return err + } + + // t.Nick (string) (string) + if t.Nick != nil { + + if len("nick") > 8192 { + return xerrors.Errorf("Value in field \"nick\" was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("nick"))); err != nil { + return err + } + if _, err := cw.WriteString(string("nick")); err != nil { + return err + } + + if t.Nick == nil { + if _, err := cw.Write(cbg.CborNull); err != nil { + return err + } + } else { + if len(*t.Nick) > 8192 { + return xerrors.Errorf("Value in field t.Nick was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(*t.Nick))); err != nil { + return err + } + if _, err := cw.WriteString(string(*t.Nick)); err != nil { + return err + } + } + } + + // t.LexiconTypeID (string) (string) + if len("$type") > 8192 { + return xerrors.Errorf("Value in field \"$type\" was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("$type"))); err != nil { + return err + } + if _, err := cw.WriteString(string("$type")); err != nil { + return err + } + + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("org.xcvr.lrc.media"))); err != nil { + return err + } + if _, err := cw.WriteString(string("org.xcvr.lrc.media")); err != nil { + return err + } + + // t.Color (uint64) (uint64) + if t.Color != nil { + + if len("color") > 8192 { + return xerrors.Errorf("Value in field \"color\" was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("color"))); err != nil { + return err + } + if _, err := cw.WriteString(string("color")); err != nil { + return err + } + + if t.Color == nil { + if _, err := cw.Write(cbg.CborNull); err != nil { + return err + } + } else { + if err := cw.WriteMajorTypeHeader(cbg.MajUnsignedInt, uint64(*t.Color)); err != nil { + return err + } + } + + } + + // t.Image (lex.Image) (struct) + if t.Image != nil { + + if len("image") > 8192 { + return xerrors.Errorf("Value in field \"image\" was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("image"))); err != nil { + return err + } + if _, err := cw.WriteString(string("image")); err != nil { + return err + } + + if err := t.Image.MarshalCBOR(cw); err != nil { + return err + } + } + + // t.PostedAt (string) (string) + if len("postedAt") > 8192 { + return xerrors.Errorf("Value in field \"postedAt\" was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("postedAt"))); err != nil { + return err + } + if _, err := cw.WriteString(string("postedAt")); err != nil { + return err + } + + if len(t.PostedAt) > 8192 { + return xerrors.Errorf("Value in field t.PostedAt was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(t.PostedAt))); err != nil { + return err + } + if _, err := cw.WriteString(string(t.PostedAt)); err != nil { + return err + } + + // t.SignetURI (string) (string) + if len("signetURI") > 8192 { + return xerrors.Errorf("Value in field \"signetURI\" was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("signetURI"))); err != nil { + return err + } + if _, err := cw.WriteString(string("signetURI")); err != nil { + return err + } + + if len(t.SignetURI) > 8192 { + return xerrors.Errorf("Value in field t.SignetURI was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(t.SignetURI))); err != nil { + return err + } + if _, err := cw.WriteString(string(t.SignetURI)); err != nil { + return err + } + return nil +} + +func (t *MediaRecord) UnmarshalCBOR(r io.Reader) (err error) { + *t = MediaRecord{} + + cr := cbg.NewCborReader(r) + + maj, extra, err := cr.ReadHeader() + if err != nil { + return err + } + defer func() { + if err == io.EOF { + err = io.ErrUnexpectedEOF + } + }() + + if maj != cbg.MajMap { + return fmt.Errorf("cbor input should be of type map") + } + + if extra > cbg.MaxLength { + return fmt.Errorf("MediaRecord: map struct too large (%d)", extra) + } + + n := extra + + nameBuf := make([]byte, 9) + for i := uint64(0); i < n; i++ { + nameLen, ok, err := cbg.ReadFullStringIntoBuf(cr, nameBuf, 8192) + if err != nil { + return err + } + + if !ok { + // Field doesn't exist on this type, so ignore it + if err := cbg.ScanForLinks(cr, func(cid.Cid) {}); err != nil { + return err + } + continue + } + + switch string(nameBuf[:nameLen]) { + // t.Nick (string) (string) + case "nick": + + { + b, err := cr.ReadByte() + if err != nil { + return err + } + if b != cbg.CborNull[0] { + if err := cr.UnreadByte(); err != nil { + return err + } + + sval, err := cbg.ReadStringWithMax(cr, 8192) + if err != nil { + return err + } + + t.Nick = (*string)(&sval) + } + } + // t.LexiconTypeID (string) (string) + case "$type": + + { + sval, err := cbg.ReadStringWithMax(cr, 8192) + if err != nil { + return err + } + + t.LexiconTypeID = string(sval) + } + // t.Color (uint64) (uint64) + case "color": + + { + + b, err := cr.ReadByte() + if err != nil { + return err + } + if b != cbg.CborNull[0] { + if err := cr.UnreadByte(); err != nil { + return err + } + maj, extra, err = cr.ReadHeader() + if err != nil { + return err + } + if maj != cbg.MajUnsignedInt { + return fmt.Errorf("wrong type for uint64 field") + } + typed := uint64(extra) + t.Color = &typed + } + + } + // t.Image (lex.Image) (struct) + case "image": + + { + + b, err := cr.ReadByte() + if err != nil { + return err + } + if b != cbg.CborNull[0] { + if err := cr.UnreadByte(); err != nil { + return err + } + t.Image = new(Image) + if err := t.Image.UnmarshalCBOR(cr); err != nil { + return xerrors.Errorf("unmarshaling t.Image pointer: %w", err) + } + } + + } + // t.PostedAt (string) (string) + case "postedAt": + + { + sval, err := cbg.ReadStringWithMax(cr, 8192) + if err != nil { + return err + } + + t.PostedAt = string(sval) + } + // t.SignetURI (string) (string) + case "signetURI": + + { + sval, err := cbg.ReadStringWithMax(cr, 8192) + if err != nil { + return err + } + + t.SignetURI = string(sval) + } default: // Field doesn't exist on this type, so ignore it diff --git a/server/internal/lex/types.go b/server/internal/lex/types.go index 7f26fd0..10bd117 100644 --- a/server/internal/lex/types.go +++ b/server/internal/lex/types.go @@ -48,21 +48,17 @@ type SignetRecord struct { type MediaRecord struct { LexiconTypeID string `json:"$type,const=org.xcvr.lrc.media" cborgen:"$type,const=org.xcvr.lrc.media"` SignetURI string `json:"signetURI" cborgen:"signetURI"` - Media Media `json:"media" cborgen:"media"` + Image *Image `json:"image,omitempty" cborgen:"image,omitempty"` Nick *string `json:"nick,omitempty" cborgen:"nick,omitempty"` Color *uint64 `json:"color,omitempty" cborgen:"color,omitempty"` PostedAt string `json:"postedAt" cborgen:"postedAt"` } -type Media struct { - Image *Image -} - type Image struct { LexiconTypeID string `json:"$type,const=org.xcvr.lrc.image" cborgen:"$type,const=org.xcvr.lrc.image"` Alt string `json:"alt" cborgen:"alt"` AspectRatio *AspectRatio `json:"aspectRatio,omitempty" cborgen:"aspectRatio,omitempty"` - Image *util.BlobSchema `json:"image,omitempty" cborgen:"image,omitempty"` + Blob *util.BlobSchema `json:"blob,omitempty" cborgen:"blob,omitempty"` } type AspectRatio struct { diff --git a/server/internal/recordmanager/media.go b/server/internal/recordmanager/media.go index 72db89a..fefc421 100644 --- a/server/internal/recordmanager/media.go +++ b/server/internal/recordmanager/media.go @@ -51,7 +51,7 @@ func (rm *RecordManager) validateImageRecord(mr *types.ParseMediaRequest) (*lex. cnum := uint64(*cptr) imr.Color = &cnum } - imr.Media.Image = mr.Image + imr.Image = mr.Image nowsyn := syntax.DatetimeNow() imr.PostedAt = nowsyn.String() nt := nowsyn.Time() @@ -68,12 +68,12 @@ func (rm *RecordManager) createImageRecord(cs *atoauth.ClientSession, imr *lex.M img.URI = uri img.DID = cs.Data.AccountDID.String() img.SignetURI = imr.SignetURI - if imr.Media.Image != nil { - img.Alt = imr.Media.Image.Alt - if imr.Media.Image.Image != nil { - img.ImageMIME = &imr.Media.Image.Image.MimeType - icid := imr.Media.Image.Image.Ref.String() - img.ImageCID = &icid + if imr.Image != nil { + img.Alt = imr.Image.Alt + if imr.Image.Blob != nil { + img.BlobMIME = &imr.Image.Blob.MimeType + icid := imr.Image.Blob.Ref.String() + img.BlobCID = &icid } } img.Nick = imr.Nick diff --git a/server/internal/types/lexicons.go b/server/internal/types/lexicons.go index fd3317a..c3b7fac 100644 --- a/server/internal/types/lexicons.go +++ b/server/internal/types/lexicons.go @@ -215,12 +215,14 @@ type Image struct { URI string DID string SignetURI string - ImageCID *string - ImageMIME *string + BlobCID *string + BlobMIME *string Alt string Nick *string Color *uint32 CID string + Width *int64 + Height *int64 PostedAt time.Time IndexedAt time.Time }