emojicreate.go (4619B)
1 // GoToSocial 2 // Copyright (C) GoToSocial Authors admin@gotosocial.org 3 // SPDX-License-Identifier: AGPL-3.0-or-later 4 // 5 // This program is free software: you can redistribute it and/or modify 6 // it under the terms of the GNU Affero General Public License as published by 7 // the Free Software Foundation, either version 3 of the License, or 8 // (at your option) any later version. 9 // 10 // This program is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU Affero General Public License for more details. 14 // 15 // You should have received a copy of the GNU Affero General Public License 16 // along with this program. If not, see <http://www.gnu.org/licenses/>. 17 18 package admin 19 20 import ( 21 "errors" 22 "fmt" 23 "net/http" 24 25 "github.com/gin-gonic/gin" 26 apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model" 27 apiutil "github.com/superseriousbusiness/gotosocial/internal/api/util" 28 "github.com/superseriousbusiness/gotosocial/internal/config" 29 "github.com/superseriousbusiness/gotosocial/internal/gtserror" 30 "github.com/superseriousbusiness/gotosocial/internal/oauth" 31 "github.com/superseriousbusiness/gotosocial/internal/validate" 32 ) 33 34 // EmojiCreatePOSTHandler swagger:operation POST /api/v1/admin/custom_emojis emojiCreate 35 // 36 // Upload and create a new instance emoji. 37 // 38 // --- 39 // tags: 40 // - admin 41 // 42 // consumes: 43 // - multipart/form-data 44 // 45 // produces: 46 // - application/json 47 // 48 // parameters: 49 // - 50 // name: shortcode 51 // in: formData 52 // description: >- 53 // The code to use for the emoji, which will be used by instance denizens to select it. 54 // This must be unique on the instance. 55 // type: string 56 // pattern: \w{2,30} 57 // required: true 58 // - 59 // name: image 60 // in: formData 61 // description: >- 62 // A png or gif image of the emoji. Animated pngs work too! 63 // To ensure compatibility with other fedi implementations, emoji size limit is 50kb by default. 64 // type: file 65 // required: true 66 // - 67 // name: category 68 // in: formData 69 // description: >- 70 // Category in which to place the new emoji. 64 characters or less. 71 // If left blank, emoji will be uncategorized. If a category with the 72 // given name doesn't exist yet, it will be created. 73 // type: string 74 // required: false 75 // 76 // security: 77 // - OAuth2 Bearer: 78 // - admin 79 // 80 // responses: 81 // '200': 82 // description: The newly-created emoji. 83 // schema: 84 // "$ref": "#/definitions/emoji" 85 // '400': 86 // description: bad request 87 // '401': 88 // description: unauthorized 89 // '403': 90 // description: forbidden 91 // '404': 92 // description: not found 93 // '406': 94 // description: not acceptable 95 // '409': 96 // description: conflict -- shortcode for this emoji is already in use 97 // '500': 98 // description: internal server error 99 func (m *Module) EmojiCreatePOSTHandler(c *gin.Context) { 100 authed, err := oauth.Authed(c, true, true, true, true) 101 if err != nil { 102 apiutil.ErrorHandler(c, gtserror.NewErrorUnauthorized(err, err.Error()), m.processor.InstanceGetV1) 103 return 104 } 105 106 if !*authed.User.Admin { 107 err := fmt.Errorf("user %s not an admin", authed.User.ID) 108 apiutil.ErrorHandler(c, gtserror.NewErrorForbidden(err, err.Error()), m.processor.InstanceGetV1) 109 return 110 } 111 112 if _, err := apiutil.NegotiateAccept(c, apiutil.JSONAcceptHeaders...); err != nil { 113 apiutil.ErrorHandler(c, gtserror.NewErrorNotAcceptable(err, err.Error()), m.processor.InstanceGetV1) 114 return 115 } 116 117 form := &apimodel.EmojiCreateRequest{} 118 if err := c.ShouldBind(form); err != nil { 119 apiutil.ErrorHandler(c, gtserror.NewErrorBadRequest(err, err.Error()), m.processor.InstanceGetV1) 120 return 121 } 122 123 if err := validateCreateEmoji(form); err != nil { 124 apiutil.ErrorHandler(c, gtserror.NewErrorBadRequest(err, err.Error()), m.processor.InstanceGetV1) 125 return 126 } 127 128 apiEmoji, errWithCode := m.processor.Admin().EmojiCreate(c.Request.Context(), authed.Account, authed.User, form) 129 if errWithCode != nil { 130 apiutil.ErrorHandler(c, errWithCode, m.processor.InstanceGetV1) 131 return 132 } 133 134 c.JSON(http.StatusOK, apiEmoji) 135 } 136 137 func validateCreateEmoji(form *apimodel.EmojiCreateRequest) error { 138 if form.Image == nil || form.Image.Size == 0 { 139 return errors.New("no emoji given") 140 } 141 142 maxSize := config.GetMediaEmojiLocalMaxSize() 143 if form.Image.Size > int64(maxSize) { 144 return fmt.Errorf("emoji image too large: image is %dKB but size limit for custom emojis is %dKB", form.Image.Size/1024, maxSize/1024) 145 } 146 147 if err := validate.EmojiShortcode(form.Shortcode); err != nil { 148 return err 149 } 150 151 return validate.EmojiCategory(form.CategoryName) 152 }