From 72d0f46b0b0930e5d8bef617a82020d09c93aea1 Mon Sep 17 00:00:00 2001 From: tobi <31960611+tsmethurst@users.noreply.github.com> Date: Fri, 5 Jan 2024 13:39:53 +0100 Subject: [PATCH] [feature] Allow webp emoji uploads / derefs (#2484) --- internal/media/manager.go | 1 + internal/media/manager_test.go | 61 ++++++++++++++++++ internal/media/processingemoji.go | 10 +-- internal/media/test/nb-flag-original.webp | Bin 0 -> 294 bytes internal/media/test/nb-flag-static.png | Bin 0 -> 878 bytes .../settings/admin/emoji/local/new-emoji.js | 2 +- 6 files changed, 66 insertions(+), 8 deletions(-) create mode 100644 internal/media/test/nb-flag-original.webp create mode 100644 internal/media/test/nb-flag-static.png diff --git a/internal/media/manager.go b/internal/media/manager.go index 5f496a71d..61f4e73dd 100644 --- a/internal/media/manager.go +++ b/internal/media/manager.go @@ -45,6 +45,7 @@ var SupportedMIMETypes = []string{ var SupportedEmojiMIMETypes = []string{ mimeImageGif, mimeImagePng, + mimeImageWebp, } type Manager struct { diff --git a/internal/media/manager_test.go b/internal/media/manager_test.go index f90c182fe..bb8afdfd2 100644 --- a/internal/media/manager_test.go +++ b/internal/media/manager_test.go @@ -303,6 +303,67 @@ func (suite *ManagerTestSuite) TestEmojiProcessBlockingNoFileSizeGiven() { suite.Equal(processedStaticBytesExpected, processedStaticBytes) } +func (suite *ManagerTestSuite) TestEmojiWebpProcess() { + ctx := context.Background() + + data := func(_ context.Context) (io.ReadCloser, int64, error) { + // load bytes from a test image + b, err := os.ReadFile("./test/nb-flag-original.webp") + if err != nil { + panic(err) + } + return io.NopCloser(bytes.NewBuffer(b)), int64(len(b)), nil + } + + emojiID := "01GDQ9G782X42BAMFASKP64343" + emojiURI := "http://localhost:8080/emoji/01GDQ9G782X42BAMFASKP64343" + + processingEmoji, err := suite.manager.ProcessEmoji(ctx, data, "nb-flag", emojiID, emojiURI, nil, false) + suite.NoError(err) + + // do a blocking call to fetch the emoji + emoji, err := processingEmoji.LoadEmoji(ctx) + suite.NoError(err) + suite.NotNil(emoji) + + // make sure it's got the stuff set on it that we expect + suite.Equal(emojiID, emoji.ID) + + // file meta should be correctly derived from the image + suite.Equal("image/webp", emoji.ImageContentType) + suite.Equal("image/png", emoji.ImageStaticContentType) + suite.Equal(294, emoji.ImageFileSize) + + // now make sure the emoji is in the database + dbEmoji, err := suite.db.GetEmojiByID(ctx, emojiID) + suite.NoError(err) + suite.NotNil(dbEmoji) + + // make sure the processed emoji file is in storage + processedFullBytes, err := suite.storage.Get(ctx, emoji.ImagePath) + suite.NoError(err) + suite.NotEmpty(processedFullBytes) + + // load the processed bytes from our test folder, to compare + processedFullBytesExpected, err := os.ReadFile("./test/nb-flag-original.webp") + suite.NoError(err) + suite.NotEmpty(processedFullBytesExpected) + + // the bytes in storage should be what we expected + suite.Equal(processedFullBytesExpected, processedFullBytes) + + // now do the same for the thumbnail and make sure it's what we expected + processedStaticBytes, err := suite.storage.Get(ctx, emoji.ImageStaticPath) + suite.NoError(err) + suite.NotEmpty(processedStaticBytes) + + processedStaticBytesExpected, err := os.ReadFile("./test/nb-flag-static.png") + suite.NoError(err) + suite.NotEmpty(processedStaticBytesExpected) + + suite.Equal(processedStaticBytesExpected, processedStaticBytes) +} + func (suite *ManagerTestSuite) TestSimpleJpegProcessBlocking() { ctx := context.Background() diff --git a/internal/media/processingemoji.go b/internal/media/processingemoji.go index 56113b27b..9287f14ce 100644 --- a/internal/media/processingemoji.go +++ b/internal/media/processingemoji.go @@ -21,6 +21,7 @@ import ( "bytes" "context" "io" + "slices" "codeberg.org/gruf/go-bytesize" "codeberg.org/gruf/go-errors/v2" @@ -57,7 +58,6 @@ func (p *ProcessingEmoji) EmojiID() string { func (p *ProcessingEmoji) LoadEmoji(ctx context.Context) (*gtsmodel.Emoji, error) { // Attempt to load synchronously. emoji, done, err := p.load(ctx) - if err == nil { // No issue, return media. return emoji, nil @@ -209,12 +209,8 @@ func (p *ProcessingEmoji) store(ctx context.Context) error { return gtserror.Newf("error parsing file type: %w", err) } - switch info.Extension { - // only supported emoji types - case "gif", "png": - - // unhandled - default: + // Ensure supported emoji img type. + if !slices.Contains(SupportedEmojiMIMETypes, info.MIME.Value) { return gtserror.Newf("unsupported emoji filetype: %s", info.Extension) } diff --git a/internal/media/test/nb-flag-original.webp b/internal/media/test/nb-flag-original.webp new file mode 100644 index 0000000000000000000000000000000000000000..a03d49ce30de28cfbfb81928b33f504e273a9750 GIT binary patch literal 294 zcmV+>0ondiNk&E<0RRA3MM6+kP&iBx0RR9mf50CQ-@qu6q)5qq2*AGy{+K|>t^sT) zXe6l_dNF{1AIQMSD}YrbNv)b3Y~WuG-}rbDLEE-5e{?^BYYaXF2|!qcK^TNZxCo1n z^Zx((?AE!ozRW$PlBAOCyM6KdgZn=3bJhVzZW}pLbj zf>S_UDBQMP!;U@(iHGUL~M{5CW;DrBv#-#OVfSsFwc9EvKOXfhk8tc zcfz%Uy#%Mk1I;OP?r{H)4RF85JaE6qY;gaNt!Ng>3NxBnuwEEfEbA!vEU0l_a4hqv s#LNpB(skex_$xf_0NAlYu+KGmZl?j5CxOidho+7|sYbSYisE zRjJ#j@p9jisTF%-F7EkIzD<=^CD-#-&+&Q{oo}<2a3*UVi;B7I6sFoMWsvE%Gg;)i zS@?cN;nY93FP`81>GeFB#j`#ptDmUb^?d*2FYyWt^F_)BhL>;L`TmEIDib5^9%Xit&l<;}-8?<(6`T-NjKm&u$Lf8Uwg)_nQ;#v;*l z%`>+@$>;N1S?hlFbNbVL&IESi z!VbxRSHGFQ{5tqNE3GMN12g^*N9cmZjowec2bb@1?++CVZjdDyV_^N$c^-WEvSrrH z1tse0>L-hx7_2MRWn^WiTB?V<`0>M{^pqb*!i4f;1r{md84EY0CB7A6i}jqYa`*J_ zez(OFtM<;bn%lSQZr;nuu9b(j$(Oy|yVth&_~R=t^^HBdCw*HzQ%)-FARFj!WlqW>k-lbv^l z#^O7L0@t@q_~5hQUW2FcDaqG`zV#DDITS-S3-#xV=yGhm)%pF0uBY@$`)>y&=CjSh jn?zv&wvU~G;s1Xv%QdV0=6qZU%ts8Ku6{1-oD!M