diff options
| author | 2025-07-04 15:30:39 +0200 | |
|---|---|---|
| committer | 2025-07-04 15:30:39 +0200 | |
| commit | 66e1ec14aa07e115580afc8e1399677f3b54eeda (patch) | |
| tree | 54aabccf5c0540abbfdea771745f354e05c8eb1a /internal/typeutils | |
| parent | [bugfix] set correct scope for StatusFavePOSTHandler (#4310) (diff) | |
| download | gotosocial-66e1ec14aa07e115580afc8e1399677f3b54eeda.tar.xz | |
[chore] move status filtering from type converter (#4306)
This finalizes the moving status filtering out of the type converter, and into its own `./internal/filter/` subpkg :)
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4306
Co-authored-by: kim <grufwub@gmail.com>
Co-committed-by: kim <grufwub@gmail.com>
Diffstat (limited to 'internal/typeutils')
| -rw-r--r-- | internal/typeutils/converter.go | 3 | ||||
| -rw-r--r-- | internal/typeutils/internaltofrontend.go | 57 | ||||
| -rw-r--r-- | internal/typeutils/internaltofrontend_test.go | 646 |
3 files changed, 16 insertions, 690 deletions
diff --git a/internal/typeutils/converter.go b/internal/typeutils/converter.go index 4f3658b0d..789404426 100644 --- a/internal/typeutils/converter.go +++ b/internal/typeutils/converter.go @@ -27,7 +27,6 @@ import ( apimodel "code.superseriousbusiness.org/gotosocial/internal/api/model" "code.superseriousbusiness.org/gotosocial/internal/filter/interaction" - "code.superseriousbusiness.org/gotosocial/internal/filter/status" "code.superseriousbusiness.org/gotosocial/internal/filter/visibility" "code.superseriousbusiness.org/gotosocial/internal/log" "code.superseriousbusiness.org/gotosocial/internal/state" @@ -38,7 +37,6 @@ type Converter struct { defaultAvatars []string randAvatars sync.Map visFilter *visibility.Filter - statusFilter *status.Filter intFilter *interaction.Filter randStats atomic.Pointer[apimodel.RandomStats] } @@ -48,7 +46,6 @@ func NewConverter(state *state.State) *Converter { state: state, defaultAvatars: populateDefaultAvatars(), visFilter: visibility.NewFilter(state), - statusFilter: status.NewFilter(state), intFilter: interaction.NewFilter(state), } } diff --git a/internal/typeutils/internaltofrontend.go b/internal/typeutils/internaltofrontend.go index a79387c0f..3b5af6579 100644 --- a/internal/typeutils/internaltofrontend.go +++ b/internal/typeutils/internaltofrontend.go @@ -51,10 +51,6 @@ const ( instanceMastodonVersion = "3.5.3" ) -// ErrHideStatus indicates that a status has -// been filtered and should not be returned at all. -var ErrHideStatus = errors.New("hide status") - var instanceStatusesSupportedMimeTypes = []string{ string(apimodel.StatusContentTypePlain), string(apimodel.StatusContentTypeMarkdown), @@ -850,13 +846,11 @@ func (c *Converter) StatusToAPIStatus( ctx context.Context, status *gtsmodel.Status, requestingAccount *gtsmodel.Account, - filterCtx gtsmodel.FilterContext, ) (*apimodel.Status, error) { return c.statusToAPIStatus( ctx, status, requestingAccount, - filterCtx, true, true, ) @@ -870,7 +864,6 @@ func (c *Converter) statusToAPIStatus( ctx context.Context, status *gtsmodel.Status, requestingAccount *gtsmodel.Account, - filterCtx gtsmodel.FilterContext, placeholdAttachments bool, addPendingNote bool, ) (*apimodel.Status, error) { @@ -878,7 +871,6 @@ func (c *Converter) statusToAPIStatus( ctx, status, requestingAccount, // Can be nil. - filterCtx, // Can be empty. ) if err != nil { return nil, err @@ -945,8 +937,7 @@ func (c *Converter) StatusToWebStatus( s *gtsmodel.Status, ) (*apimodel.WebStatus, error) { apiStatus, err := c.statusToFrontend(ctx, s, - nil, // No authed requester. - gtsmodel.FilterContextNone, // No filters. + nil, // No authed requester. ) if err != nil { return nil, err @@ -1115,7 +1106,6 @@ func (c *Converter) statusToFrontend( ctx context.Context, status *gtsmodel.Status, requestingAccount *gtsmodel.Account, - filterCtx gtsmodel.FilterContext, ) ( *apimodel.Status, error, @@ -1123,7 +1113,6 @@ func (c *Converter) statusToFrontend( apiStatus, err := c.baseStatusToFrontend(ctx, status, requestingAccount, - filterCtx, ) if err != nil { return nil, err @@ -1133,12 +1122,8 @@ func (c *Converter) statusToFrontend( reblog, err := c.baseStatusToFrontend(ctx, status.BoostOf, requestingAccount, - filterCtx, ) - if errors.Is(err, ErrHideStatus) { - // If we'd hide the original status, hide the boost. - return nil, err - } else if err != nil { + if err != nil { return nil, gtserror.Newf("error converting boosted status: %w", err) } @@ -1165,7 +1150,6 @@ func (c *Converter) baseStatusToFrontend( ctx context.Context, status *gtsmodel.Status, requester *gtsmodel.Account, - filterCtx gtsmodel.FilterContext, ) ( *apimodel.Status, error, @@ -1340,20 +1324,6 @@ func (c *Converter) baseStatusToFrontend( apiStatus.URL = apiStatus.URI } - var hide bool - - // Pass the status through any stored filters of requesting account's, in context. - apiStatus.Filtered, hide, err = c.statusFilter.StatusFilterResultsInContext(ctx, - requester, - status, - filterCtx, - ) - if err != nil { - return nil, gtserror.Newf("error filtering status %s: %w", status.URI, err) - } else if hide { - return nil, ErrHideStatus - } - return apiStatus, nil } @@ -1866,7 +1836,6 @@ func (c *Converter) RelationshipToAPIRelationship(ctx context.Context, r *gtsmod func (c *Converter) NotificationToAPINotification( ctx context.Context, notif *gtsmodel.Notification, - filter bool, ) (*apimodel.Notification, error) { // Ensure notif populated. if err := c.state.DB.PopulateNotification(ctx, notif); err != nil { @@ -1882,27 +1851,14 @@ func (c *Converter) NotificationToAPINotification( // Get status that triggered this notif, if set. var apiStatus *apimodel.Status if notif.Status != nil { - var filterCtx gtsmodel.FilterContext - - if filter { - filterCtx = gtsmodel.FilterContextNotifications - } - apiStatus, err = c.StatusToAPIStatus(ctx, notif.Status, notif.TargetAccount, - filterCtx, ) - if err != nil && !errors.Is(err, ErrHideStatus) { + if err != nil { return nil, gtserror.Newf("error converting status to api: %w", err) } - if apiStatus == nil { - // Notif filtered for this - // status, nothing to do. - return nil, err - } - if apiStatus.Reblog != nil { // Use the actual reblog status // for the notifications endpoint. @@ -1926,7 +1882,6 @@ func (c *Converter) ConversationToAPIConversation( ctx context.Context, conversation *gtsmodel.Conversation, requester *gtsmodel.Account, - filters []*gtsmodel.Filter, ) (*apimodel.Conversation, error) { apiConversation := &apimodel.Conversation{ ID: conversation.ID, @@ -1941,9 +1896,8 @@ func (c *Converter) ConversationToAPIConversation( ctx, conversation.LastStatus, requester, - gtsmodel.FilterContextNotifications, ) - if err != nil && !errors.Is(err, ErrHideStatus) { + if err != nil { return nil, gtserror.Newf( "error converting status %s to API representation: %w", conversation.LastStatus.ID, @@ -2209,7 +2163,6 @@ func (c *Converter) ReportToAdminAPIReport(ctx context.Context, r *gtsmodel.Repo ctx, s, requestingAccount, - gtsmodel.FilterContextNone, true, // Placehold unknown attachments. // Don't add note about @@ -2913,7 +2866,6 @@ func (c *Converter) InteractionReqToAPIInteractionReq( ctx, req.Status, requestingAcct, - gtsmodel.FilterContextNone, ) if err != nil { err := gtserror.Newf("error converting interacted status: %w", err) @@ -2926,7 +2878,6 @@ func (c *Converter) InteractionReqToAPIInteractionReq( ctx, req.Reply, requestingAcct, - gtsmodel.FilterContextNone, true, // Placehold unknown attachments. // Don't add note about pending; diff --git a/internal/typeutils/internaltofrontend_test.go b/internal/typeutils/internaltofrontend_test.go index 1fc55acca..8b0d15f10 100644 --- a/internal/typeutils/internaltofrontend_test.go +++ b/internal/typeutils/internaltofrontend_test.go @@ -24,12 +24,9 @@ import ( "strings" "testing" - apimodel "code.superseriousbusiness.org/gotosocial/internal/api/model" "code.superseriousbusiness.org/gotosocial/internal/config" "code.superseriousbusiness.org/gotosocial/internal/db" "code.superseriousbusiness.org/gotosocial/internal/gtsmodel" - "code.superseriousbusiness.org/gotosocial/internal/id" - "code.superseriousbusiness.org/gotosocial/internal/typeutils" "code.superseriousbusiness.org/gotosocial/internal/util" "code.superseriousbusiness.org/gotosocial/testrig" "github.com/stretchr/testify/suite" @@ -466,7 +463,7 @@ func (suite *InternalToFrontendTestSuite) TestLocalInstanceAccountToFrontendBloc func (suite *InternalToFrontendTestSuite) TestStatusToFrontend() { testStatus := suite.testStatuses["admin_account_status_1"] requestingAccount := suite.testAccounts["local_account_1"] - apiStatus, err := suite.typeconverter.StatusToAPIStatus(suite.T().Context(), testStatus, requestingAccount, gtsmodel.FilterContextNone) + apiStatus, err := suite.typeconverter.StatusToAPIStatus(suite.T().Context(), testStatus, requestingAccount) suite.NoError(err) b, err := json.MarshalIndent(apiStatus, "", " ") @@ -629,7 +626,7 @@ func (suite *InternalToFrontendTestSuite) TestStatusToFrontendHTMLContentWarning testStatus.ContentWarning = `<p>First paragraph of content warning</p><h4>Here's the title!</h4><p></p><p>Big boobs<br>Tee hee!<br><br>Some more text<br>And a bunch more<br><br>Hasta la victoria siempre!</p>` requestingAccount := suite.testAccounts["local_account_1"] - apiStatus, err := suite.typeconverter.StatusToAPIStatus(suite.T().Context(), testStatus, requestingAccount, gtsmodel.FilterContextNone) + apiStatus, err := suite.typeconverter.StatusToAPIStatus(suite.T().Context(), testStatus, requestingAccount) suite.NoError(err) b, err := json.MarshalIndent(apiStatus, "", " ") @@ -795,7 +792,7 @@ func (suite *InternalToFrontendTestSuite) TestStatusToFrontendApplicationDeleted } requestingAccount := suite.testAccounts["local_account_1"] - apiStatus, err := suite.typeconverter.StatusToAPIStatus(ctx, testStatus, requestingAccount, gtsmodel.FilterContextNone) + apiStatus, err := suite.typeconverter.StatusToAPIStatus(ctx, testStatus, requestingAccount) suite.NoError(err) b, err := json.MarshalIndent(apiStatus, "", " ") @@ -950,625 +947,11 @@ func (suite *InternalToFrontendTestSuite) TestStatusToFrontendApplicationDeleted }`, string(b)) } -// Modify a fixture status into a status that should be filtered, -// and then filter it, returning the API status or any error from converting it. -func (suite *InternalToFrontendTestSuite) filteredStatusToFrontend(action gtsmodel.FilterAction, boost bool) (*apimodel.Status, error) { - ctx := suite.T().Context() - - testStatus := suite.testStatuses["admin_account_status_1"] - testStatus.Content += " fnord" - testStatus.Text += " fnord" - - if boost { - // Modify a fixture boost into a boost of the above status. - boostStatus := suite.testStatuses["admin_account_status_4"] - boostStatus.BoostOf = testStatus - boostStatus.BoostOfID = testStatus.ID - testStatus = boostStatus - } - - requestingAccount := suite.testAccounts["local_account_1"] - - expectedMatchingFilter := suite.testFilters["local_account_1_filter_1"] - expectedMatchingFilter.Action = action - - err := suite.state.DB.UpdateFilter(ctx, expectedMatchingFilter, "action") - suite.NoError(err) - - return suite.typeconverter.StatusToAPIStatus( - suite.T().Context(), - testStatus, - requestingAccount, - gtsmodel.FilterContextHome, - ) -} - -// Test that a status which is filtered with a warn filter by the requesting user has `filtered` set correctly. -func (suite *InternalToFrontendTestSuite) TestWarnFilteredStatusToFrontend() { - apiStatus, err := suite.filteredStatusToFrontend(gtsmodel.FilterActionWarn, false) - suite.NoError(err) - - b, err := json.MarshalIndent(apiStatus, "", " ") - suite.NoError(err) - - suite.Equal(`{ - "id": "01F8MH75CBF9JFX4ZAD54N0W0R", - "created_at": "2021-10-20T11:36:45.000Z", - "edited_at": null, - "in_reply_to_id": null, - "in_reply_to_account_id": null, - "sensitive": false, - "spoiler_text": "", - "visibility": "public", - "language": "en", - "uri": "http://localhost:8080/users/admin/statuses/01F8MH75CBF9JFX4ZAD54N0W0R", - "url": "http://localhost:8080/@admin/statuses/01F8MH75CBF9JFX4ZAD54N0W0R", - "replies_count": 1, - "reblogs_count": 0, - "favourites_count": 1, - "favourited": true, - "reblogged": false, - "muted": false, - "bookmarked": true, - "pinned": false, - "content": "\u003cp\u003ehello world! \u003ca href=\"http://localhost:8080/tags/welcome\" class=\"mention hashtag\" rel=\"tag nofollow noreferrer noopener\" target=\"_blank\"\u003e#\u003cspan\u003ewelcome\u003c/span\u003e\u003c/a\u003e ! first post on the instance :rainbow: !\u003c/p\u003e fnord", - "reblog": null, - "application": { - "name": "superseriousbusiness", - "website": "https://superserious.business" - }, - "account": { - "id": "01F8MH17FWEB39HZJ76B6VXSKF", - "username": "admin", - "acct": "admin", - "display_name": "", - "locked": false, - "discoverable": true, - "bot": false, - "created_at": "2022-05-17T13:10:59.000Z", - "note": "", - "url": "http://localhost:8080/@admin", - "avatar": "", - "avatar_static": "", - "header": "http://localhost:8080/assets/default_header.webp", - "header_static": "http://localhost:8080/assets/default_header.webp", - "header_description": "Flat gray background (default header).", - "followers_count": 1, - "following_count": 1, - "statuses_count": 4, - "last_status_at": "2021-10-20", - "emojis": [], - "fields": [], - "enable_rss": true, - "roles": [ - { - "id": "admin", - "name": "admin", - "color": "" - } - ], - "group": false - }, - "media_attachments": [ - { - "id": "01F8MH6NEM8D7527KZAECTCR76", - "type": "image", - "url": "http://localhost:8080/fileserver/01F8MH17FWEB39HZJ76B6VXSKF/attachment/original/01F8MH6NEM8D7527KZAECTCR76.jpg", - "text_url": "http://localhost:8080/fileserver/01F8MH17FWEB39HZJ76B6VXSKF/attachment/original/01F8MH6NEM8D7527KZAECTCR76.jpg", - "preview_url": "http://localhost:8080/fileserver/01F8MH17FWEB39HZJ76B6VXSKF/attachment/small/01F8MH6NEM8D7527KZAECTCR76.webp", - "remote_url": null, - "preview_remote_url": null, - "meta": { - "original": { - "width": 1200, - "height": 630, - "size": "1200x630", - "aspect": 1.9047619 - }, - "small": { - "width": 512, - "height": 268, - "size": "512x268", - "aspect": 1.9104477 - }, - "focus": { - "x": -0.5, - "y": 0.5 - } - }, - "description": "Black and white image of some 50's style text saying: Welcome On Board", - "blurhash": "LIIE|gRj00WB-;j[t7j[4nWBj[Rj" - } - ], - "mentions": [], - "tags": [ - { - "name": "welcome", - "url": "http://localhost:8080/tags/welcome" - } - ], - "emojis": [ - { - "shortcode": "rainbow", - "url": "http://localhost:8080/fileserver/01AY6P665V14JJR0AFVRT7311Y/emoji/original/01F8MH9H8E4VG3KDYJR9EGPXCQ.png", - "static_url": "http://localhost:8080/fileserver/01AY6P665V14JJR0AFVRT7311Y/emoji/static/01F8MH9H8E4VG3KDYJR9EGPXCQ.png", - "visible_in_picker": true, - "category": "reactions" - } - ], - "card": null, - "poll": null, - "text": "hello world! #welcome ! first post on the instance :rainbow: ! fnord", - "content_type": "text/plain", - "filtered": [ - { - "filter": { - "id": "01HN26VM6KZTW1ANNRVSBMA461", - "title": "fnord", - "context": [ - "home", - "public" - ], - "expires_at": null, - "filter_action": "warn", - "keywords": [ - { - "id": "01HN272TAVWAXX72ZX4M8JZ0PS", - "keyword": "fnord", - "whole_word": true - } - ], - "statuses": [] - }, - "keyword_matches": [ - "fnord" - ], - "status_matches": [] - } - ], - "interaction_policy": { - "can_favourite": { - "automatic_approval": [ - "public", - "me" - ], - "manual_approval": [], - "always": [ - "public", - "me" - ], - "with_approval": [] - }, - "can_reply": { - "automatic_approval": [ - "public", - "me" - ], - "manual_approval": [], - "always": [ - "public", - "me" - ], - "with_approval": [] - }, - "can_reblog": { - "automatic_approval": [ - "public", - "me" - ], - "manual_approval": [], - "always": [ - "public", - "me" - ], - "with_approval": [] - } - } -}`, string(b)) -} - -// Test that a status which is filtered with a warn filter by the requesting user has `filtered` set correctly when boosted. -func (suite *InternalToFrontendTestSuite) TestWarnFilteredBoostToFrontend() { - apiStatus, err := suite.filteredStatusToFrontend(gtsmodel.FilterActionWarn, true) - suite.NoError(err) - - b, err := json.MarshalIndent(apiStatus, "", " ") - suite.NoError(err) - - suite.Equal(`{ - "id": "01G36SF3V6Y6V5BF9P4R7PQG7G", - "created_at": "2021-10-20T10:41:37.000Z", - "edited_at": null, - "in_reply_to_id": null, - "in_reply_to_account_id": null, - "sensitive": false, - "spoiler_text": "", - "visibility": "public", - "language": null, - "uri": "http://localhost:8080/users/admin/statuses/01G36SF3V6Y6V5BF9P4R7PQG7G", - "url": "http://localhost:8080/@admin/statuses/01G36SF3V6Y6V5BF9P4R7PQG7G", - "replies_count": 0, - "reblogs_count": 0, - "favourites_count": 0, - "favourited": true, - "reblogged": false, - "muted": false, - "bookmarked": true, - "pinned": false, - "content": "", - "reblog": { - "id": "01F8MH75CBF9JFX4ZAD54N0W0R", - "created_at": "2021-10-20T11:36:45.000Z", - "edited_at": null, - "in_reply_to_id": null, - "in_reply_to_account_id": null, - "sensitive": false, - "spoiler_text": "", - "visibility": "public", - "language": "en", - "uri": "http://localhost:8080/users/admin/statuses/01F8MH75CBF9JFX4ZAD54N0W0R", - "url": "http://localhost:8080/@admin/statuses/01F8MH75CBF9JFX4ZAD54N0W0R", - "replies_count": 1, - "reblogs_count": 0, - "favourites_count": 1, - "favourited": true, - "reblogged": false, - "muted": false, - "bookmarked": true, - "pinned": false, - "content": "\u003cp\u003ehello world! \u003ca href=\"http://localhost:8080/tags/welcome\" class=\"mention hashtag\" rel=\"tag nofollow noreferrer noopener\" target=\"_blank\"\u003e#\u003cspan\u003ewelcome\u003c/span\u003e\u003c/a\u003e ! first post on the instance :rainbow: !\u003c/p\u003e fnord", - "reblog": null, - "application": { - "name": "superseriousbusiness", - "website": "https://superserious.business" - }, - "account": { - "id": "01F8MH1H7YV1Z7D2C8K2730QBF", - "username": "the_mighty_zork", - "acct": "the_mighty_zork", - "display_name": "original zork (he/they)", - "locked": false, - "discoverable": true, - "bot": false, - "created_at": "2022-05-20T11:09:18.000Z", - "note": "\u003cp\u003ehey yo this is my profile!\u003c/p\u003e", - "url": "http://localhost:8080/@the_mighty_zork", - "avatar": "http://localhost:8080/fileserver/01F8MH1H7YV1Z7D2C8K2730QBF/avatar/original/01F8MH58A357CV5K7R7TJMSH6S.jpg", - "avatar_static": "http://localhost:8080/fileserver/01F8MH1H7YV1Z7D2C8K2730QBF/avatar/small/01F8MH58A357CV5K7R7TJMSH6S.webp", - "avatar_description": "a green goblin looking nasty", - "avatar_media_id": "01F8MH58A357CV5K7R7TJMSH6S", - "header": "http://localhost:8080/fileserver/01F8MH1H7YV1Z7D2C8K2730QBF/header/original/01PFPMWK2FF0D9WMHEJHR07C3Q.jpg", - "header_static": "http://localhost:8080/fileserver/01F8MH1H7YV1Z7D2C8K2730QBF/header/small/01PFPMWK2FF0D9WMHEJHR07C3Q.webp", - "header_description": "A very old-school screenshot of the original team fortress mod for quake", - "header_media_id": "01PFPMWK2FF0D9WMHEJHR07C3Q", - "followers_count": 2, - "following_count": 2, - "statuses_count": 9, - "last_status_at": "2024-11-01", - "emojis": [], - "fields": [], - "enable_rss": true, - "group": false - }, - "media_attachments": [ - { - "id": "01F8MH6NEM8D7527KZAECTCR76", - "type": "image", - "url": "http://localhost:8080/fileserver/01F8MH17FWEB39HZJ76B6VXSKF/attachment/original/01F8MH6NEM8D7527KZAECTCR76.jpg", - "text_url": "http://localhost:8080/fileserver/01F8MH17FWEB39HZJ76B6VXSKF/attachment/original/01F8MH6NEM8D7527KZAECTCR76.jpg", - "preview_url": "http://localhost:8080/fileserver/01F8MH17FWEB39HZJ76B6VXSKF/attachment/small/01F8MH6NEM8D7527KZAECTCR76.webp", - "remote_url": null, - "preview_remote_url": null, - "meta": { - "original": { - "width": 1200, - "height": 630, - "size": "1200x630", - "aspect": 1.9047619 - }, - "small": { - "width": 512, - "height": 268, - "size": "512x268", - "aspect": 1.9104477 - }, - "focus": { - "x": -0.5, - "y": 0.5 - } - }, - "description": "Black and white image of some 50's style text saying: Welcome On Board", - "blurhash": "LIIE|gRj00WB-;j[t7j[4nWBj[Rj" - } - ], - "mentions": [], - "tags": [ - { - "name": "welcome", - "url": "http://localhost:8080/tags/welcome" - } - ], - "emojis": [ - { - "shortcode": "rainbow", - "url": "http://localhost:8080/fileserver/01AY6P665V14JJR0AFVRT7311Y/emoji/original/01F8MH9H8E4VG3KDYJR9EGPXCQ.png", - "static_url": "http://localhost:8080/fileserver/01AY6P665V14JJR0AFVRT7311Y/emoji/static/01F8MH9H8E4VG3KDYJR9EGPXCQ.png", - "visible_in_picker": true, - "category": "reactions" - } - ], - "card": null, - "poll": null, - "text": "hello world! #welcome ! first post on the instance :rainbow: ! fnord", - "content_type": "text/plain", - "filtered": [ - { - "filter": { - "id": "01HN26VM6KZTW1ANNRVSBMA461", - "title": "fnord", - "context": [ - "home", - "public" - ], - "expires_at": null, - "filter_action": "warn", - "keywords": [ - { - "id": "01HN272TAVWAXX72ZX4M8JZ0PS", - "keyword": "fnord", - "whole_word": true - } - ], - "statuses": [] - }, - "keyword_matches": [ - "fnord" - ], - "status_matches": [] - } - ], - "interaction_policy": { - "can_favourite": { - "automatic_approval": [ - "public", - "me" - ], - "manual_approval": [], - "always": [ - "public", - "me" - ], - "with_approval": [] - }, - "can_reply": { - "automatic_approval": [ - "public", - "me" - ], - "manual_approval": [], - "always": [ - "public", - "me" - ], - "with_approval": [] - }, - "can_reblog": { - "automatic_approval": [ - "public", - "me" - ], - "manual_approval": [], - "always": [ - "public", - "me" - ], - "with_approval": [] - } - } - }, - "application": { - "name": "superseriousbusiness", - "website": "https://superserious.business" - }, - "account": { - "id": "01F8MH17FWEB39HZJ76B6VXSKF", - "username": "admin", - "acct": "admin", - "display_name": "", - "locked": false, - "discoverable": true, - "bot": false, - "created_at": "2022-05-17T13:10:59.000Z", - "note": "", - "url": "http://localhost:8080/@admin", - "avatar": "", - "avatar_static": "", - "header": "http://localhost:8080/assets/default_header.webp", - "header_static": "http://localhost:8080/assets/default_header.webp", - "header_description": "Flat gray background (default header).", - "followers_count": 1, - "following_count": 1, - "statuses_count": 4, - "last_status_at": "2021-10-20", - "emojis": [], - "fields": [], - "enable_rss": true, - "roles": [ - { - "id": "admin", - "name": "admin", - "color": "" - } - ], - "group": false - }, - "media_attachments": [], - "mentions": [], - "tags": [], - "emojis": [], - "card": null, - "poll": null, - "filtered": [ - { - "filter": { - "id": "01HN26VM6KZTW1ANNRVSBMA461", - "title": "fnord", - "context": [ - "home", - "public" - ], - "expires_at": null, - "filter_action": "warn", - "keywords": [ - { - "id": "01HN272TAVWAXX72ZX4M8JZ0PS", - "keyword": "fnord", - "whole_word": true - } - ], - "statuses": [] - }, - "keyword_matches": [ - "fnord" - ], - "status_matches": [] - } - ], - "interaction_policy": { - "can_favourite": { - "automatic_approval": [ - "public", - "me" - ], - "manual_approval": [], - "always": [ - "public", - "me" - ], - "with_approval": [] - }, - "can_reply": { - "automatic_approval": [ - "public", - "me" - ], - "manual_approval": [], - "always": [ - "public", - "me" - ], - "with_approval": [] - }, - "can_reblog": { - "automatic_approval": [ - "public", - "me" - ], - "manual_approval": [], - "always": [ - "public", - "me" - ], - "with_approval": [] - } - } -}`, string(b)) -} - -// Test that a status which is filtered with a hide filter by the requesting user results in the ErrHideStatus error. -func (suite *InternalToFrontendTestSuite) TestHideFilteredStatusToFrontend() { - _, err := suite.filteredStatusToFrontend(gtsmodel.FilterActionHide, false) - suite.ErrorIs(err, typeutils.ErrHideStatus) -} - -// Test that a status which is filtered with a hide filter by the requesting user results in the ErrHideStatus error for a boost of that status. -func (suite *InternalToFrontendTestSuite) TestHideFilteredBoostToFrontend() { - _, err := suite.filteredStatusToFrontend(gtsmodel.FilterActionHide, true) - suite.ErrorIs(err, typeutils.ErrHideStatus) -} - -// Test that a hashtag filter for a hashtag in Mastodon HTML content works the way most users would expect. -func (suite *InternalToFrontendTestSuite) testHashtagFilteredStatusToFrontend(wholeWord bool, boost bool) { - ctx := suite.T().Context() - - testStatus := new(gtsmodel.Status) - *testStatus = *suite.testStatuses["admin_account_status_1"] - testStatus.Content = `<p>doggo doggin' it</p><p><a href="https://example.test/tags/dogsofmastodon" class="mention hashtag" rel="tag nofollow noreferrer noopener" target="_blank">#<span>dogsofmastodon</span></a></p>` - - if boost { - boost, err := suite.typeconverter.StatusToBoost( - suite.T().Context(), - testStatus, - suite.testAccounts["admin_account"], - "", - ) - if err != nil { - suite.FailNow(err.Error()) - } - testStatus = boost - } - - var err error - - requestingAccount := suite.testAccounts["local_account_1"] - - filter := >smodel.Filter{ - ID: id.NewULID(), - Title: id.NewULID(), - AccountID: requestingAccount.ID, - Action: gtsmodel.FilterActionWarn, - Contexts: gtsmodel.FilterContexts(gtsmodel.FilterContextHome), - } - - filterKeyword := >smodel.FilterKeyword{ - ID: id.NewULID(), - FilterID: filter.ID, - Keyword: "#dogsofmastodon", - WholeWord: &wholeWord, - } - - filter.KeywordIDs = []string{filterKeyword.ID} - - err = suite.state.DB.PutFilterKeyword(ctx, filterKeyword) - suite.NoError(err) - - err = suite.state.DB.PutFilter(ctx, filter) - suite.NoError(err) - - apiStatus, err := suite.typeconverter.StatusToAPIStatus( - suite.T().Context(), - testStatus, - requestingAccount, - gtsmodel.FilterContextHome, - ) - if err != nil { - suite.FailNow(err.Error()) - } - - suite.NotEmpty(apiStatus.Filtered) -} - -func (suite *InternalToFrontendTestSuite) TestHashtagWholeWordFilteredStatusToFrontend() { - suite.testHashtagFilteredStatusToFrontend(true, false) -} - -func (suite *InternalToFrontendTestSuite) TestHashtagWholeWordFilteredBoostToFrontend() { - suite.testHashtagFilteredStatusToFrontend(true, true) -} - -func (suite *InternalToFrontendTestSuite) TestHashtagAnywhereFilteredStatusToFrontend() { - suite.testHashtagFilteredStatusToFrontend(false, false) -} - -func (suite *InternalToFrontendTestSuite) TestHashtagAnywhereFilteredBoostToFrontend() { - suite.testHashtagFilteredStatusToFrontend(false, true) -} - func (suite *InternalToFrontendTestSuite) TestStatusToFrontendUnknownAttachments() { testStatus := suite.testStatuses["remote_account_2_status_1"] requestingAccount := suite.testAccounts["admin_account"] - apiStatus, err := suite.typeconverter.StatusToAPIStatus(suite.T().Context(), testStatus, requestingAccount, gtsmodel.FilterContextNone) + apiStatus, err := suite.typeconverter.StatusToAPIStatus(suite.T().Context(), testStatus, requestingAccount) suite.NoError(err) b, err := json.MarshalIndent(apiStatus, "", " ") @@ -1895,7 +1278,7 @@ func (suite *InternalToFrontendTestSuite) TestStatusToFrontendUnknownLanguage() *testStatus = *suite.testStatuses["admin_account_status_1"] testStatus.Language = "" requestingAccount := suite.testAccounts["local_account_1"] - apiStatus, err := suite.typeconverter.StatusToAPIStatus(suite.T().Context(), testStatus, requestingAccount, gtsmodel.FilterContextNone) + apiStatus, err := suite.typeconverter.StatusToAPIStatus(suite.T().Context(), testStatus, requestingAccount) suite.NoError(err) b, err := json.MarshalIndent(apiStatus, "", " ") @@ -2056,7 +1439,7 @@ func (suite *InternalToFrontendTestSuite) TestStatusToFrontendPartialInteraction *testStatus = *suite.testStatuses["local_account_1_status_3"] testStatus.Language = "" requestingAccount := suite.testAccounts["admin_account"] - apiStatus, err := suite.typeconverter.StatusToAPIStatus(suite.T().Context(), testStatus, requestingAccount, gtsmodel.FilterContextNone) + apiStatus, err := suite.typeconverter.StatusToAPIStatus(suite.T().Context(), testStatus, requestingAccount) suite.NoError(err) b, err := json.MarshalIndent(apiStatus, "", " ") @@ -2169,7 +1552,6 @@ func (suite *InternalToFrontendTestSuite) TestStatusToAPIStatusPendingApproval() suite.T().Context(), testStatus, requestingAccount, - gtsmodel.FilterContextNone, ) if err != nil { suite.FailNow(err.Error()) @@ -3933,10 +3315,9 @@ func (suite *InternalToFrontendTestSuite) TestIntReqToAPI() { func (suite *InternalToFrontendTestSuite) TestConversationToAPISelfConvo() { var ( - ctx = suite.T().Context() - requester = suite.testAccounts["local_account_1"] - lastStatus = suite.testStatuses["local_account_1_status_1"] - filters []*gtsmodel.Filter = nil + ctx = suite.T().Context() + requester = suite.testAccounts["local_account_1"] + lastStatus = suite.testStatuses["local_account_1_status_1"] ) convo := >smodel.Conversation{ @@ -3954,7 +3335,6 @@ func (suite *InternalToFrontendTestSuite) TestConversationToAPISelfConvo() { ctx, convo, requester, - filters, ) if err != nil { suite.FailNow(err.Error()) @@ -4106,10 +3486,9 @@ func (suite *InternalToFrontendTestSuite) TestConversationToAPISelfConvo() { func (suite *InternalToFrontendTestSuite) TestConversationToAPI() { var ( - ctx = suite.T().Context() - requester = suite.testAccounts["local_account_1"] - lastStatus = suite.testStatuses["local_account_1_status_1"] - filters []*gtsmodel.Filter = nil + ctx = suite.T().Context() + requester = suite.testAccounts["local_account_1"] + lastStatus = suite.testStatuses["local_account_1_status_1"] ) convo := >smodel.Conversation{ @@ -4129,7 +3508,6 @@ func (suite *InternalToFrontendTestSuite) TestConversationToAPI() { ctx, convo, requester, - filters, ) if err != nil { suite.FailNow(err.Error()) |
