summaryrefslogtreecommitdiff
path: root/internal
diff options
context:
space:
mode:
authorLibravatar tobi <31960611+tsmethurst@users.noreply.github.com>2023-11-27 14:14:28 +0100
committerLibravatar GitHub <noreply@github.com>2023-11-27 13:14:28 +0000
commite4e0a5e3f66f38e17a8abdafbeac251c75323b0e (patch)
tree6dc6211acd78df9fa3b933f19ab3275c187a5106 /internal
parent[chore]: Bump golang.org/x/net from 0.17.0 to 0.18.0 (#2390) (diff)
downloadgotosocial-e4e0a5e3f66f38e17a8abdafbeac251c75323b0e.tar.xz
[bugfix] Add Actor to outgoing poll vote Create; other fixes (#2384)
Diffstat (limited to 'internal')
-rw-r--r--internal/processing/workers/federate.go7
-rw-r--r--internal/typeutils/converter_test.go2
-rw-r--r--internal/typeutils/internaltoas.go37
-rw-r--r--internal/typeutils/internaltoas_test.go42
-rw-r--r--internal/typeutils/wrap.go38
5 files changed, 76 insertions, 50 deletions
diff --git a/internal/processing/workers/federate.go b/internal/processing/workers/federate.go
index 44432998d..aacb8dcc8 100644
--- a/internal/processing/workers/federate.go
+++ b/internal/processing/workers/federate.go
@@ -194,14 +194,13 @@ func (f *federate) CreatePollVote(ctx context.Context, poll *gtsmodel.Poll, vote
return err
}
- // Convert votes to AS PollOptionable implementing type.
- notes, err := f.converter.PollVoteToASOptions(ctx, vote)
+ // Convert vote to AS Create with vote choices as Objects.
+ create, err := f.converter.PollVoteToASCreate(ctx, vote)
if err != nil {
return gtserror.Newf("error converting to notes: %w", err)
}
- // Send a Create activity with PollOptionables via the Actor's outbox.
- create := typeutils.WrapPollOptionablesInCreate(notes...)
+ // Send the Create via the Actor's outbox.
if _, err := f.FederatingActor().Send(ctx, outboxIRI, create); err != nil {
return gtserror.Newf("error sending Create activity via outbox %s: %w", outboxIRI, err)
}
diff --git a/internal/typeutils/converter_test.go b/internal/typeutils/converter_test.go
index 0195a6889..8a0dcd0fd 100644
--- a/internal/typeutils/converter_test.go
+++ b/internal/typeutils/converter_test.go
@@ -480,6 +480,7 @@ type TypeUtilsTestSuite struct {
testEmojis map[string]*gtsmodel.Emoji
testReports map[string]*gtsmodel.Report
testMentions map[string]*gtsmodel.Mention
+ testPollVotes map[string]*gtsmodel.PollVote
typeconverter *typeutils.Converter
}
@@ -502,6 +503,7 @@ func (suite *TypeUtilsTestSuite) SetupTest() {
suite.testEmojis = testrig.NewTestEmojis()
suite.testReports = testrig.NewTestReports()
suite.testMentions = testrig.NewTestMentions()
+ suite.testPollVotes = testrig.NewTestPollVotes()
suite.typeconverter = typeutils.NewConverter(&suite.state)
testrig.StandardDBSetup(suite.db, nil)
diff --git a/internal/typeutils/internaltoas.go b/internal/typeutils/internaltoas.go
index ff502296b..0ffad6fc1 100644
--- a/internal/typeutils/internaltoas.go
+++ b/internal/typeutils/internaltoas.go
@@ -1659,7 +1659,17 @@ func (c *Converter) ReportToASFlag(ctx context.Context, r *gtsmodel.Report) (voc
return flag, nil
}
-func (c *Converter) PollVoteToASOptions(ctx context.Context, vote *gtsmodel.PollVote) ([]ap.PollOptionable, error) {
+// PollVoteToASCreate converts a vote on a poll into a Create
+// activity, suitable for federation, with each choice in the
+// vote appended as a Note to the Create's Object field.
+func (c *Converter) PollVoteToASCreate(
+ ctx context.Context,
+ vote *gtsmodel.PollVote,
+) (vocab.ActivityStreamsCreate, error) {
+ if len(vote.Choices) == 0 {
+ panic("no vote.Choices")
+ }
+
// Ensure the vote is fully populated (this fetches author).
if err := c.state.DB.PopulatePollVote(ctx, vote); err != nil {
return nil, gtserror.Newf("error populating vote from db: %w", err)
@@ -1694,11 +1704,22 @@ func (c *Converter) PollVoteToASOptions(ctx context.Context, vote *gtsmodel.Poll
return nil, gtserror.Newf("invalid account uri: %w", err)
}
- // Preallocate the return slice of notes.
- notes := make([]ap.PollOptionable, len(vote.Choices))
+ // Allocate Create activity and address 'To' poll author.
+ create := streams.NewActivityStreamsCreate()
+ ap.AppendTo(create, pollAuthorIRI)
+
+ // Create ID formatted as: {$voterIRI}/activity#vote/{$statusIRI}.
+ id := author.URI + "/activity#vote/" + poll.Status.URI
+ ap.MustSet(ap.SetJSONLDIdStr, ap.WithJSONLDId(create), id)
+
+ // Set Create actor appropriately.
+ ap.AppendActor(create, authorIRI)
+
+ // Set publish time for activity.
+ ap.SetPublished(create, vote.CreatedAt)
- for i, choice := range vote.Choices {
- // Create new note to represent vote.
+ // Parse each choice to a Note and add it to the Create.
+ for _, choice := range vote.Choices {
note := streams.NewActivityStreamsNote()
// For AP IRI generate from author URI + poll ID + vote choice.
@@ -1715,9 +1736,9 @@ func (c *Converter) PollVoteToASOptions(ctx context.Context, vote *gtsmodel.Poll
ap.AppendInReplyTo(note, statusIRI)
ap.AppendTo(note, pollAuthorIRI)
- // Set note in return slice.
- notes[i] = note
+ // Append this note as Create Object.
+ appendStatusableToActivity(create, note, false)
}
- return notes, nil
+ return create, nil
}
diff --git a/internal/typeutils/internaltoas_test.go b/internal/typeutils/internaltoas_test.go
index 878040dcc..0e0607279 100644
--- a/internal/typeutils/internaltoas_test.go
+++ b/internal/typeutils/internaltoas_test.go
@@ -879,6 +879,48 @@ func (suite *InternalToASTestSuite) TestPinnedStatusesToASOneItem() {
}`, string(bytes))
}
+func (suite *InternalToASTestSuite) TestPollVoteToASCreate() {
+ vote := suite.testPollVotes["remote_account_1_status_2_poll_vote_local_account_1"]
+
+ create, err := suite.typeconverter.PollVoteToASCreate(context.Background(), vote)
+ if err != nil {
+ suite.FailNow(err.Error())
+ }
+
+ createI, err := ap.Serialize(create)
+ suite.NoError(err)
+
+ bytes, err := json.MarshalIndent(createI, "", " ")
+ suite.NoError(err)
+
+ suite.Equal(`{
+ "@context": "https://www.w3.org/ns/activitystreams",
+ "actor": "http://localhost:8080/users/the_mighty_zork",
+ "id": "http://localhost:8080/users/the_mighty_zork/activity#vote/http://fossbros-anonymous.io/users/foss_satan/statuses/01HEN2QRFA8H3C6QPN7RD4KSR6",
+ "object": [
+ {
+ "attributedTo": "http://localhost:8080/users/the_mighty_zork",
+ "id": "http://localhost:8080/users/the_mighty_zork#01HEN2R65468ZG657C4ZPHJ4EX/votes/1",
+ "inReplyTo": "http://fossbros-anonymous.io/users/foss_satan/statuses/01HEN2QRFA8H3C6QPN7RD4KSR6",
+ "name": "tissues",
+ "to": "http://fossbros-anonymous.io/users/foss_satan",
+ "type": "Note"
+ },
+ {
+ "attributedTo": "http://localhost:8080/users/the_mighty_zork",
+ "id": "http://localhost:8080/users/the_mighty_zork#01HEN2R65468ZG657C4ZPHJ4EX/votes/2",
+ "inReplyTo": "http://fossbros-anonymous.io/users/foss_satan/statuses/01HEN2QRFA8H3C6QPN7RD4KSR6",
+ "name": "financial times",
+ "to": "http://fossbros-anonymous.io/users/foss_satan",
+ "type": "Note"
+ }
+ ],
+ "published": "2021-09-11T11:45:37+02:00",
+ "to": "http://fossbros-anonymous.io/users/foss_satan",
+ "type": "Create"
+}`, string(bytes))
+}
+
func TestInternalToASTestSuite(t *testing.T) {
suite.Run(t, new(InternalToASTestSuite))
}
diff --git a/internal/typeutils/wrap.go b/internal/typeutils/wrap.go
index 5deca0e5b..5892e0a66 100644
--- a/internal/typeutils/wrap.go
+++ b/internal/typeutils/wrap.go
@@ -19,7 +19,6 @@ package typeutils
import (
"net/url"
- "time"
"github.com/superseriousbusiness/activity/pub"
"github.com/superseriousbusiness/activity/streams"
@@ -91,43 +90,6 @@ func WrapStatusableInCreate(status ap.Statusable, iriOnly bool) vocab.ActivitySt
return create
}
-func WrapPollOptionablesInCreate(options ...ap.PollOptionable) vocab.ActivityStreamsCreate {
- if len(options) == 0 {
- panic("no options")
- }
-
- // Extract attributedTo IRI from any option.
- attribTos := ap.GetAttributedTo(options[0])
- if len(attribTos) != 1 {
- panic("invalid attributedTo count")
- }
-
- // Extract target status IRI from any option.
- replyTos := ap.GetInReplyTo(options[0])
- if len(replyTos) != 1 {
- panic("invalid inReplyTo count")
- }
-
- // Allocate create activity and copy over 'To' property.
- create := streams.NewActivityStreamsCreate()
- ap.AppendTo(create, ap.GetTo(options[0])...)
-
- // Activity ID formatted as: {$statusIRI}/activity#vote/{$voterIRI}.
- id := replyTos[0].String() + "/activity#vote/" + attribTos[0].String()
- ap.MustSet(ap.SetJSONLDIdStr, ap.WithJSONLDId(create), id)
-
- // Set a current publish time for activity.
- ap.SetPublished(create, time.Now())
-
- // Append each poll option as object to activity.
- for _, option := range options {
- status, _ := ap.ToStatusable(option)
- appendStatusableToActivity(create, status, false)
- }
-
- return create
-}
-
func WrapStatusableInUpdate(status ap.Statusable, iriOnly bool) vocab.ActivityStreamsUpdate {
update := streams.NewActivityStreamsUpdate()
wrapStatusableInActivity(update, status, iriOnly)