From ef16919d4a551ead52bb0c7f9ae3f6974b073472 Mon Sep 17 00:00:00 2001 From: tobi <31960611+tsmethurst@users.noreply.github.com> Date: Wed, 17 Apr 2024 14:06:49 +0200 Subject: [PATCH] [feature] Stub status history endpoint (#2847) --- docs/api/swagger.yaml | 83 +++++++++++ internal/api/client/statuses/status.go | 6 + internal/api/client/statuses/statushistory.go | 97 +++++++++++++ .../api/client/statuses/statushistory_test.go | 133 ++++++++++++++++++ internal/api/model/status.go | 30 ++++ internal/processing/status/get.go | 32 +++++ 6 files changed, 381 insertions(+) create mode 100644 internal/api/client/statuses/statushistory.go create mode 100644 internal/api/client/statuses/statushistory_test.go diff --git a/docs/api/swagger.yaml b/docs/api/swagger.yaml index d636b7586..18c22a980 100644 --- a/docs/api/swagger.yaml +++ b/docs/api/swagger.yaml @@ -2214,6 +2214,52 @@ definitions: type: object x-go-name: Context x-go-package: github.com/superseriousbusiness/gotosocial/internal/api/model + statusEdit: + description: |- + StatusEdit represents one historical revision of a status, containing + partial information about the state of the status at that revision. + properties: + account: + $ref: '#/definitions/account' + content: + description: |- + The content of this status at this revision. + Should be HTML, but might also be plaintext in some cases. + example:
Hey this is a status!
+ type: string + x-go-name: Content + created_at: + description: The date when this revision was created (ISO 8601 Datetime). + example: "2021-07-30T09:20:25+00:00" + type: string + x-go-name: CreatedAt + emojis: + description: Custom emoji to be used when rendering status content. + items: + $ref: '#/definitions/emoji' + type: array + x-go-name: Emojis + media_attachments: + description: Media that is attached to this status. + items: + $ref: '#/definitions/attachment' + type: array + x-go-name: MediaAttachments + poll: + $ref: '#/definitions/poll' + sensitive: + description: Status marked sensitive at this revision. + example: false + type: boolean + x-go-name: Sensitive + spoiler_text: + description: Subject, summary, or content warning for the status at this revision. + example: warning nsfw + type: string + x-go-name: SpoilerText + type: object + x-go-name: StatusEdit + x-go-package: github.com/superseriousbusiness/gotosocial/internal/api/model statusReblogged: properties: account: @@ -7464,6 +7510,43 @@ paths: summary: View accounts that have faved/starred/liked the target status. tags: - statuses + /api/v1/statuses/{id}/history: + get: + description: 'UNIMPLEMENTED: Currently this endpoint will always return an array of length 1, containing only the latest/current version of the status.' + operationId: statusHistoryGet + parameters: + - description: Target status ID. + in: path + name: id + required: true + type: string + produces: + - application/json + responses: + "200": + description: "" + schema: + items: + $ref: '#/definitions/statusEdit' + type: array + "400": + description: bad request + "401": + description: unauthorized + "403": + description: forbidden + "404": + description: not found + "406": + description: not acceptable + "500": + description: internal server error + security: + - OAuth2 Bearer: + - read:statuses + summary: View edit history of status with the given ID. + tags: + - statuses /api/v1/statuses/{id}/mute: post: description: |- diff --git a/internal/api/client/statuses/status.go b/internal/api/client/statuses/status.go index c93d69994..266481b91 100644 --- a/internal/api/client/statuses/status.go +++ b/internal/api/client/statuses/status.go @@ -64,6 +64,9 @@ // ContextPath is used for fetching context of posts ContextPath = BasePathWithID + "/context" + + // HistoryPath is used for fetching history of posts. + HistoryPath = BasePathWithID + "/history" ) type Module struct { @@ -104,4 +107,7 @@ func (m *Module) Route(attachHandler func(method string, path string, f ...gin.H // context / status thread attachHandler(http.MethodGet, ContextPath, m.StatusContextGETHandler) + + // history/edit stuff + attachHandler(http.MethodGet, HistoryPath, m.StatusHistoryGETHandler) } diff --git a/internal/api/client/statuses/statushistory.go b/internal/api/client/statuses/statushistory.go new file mode 100644 index 000000000..ba1af58cf --- /dev/null +++ b/internal/api/client/statuses/statushistory.go @@ -0,0 +1,97 @@ +// GoToSocial +// Copyright (C) GoToSocial Authors admin@gotosocial.org +// SPDX-License-Identifier: AGPL-3.0-or-later +// +// 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, seeHey this is a status!
+ Content string `json:"content"` + // Subject, summary, or content warning for the status at this revision. + // example: warning nsfw + SpoilerText string `json:"spoiler_text"` + // Status marked sensitive at this revision. + // example: false + Sensitive bool `json:"sensitive"` + // The date when this revision was created (ISO 8601 Datetime). + // example: 2021-07-30T09:20:25+00:00 + CreatedAt string `json:"created_at"` + // The account that authored this status. + Account *Account `json:"account"` + // The poll attached to the status at this revision. + // Note that edits changing the poll options will be collapsed together into one edit, since this action resets the poll. + // nullable: true + Poll *Poll `json:"poll"` + // Media that is attached to this status. + MediaAttachments []*Attachment `json:"media_attachments"` + // Custom emoji to be used when rendering status content. + Emojis []Emoji `json:"emojis"` +} diff --git a/internal/processing/status/get.go b/internal/processing/status/get.go index 7256d2f82..8b0c21adf 100644 --- a/internal/processing/status/get.go +++ b/internal/processing/status/get.go @@ -25,8 +25,40 @@ apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model" "github.com/superseriousbusiness/gotosocial/internal/gtserror" "github.com/superseriousbusiness/gotosocial/internal/gtsmodel" + "github.com/superseriousbusiness/gotosocial/internal/util" ) +// HistoryGet gets edit history for the target status, taking account of privacy settings and blocks etc. +// TODO: currently this just returns the latest version of the status. +func (p *Processor) HistoryGet(ctx context.Context, requestingAccount *gtsmodel.Account, targetStatusID string) ([]*apimodel.StatusEdit, gtserror.WithCode) { + targetStatus, errWithCode := p.c.GetVisibleTargetStatus(ctx, + requestingAccount, + targetStatusID, + nil, // default freshness + ) + if errWithCode != nil { + return nil, errWithCode + } + + apiStatus, errWithCode := p.c.GetAPIStatus(ctx, requestingAccount, targetStatus) + if errWithCode != nil { + return nil, errWithCode + } + + return []*apimodel.StatusEdit{ + { + Content: apiStatus.Content, + SpoilerText: apiStatus.SpoilerText, + Sensitive: apiStatus.Sensitive, + CreatedAt: util.FormatISO8601(targetStatus.UpdatedAt), + Account: apiStatus.Account, + Poll: apiStatus.Poll, + MediaAttachments: apiStatus.MediaAttachments, + Emojis: apiStatus.Emojis, + }, + }, nil +} + // Get gets the given status, taking account of privacy settings and blocks etc. func (p *Processor) Get(ctx context.Context, requestingAccount *gtsmodel.Account, targetStatusID string) (*apimodel.Status, gtserror.WithCode) { targetStatus, errWithCode := p.c.GetVisibleTargetStatus(ctx,