summaryrefslogtreecommitdiff
path: root/internal/processing/stream
diff options
context:
space:
mode:
authorLibravatar Sam Lade <sam@sentynel.com>2023-12-16 11:55:49 +0000
committerLibravatar GitHub <noreply@github.com>2023-12-16 12:55:49 +0100
commit285d55dda8b4de70661b16db4986d47e4e586ea2 (patch)
tree17e460f916370898d3568c6ba569686e9350aedd /internal/processing/stream
parent[feature] Run ANALYZE after migrations on SQLite (#2428) (diff)
downloadgotosocial-285d55dda8b4de70661b16db4986d47e4e586ea2.tar.xz
[feature] Push status edit messages into open streams (#2418)
* push status edit messages into open streams * fix a few comments * test++ * commented out code? moi?
Diffstat (limited to 'internal/processing/stream')
-rw-r--r--internal/processing/stream/statusupdate.go38
-rw-r--r--internal/processing/stream/statusupdate_test.go137
-rw-r--r--internal/processing/stream/stream_test.go2
3 files changed, 177 insertions, 0 deletions
diff --git a/internal/processing/stream/statusupdate.go b/internal/processing/stream/statusupdate.go
new file mode 100644
index 000000000..fd8e388ce
--- /dev/null
+++ b/internal/processing/stream/statusupdate.go
@@ -0,0 +1,38 @@
+// 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 (
+ "encoding/json"
+ "fmt"
+
+ apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model"
+ "github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
+ "github.com/superseriousbusiness/gotosocial/internal/stream"
+)
+
+// StatusUpdate streams the given edited status to any open, appropriate
+// streams belonging to the given account.
+func (p *Processor) StatusUpdate(s *apimodel.Status, account *gtsmodel.Account, streamTypes []string) error {
+ bytes, err := json.Marshal(s)
+ if err != nil {
+ return fmt.Errorf("error marshalling status to json: %s", err)
+ }
+
+ return p.toAccount(string(bytes), stream.EventTypeStatusUpdate, streamTypes, account.ID)
+}
diff --git a/internal/processing/stream/statusupdate_test.go b/internal/processing/stream/statusupdate_test.go
new file mode 100644
index 000000000..7b987b412
--- /dev/null
+++ b/internal/processing/stream/statusupdate_test.go
@@ -0,0 +1,137 @@
+// 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_test
+
+import (
+ "bytes"
+ "context"
+ "encoding/json"
+ "testing"
+
+ "github.com/stretchr/testify/suite"
+ "github.com/superseriousbusiness/gotosocial/internal/stream"
+ "github.com/superseriousbusiness/gotosocial/internal/typeutils"
+)
+
+type StatusUpdateTestSuite struct {
+ StreamTestSuite
+}
+
+func (suite *StatusUpdateTestSuite) TestStreamNotification() {
+ account := suite.testAccounts["local_account_1"]
+
+ openStream, errWithCode := suite.streamProcessor.Open(context.Background(), account, "user")
+ suite.NoError(errWithCode)
+
+ editedStatus := suite.testStatuses["remote_account_1_status_1"]
+ apiStatus, err := typeutils.NewConverter(&suite.state).StatusToAPIStatus(context.Background(), editedStatus, account)
+ suite.NoError(err)
+
+ err = suite.streamProcessor.StatusUpdate(apiStatus, account, []string{stream.TimelineHome})
+ suite.NoError(err)
+
+ msg := <-openStream.Messages
+ dst := new(bytes.Buffer)
+ err = json.Indent(dst, []byte(msg.Payload), "", " ")
+ suite.NoError(err)
+ suite.Equal(`{
+ "id": "01FVW7JHQFSFK166WWKR8CBA6M",
+ "created_at": "2021-09-20T10:40:37.000Z",
+ "in_reply_to_id": null,
+ "in_reply_to_account_id": null,
+ "sensitive": false,
+ "spoiler_text": "",
+ "visibility": "unlisted",
+ "language": "en",
+ "uri": "http://fossbros-anonymous.io/users/foss_satan/statuses/01FVW7JHQFSFK166WWKR8CBA6M",
+ "url": "http://fossbros-anonymous.io/@foss_satan/statuses/01FVW7JHQFSFK166WWKR8CBA6M",
+ "replies_count": 0,
+ "reblogs_count": 0,
+ "favourites_count": 0,
+ "favourited": false,
+ "reblogged": false,
+ "muted": false,
+ "bookmarked": false,
+ "pinned": false,
+ "content": "dark souls status bot: \"thoughts of dog\"",
+ "reblog": null,
+ "account": {
+ "id": "01F8MH5ZK5VRH73AKHQM6Y9VNX",
+ "username": "foss_satan",
+ "acct": "foss_satan@fossbros-anonymous.io",
+ "display_name": "big gerald",
+ "locked": false,
+ "discoverable": true,
+ "bot": false,
+ "created_at": "2021-09-26T10:52:36.000Z",
+ "note": "i post about like, i dunno, stuff, or whatever!!!!",
+ "url": "http://fossbros-anonymous.io/@foss_satan",
+ "avatar": "",
+ "avatar_static": "",
+ "header": "http://localhost:8080/assets/default_header.png",
+ "header_static": "http://localhost:8080/assets/default_header.png",
+ "followers_count": 0,
+ "following_count": 0,
+ "statuses_count": 3,
+ "last_status_at": "2021-09-11T09:40:37.000Z",
+ "emojis": [],
+ "fields": []
+ },
+ "media_attachments": [
+ {
+ "id": "01FVW7RXPQ8YJHTEXYPE7Q8ZY0",
+ "type": "image",
+ "url": "http://localhost:8080/fileserver/01F8MH5ZK5VRH73AKHQM6Y9VNX/attachment/original/01FVW7RXPQ8YJHTEXYPE7Q8ZY0.jpg",
+ "text_url": "http://localhost:8080/fileserver/01F8MH5ZK5VRH73AKHQM6Y9VNX/attachment/original/01FVW7RXPQ8YJHTEXYPE7Q8ZY0.jpg",
+ "preview_url": "http://localhost:8080/fileserver/01F8MH5ZK5VRH73AKHQM6Y9VNX/attachment/small/01FVW7RXPQ8YJHTEXYPE7Q8ZY0.jpg",
+ "remote_url": "http://fossbros-anonymous.io/attachments/original/13bbc3f8-2b5e-46ea-9531-40b4974d9912.jpg",
+ "preview_remote_url": "http://fossbros-anonymous.io/attachments/small/a499f55b-2d1e-4acd-98d2-1ac2ba6d79b9.jpg",
+ "meta": {
+ "original": {
+ "width": 472,
+ "height": 291,
+ "size": "472x291",
+ "aspect": 1.6219932
+ },
+ "small": {
+ "width": 472,
+ "height": 291,
+ "size": "472x291",
+ "aspect": 1.6219932
+ },
+ "focus": {
+ "x": 0,
+ "y": 0
+ }
+ },
+ "description": "tweet from thoughts of dog: i drank. all the water. in my bowl. earlier. but just now. i returned. to the same bowl. and it was. full again.. the bowl. is haunted",
+ "blurhash": "LARysgM_IU_3~pD%M_Rj_39FIAt6"
+ }
+ ],
+ "mentions": [],
+ "tags": [],
+ "emojis": [],
+ "card": null,
+ "poll": null
+}`, dst.String())
+ suite.Equal(msg.Event, "status.update")
+}
+
+func TestStatusUpdateTestSuite(t *testing.T) {
+ suite.Run(t, &StatusUpdateTestSuite{})
+}
diff --git a/internal/processing/stream/stream_test.go b/internal/processing/stream/stream_test.go
index bd12674e7..2569ac701 100644
--- a/internal/processing/stream/stream_test.go
+++ b/internal/processing/stream/stream_test.go
@@ -30,6 +30,7 @@ import (
type StreamTestSuite struct {
suite.Suite
testAccounts map[string]*gtsmodel.Account
+ testStatuses map[string]*gtsmodel.Status
testTokens map[string]*gtsmodel.Token
db db.DB
oauthServer oauth.Server
@@ -45,6 +46,7 @@ func (suite *StreamTestSuite) SetupTest() {
testrig.InitTestConfig()
suite.testAccounts = testrig.NewTestAccounts()
+ suite.testStatuses = testrig.NewTestStatuses()
suite.testTokens = testrig.NewTestTokens()
suite.db = testrig.NewTestDB(&suite.state)
suite.state.DB = suite.db