commit 6a95f5fa67ad27937198e0c9e25e3d8fe1f2bd2c
parent 70d65b683fa963d2a8761182a2ddd2f4f9a86bb4
Author: tobi <31960611+tsmethurst@users.noreply.github.com>
Date: Thu, 13 Oct 2022 16:37:55 +0200
[feature] Add `/api/v1/admin/custom_emojis/{id}` endpoint for single emoji GET (#910)
* fix error in prev swagger docs
* add GET for single admin emoji
Diffstat:
10 files changed, 244 insertions(+), 172 deletions(-)
diff --git a/docs/api/swagger.yaml b/docs/api/swagger.yaml
@@ -2773,8 +2773,8 @@ paths:
in: query
name: filter
type: string
- - default: 30
- description: Number of emojis to return. If below 1, will be set to 1, if greater than 50, will be set to 50.
+ - default: 50
+ description: Number of emojis to return. Less than 1, or not set, means unlimited (all emojis).
in: query
name: limit
type: integer
@@ -2861,6 +2861,37 @@ paths:
summary: Upload and create a new instance emoji.
tags:
- admin
+ /api/v1/admin/custom_emojis/{id}:
+ get:
+ operationId: emojiGet
+ parameters:
+ - description: The id of the emoji.
+ in: path
+ name: id
+ required: true
+ type: string
+ produces:
+ - application/json
+ responses:
+ "200":
+ description: A single emoji.
+ schema:
+ $ref: '#/definitions/adminEmoji'
+ "400":
+ description: bad request
+ "401":
+ description: unauthorized
+ "403":
+ description: forbidden
+ "404":
+ description: not found
+ "406":
+ description: not acceptable
+ "500":
+ description: internal server error
+ summary: Get the admin view of a single emoji.
+ tags:
+ - admin
/api/v1/admin/domain_blocks:
get:
operationId: domainBlocksGet
diff --git a/internal/api/client/admin/admin_test.go b/internal/api/client/admin/admin_test.go
@@ -60,6 +60,7 @@ type AdminStandardTestSuite struct {
testAccounts map[string]*gtsmodel.Account
testAttachments map[string]*gtsmodel.MediaAttachment
testStatuses map[string]*gtsmodel.Status
+ testEmojis map[string]*gtsmodel.Emoji
// module being tested
adminModule *admin.Module
@@ -73,6 +74,7 @@ func (suite *AdminStandardTestSuite) SetupSuite() {
suite.testAccounts = testrig.NewTestAccounts()
suite.testAttachments = testrig.NewTestAttachments()
suite.testStatuses = testrig.NewTestStatuses()
+ suite.testEmojis = testrig.NewTestEmojis()
}
func (suite *AdminStandardTestSuite) SetupTest() {
diff --git a/internal/api/client/admin/emojiget.go b/internal/api/client/admin/emojiget.go
@@ -19,27 +19,19 @@
package admin
import (
+ "errors"
"fmt"
"net/http"
- "strconv"
- "strings"
"github.com/gin-gonic/gin"
"github.com/superseriousbusiness/gotosocial/internal/api"
- "github.com/superseriousbusiness/gotosocial/internal/config"
- "github.com/superseriousbusiness/gotosocial/internal/db"
"github.com/superseriousbusiness/gotosocial/internal/gtserror"
"github.com/superseriousbusiness/gotosocial/internal/oauth"
)
-// EmojisGETHandler swagger:operation GET /api/v1/admin/custom_emojis emojisGet
+// EmojiGETHandler swagger:operation GET /api/v1/admin/custom_emojis/{id} emojiGet
//
-// View local and remote emojis available to / known by this instance.
-//
-// The next and previous queries can be parsed from the returned Link header.
-// Example:
-//
-// `<http://localhost:8080/api/v1/admin/custom_emojis?limit=30&max_shortcode_domain=yell@fossbros-anonymous.io&filter=domain:all>; rel="next", <http://localhost:8080/api/v1/admin/custom_emojis?limit=30&min_shortcode_domain=rainbow@&filter=domain:all>; rel="prev"`
+// Get the admin view of a single emoji.
//
// ---
// tags:
@@ -50,66 +42,17 @@ import (
//
// parameters:
// -
-// name: filter
+// name: id
// type: string
-// description: |-
-// Comma-separated list of filters to apply to results. Recognized filters are:
-//
-// `domain:[domain]` -- show emojis from the given domain, eg `?filter=domain:example.org` will show emojis from `example.org` only.
-// Instead of giving a specific domain, you can also give either one of the key words `local` or `all` to show either local emojis only (`domain:local`) or show all emojis from all domains (`domain:all`).
-// Note: `domain:*` is equivalent to `domain:all` (including local).
-// If no domain filter is provided, `domain:all` will be assumed.
-//
-// `disabled` -- include emojis that have been disabled.
-//
-// `enabled` -- include emojis that are enabled.
-//
-// `shortcode:[shortcode]` -- show only emojis with the given shortcode, eg `?filter=shortcode:blob_cat_uwu` will show only emojis with the shortcode `blob_cat_uwu` (case sensitive).
-//
-// If neither `disabled` or `enabled` are provided, both disabled and enabled emojis will be shown.
-//
-// If no filter query string is provided, the default `domain:all` will be used, which will show all emojis from all domains.
-// in: query
-// required: false
-// default: "domain:all"
-// -
-// name: limit
-// type: integer
-// description: Number of emojis to return. Less than 1, or not set, means unlimited (all emojis).
-// default: 50
-// in: query
-// -
-// name: max_shortcode_domain
-// type: string
-// description: >-
-// Return only emojis with `[shortcode]@[domain]` *LOWER* (alphabetically) than given `[shortcode]@[domain]`.
-// For example, if `max_shortcode_domain=beep@example.org`, then returned values might include emojis with
-// `[shortcode]@[domain]`s like `car@example.org`, `debian@aaa.com`, `test@` (local emoji), etc.
-//
-// Emoji with the given `[shortcode]@[domain]` will not be included in the result set.
-// in: query
-// -
-// name: min_shortcode_domain
-// type: string
-// description: >-
-// Return only emojis with `[shortcode]@[domain]` *HIGHER* (alphabetically) than given `[shortcode]@[domain]`.
-// For example, if `max_shortcode_domain=beep@example.org`, then returned values might include emojis with
-// `[shortcode]@[domain]`s like `arse@test.com`, `0101_binary@hackers.net`, `bee@` (local emoji), etc.
-//
-// Emoji with the given `[shortcode]@[domain]` will not be included in the result set.
-// in: query
+// description: The id of the emoji.
+// in: path
+// required: true
//
// responses:
// '200':
-// headers:
-// Link:
-// type: string
-// description: Links to the next and previous queries.
-// description: An array of emojis, arranged alphabetically by shortcode and domain.
+// description: A single emoji.
// schema:
-// type: array
-// items:
-// "$ref": "#/definitions/adminEmoji"
+// "$ref": "#/definitions/adminEmoji"
// '400':
// description: bad request
// '401':
@@ -122,7 +65,7 @@ import (
// description: not acceptable
// '500':
// description: internal server error
-func (m *Module) EmojisGETHandler(c *gin.Context) {
+func (m *Module) EmojiGETHandler(c *gin.Context) {
authed, err := oauth.Authed(c, true, true, true, true)
if err != nil {
api.ErrorHandler(c, gtserror.NewErrorUnauthorized(err, err.Error()), m.processor.InstanceGet)
@@ -140,72 +83,18 @@ func (m *Module) EmojisGETHandler(c *gin.Context) {
return
}
- maxShortcodeDomain := c.Query(MaxShortcodeDomainKey)
- minShortcodeDomain := c.Query(MinShortcodeDomainKey)
-
- limit := 50
- limitString := c.Query(LimitKey)
- if limitString != "" {
- i, err := strconv.ParseInt(limitString, 10, 64)
- if err != nil {
- err := fmt.Errorf("error parsing %s: %s", LimitKey, err)
- api.ErrorHandler(c, gtserror.NewErrorBadRequest(err, err.Error()), m.processor.InstanceGet)
- return
- }
- limit = int(i)
- }
- if limit < 0 {
- limit = 0
- }
-
- var domain string
- var includeDisabled bool
- var includeEnabled bool
- var shortcode string
- if filterParam := c.Query(FilterQueryKey); filterParam != "" {
- filters := strings.Split(filterParam, ",")
- for _, filter := range filters {
- lower := strings.ToLower(filter)
- switch {
- case strings.HasPrefix(lower, "domain:"):
- domain = strings.TrimPrefix(lower, "domain:")
- case lower == "disabled":
- includeDisabled = true
- case lower == "enabled":
- includeEnabled = true
- case strings.HasPrefix(lower, "shortcode:"):
- shortcode = strings.Trim(filter[10:], ":") // remove any errant ":"
- default:
- err := fmt.Errorf("filter %s not recognized; accepted values are 'domain:[domain]', 'disabled', 'enabled', 'shortcode:[shortcode]'", filter)
- api.ErrorHandler(c, gtserror.NewErrorBadRequest(err, err.Error()), m.processor.InstanceGet)
- return
- }
- }
- }
-
- if domain == "" {
- // default is to show all domains
- domain = db.EmojiAllDomains
- } else if domain == "local" || domain == config.GetHost() || domain == config.GetAccountDomain() {
- // pass empty string for local domain
- domain = ""
- }
-
- // normalize filters
- if !includeDisabled && !includeEnabled {
- // include both if neither specified
- includeDisabled = true
- includeEnabled = true
+ emojiID := c.Param(IDKey)
+ if emojiID == "" {
+ err := errors.New("no emoji id specified")
+ api.ErrorHandler(c, gtserror.NewErrorBadRequest(err, err.Error()), m.processor.InstanceGet)
+ return
}
- resp, errWithCode := m.processor.AdminEmojisGet(c.Request.Context(), authed, domain, includeDisabled, includeEnabled, shortcode, maxShortcodeDomain, minShortcodeDomain, limit)
+ emoji, errWithCode := m.processor.AdminEmojiGet(c.Request.Context(), authed, emojiID)
if errWithCode != nil {
api.ErrorHandler(c, errWithCode, m.processor.InstanceGet)
return
}
- if resp.LinkHeader != "" {
- c.Header("Link", resp.LinkHeader)
- }
- c.JSON(http.StatusOK, resp.Items)
+ c.JSON(http.StatusOK, emoji)
}
diff --git a/internal/api/client/admin/emojiget_test.go b/internal/api/client/admin/emojiget_test.go
@@ -19,7 +19,6 @@
package admin_test
import (
- "encoding/json"
"io"
"net/http"
"net/http/httptest"
@@ -27,86 +26,62 @@ import (
"github.com/stretchr/testify/suite"
"github.com/superseriousbusiness/gotosocial/internal/api/client/admin"
- apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model"
)
type EmojiGetTestSuite struct {
AdminStandardTestSuite
}
-func (suite *EmojiGetTestSuite) TestEmojiGet() {
+func (suite *EmojiGetTestSuite) TestEmojiGet1() {
recorder := httptest.NewRecorder()
+ testEmoji := suite.testEmojis["rainbow"]
- path := admin.EmojiPath + "?filter=domain:all&limit=1"
+ path := admin.EmojiPathWithID
ctx := suite.newContext(recorder, http.MethodGet, nil, path, "application/json")
+ ctx.AddParam(admin.IDKey, testEmoji.ID)
- suite.adminModule.EmojisGETHandler(ctx)
+ suite.adminModule.EmojiGETHandler(ctx)
suite.Equal(http.StatusOK, recorder.Code)
b, err := io.ReadAll(recorder.Body)
suite.NoError(err)
suite.NotNil(b)
- apiEmojis := []*apimodel.AdminEmoji{}
- if err := json.Unmarshal(b, &apiEmojis); err != nil {
- suite.FailNow(err.Error())
- }
-
- suite.Len(apiEmojis, 1)
- suite.Equal("rainbow", apiEmojis[0].Shortcode)
- suite.Equal("", apiEmojis[0].Domain)
-
- suite.Equal(`<http://localhost:8080/api/v1/admin/custom_emojis?limit=1&max_shortcode_domain=rainbow@&filter=domain:all>; rel="next", <http://localhost:8080/api/v1/admin/custom_emojis?limit=1&min_shortcode_domain=rainbow@&filter=domain:all>; rel="prev"`, recorder.Header().Get("link"))
+ suite.Equal(`{"shortcode":"rainbow","url":"http://localhost:8080/fileserver/01F8MH17FWEB39HZJ76B6VXSKF/emoji/original/01F8MH9H8E4VG3KDYJR9EGPXCQ.png","static_url":"http://localhost:8080/fileserver/01F8MH17FWEB39HZJ76B6VXSKF/emoji/static/01F8MH9H8E4VG3KDYJR9EGPXCQ.png","visible_in_picker":true,"id":"01F8MH9H8E4VG3KDYJR9EGPXCQ","disabled":false,"updated_at":"2021-09-20T10:40:37.000Z","total_file_size":47115,"content_type":"image/png","uri":"http://localhost:8080/emoji/01F8MH9H8E4VG3KDYJR9EGPXCQ"}`, string(b))
}
func (suite *EmojiGetTestSuite) TestEmojiGet2() {
recorder := httptest.NewRecorder()
+ testEmoji := suite.testEmojis["yell"]
- path := admin.EmojiPath + "?filter=domain:all&limit=1&max_shortcode_domain=rainbow@"
+ path := admin.EmojiPathWithID
ctx := suite.newContext(recorder, http.MethodGet, nil, path, "application/json")
+ ctx.AddParam(admin.IDKey, testEmoji.ID)
- suite.adminModule.EmojisGETHandler(ctx)
+ suite.adminModule.EmojiGETHandler(ctx)
suite.Equal(http.StatusOK, recorder.Code)
b, err := io.ReadAll(recorder.Body)
suite.NoError(err)
suite.NotNil(b)
- apiEmojis := []*apimodel.AdminEmoji{}
- if err := json.Unmarshal(b, &apiEmojis); err != nil {
- suite.FailNow(err.Error())
- }
-
- suite.Len(apiEmojis, 1)
- suite.Equal("yell", apiEmojis[0].Shortcode)
- suite.Equal("fossbros-anonymous.io", apiEmojis[0].Domain)
-
- suite.Equal(`<http://localhost:8080/api/v1/admin/custom_emojis?limit=1&max_shortcode_domain=yell@fossbros-anonymous.io&filter=domain:all>; rel="next", <http://localhost:8080/api/v1/admin/custom_emojis?limit=1&min_shortcode_domain=yell@fossbros-anonymous.io&filter=domain:all>; rel="prev"`, recorder.Header().Get("link"))
+ suite.Equal(`{"shortcode":"yell","url":"http://localhost:8080/fileserver/01GD5KR15NHTY8FZ01CD4D08XP/emoji/original/01GD5KP5CQEE1R3X43Y1EHS2CW.png","static_url":"http://localhost:8080/fileserver/01GD5KR15NHTY8FZ01CD4D08XP/emoji/static/01GD5KP5CQEE1R3X43Y1EHS2CW.png","visible_in_picker":false,"id":"01GD5KP5CQEE1R3X43Y1EHS2CW","disabled":false,"domain":"fossbros-anonymous.io","updated_at":"2020-03-18T12:12:00.000Z","total_file_size":21697,"content_type":"image/png","uri":"http://fossbros-anonymous.io/emoji/01GD5KP5CQEE1R3X43Y1EHS2CW"}`, string(b))
}
-func (suite *EmojiGetTestSuite) TestEmojiGet3() {
+func (suite *EmojiGetTestSuite) TestEmojiGetNotFound() {
recorder := httptest.NewRecorder()
- path := admin.EmojiPath + "?filter=domain:all&limit=1&min_shortcode_domain=yell@fossbros-anonymous.io"
+ path := admin.EmojiPathWithID
ctx := suite.newContext(recorder, http.MethodGet, nil, path, "application/json")
+ ctx.AddParam(admin.IDKey, "01GF8VRXX1R00X7XH8973Z29R1")
- suite.adminModule.EmojisGETHandler(ctx)
- suite.Equal(http.StatusOK, recorder.Code)
+ suite.adminModule.EmojiGETHandler(ctx)
+ suite.Equal(http.StatusNotFound, recorder.Code)
b, err := io.ReadAll(recorder.Body)
suite.NoError(err)
suite.NotNil(b)
-
- apiEmojis := []*apimodel.AdminEmoji{}
- if err := json.Unmarshal(b, &apiEmojis); err != nil {
- suite.FailNow(err.Error())
- }
-
- suite.Len(apiEmojis, 1)
- suite.Equal("rainbow", apiEmojis[0].Shortcode)
- suite.Equal("", apiEmojis[0].Domain)
-
- suite.Equal(`<http://localhost:8080/api/v1/admin/custom_emojis?limit=1&max_shortcode_domain=rainbow@&filter=domain:all>; rel="next", <http://localhost:8080/api/v1/admin/custom_emojis?limit=1&min_shortcode_domain=rainbow@&filter=domain:all>; rel="prev"`, recorder.Header().Get("link"))
+ suite.Equal(`{"error":"Not Found"}`, string(b))
}
func TestEmojiGetTestSuite(t *testing.T) {
diff --git a/internal/api/client/admin/emojiget.go b/internal/api/client/admin/emojisget.go
diff --git a/internal/api/client/admin/emojisget_test.go b/internal/api/client/admin/emojisget_test.go
@@ -0,0 +1,114 @@
+/*
+ GoToSocial
+ Copyright (C) 2021-2022 GoToSocial Authors admin@gotosocial.org
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+package admin_test
+
+import (
+ "encoding/json"
+ "io"
+ "net/http"
+ "net/http/httptest"
+ "testing"
+
+ "github.com/stretchr/testify/suite"
+ "github.com/superseriousbusiness/gotosocial/internal/api/client/admin"
+ apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model"
+)
+
+type EmojisGetTestSuite struct {
+ AdminStandardTestSuite
+}
+
+func (suite *EmojisGetTestSuite) TestEmojiGet() {
+ recorder := httptest.NewRecorder()
+
+ path := admin.EmojiPath + "?filter=domain:all&limit=1"
+ ctx := suite.newContext(recorder, http.MethodGet, nil, path, "application/json")
+
+ suite.adminModule.EmojisGETHandler(ctx)
+ suite.Equal(http.StatusOK, recorder.Code)
+
+ b, err := io.ReadAll(recorder.Body)
+ suite.NoError(err)
+ suite.NotNil(b)
+
+ apiEmojis := []*apimodel.AdminEmoji{}
+ if err := json.Unmarshal(b, &apiEmojis); err != nil {
+ suite.FailNow(err.Error())
+ }
+
+ suite.Len(apiEmojis, 1)
+ suite.Equal("rainbow", apiEmojis[0].Shortcode)
+ suite.Equal("", apiEmojis[0].Domain)
+
+ suite.Equal(`<http://localhost:8080/api/v1/admin/custom_emojis?limit=1&max_shortcode_domain=rainbow@&filter=domain:all>; rel="next", <http://localhost:8080/api/v1/admin/custom_emojis?limit=1&min_shortcode_domain=rainbow@&filter=domain:all>; rel="prev"`, recorder.Header().Get("link"))
+}
+
+func (suite *EmojisGetTestSuite) TestEmojiGet2() {
+ recorder := httptest.NewRecorder()
+
+ path := admin.EmojiPath + "?filter=domain:all&limit=1&max_shortcode_domain=rainbow@"
+ ctx := suite.newContext(recorder, http.MethodGet, nil, path, "application/json")
+
+ suite.adminModule.EmojisGETHandler(ctx)
+ suite.Equal(http.StatusOK, recorder.Code)
+
+ b, err := io.ReadAll(recorder.Body)
+ suite.NoError(err)
+ suite.NotNil(b)
+
+ apiEmojis := []*apimodel.AdminEmoji{}
+ if err := json.Unmarshal(b, &apiEmojis); err != nil {
+ suite.FailNow(err.Error())
+ }
+
+ suite.Len(apiEmojis, 1)
+ suite.Equal("yell", apiEmojis[0].Shortcode)
+ suite.Equal("fossbros-anonymous.io", apiEmojis[0].Domain)
+
+ suite.Equal(`<http://localhost:8080/api/v1/admin/custom_emojis?limit=1&max_shortcode_domain=yell@fossbros-anonymous.io&filter=domain:all>; rel="next", <http://localhost:8080/api/v1/admin/custom_emojis?limit=1&min_shortcode_domain=yell@fossbros-anonymous.io&filter=domain:all>; rel="prev"`, recorder.Header().Get("link"))
+}
+
+func (suite *EmojisGetTestSuite) TestEmojiGet3() {
+ recorder := httptest.NewRecorder()
+
+ path := admin.EmojiPath + "?filter=domain:all&limit=1&min_shortcode_domain=yell@fossbros-anonymous.io"
+ ctx := suite.newContext(recorder, http.MethodGet, nil, path, "application/json")
+
+ suite.adminModule.EmojisGETHandler(ctx)
+ suite.Equal(http.StatusOK, recorder.Code)
+
+ b, err := io.ReadAll(recorder.Body)
+ suite.NoError(err)
+ suite.NotNil(b)
+
+ apiEmojis := []*apimodel.AdminEmoji{}
+ if err := json.Unmarshal(b, &apiEmojis); err != nil {
+ suite.FailNow(err.Error())
+ }
+
+ suite.Len(apiEmojis, 1)
+ suite.Equal("rainbow", apiEmojis[0].Shortcode)
+ suite.Equal("", apiEmojis[0].Domain)
+
+ suite.Equal(`<http://localhost:8080/api/v1/admin/custom_emojis?limit=1&max_shortcode_domain=rainbow@&filter=domain:all>; rel="next", <http://localhost:8080/api/v1/admin/custom_emojis?limit=1&min_shortcode_domain=rainbow@&filter=domain:all>; rel="prev"`, recorder.Header().Get("link"))
+}
+
+func TestEmojisGetTestSuite(t *testing.T) {
+ suite.Run(t, &EmojisGetTestSuite{})
+}
diff --git a/internal/processing/admin.go b/internal/processing/admin.go
@@ -38,6 +38,10 @@ func (p *processor) AdminEmojisGet(ctx context.Context, authed *oauth.Auth, doma
return p.adminProcessor.EmojisGet(ctx, authed.Account, authed.User, domain, includeDisabled, includeEnabled, shortcode, maxShortcodeDomain, minShortcodeDomain, limit)
}
+func (p *processor) AdminEmojiGet(ctx context.Context, authed *oauth.Auth, id string) (*apimodel.AdminEmoji, gtserror.WithCode) {
+ return p.adminProcessor.EmojiGet(ctx, authed.Account, authed.User, id)
+}
+
func (p *processor) AdminDomainBlockCreate(ctx context.Context, authed *oauth.Auth, form *apimodel.DomainBlockCreateRequest) (*apimodel.DomainBlock, gtserror.WithCode) {
return p.adminProcessor.DomainBlockCreate(ctx, authed.Account, form.Domain, form.Obfuscate, form.PublicComment, form.PrivateComment, "")
}
diff --git a/internal/processing/admin/admin.go b/internal/processing/admin/admin.go
@@ -42,6 +42,7 @@ type Processor interface {
AccountAction(ctx context.Context, account *gtsmodel.Account, form *apimodel.AdminAccountActionRequest) gtserror.WithCode
EmojiCreate(ctx context.Context, account *gtsmodel.Account, user *gtsmodel.User, form *apimodel.EmojiCreateRequest) (*apimodel.Emoji, gtserror.WithCode)
EmojisGet(ctx context.Context, account *gtsmodel.Account, user *gtsmodel.User, domain string, includeDisabled bool, includeEnabled bool, shortcode string, maxShortcodeDomain string, minShortcodeDomain string, limit int) (*apimodel.PageableResponse, gtserror.WithCode)
+ EmojiGet(ctx context.Context, account *gtsmodel.Account, user *gtsmodel.User, id string) (*apimodel.AdminEmoji, gtserror.WithCode)
MediaPrune(ctx context.Context, mediaRemoteCacheDays int) gtserror.WithCode
}
diff --git a/internal/processing/admin/getemoji.go b/internal/processing/admin/getemoji.go
@@ -0,0 +1,54 @@
+/*
+ GoToSocial
+ Copyright (C) 2021-2022 GoToSocial Authors admin@gotosocial.org
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+package admin
+
+import (
+ "context"
+ "errors"
+ "fmt"
+
+ apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model"
+ "github.com/superseriousbusiness/gotosocial/internal/db"
+ "github.com/superseriousbusiness/gotosocial/internal/gtserror"
+ "github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
+)
+
+func (p *processor) EmojiGet(ctx context.Context, account *gtsmodel.Account, user *gtsmodel.User, id string) (*apimodel.AdminEmoji, gtserror.WithCode) {
+ if !*user.Admin {
+ return nil, gtserror.NewErrorUnauthorized(fmt.Errorf("user %s not an admin", user.ID), "user is not an admin")
+ }
+
+ emoji, err := p.db.GetEmojiByID(ctx, id)
+ if err != nil {
+ if errors.Is(err, db.ErrNoEntries) {
+ err = fmt.Errorf("EmojiGet: no emoji with id %s found in the db", id)
+ return nil, gtserror.NewErrorNotFound(err)
+ }
+ err := fmt.Errorf("EmojiGet: db error: %s", err)
+ return nil, gtserror.NewErrorInternalError(err)
+ }
+
+ adminEmoji, err := p.tc.EmojiToAdminAPIEmoji(ctx, emoji)
+ if err != nil {
+ err = fmt.Errorf("EmojiGet: error converting emoji to admin api emoji: %s", err)
+ return nil, gtserror.NewErrorInternalError(err)
+ }
+
+ return adminEmoji, nil
+}
diff --git a/internal/processing/processor.go b/internal/processing/processor.go
@@ -114,6 +114,8 @@ type Processor interface {
AdminEmojiCreate(ctx context.Context, authed *oauth.Auth, form *apimodel.EmojiCreateRequest) (*apimodel.Emoji, gtserror.WithCode)
// AdminEmojisGet allows admins to view emojis based on various filters.
AdminEmojisGet(ctx context.Context, authed *oauth.Auth, domain string, includeDisabled bool, includeEnabled bool, shortcode string, maxShortcodeDomain string, minShortcodeDomain string, limit int) (*apimodel.PageableResponse, gtserror.WithCode)
+ // AdminEmojiGet returns the admin view of an emoji with the given ID
+ AdminEmojiGet(ctx context.Context, authed *oauth.Auth, id string) (*apimodel.AdminEmoji, gtserror.WithCode)
// AdminDomainBlockCreate handles the creation of a new domain block by an admin, using the given form.
AdminDomainBlockCreate(ctx context.Context, authed *oauth.Auth, form *apimodel.DomainBlockCreateRequest) (*apimodel.DomainBlock, gtserror.WithCode)
// AdminDomainBlocksImport handles the import of multiple domain blocks by an admin, using the given form.