mirror of
				https://github.com/superseriousbusiness/gotosocial
				synced 2025-06-05 21:59:39 +02:00 
			
		
		
		
	[feature] Implement filters_changed stream event (#2972)
This commit is contained in:
		| @@ -8651,7 +8651,7 @@ paths: | |||||||
|                                     `update`: a new status has been received. |                                     `update`: a new status has been received. | ||||||
|                                     `notification`: a new notification has been received. |                                     `notification`: a new notification has been received. | ||||||
|                                     `delete`: a status has been deleted. |                                     `delete`: a status has been deleted. | ||||||
|                                     `filters_changed`: not implemented. |                                     `filters_changed`: filters (including keywords and statuses) have changed. | ||||||
|                                 enum: |                                 enum: | ||||||
|                                     - update |                                     - update | ||||||
|                                     - notification |                                     - notification | ||||||
| @@ -8668,6 +8668,7 @@ paths: | |||||||
|                                     If `event` = `update`, then the payload will be a JSON string of a status. |                                     If `event` = `update`, then the payload will be a JSON string of a status. | ||||||
|                                     If `event` = `notification`, then the payload will be a JSON string of a notification. |                                     If `event` = `notification`, then the payload will be a JSON string of a notification. | ||||||
|                                     If `event` = `delete`, then the payload will be a status ID. |                                     If `event` = `delete`, then the payload will be a status ID. | ||||||
|  |                                     If `event` = `filters_changed`, then there is no payload. | ||||||
|                                 example: '{"id":"01FC3TZ5CFG6H65GCKCJRKA669","created_at":"2021-08-02T16:25:52Z","sensitive":false,"spoiler_text":"","visibility":"public","language":"en","uri":"https://gts.superseriousbusiness.org/users/dumpsterqueer/statuses/01FC3TZ5CFG6H65GCKCJRKA669","url":"https://gts.superseriousbusiness.org/@dumpsterqueer/statuses/01FC3TZ5CFG6H65GCKCJRKA669","replies_count":0,"reblogs_count":0,"favourites_count":0,"favourited":false,"reblogged":false,"muted":false,"bookmarked":fals…//gts.superseriousbusiness.org/fileserver/01JNN207W98SGG3CBJ76R5MVDN/header/original/019036W043D8FXPJKSKCX7G965.png","header_static":"https://gts.superseriousbusiness.org/fileserver/01JNN207W98SGG3CBJ76R5MVDN/header/small/019036W043D8FXPJKSKCX7G965.png","followers_count":33,"following_count":28,"statuses_count":126,"last_status_at":"2021-08-02T16:25:52Z","emojis":[],"fields":[]},"media_attachments":[],"mentions":[],"tags":[],"emojis":[],"card":null,"poll":null,"text":"a"}' |                                 example: '{"id":"01FC3TZ5CFG6H65GCKCJRKA669","created_at":"2021-08-02T16:25:52Z","sensitive":false,"spoiler_text":"","visibility":"public","language":"en","uri":"https://gts.superseriousbusiness.org/users/dumpsterqueer/statuses/01FC3TZ5CFG6H65GCKCJRKA669","url":"https://gts.superseriousbusiness.org/@dumpsterqueer/statuses/01FC3TZ5CFG6H65GCKCJRKA669","replies_count":0,"reblogs_count":0,"favourites_count":0,"favourited":false,"reblogged":false,"muted":false,"bookmarked":fals…//gts.superseriousbusiness.org/fileserver/01JNN207W98SGG3CBJ76R5MVDN/header/original/019036W043D8FXPJKSKCX7G965.png","header_static":"https://gts.superseriousbusiness.org/fileserver/01JNN207W98SGG3CBJ76R5MVDN/header/small/019036W043D8FXPJKSKCX7G965.png","followers_count":33,"following_count":28,"statuses_count":126,"last_status_at":"2021-08-02T16:25:52Z","emojis":[],"fields":[]},"media_attachments":[],"mentions":[],"tags":[],"emojis":[],"card":null,"poll":null,"text":"a"}' | ||||||
|                                 type: string |                                 type: string | ||||||
|                             stream: |                             stream: | ||||||
|   | |||||||
| @@ -18,6 +18,10 @@ | |||||||
| package v1_test | package v1_test | ||||||
|  |  | ||||||
| import ( | import ( | ||||||
|  | 	"context" | ||||||
|  | 	"testing" | ||||||
|  | 	"time" | ||||||
|  |  | ||||||
| 	"github.com/stretchr/testify/suite" | 	"github.com/stretchr/testify/suite" | ||||||
| 	filtersV1 "github.com/superseriousbusiness/gotosocial/internal/api/client/filters/v1" | 	filtersV1 "github.com/superseriousbusiness/gotosocial/internal/api/client/filters/v1" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/config" | 	"github.com/superseriousbusiness/gotosocial/internal/config" | ||||||
| @@ -30,9 +34,9 @@ import ( | |||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/processing" | 	"github.com/superseriousbusiness/gotosocial/internal/processing" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/state" | 	"github.com/superseriousbusiness/gotosocial/internal/state" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/storage" | 	"github.com/superseriousbusiness/gotosocial/internal/storage" | ||||||
|  | 	"github.com/superseriousbusiness/gotosocial/internal/stream" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/typeutils" | 	"github.com/superseriousbusiness/gotosocial/internal/typeutils" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/testrig" | 	"github.com/superseriousbusiness/gotosocial/testrig" | ||||||
| 	"testing" |  | ||||||
| ) | ) | ||||||
|  |  | ||||||
| type FiltersTestSuite struct { | type FiltersTestSuite struct { | ||||||
| @@ -112,6 +116,44 @@ func (suite *FiltersTestSuite) TearDownTest() { | |||||||
| 	testrig.StopWorkers(&suite.state) | 	testrig.StopWorkers(&suite.state) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func (suite *FiltersTestSuite) openHomeStream(account *gtsmodel.Account) *stream.Stream { | ||||||
|  | 	stream, err := suite.processor.Stream().Open(context.Background(), account, stream.TimelineHome) | ||||||
|  | 	if err != nil { | ||||||
|  | 		suite.FailNow(err.Error()) | ||||||
|  | 	} | ||||||
|  | 	return stream | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (suite *FiltersTestSuite) checkStreamed( | ||||||
|  | 	str *stream.Stream, | ||||||
|  | 	expectMessage bool, | ||||||
|  | 	expectPayload string, | ||||||
|  | 	expectEventType string, | ||||||
|  | ) { | ||||||
|  | 	// Set a 5s timeout on context. | ||||||
|  | 	ctx := context.Background() | ||||||
|  | 	ctx, cncl := context.WithTimeout(ctx, time.Second*5) | ||||||
|  | 	defer cncl() | ||||||
|  |  | ||||||
|  | 	msg, ok := str.Recv(ctx) | ||||||
|  |  | ||||||
|  | 	if expectMessage && !ok { | ||||||
|  | 		suite.FailNow("expected a message but message was not received") | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if !expectMessage && ok { | ||||||
|  | 		suite.FailNow("expected no message but message was received") | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if expectPayload != "" && msg.Payload != expectPayload { | ||||||
|  | 		suite.FailNow("", "expected payload %s but payload was: %s", expectPayload, msg.Payload) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if expectEventType != "" && msg.Event != expectEventType { | ||||||
|  | 		suite.FailNow("", "expected event type %s but event type was: %s", expectEventType, msg.Event) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
| func TestFiltersTestSuite(t *testing.T) { | func TestFiltersTestSuite(t *testing.T) { | ||||||
| 	suite.Run(t, new(FiltersTestSuite)) | 	suite.Run(t, new(FiltersTestSuite)) | ||||||
| } | } | ||||||
|   | |||||||
| @@ -27,6 +27,7 @@ import ( | |||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/config" | 	"github.com/superseriousbusiness/gotosocial/internal/config" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/gtserror" | 	"github.com/superseriousbusiness/gotosocial/internal/gtserror" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/oauth" | 	"github.com/superseriousbusiness/gotosocial/internal/oauth" | ||||||
|  | 	"github.com/superseriousbusiness/gotosocial/internal/stream" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/testrig" | 	"github.com/superseriousbusiness/gotosocial/testrig" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| @@ -88,12 +89,16 @@ func (suite *FiltersTestSuite) deleteFilter( | |||||||
| } | } | ||||||
|  |  | ||||||
| func (suite *FiltersTestSuite) TestDeleteFilter() { | func (suite *FiltersTestSuite) TestDeleteFilter() { | ||||||
|  | 	homeStream := suite.openHomeStream(suite.testAccounts["local_account_1"]) | ||||||
|  |  | ||||||
| 	id := suite.testFilterKeywords["local_account_1_filter_1_keyword_1"].ID | 	id := suite.testFilterKeywords["local_account_1_filter_1_keyword_1"].ID | ||||||
|  |  | ||||||
| 	err := suite.deleteFilter(id, http.StatusOK, "") | 	err := suite.deleteFilter(id, http.StatusOK, "") | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		suite.FailNow(err.Error()) | 		suite.FailNow(err.Error()) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	suite.checkStreamed(homeStream, true, "", stream.EventTypeFiltersChanged) | ||||||
| } | } | ||||||
|  |  | ||||||
| func (suite *FiltersTestSuite) TestDeleteAnotherAccountsFilter() { | func (suite *FiltersTestSuite) TestDeleteAnotherAccountsFilter() { | ||||||
|   | |||||||
| @@ -31,6 +31,7 @@ import ( | |||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/config" | 	"github.com/superseriousbusiness/gotosocial/internal/config" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/gtserror" | 	"github.com/superseriousbusiness/gotosocial/internal/gtserror" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/oauth" | 	"github.com/superseriousbusiness/gotosocial/internal/oauth" | ||||||
|  | 	"github.com/superseriousbusiness/gotosocial/internal/stream" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/testrig" | 	"github.com/superseriousbusiness/gotosocial/testrig" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| @@ -116,6 +117,8 @@ func (suite *FiltersTestSuite) postFilter( | |||||||
| } | } | ||||||
|  |  | ||||||
| func (suite *FiltersTestSuite) TestPostFilterFull() { | func (suite *FiltersTestSuite) TestPostFilterFull() { | ||||||
|  | 	homeStream := suite.openHomeStream(suite.testAccounts["local_account_1"]) | ||||||
|  |  | ||||||
| 	phrase := "GNU/Linux" | 	phrase := "GNU/Linux" | ||||||
| 	context := []string{"home", "public"} | 	context := []string{"home", "public"} | ||||||
| 	irreversible := false | 	irreversible := false | ||||||
| @@ -137,9 +140,13 @@ func (suite *FiltersTestSuite) TestPostFilterFull() { | |||||||
| 	if suite.NotNil(filter.ExpiresAt) { | 	if suite.NotNil(filter.ExpiresAt) { | ||||||
| 		suite.NotEmpty(*filter.ExpiresAt) | 		suite.NotEmpty(*filter.ExpiresAt) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	suite.checkStreamed(homeStream, true, "", stream.EventTypeFiltersChanged) | ||||||
| } | } | ||||||
|  |  | ||||||
| func (suite *FiltersTestSuite) TestPostFilterFullJSON() { | func (suite *FiltersTestSuite) TestPostFilterFullJSON() { | ||||||
|  | 	homeStream := suite.openHomeStream(suite.testAccounts["local_account_1"]) | ||||||
|  |  | ||||||
| 	// Use a numeric literal with a fractional part to test the JSON-specific handling for non-integer "expires_in". | 	// Use a numeric literal with a fractional part to test the JSON-specific handling for non-integer "expires_in". | ||||||
| 	requestJson := `{ | 	requestJson := `{ | ||||||
| 		"phrase":"GNU/Linux", | 		"phrase":"GNU/Linux", | ||||||
| @@ -166,9 +173,13 @@ func (suite *FiltersTestSuite) TestPostFilterFullJSON() { | |||||||
| 	if suite.NotNil(filter.ExpiresAt) { | 	if suite.NotNil(filter.ExpiresAt) { | ||||||
| 		suite.NotEmpty(*filter.ExpiresAt) | 		suite.NotEmpty(*filter.ExpiresAt) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	suite.checkStreamed(homeStream, true, "", stream.EventTypeFiltersChanged) | ||||||
| } | } | ||||||
|  |  | ||||||
| func (suite *FiltersTestSuite) TestPostFilterMinimal() { | func (suite *FiltersTestSuite) TestPostFilterMinimal() { | ||||||
|  | 	homeStream := suite.openHomeStream(suite.testAccounts["local_account_1"]) | ||||||
|  |  | ||||||
| 	phrase := "GNU/Linux" | 	phrase := "GNU/Linux" | ||||||
| 	context := []string{"home"} | 	context := []string{"home"} | ||||||
| 	filter, err := suite.postFilter(&phrase, &context, nil, nil, nil, nil, http.StatusOK, "") | 	filter, err := suite.postFilter(&phrase, &context, nil, nil, nil, nil, http.StatusOK, "") | ||||||
| @@ -185,6 +196,8 @@ func (suite *FiltersTestSuite) TestPostFilterMinimal() { | |||||||
| 	suite.False(filter.Irreversible) | 	suite.False(filter.Irreversible) | ||||||
| 	suite.False(filter.WholeWord) | 	suite.False(filter.WholeWord) | ||||||
| 	suite.Nil(filter.ExpiresAt) | 	suite.Nil(filter.ExpiresAt) | ||||||
|  |  | ||||||
|  | 	suite.checkStreamed(homeStream, true, "", stream.EventTypeFiltersChanged) | ||||||
| } | } | ||||||
|  |  | ||||||
| func (suite *FiltersTestSuite) TestPostFilterEmptyPhrase() { | func (suite *FiltersTestSuite) TestPostFilterEmptyPhrase() { | ||||||
|   | |||||||
| @@ -31,6 +31,7 @@ import ( | |||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/config" | 	"github.com/superseriousbusiness/gotosocial/internal/config" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/gtserror" | 	"github.com/superseriousbusiness/gotosocial/internal/gtserror" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/oauth" | 	"github.com/superseriousbusiness/gotosocial/internal/oauth" | ||||||
|  | 	"github.com/superseriousbusiness/gotosocial/internal/stream" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/testrig" | 	"github.com/superseriousbusiness/gotosocial/testrig" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| @@ -119,6 +120,8 @@ func (suite *FiltersTestSuite) putFilter( | |||||||
| } | } | ||||||
|  |  | ||||||
| func (suite *FiltersTestSuite) TestPutFilterFull() { | func (suite *FiltersTestSuite) TestPutFilterFull() { | ||||||
|  | 	homeStream := suite.openHomeStream(suite.testAccounts["local_account_1"]) | ||||||
|  |  | ||||||
| 	id := suite.testFilterKeywords["local_account_1_filter_1_keyword_1"].ID | 	id := suite.testFilterKeywords["local_account_1_filter_1_keyword_1"].ID | ||||||
| 	phrase := "GNU/Linux" | 	phrase := "GNU/Linux" | ||||||
| 	context := []string{"home", "public"} | 	context := []string{"home", "public"} | ||||||
| @@ -141,9 +144,13 @@ func (suite *FiltersTestSuite) TestPutFilterFull() { | |||||||
| 	if suite.NotNil(filter.ExpiresAt) { | 	if suite.NotNil(filter.ExpiresAt) { | ||||||
| 		suite.NotEmpty(*filter.ExpiresAt) | 		suite.NotEmpty(*filter.ExpiresAt) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	suite.checkStreamed(homeStream, true, "", stream.EventTypeFiltersChanged) | ||||||
| } | } | ||||||
|  |  | ||||||
| func (suite *FiltersTestSuite) TestPutFilterFullJSON() { | func (suite *FiltersTestSuite) TestPutFilterFullJSON() { | ||||||
|  | 	homeStream := suite.openHomeStream(suite.testAccounts["local_account_1"]) | ||||||
|  |  | ||||||
| 	id := suite.testFilterKeywords["local_account_1_filter_1_keyword_1"].ID | 	id := suite.testFilterKeywords["local_account_1_filter_1_keyword_1"].ID | ||||||
| 	// Use a numeric literal with a fractional part to test the JSON-specific handling for non-integer "expires_in". | 	// Use a numeric literal with a fractional part to test the JSON-specific handling for non-integer "expires_in". | ||||||
| 	requestJson := `{ | 	requestJson := `{ | ||||||
| @@ -171,9 +178,13 @@ func (suite *FiltersTestSuite) TestPutFilterFullJSON() { | |||||||
| 	if suite.NotNil(filter.ExpiresAt) { | 	if suite.NotNil(filter.ExpiresAt) { | ||||||
| 		suite.NotEmpty(*filter.ExpiresAt) | 		suite.NotEmpty(*filter.ExpiresAt) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	suite.checkStreamed(homeStream, true, "", stream.EventTypeFiltersChanged) | ||||||
| } | } | ||||||
|  |  | ||||||
| func (suite *FiltersTestSuite) TestPutFilterMinimal() { | func (suite *FiltersTestSuite) TestPutFilterMinimal() { | ||||||
|  | 	homeStream := suite.openHomeStream(suite.testAccounts["local_account_1"]) | ||||||
|  |  | ||||||
| 	id := suite.testFilterKeywords["local_account_1_filter_1_keyword_1"].ID | 	id := suite.testFilterKeywords["local_account_1_filter_1_keyword_1"].ID | ||||||
| 	phrase := "GNU/Linux" | 	phrase := "GNU/Linux" | ||||||
| 	context := []string{"home"} | 	context := []string{"home"} | ||||||
| @@ -191,6 +202,8 @@ func (suite *FiltersTestSuite) TestPutFilterMinimal() { | |||||||
| 	suite.False(filter.Irreversible) | 	suite.False(filter.Irreversible) | ||||||
| 	suite.False(filter.WholeWord) | 	suite.False(filter.WholeWord) | ||||||
| 	suite.Nil(filter.ExpiresAt) | 	suite.Nil(filter.ExpiresAt) | ||||||
|  |  | ||||||
|  | 	suite.checkStreamed(homeStream, true, "", stream.EventTypeFiltersChanged) | ||||||
| } | } | ||||||
|  |  | ||||||
| func (suite *FiltersTestSuite) TestPutFilterEmptyPhrase() { | func (suite *FiltersTestSuite) TestPutFilterEmptyPhrase() { | ||||||
|   | |||||||
| @@ -18,7 +18,9 @@ | |||||||
| package v2_test | package v2_test | ||||||
|  |  | ||||||
| import ( | import ( | ||||||
|  | 	"context" | ||||||
| 	"testing" | 	"testing" | ||||||
|  | 	"time" | ||||||
|  |  | ||||||
| 	"github.com/stretchr/testify/suite" | 	"github.com/stretchr/testify/suite" | ||||||
| 	filtersV2 "github.com/superseriousbusiness/gotosocial/internal/api/client/filters/v2" | 	filtersV2 "github.com/superseriousbusiness/gotosocial/internal/api/client/filters/v2" | ||||||
| @@ -32,6 +34,7 @@ import ( | |||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/processing" | 	"github.com/superseriousbusiness/gotosocial/internal/processing" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/state" | 	"github.com/superseriousbusiness/gotosocial/internal/state" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/storage" | 	"github.com/superseriousbusiness/gotosocial/internal/storage" | ||||||
|  | 	"github.com/superseriousbusiness/gotosocial/internal/stream" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/typeutils" | 	"github.com/superseriousbusiness/gotosocial/internal/typeutils" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/testrig" | 	"github.com/superseriousbusiness/gotosocial/testrig" | ||||||
| ) | ) | ||||||
| @@ -113,6 +116,44 @@ func (suite *FiltersTestSuite) TearDownTest() { | |||||||
| 	testrig.StopWorkers(&suite.state) | 	testrig.StopWorkers(&suite.state) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func (suite *FiltersTestSuite) openHomeStream(account *gtsmodel.Account) *stream.Stream { | ||||||
|  | 	stream, err := suite.processor.Stream().Open(context.Background(), account, stream.TimelineHome) | ||||||
|  | 	if err != nil { | ||||||
|  | 		suite.FailNow(err.Error()) | ||||||
|  | 	} | ||||||
|  | 	return stream | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (suite *FiltersTestSuite) checkStreamed( | ||||||
|  | 	str *stream.Stream, | ||||||
|  | 	expectMessage bool, | ||||||
|  | 	expectPayload string, | ||||||
|  | 	expectEventType string, | ||||||
|  | ) { | ||||||
|  | 	// Set a 5s timeout on context. | ||||||
|  | 	ctx := context.Background() | ||||||
|  | 	ctx, cncl := context.WithTimeout(ctx, time.Second*5) | ||||||
|  | 	defer cncl() | ||||||
|  |  | ||||||
|  | 	msg, ok := str.Recv(ctx) | ||||||
|  |  | ||||||
|  | 	if expectMessage && !ok { | ||||||
|  | 		suite.FailNow("expected a message but message was not received") | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if !expectMessage && ok { | ||||||
|  | 		suite.FailNow("expected no message but message was received") | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if expectPayload != "" && msg.Payload != expectPayload { | ||||||
|  | 		suite.FailNow("", "expected payload %s but payload was: %s", expectPayload, msg.Payload) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if expectEventType != "" && msg.Event != expectEventType { | ||||||
|  | 		suite.FailNow("", "expected event type %s but event type was: %s", expectEventType, msg.Event) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
| func TestFiltersTestSuite(t *testing.T) { | func TestFiltersTestSuite(t *testing.T) { | ||||||
| 	suite.Run(t, new(FiltersTestSuite)) | 	suite.Run(t, new(FiltersTestSuite)) | ||||||
| } | } | ||||||
|   | |||||||
| @@ -27,6 +27,7 @@ import ( | |||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/config" | 	"github.com/superseriousbusiness/gotosocial/internal/config" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/gtserror" | 	"github.com/superseriousbusiness/gotosocial/internal/gtserror" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/oauth" | 	"github.com/superseriousbusiness/gotosocial/internal/oauth" | ||||||
|  | 	"github.com/superseriousbusiness/gotosocial/internal/stream" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/testrig" | 	"github.com/superseriousbusiness/gotosocial/testrig" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| @@ -88,12 +89,16 @@ func (suite *FiltersTestSuite) deleteFilter( | |||||||
| } | } | ||||||
|  |  | ||||||
| func (suite *FiltersTestSuite) TestDeleteFilter() { | func (suite *FiltersTestSuite) TestDeleteFilter() { | ||||||
|  | 	homeStream := suite.openHomeStream(suite.testAccounts["local_account_1"]) | ||||||
|  |  | ||||||
| 	id := suite.testFilters["local_account_1_filter_1"].ID | 	id := suite.testFilters["local_account_1_filter_1"].ID | ||||||
|  |  | ||||||
| 	err := suite.deleteFilter(id, http.StatusOK, "") | 	err := suite.deleteFilter(id, http.StatusOK, "") | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		suite.FailNow(err.Error()) | 		suite.FailNow(err.Error()) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	suite.checkStreamed(homeStream, true, "", stream.EventTypeFiltersChanged) | ||||||
| } | } | ||||||
|  |  | ||||||
| func (suite *FiltersTestSuite) TestDeleteAnotherAccountsFilter() { | func (suite *FiltersTestSuite) TestDeleteAnotherAccountsFilter() { | ||||||
|   | |||||||
| @@ -27,6 +27,7 @@ import ( | |||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/config" | 	"github.com/superseriousbusiness/gotosocial/internal/config" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/gtserror" | 	"github.com/superseriousbusiness/gotosocial/internal/gtserror" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/oauth" | 	"github.com/superseriousbusiness/gotosocial/internal/oauth" | ||||||
|  | 	"github.com/superseriousbusiness/gotosocial/internal/stream" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/testrig" | 	"github.com/superseriousbusiness/gotosocial/testrig" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| @@ -88,12 +89,16 @@ func (suite *FiltersTestSuite) deleteFilterKeyword( | |||||||
| } | } | ||||||
|  |  | ||||||
| func (suite *FiltersTestSuite) TestDeleteFilterKeyword() { | func (suite *FiltersTestSuite) TestDeleteFilterKeyword() { | ||||||
|  | 	homeStream := suite.openHomeStream(suite.testAccounts["local_account_1"]) | ||||||
|  |  | ||||||
| 	id := suite.testFilterKeywords["local_account_1_filter_1_keyword_1"].ID | 	id := suite.testFilterKeywords["local_account_1_filter_1_keyword_1"].ID | ||||||
|  |  | ||||||
| 	err := suite.deleteFilterKeyword(id, http.StatusOK, "") | 	err := suite.deleteFilterKeyword(id, http.StatusOK, "") | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		suite.FailNow(err.Error()) | 		suite.FailNow(err.Error()) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	suite.checkStreamed(homeStream, true, "", stream.EventTypeFiltersChanged) | ||||||
| } | } | ||||||
|  |  | ||||||
| func (suite *FiltersTestSuite) TestDeleteAnotherAccountsFilterKeyword() { | func (suite *FiltersTestSuite) TestDeleteAnotherAccountsFilterKeyword() { | ||||||
|   | |||||||
| @@ -31,6 +31,7 @@ import ( | |||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/config" | 	"github.com/superseriousbusiness/gotosocial/internal/config" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/gtserror" | 	"github.com/superseriousbusiness/gotosocial/internal/gtserror" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/oauth" | 	"github.com/superseriousbusiness/gotosocial/internal/oauth" | ||||||
|  | 	"github.com/superseriousbusiness/gotosocial/internal/stream" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/testrig" | 	"github.com/superseriousbusiness/gotosocial/testrig" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| @@ -107,6 +108,8 @@ func (suite *FiltersTestSuite) postFilterKeyword( | |||||||
| } | } | ||||||
|  |  | ||||||
| func (suite *FiltersTestSuite) TestPostFilterKeywordFull() { | func (suite *FiltersTestSuite) TestPostFilterKeywordFull() { | ||||||
|  | 	homeStream := suite.openHomeStream(suite.testAccounts["local_account_1"]) | ||||||
|  |  | ||||||
| 	filterID := suite.testFilters["local_account_1_filter_1"].ID | 	filterID := suite.testFilters["local_account_1_filter_1"].ID | ||||||
| 	keyword := "fnords" | 	keyword := "fnords" | ||||||
| 	wholeWord := true | 	wholeWord := true | ||||||
| @@ -117,9 +120,13 @@ func (suite *FiltersTestSuite) TestPostFilterKeywordFull() { | |||||||
|  |  | ||||||
| 	suite.Equal(keyword, filterKeyword.Keyword) | 	suite.Equal(keyword, filterKeyword.Keyword) | ||||||
| 	suite.Equal(wholeWord, filterKeyword.WholeWord) | 	suite.Equal(wholeWord, filterKeyword.WholeWord) | ||||||
|  |  | ||||||
|  | 	suite.checkStreamed(homeStream, true, "", stream.EventTypeFiltersChanged) | ||||||
| } | } | ||||||
|  |  | ||||||
| func (suite *FiltersTestSuite) TestPostFilterKeywordFullJSON() { | func (suite *FiltersTestSuite) TestPostFilterKeywordFullJSON() { | ||||||
|  | 	homeStream := suite.openHomeStream(suite.testAccounts["local_account_1"]) | ||||||
|  |  | ||||||
| 	filterID := suite.testFilters["local_account_1_filter_1"].ID | 	filterID := suite.testFilters["local_account_1_filter_1"].ID | ||||||
| 	requestJson := `{ | 	requestJson := `{ | ||||||
| 		"keyword": "fnords", | 		"keyword": "fnords", | ||||||
| @@ -132,9 +139,13 @@ func (suite *FiltersTestSuite) TestPostFilterKeywordFullJSON() { | |||||||
|  |  | ||||||
| 	suite.Equal("fnords", filterKeyword.Keyword) | 	suite.Equal("fnords", filterKeyword.Keyword) | ||||||
| 	suite.True(filterKeyword.WholeWord) | 	suite.True(filterKeyword.WholeWord) | ||||||
|  |  | ||||||
|  | 	suite.checkStreamed(homeStream, true, "", stream.EventTypeFiltersChanged) | ||||||
| } | } | ||||||
|  |  | ||||||
| func (suite *FiltersTestSuite) TestPostFilterKeywordMinimal() { | func (suite *FiltersTestSuite) TestPostFilterKeywordMinimal() { | ||||||
|  | 	homeStream := suite.openHomeStream(suite.testAccounts["local_account_1"]) | ||||||
|  |  | ||||||
| 	filterID := suite.testFilters["local_account_1_filter_1"].ID | 	filterID := suite.testFilters["local_account_1_filter_1"].ID | ||||||
| 	keyword := "fnords" | 	keyword := "fnords" | ||||||
| 	filterKeyword, err := suite.postFilterKeyword(filterID, &keyword, nil, nil, http.StatusOK, "") | 	filterKeyword, err := suite.postFilterKeyword(filterID, &keyword, nil, nil, http.StatusOK, "") | ||||||
| @@ -144,6 +155,8 @@ func (suite *FiltersTestSuite) TestPostFilterKeywordMinimal() { | |||||||
|  |  | ||||||
| 	suite.Equal(keyword, filterKeyword.Keyword) | 	suite.Equal(keyword, filterKeyword.Keyword) | ||||||
| 	suite.False(filterKeyword.WholeWord) | 	suite.False(filterKeyword.WholeWord) | ||||||
|  |  | ||||||
|  | 	suite.checkStreamed(homeStream, true, "", stream.EventTypeFiltersChanged) | ||||||
| } | } | ||||||
|  |  | ||||||
| func (suite *FiltersTestSuite) TestPostFilterKeywordEmptyKeyword() { | func (suite *FiltersTestSuite) TestPostFilterKeywordEmptyKeyword() { | ||||||
|   | |||||||
| @@ -31,6 +31,7 @@ import ( | |||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/config" | 	"github.com/superseriousbusiness/gotosocial/internal/config" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/gtserror" | 	"github.com/superseriousbusiness/gotosocial/internal/gtserror" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/oauth" | 	"github.com/superseriousbusiness/gotosocial/internal/oauth" | ||||||
|  | 	"github.com/superseriousbusiness/gotosocial/internal/stream" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/testrig" | 	"github.com/superseriousbusiness/gotosocial/testrig" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| @@ -107,6 +108,8 @@ func (suite *FiltersTestSuite) putFilterKeyword( | |||||||
| } | } | ||||||
|  |  | ||||||
| func (suite *FiltersTestSuite) TestPutFilterKeywordFull() { | func (suite *FiltersTestSuite) TestPutFilterKeywordFull() { | ||||||
|  | 	homeStream := suite.openHomeStream(suite.testAccounts["local_account_1"]) | ||||||
|  |  | ||||||
| 	filterKeywordID := suite.testFilterKeywords["local_account_1_filter_1_keyword_1"].ID | 	filterKeywordID := suite.testFilterKeywords["local_account_1_filter_1_keyword_1"].ID | ||||||
| 	keyword := "fnords" | 	keyword := "fnords" | ||||||
| 	wholeWord := true | 	wholeWord := true | ||||||
| @@ -117,9 +120,13 @@ func (suite *FiltersTestSuite) TestPutFilterKeywordFull() { | |||||||
|  |  | ||||||
| 	suite.Equal(keyword, filterKeyword.Keyword) | 	suite.Equal(keyword, filterKeyword.Keyword) | ||||||
| 	suite.Equal(wholeWord, filterKeyword.WholeWord) | 	suite.Equal(wholeWord, filterKeyword.WholeWord) | ||||||
|  |  | ||||||
|  | 	suite.checkStreamed(homeStream, true, "", stream.EventTypeFiltersChanged) | ||||||
| } | } | ||||||
|  |  | ||||||
| func (suite *FiltersTestSuite) TestPutFilterKeywordFullJSON() { | func (suite *FiltersTestSuite) TestPutFilterKeywordFullJSON() { | ||||||
|  | 	homeStream := suite.openHomeStream(suite.testAccounts["local_account_1"]) | ||||||
|  |  | ||||||
| 	filterKeywordID := suite.testFilterKeywords["local_account_1_filter_1_keyword_1"].ID | 	filterKeywordID := suite.testFilterKeywords["local_account_1_filter_1_keyword_1"].ID | ||||||
| 	requestJson := `{ | 	requestJson := `{ | ||||||
| 		"keyword": "fnords", | 		"keyword": "fnords", | ||||||
| @@ -132,9 +139,13 @@ func (suite *FiltersTestSuite) TestPutFilterKeywordFullJSON() { | |||||||
|  |  | ||||||
| 	suite.Equal("fnords", filterKeyword.Keyword) | 	suite.Equal("fnords", filterKeyword.Keyword) | ||||||
| 	suite.True(filterKeyword.WholeWord) | 	suite.True(filterKeyword.WholeWord) | ||||||
|  |  | ||||||
|  | 	suite.checkStreamed(homeStream, true, "", stream.EventTypeFiltersChanged) | ||||||
| } | } | ||||||
|  |  | ||||||
| func (suite *FiltersTestSuite) TestPutFilterKeywordMinimal() { | func (suite *FiltersTestSuite) TestPutFilterKeywordMinimal() { | ||||||
|  | 	homeStream := suite.openHomeStream(suite.testAccounts["local_account_1"]) | ||||||
|  |  | ||||||
| 	filterKeywordID := suite.testFilterKeywords["local_account_1_filter_1_keyword_1"].ID | 	filterKeywordID := suite.testFilterKeywords["local_account_1_filter_1_keyword_1"].ID | ||||||
| 	keyword := "fnords" | 	keyword := "fnords" | ||||||
| 	filterKeyword, err := suite.putFilterKeyword(filterKeywordID, &keyword, nil, nil, http.StatusOK, "") | 	filterKeyword, err := suite.putFilterKeyword(filterKeywordID, &keyword, nil, nil, http.StatusOK, "") | ||||||
| @@ -144,6 +155,8 @@ func (suite *FiltersTestSuite) TestPutFilterKeywordMinimal() { | |||||||
|  |  | ||||||
| 	suite.Equal(keyword, filterKeyword.Keyword) | 	suite.Equal(keyword, filterKeyword.Keyword) | ||||||
| 	suite.False(filterKeyword.WholeWord) | 	suite.False(filterKeyword.WholeWord) | ||||||
|  |  | ||||||
|  | 	suite.checkStreamed(homeStream, true, "", stream.EventTypeFiltersChanged) | ||||||
| } | } | ||||||
|  |  | ||||||
| func (suite *FiltersTestSuite) TestPutFilterKeywordEmptyKeyword() { | func (suite *FiltersTestSuite) TestPutFilterKeywordEmptyKeyword() { | ||||||
|   | |||||||
| @@ -31,6 +31,7 @@ import ( | |||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/config" | 	"github.com/superseriousbusiness/gotosocial/internal/config" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/gtserror" | 	"github.com/superseriousbusiness/gotosocial/internal/gtserror" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/oauth" | 	"github.com/superseriousbusiness/gotosocial/internal/oauth" | ||||||
|  | 	"github.com/superseriousbusiness/gotosocial/internal/stream" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/testrig" | 	"github.com/superseriousbusiness/gotosocial/testrig" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| @@ -104,6 +105,8 @@ func (suite *FiltersTestSuite) postFilter(title *string, context *[]string, acti | |||||||
| } | } | ||||||
|  |  | ||||||
| func (suite *FiltersTestSuite) TestPostFilterFull() { | func (suite *FiltersTestSuite) TestPostFilterFull() { | ||||||
|  | 	homeStream := suite.openHomeStream(suite.testAccounts["local_account_1"]) | ||||||
|  |  | ||||||
| 	title := "GNU/Linux" | 	title := "GNU/Linux" | ||||||
| 	context := []string{"home", "public"} | 	context := []string{"home", "public"} | ||||||
| 	action := "warn" | 	action := "warn" | ||||||
| @@ -125,9 +128,13 @@ func (suite *FiltersTestSuite) TestPostFilterFull() { | |||||||
| 	} | 	} | ||||||
| 	suite.Empty(filter.Keywords) | 	suite.Empty(filter.Keywords) | ||||||
| 	suite.Empty(filter.Statuses) | 	suite.Empty(filter.Statuses) | ||||||
|  |  | ||||||
|  | 	suite.checkStreamed(homeStream, true, "", stream.EventTypeFiltersChanged) | ||||||
| } | } | ||||||
|  |  | ||||||
| func (suite *FiltersTestSuite) TestPostFilterFullJSON() { | func (suite *FiltersTestSuite) TestPostFilterFullJSON() { | ||||||
|  | 	homeStream := suite.openHomeStream(suite.testAccounts["local_account_1"]) | ||||||
|  |  | ||||||
| 	// Use a numeric literal with a fractional part to test the JSON-specific handling for non-integer "expires_in". | 	// Use a numeric literal with a fractional part to test the JSON-specific handling for non-integer "expires_in". | ||||||
| 	requestJson := `{ | 	requestJson := `{ | ||||||
| 		"title": "GNU/Linux", | 		"title": "GNU/Linux", | ||||||
| @@ -155,9 +162,13 @@ func (suite *FiltersTestSuite) TestPostFilterFullJSON() { | |||||||
| 	} | 	} | ||||||
| 	suite.Empty(filter.Keywords) | 	suite.Empty(filter.Keywords) | ||||||
| 	suite.Empty(filter.Statuses) | 	suite.Empty(filter.Statuses) | ||||||
|  |  | ||||||
|  | 	suite.checkStreamed(homeStream, true, "", stream.EventTypeFiltersChanged) | ||||||
| } | } | ||||||
|  |  | ||||||
| func (suite *FiltersTestSuite) TestPostFilterMinimal() { | func (suite *FiltersTestSuite) TestPostFilterMinimal() { | ||||||
|  | 	homeStream := suite.openHomeStream(suite.testAccounts["local_account_1"]) | ||||||
|  |  | ||||||
| 	title := "GNU/Linux" | 	title := "GNU/Linux" | ||||||
| 	context := []string{"home"} | 	context := []string{"home"} | ||||||
| 	filter, err := suite.postFilter(&title, &context, nil, nil, nil, http.StatusOK, "") | 	filter, err := suite.postFilter(&title, &context, nil, nil, nil, http.StatusOK, "") | ||||||
| @@ -175,6 +186,8 @@ func (suite *FiltersTestSuite) TestPostFilterMinimal() { | |||||||
| 	suite.Nil(filter.ExpiresAt) | 	suite.Nil(filter.ExpiresAt) | ||||||
| 	suite.Empty(filter.Keywords) | 	suite.Empty(filter.Keywords) | ||||||
| 	suite.Empty(filter.Statuses) | 	suite.Empty(filter.Statuses) | ||||||
|  |  | ||||||
|  | 	suite.checkStreamed(homeStream, true, "", stream.EventTypeFiltersChanged) | ||||||
| } | } | ||||||
|  |  | ||||||
| func (suite *FiltersTestSuite) TestPostFilterEmptyTitle() { | func (suite *FiltersTestSuite) TestPostFilterEmptyTitle() { | ||||||
|   | |||||||
| @@ -31,6 +31,7 @@ import ( | |||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/config" | 	"github.com/superseriousbusiness/gotosocial/internal/config" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/gtserror" | 	"github.com/superseriousbusiness/gotosocial/internal/gtserror" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/oauth" | 	"github.com/superseriousbusiness/gotosocial/internal/oauth" | ||||||
|  | 	"github.com/superseriousbusiness/gotosocial/internal/stream" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/testrig" | 	"github.com/superseriousbusiness/gotosocial/testrig" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| @@ -106,6 +107,8 @@ func (suite *FiltersTestSuite) putFilter(filterID string, title *string, context | |||||||
| } | } | ||||||
|  |  | ||||||
| func (suite *FiltersTestSuite) TestPutFilterFull() { | func (suite *FiltersTestSuite) TestPutFilterFull() { | ||||||
|  | 	homeStream := suite.openHomeStream(suite.testAccounts["local_account_1"]) | ||||||
|  |  | ||||||
| 	id := suite.testFilters["local_account_1_filter_2"].ID | 	id := suite.testFilters["local_account_1_filter_2"].ID | ||||||
| 	title := "messy synoptic varblabbles" | 	title := "messy synoptic varblabbles" | ||||||
| 	context := []string{"home", "public"} | 	context := []string{"home", "public"} | ||||||
| @@ -128,9 +131,13 @@ func (suite *FiltersTestSuite) TestPutFilterFull() { | |||||||
| 	} | 	} | ||||||
| 	suite.Len(filter.Keywords, 3) | 	suite.Len(filter.Keywords, 3) | ||||||
| 	suite.Len(filter.Statuses, 0) | 	suite.Len(filter.Statuses, 0) | ||||||
|  |  | ||||||
|  | 	suite.checkStreamed(homeStream, true, "", stream.EventTypeFiltersChanged) | ||||||
| } | } | ||||||
|  |  | ||||||
| func (suite *FiltersTestSuite) TestPutFilterFullJSON() { | func (suite *FiltersTestSuite) TestPutFilterFullJSON() { | ||||||
|  | 	homeStream := suite.openHomeStream(suite.testAccounts["local_account_1"]) | ||||||
|  |  | ||||||
| 	id := suite.testFilters["local_account_1_filter_2"].ID | 	id := suite.testFilters["local_account_1_filter_2"].ID | ||||||
| 	// Use a numeric literal with a fractional part to test the JSON-specific handling for non-integer "expires_in". | 	// Use a numeric literal with a fractional part to test the JSON-specific handling for non-integer "expires_in". | ||||||
| 	requestJson := `{ | 	requestJson := `{ | ||||||
| @@ -158,9 +165,13 @@ func (suite *FiltersTestSuite) TestPutFilterFullJSON() { | |||||||
| 	} | 	} | ||||||
| 	suite.Len(filter.Keywords, 3) | 	suite.Len(filter.Keywords, 3) | ||||||
| 	suite.Len(filter.Statuses, 0) | 	suite.Len(filter.Statuses, 0) | ||||||
|  |  | ||||||
|  | 	suite.checkStreamed(homeStream, true, "", stream.EventTypeFiltersChanged) | ||||||
| } | } | ||||||
|  |  | ||||||
| func (suite *FiltersTestSuite) TestPutFilterMinimal() { | func (suite *FiltersTestSuite) TestPutFilterMinimal() { | ||||||
|  | 	homeStream := suite.openHomeStream(suite.testAccounts["local_account_1"]) | ||||||
|  |  | ||||||
| 	id := suite.testFilters["local_account_1_filter_1"].ID | 	id := suite.testFilters["local_account_1_filter_1"].ID | ||||||
| 	title := "GNU/Linux" | 	title := "GNU/Linux" | ||||||
| 	context := []string{"home"} | 	context := []string{"home"} | ||||||
| @@ -177,6 +188,8 @@ func (suite *FiltersTestSuite) TestPutFilterMinimal() { | |||||||
| 	suite.ElementsMatch(context, filterContext) | 	suite.ElementsMatch(context, filterContext) | ||||||
| 	suite.Equal(apimodel.FilterActionWarn, filter.FilterAction) | 	suite.Equal(apimodel.FilterActionWarn, filter.FilterAction) | ||||||
| 	suite.Nil(filter.ExpiresAt) | 	suite.Nil(filter.ExpiresAt) | ||||||
|  |  | ||||||
|  | 	suite.checkStreamed(homeStream, true, "", stream.EventTypeFiltersChanged) | ||||||
| } | } | ||||||
|  |  | ||||||
| func (suite *FiltersTestSuite) TestPutFilterEmptyTitle() { | func (suite *FiltersTestSuite) TestPutFilterEmptyTitle() { | ||||||
|   | |||||||
| @@ -27,6 +27,7 @@ import ( | |||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/config" | 	"github.com/superseriousbusiness/gotosocial/internal/config" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/gtserror" | 	"github.com/superseriousbusiness/gotosocial/internal/gtserror" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/oauth" | 	"github.com/superseriousbusiness/gotosocial/internal/oauth" | ||||||
|  | 	"github.com/superseriousbusiness/gotosocial/internal/stream" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/testrig" | 	"github.com/superseriousbusiness/gotosocial/testrig" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| @@ -50,7 +51,7 @@ func (suite *FiltersTestSuite) deleteFilterStatus( | |||||||
| 	ctx.AddParam("id", filterStatusID) | 	ctx.AddParam("id", filterStatusID) | ||||||
|  |  | ||||||
| 	// trigger the handler | 	// trigger the handler | ||||||
| 	suite.filtersModule.FilterDELETEHandler(ctx) | 	suite.filtersModule.FilterStatusDELETEHandler(ctx) | ||||||
|  |  | ||||||
| 	// read the response | 	// read the response | ||||||
| 	result := recorder.Result() | 	result := recorder.Result() | ||||||
| @@ -85,12 +86,16 @@ func (suite *FiltersTestSuite) deleteFilterStatus( | |||||||
| } | } | ||||||
|  |  | ||||||
| func (suite *FiltersTestSuite) TestDeleteFilterStatus() { | func (suite *FiltersTestSuite) TestDeleteFilterStatus() { | ||||||
|  | 	homeStream := suite.openHomeStream(suite.testAccounts["local_account_1"]) | ||||||
|  |  | ||||||
| 	id := suite.testFilterStatuses["local_account_1_filter_3_status_1"].ID | 	id := suite.testFilterStatuses["local_account_1_filter_3_status_1"].ID | ||||||
|  |  | ||||||
| 	err := suite.deleteFilterStatus(id, http.StatusOK, "") | 	err := suite.deleteFilterStatus(id, http.StatusOK, "") | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		suite.FailNow(err.Error()) | 		suite.FailNow(err.Error()) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	suite.checkStreamed(homeStream, true, "", stream.EventTypeFiltersChanged) | ||||||
| } | } | ||||||
|  |  | ||||||
| func (suite *FiltersTestSuite) TestDeleteAnotherAccountsFilterStatus() { | func (suite *FiltersTestSuite) TestDeleteAnotherAccountsFilterStatus() { | ||||||
|   | |||||||
| @@ -30,6 +30,7 @@ import ( | |||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/config" | 	"github.com/superseriousbusiness/gotosocial/internal/config" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/gtserror" | 	"github.com/superseriousbusiness/gotosocial/internal/gtserror" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/oauth" | 	"github.com/superseriousbusiness/gotosocial/internal/oauth" | ||||||
|  | 	"github.com/superseriousbusiness/gotosocial/internal/stream" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/testrig" | 	"github.com/superseriousbusiness/gotosocial/testrig" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| @@ -102,6 +103,8 @@ func (suite *FiltersTestSuite) postFilterStatus( | |||||||
| } | } | ||||||
|  |  | ||||||
| func (suite *FiltersTestSuite) TestPostFilterStatus() { | func (suite *FiltersTestSuite) TestPostFilterStatus() { | ||||||
|  | 	homeStream := suite.openHomeStream(suite.testAccounts["local_account_1"]) | ||||||
|  |  | ||||||
| 	filterID := suite.testFilters["local_account_1_filter_1"].ID | 	filterID := suite.testFilters["local_account_1_filter_1"].ID | ||||||
| 	statusID := suite.testStatuses["admin_account_status_1"].ID | 	statusID := suite.testStatuses["admin_account_status_1"].ID | ||||||
| 	filterStatus, err := suite.postFilterStatus(filterID, &statusID, nil, http.StatusOK, "") | 	filterStatus, err := suite.postFilterStatus(filterID, &statusID, nil, http.StatusOK, "") | ||||||
| @@ -110,9 +113,13 @@ func (suite *FiltersTestSuite) TestPostFilterStatus() { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	suite.Equal(statusID, filterStatus.StatusID) | 	suite.Equal(statusID, filterStatus.StatusID) | ||||||
|  |  | ||||||
|  | 	suite.checkStreamed(homeStream, true, "", stream.EventTypeFiltersChanged) | ||||||
| } | } | ||||||
|  |  | ||||||
| func (suite *FiltersTestSuite) TestPostFilterStatusJSON() { | func (suite *FiltersTestSuite) TestPostFilterStatusJSON() { | ||||||
|  | 	homeStream := suite.openHomeStream(suite.testAccounts["local_account_1"]) | ||||||
|  |  | ||||||
| 	filterID := suite.testFilters["local_account_1_filter_1"].ID | 	filterID := suite.testFilters["local_account_1_filter_1"].ID | ||||||
| 	requestJson := `{ | 	requestJson := `{ | ||||||
| 		"status_id": "01F8MH75CBF9JFX4ZAD54N0W0R" | 		"status_id": "01F8MH75CBF9JFX4ZAD54N0W0R" | ||||||
| @@ -123,6 +130,8 @@ func (suite *FiltersTestSuite) TestPostFilterStatusJSON() { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	suite.Equal(suite.testStatuses["admin_account_status_1"].ID, filterStatus.StatusID) | 	suite.Equal(suite.testStatuses["admin_account_status_1"].ID, filterStatus.StatusID) | ||||||
|  |  | ||||||
|  | 	suite.checkStreamed(homeStream, true, "", stream.EventTypeFiltersChanged) | ||||||
| } | } | ||||||
|  |  | ||||||
| func (suite *FiltersTestSuite) TestPostFilterStatusEmptyStatusID() { | func (suite *FiltersTestSuite) TestPostFilterStatusEmptyStatusID() { | ||||||
|   | |||||||
| @@ -125,7 +125,7 @@ import ( | |||||||
| //							`update`: a new status has been received. | //							`update`: a new status has been received. | ||||||
| //							`notification`: a new notification has been received. | //							`notification`: a new notification has been received. | ||||||
| //							`delete`: a status has been deleted. | //							`delete`: a status has been deleted. | ||||||
| //							`filters_changed`: not implemented. | //							`filters_changed`: filters (including keywords and statuses) have changed. | ||||||
| //						type: string | //						type: string | ||||||
| //						enum: | //						enum: | ||||||
| //						- update | //						- update | ||||||
| @@ -142,6 +142,7 @@ import ( | |||||||
| //							If `event` = `update`, then the payload will be a JSON string of a status. | //							If `event` = `update`, then the payload will be a JSON string of a status. | ||||||
| //							If `event` = `notification`, then the payload will be a JSON string of a notification. | //							If `event` = `notification`, then the payload will be a JSON string of a notification. | ||||||
| //							If `event` = `delete`, then the payload will be a status ID. | //							If `event` = `delete`, then the payload will be a status ID. | ||||||
|  | //							If `event` = `filters_changed`, then there is no payload. | ||||||
| //						type: string | //						type: string | ||||||
| //						example: "{\"id\":\"01FC3TZ5CFG6H65GCKCJRKA669\",\"created_at\":\"2021-08-02T16:25:52Z\",\"sensitive\":false,\"spoiler_text\":\"\",\"visibility\":\"public\",\"language\":\"en\",\"uri\":\"https://gts.superseriousbusiness.org/users/dumpsterqueer/statuses/01FC3TZ5CFG6H65GCKCJRKA669\",\"url\":\"https://gts.superseriousbusiness.org/@dumpsterqueer/statuses/01FC3TZ5CFG6H65GCKCJRKA669\",\"replies_count\":0,\"reblogs_count\":0,\"favourites_count\":0,\"favourited\":false,\"reblogged\":false,\"muted\":false,\"bookmarked\":fals…//gts.superseriousbusiness.org/fileserver/01JNN207W98SGG3CBJ76R5MVDN/header/original/019036W043D8FXPJKSKCX7G965.png\",\"header_static\":\"https://gts.superseriousbusiness.org/fileserver/01JNN207W98SGG3CBJ76R5MVDN/header/small/019036W043D8FXPJKSKCX7G965.png\",\"followers_count\":33,\"following_count\":28,\"statuses_count\":126,\"last_status_at\":\"2021-08-02T16:25:52Z\",\"emojis\":[],\"fields\":[]},\"media_attachments\":[],\"mentions\":[],\"tags\":[],\"emojis\":[],\"card\":null,\"poll\":null,\"text\":\"a\"}" | //						example: "{\"id\":\"01FC3TZ5CFG6H65GCKCJRKA669\",\"created_at\":\"2021-08-02T16:25:52Z\",\"sensitive\":false,\"spoiler_text\":\"\",\"visibility\":\"public\",\"language\":\"en\",\"uri\":\"https://gts.superseriousbusiness.org/users/dumpsterqueer/statuses/01FC3TZ5CFG6H65GCKCJRKA669\",\"url\":\"https://gts.superseriousbusiness.org/@dumpsterqueer/statuses/01FC3TZ5CFG6H65GCKCJRKA669\",\"replies_count\":0,\"reblogs_count\":0,\"favourites_count\":0,\"favourited\":false,\"reblogged\":false,\"muted\":false,\"bookmarked\":fals…//gts.superseriousbusiness.org/fileserver/01JNN207W98SGG3CBJ76R5MVDN/header/original/019036W043D8FXPJKSKCX7G965.png\",\"header_static\":\"https://gts.superseriousbusiness.org/fileserver/01JNN207W98SGG3CBJ76R5MVDN/header/small/019036W043D8FXPJKSKCX7G965.png\",\"followers_count\":33,\"following_count\":28,\"statuses_count\":126,\"last_status_at\":\"2021-08-02T16:25:52Z\",\"emojis\":[],\"fields\":[]},\"media_attachments\":[],\"mentions\":[],\"tags\":[],\"emojis\":[],\"card\":null,\"poll\":null,\"text\":\"a\"}" | ||||||
| //		'401': | //		'401': | ||||||
|   | |||||||
| @@ -83,5 +83,13 @@ func (p *Processor) Create(ctx context.Context, account *gtsmodel.Account, form | |||||||
| 		return nil, gtserror.NewErrorInternalError(err) | 		return nil, gtserror.NewErrorInternalError(err) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return p.apiFilter(ctx, filterKeyword) | 	apiFilter, errWithCode := p.apiFilter(ctx, filterKeyword) | ||||||
|  | 	if errWithCode != nil { | ||||||
|  | 		return nil, errWithCode | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// Send a filters changed event. | ||||||
|  | 	p.stream.FiltersChanged(ctx, account) | ||||||
|  |  | ||||||
|  | 	return apiFilter, nil | ||||||
| } | } | ||||||
|   | |||||||
| @@ -63,5 +63,8 @@ func (p *Processor) Delete( | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	// Send a filters changed event. | ||||||
|  | 	p.stream.FiltersChanged(ctx, account) | ||||||
|  |  | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|   | |||||||
| @@ -18,6 +18,7 @@ | |||||||
| package v1 | package v1 | ||||||
|  |  | ||||||
| import ( | import ( | ||||||
|  | 	"github.com/superseriousbusiness/gotosocial/internal/processing/stream" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/state" | 	"github.com/superseriousbusiness/gotosocial/internal/state" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/typeutils" | 	"github.com/superseriousbusiness/gotosocial/internal/typeutils" | ||||||
| ) | ) | ||||||
| @@ -25,11 +26,13 @@ import ( | |||||||
| type Processor struct { | type Processor struct { | ||||||
| 	state     *state.State | 	state     *state.State | ||||||
| 	converter *typeutils.Converter | 	converter *typeutils.Converter | ||||||
|  | 	stream    *stream.Processor | ||||||
| } | } | ||||||
|  |  | ||||||
| func New(state *state.State, converter *typeutils.Converter) Processor { | func New(state *state.State, converter *typeutils.Converter, stream *stream.Processor) Processor { | ||||||
| 	return Processor{ | 	return Processor{ | ||||||
| 		state:     state, | 		state:     state, | ||||||
| 		converter: converter, | 		converter: converter, | ||||||
|  | 		stream:    stream, | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|   | |||||||
| @@ -163,5 +163,13 @@ func (p *Processor) Update( | |||||||
| 		return nil, gtserror.NewErrorInternalError(err) | 		return nil, gtserror.NewErrorInternalError(err) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return p.apiFilter(ctx, filterKeyword) | 	apiFilter, errWithCode := p.apiFilter(ctx, filterKeyword) | ||||||
|  | 	if errWithCode != nil { | ||||||
|  | 		return nil, errWithCode | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// Send a filters changed event. | ||||||
|  | 	p.stream.FiltersChanged(ctx, account) | ||||||
|  |  | ||||||
|  | 	return apiFilter, nil | ||||||
| } | } | ||||||
|   | |||||||
| @@ -71,5 +71,13 @@ func (p *Processor) Create(ctx context.Context, account *gtsmodel.Account, form | |||||||
| 		return nil, gtserror.NewErrorInternalError(err) | 		return nil, gtserror.NewErrorInternalError(err) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return p.apiFilter(ctx, filter) | 	apiFilter, errWithCode := p.apiFilter(ctx, filter) | ||||||
|  | 	if errWithCode != nil { | ||||||
|  | 		return nil, errWithCode | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// Send a filters changed event. | ||||||
|  | 	p.stream.FiltersChanged(ctx, account) | ||||||
|  |  | ||||||
|  | 	return apiFilter, nil | ||||||
| } | } | ||||||
|   | |||||||
| @@ -49,5 +49,8 @@ func (p *Processor) Delete( | |||||||
| 		return gtserror.NewErrorInternalError(err) | 		return gtserror.NewErrorInternalError(err) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	// Send a filters changed event. | ||||||
|  | 	p.stream.FiltersChanged(ctx, account) | ||||||
|  |  | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|   | |||||||
| @@ -18,6 +18,7 @@ | |||||||
| package v2 | package v2 | ||||||
|  |  | ||||||
| import ( | import ( | ||||||
|  | 	"github.com/superseriousbusiness/gotosocial/internal/processing/stream" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/state" | 	"github.com/superseriousbusiness/gotosocial/internal/state" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/typeutils" | 	"github.com/superseriousbusiness/gotosocial/internal/typeutils" | ||||||
| ) | ) | ||||||
| @@ -25,11 +26,13 @@ import ( | |||||||
| type Processor struct { | type Processor struct { | ||||||
| 	state     *state.State | 	state     *state.State | ||||||
| 	converter *typeutils.Converter | 	converter *typeutils.Converter | ||||||
|  | 	stream    *stream.Processor | ||||||
| } | } | ||||||
|  |  | ||||||
| func New(state *state.State, converter *typeutils.Converter) Processor { | func New(state *state.State, converter *typeutils.Converter, stream *stream.Processor) Processor { | ||||||
| 	return Processor{ | 	return Processor{ | ||||||
| 		state:     state, | 		state:     state, | ||||||
| 		converter: converter, | 		converter: converter, | ||||||
|  | 		stream:    stream, | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|   | |||||||
| @@ -63,5 +63,8 @@ func (p *Processor) KeywordCreate(ctx context.Context, account *gtsmodel.Account | |||||||
| 		return nil, gtserror.NewErrorInternalError(err) | 		return nil, gtserror.NewErrorInternalError(err) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	// Send a filters changed event. | ||||||
|  | 	p.stream.FiltersChanged(ctx, account) | ||||||
|  |  | ||||||
| 	return p.converter.FilterKeywordToAPIFilterKeyword(ctx, filterKeyword), nil | 	return p.converter.FilterKeywordToAPIFilterKeyword(ctx, filterKeyword), nil | ||||||
| } | } | ||||||
|   | |||||||
| @@ -49,5 +49,8 @@ func (p *Processor) KeywordDelete( | |||||||
| 		return gtserror.NewErrorInternalError(err) | 		return gtserror.NewErrorInternalError(err) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	// Send a filters changed event. | ||||||
|  | 	p.stream.FiltersChanged(ctx, account) | ||||||
|  |  | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|   | |||||||
| @@ -62,5 +62,8 @@ func (p *Processor) KeywordUpdate( | |||||||
| 		return nil, gtserror.NewErrorInternalError(err) | 		return nil, gtserror.NewErrorInternalError(err) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	// Send a filters changed event. | ||||||
|  | 	p.stream.FiltersChanged(ctx, account) | ||||||
|  |  | ||||||
| 	return p.converter.FilterKeywordToAPIFilterKeyword(ctx, filterKeyword), nil | 	return p.converter.FilterKeywordToAPIFilterKeyword(ctx, filterKeyword), nil | ||||||
| } | } | ||||||
|   | |||||||
| @@ -62,5 +62,8 @@ func (p *Processor) StatusCreate(ctx context.Context, account *gtsmodel.Account, | |||||||
| 		return nil, gtserror.NewErrorInternalError(err) | 		return nil, gtserror.NewErrorInternalError(err) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	// Send a filters changed event. | ||||||
|  | 	p.stream.FiltersChanged(ctx, account) | ||||||
|  |  | ||||||
| 	return p.converter.FilterStatusToAPIFilterStatus(ctx, filterStatus), nil | 	return p.converter.FilterStatusToAPIFilterStatus(ctx, filterStatus), nil | ||||||
| } | } | ||||||
|   | |||||||
| @@ -49,5 +49,8 @@ func (p *Processor) StatusDelete( | |||||||
| 		return gtserror.NewErrorInternalError(err) | 		return gtserror.NewErrorInternalError(err) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	// Send a filters changed event. | ||||||
|  | 	p.stream.FiltersChanged(ctx, account) | ||||||
|  |  | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|   | |||||||
| @@ -121,5 +121,13 @@ func (p *Processor) Update( | |||||||
| 	filter.Keywords = filterKeywords | 	filter.Keywords = filterKeywords | ||||||
| 	filter.Statuses = filterStatuses | 	filter.Statuses = filterStatuses | ||||||
|  |  | ||||||
| 	return p.apiFilter(ctx, filter) | 	apiFilter, errWithCode := p.apiFilter(ctx, filter) | ||||||
|  | 	if errWithCode != nil { | ||||||
|  | 		return nil, errWithCode | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// Send a filters changed event. | ||||||
|  | 	p.stream.FiltersChanged(ctx, account) | ||||||
|  |  | ||||||
|  | 	return apiFilter, nil | ||||||
| } | } | ||||||
|   | |||||||
| @@ -189,8 +189,8 @@ func NewProcessor( | |||||||
| 	processor.account = account.New(&common, state, converter, mediaManager, federator, filter, parseMentionFunc) | 	processor.account = account.New(&common, state, converter, mediaManager, federator, filter, parseMentionFunc) | ||||||
| 	processor.admin = admin.New(state, cleaner, converter, mediaManager, federator.TransportController(), emailSender) | 	processor.admin = admin.New(state, cleaner, converter, mediaManager, federator.TransportController(), emailSender) | ||||||
| 	processor.fedi = fedi.New(state, &common, converter, federator, filter) | 	processor.fedi = fedi.New(state, &common, converter, federator, filter) | ||||||
| 	processor.filtersv1 = filtersv1.New(state, converter) | 	processor.filtersv1 = filtersv1.New(state, converter, &processor.stream) | ||||||
| 	processor.filtersv2 = filtersv2.New(state, converter) | 	processor.filtersv2 = filtersv2.New(state, converter, &processor.stream) | ||||||
| 	processor.list = list.New(state, converter) | 	processor.list = list.New(state, converter) | ||||||
| 	processor.markers = markers.New(state, converter) | 	processor.markers = markers.New(state, converter) | ||||||
| 	processor.polls = polls.New(&common, state, converter) | 	processor.polls = polls.New(&common, state, converter) | ||||||
|   | |||||||
							
								
								
									
										36
									
								
								internal/processing/stream/filterschanged.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								internal/processing/stream/filterschanged.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,36 @@ | |||||||
|  | // 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, see <http://www.gnu.org/licenses/>. | ||||||
|  |  | ||||||
|  | package stream | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"context" | ||||||
|  |  | ||||||
|  | 	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel" | ||||||
|  | 	"github.com/superseriousbusiness/gotosocial/internal/stream" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | // FiltersChanged streams a filters changed event to any open, appropriate streams belonging to the given account. | ||||||
|  | // Filter changes have no payload. | ||||||
|  | func (p *Processor) FiltersChanged(ctx context.Context, account *gtsmodel.Account) { | ||||||
|  | 	p.streams.Post(ctx, account.ID, stream.Message{ | ||||||
|  | 		Event: stream.EventTypeFiltersChanged, | ||||||
|  | 		Stream: []string{ | ||||||
|  | 			stream.TimelineHome, | ||||||
|  | 		}, | ||||||
|  | 	}) | ||||||
|  | } | ||||||
| @@ -42,6 +42,10 @@ const ( | |||||||
| 	// user's timeline has been edited (yes this | 	// user's timeline has been edited (yes this | ||||||
| 	// is a confusing name, blame Mastodon ...). | 	// is a confusing name, blame Mastodon ...). | ||||||
| 	EventTypeStatusUpdate = "status.update" | 	EventTypeStatusUpdate = "status.update" | ||||||
|  |  | ||||||
|  | 	// EventTypeFiltersChanged -- the user's filters | ||||||
|  | 	// (including keywords and statuses) have changed. | ||||||
|  | 	EventTypeFiltersChanged = "filters_changed" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| const ( | const ( | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user