summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/federation/actors.md8
-rw-r--r--internal/ap/activitystreams.go16
-rw-r--r--internal/ap/ap_test.go11
-rw-r--r--internal/ap/interfaces.go2
-rw-r--r--internal/api/activitypub/users/inboxpost_test.go60
-rw-r--r--internal/federation/federator_test.go4
-rw-r--r--internal/processing/fedi/user.go13
-rw-r--r--internal/processing/workers/federate.go23
-rw-r--r--internal/typeutils/internaltoas.go94
-rw-r--r--internal/typeutils/internaltoas_test.go91
-rw-r--r--internal/typeutils/wrap.go71
-rw-r--r--internal/typeutils/wrap_test.go80
-rw-r--r--testrig/testmodels.go14
-rw-r--r--testrig/transportcontroller.go3
14 files changed, 315 insertions, 175 deletions
diff --git a/docs/federation/actors.md b/docs/federation/actors.md
index d5dc61e19..ba2283ee9 100644
--- a/docs/federation/actors.md
+++ b/docs/federation/actors.md
@@ -1,5 +1,13 @@
# Actors and Actor Properties
+## `Service` vs `Person` actors
+
+GoToSocial serves most accounts as the ActivityStreams `Person` type described [here](https://www.w3.org/TR/activitystreams-vocabulary/#dfn-person).
+
+Accounts that users have selected to mark as bot accounts, however, will use the `Service` type described [here](https://www.w3.org/TR/activitystreams-vocabulary/#dfn-service).
+
+This type distinction can be used by remote servers to distinguish between bot accounts and "regular" user accounts.
+
## Inbox
GoToSocial implements Inboxes for Actors following the ActivityPub specification [here](https://www.w3.org/TR/activitypub/#inbox).
diff --git a/internal/ap/activitystreams.go b/internal/ap/activitystreams.go
index 8c53ae501..50955ce2c 100644
--- a/internal/ap/activitystreams.go
+++ b/internal/ap/activitystreams.go
@@ -17,6 +17,22 @@
package ap
+import (
+ "net/url"
+
+ "github.com/superseriousbusiness/activity/pub"
+)
+
+// PublicURI returns a fresh copy of the *url.URL version of the
+// magic ActivityPub URI https://www.w3.org/ns/activitystreams#Public
+func PublicURI() *url.URL {
+ publicURI, err := url.Parse(pub.PublicActivityPubIRI)
+ if err != nil {
+ panic(err)
+ }
+ return publicURI
+}
+
// https://www.w3.org/TR/activitystreams-vocabulary
const (
ActivityAccept = "Accept" // ActivityStreamsAccept https://www.w3.org/TR/activitystreams-vocabulary/#dfn-accept
diff --git a/internal/ap/ap_test.go b/internal/ap/ap_test.go
index f982e4443..3738c8c9c 100644
--- a/internal/ap/ap_test.go
+++ b/internal/ap/ap_test.go
@@ -24,7 +24,6 @@ import (
"io"
"github.com/stretchr/testify/suite"
- "github.com/superseriousbusiness/activity/pub"
"github.com/superseriousbusiness/activity/streams"
"github.com/superseriousbusiness/activity/streams/vocab"
"github.com/superseriousbusiness/gotosocial/internal/ap"
@@ -111,7 +110,7 @@ func noteWithMentions1() vocab.ActivityStreamsNote {
// Anyone can like.
canLikeAlwaysProp := streams.NewGoToSocialAlwaysProperty()
- canLikeAlwaysProp.AppendIRI(testrig.URLMustParse(pub.PublicActivityPubIRI))
+ canLikeAlwaysProp.AppendIRI(ap.PublicURI())
canLike.SetGoToSocialAlways(canLikeAlwaysProp)
// Empty approvalRequired.
@@ -128,7 +127,7 @@ func noteWithMentions1() vocab.ActivityStreamsNote {
// Anyone can reply.
canReplyAlwaysProp := streams.NewGoToSocialAlwaysProperty()
- canReplyAlwaysProp.AppendIRI(testrig.URLMustParse(pub.PublicActivityPubIRI))
+ canReplyAlwaysProp.AppendIRI(ap.PublicURI())
canReply.SetGoToSocialAlways(canReplyAlwaysProp)
// Set empty approvalRequired.
@@ -151,7 +150,7 @@ func noteWithMentions1() vocab.ActivityStreamsNote {
// Public requires approval to announce.
canAnnounceApprovalRequiredProp := streams.NewGoToSocialApprovalRequiredProperty()
- canAnnounceApprovalRequiredProp.AppendIRI(testrig.URLMustParse(pub.PublicActivityPubIRI))
+ canAnnounceApprovalRequiredProp.AppendIRI(ap.PublicURI())
canAnnounce.SetGoToSocialApprovalRequired(canAnnounceApprovalRequiredProp)
// Set canAnnounce on the policy.
@@ -266,7 +265,7 @@ func addressable1() ap.Addressable {
note := streams.NewActivityStreamsNote()
toProp := streams.NewActivityStreamsToProperty()
- toProp.AppendIRI(testrig.URLMustParse(pub.PublicActivityPubIRI))
+ toProp.AppendIRI(ap.PublicURI())
note.SetActivityStreamsTo(toProp)
@@ -288,7 +287,7 @@ func addressable2() ap.Addressable {
note.SetActivityStreamsTo(toProp)
ccProp := streams.NewActivityStreamsCcProperty()
- ccProp.AppendIRI(testrig.URLMustParse(pub.PublicActivityPubIRI))
+ ccProp.AppendIRI(ap.PublicURI())
note.SetActivityStreamsCc(ccProp)
diff --git a/internal/ap/interfaces.go b/internal/ap/interfaces.go
index 1f08fde37..fdd5e4a0b 100644
--- a/internal/ap/interfaces.go
+++ b/internal/ap/interfaces.go
@@ -188,6 +188,7 @@ type Accountable interface {
WithTag
WithPublished
WithUpdated
+ WithImage
}
// Statusable represents the minimum activitypub interface for representing a 'status'.
@@ -439,6 +440,7 @@ type WithValue interface {
// WithImage represents an activity with ActivityStreamsImageProperty
type WithImage interface {
GetActivityStreamsImage() vocab.ActivityStreamsImageProperty
+ SetActivityStreamsImage(vocab.ActivityStreamsImageProperty)
}
// WithSummary represents an activity with ActivityStreamsSummaryProperty
diff --git a/internal/api/activitypub/users/inboxpost_test.go b/internal/api/activitypub/users/inboxpost_test.go
index 64c9f7e6c..f87224d65 100644
--- a/internal/api/activitypub/users/inboxpost_test.go
+++ b/internal/api/activitypub/users/inboxpost_test.go
@@ -177,38 +177,6 @@ func (suite *InboxPostTestSuite) newUndo(
return undo
}
-func (suite *InboxPostTestSuite) newUpdatePerson(person vocab.ActivityStreamsPerson, cc string, updateIRI string) vocab.ActivityStreamsUpdate {
- // create an update
- update := streams.NewActivityStreamsUpdate()
-
- // set the appropriate actor on it
- updateActor := streams.NewActivityStreamsActorProperty()
- updateActor.AppendIRI(person.GetJSONLDId().Get())
- update.SetActivityStreamsActor(updateActor)
-
- // Set the person as the 'object' property.
- updateObject := streams.NewActivityStreamsObjectProperty()
- updateObject.AppendActivityStreamsPerson(person)
- update.SetActivityStreamsObject(updateObject)
-
- // Set the To of the update as public
- updateTo := streams.NewActivityStreamsToProperty()
- updateTo.AppendIRI(testrig.URLMustParse(pub.PublicActivityPubIRI))
- update.SetActivityStreamsTo(updateTo)
-
- // set the cc of the update to the receivingAccount
- updateCC := streams.NewActivityStreamsCcProperty()
- updateCC.AppendIRI(testrig.URLMustParse(cc))
- update.SetActivityStreamsCc(updateCC)
-
- // set some random-ass ID for the activity
- updateID := streams.NewJSONLDIdProperty()
- updateID.SetIRI(testrig.URLMustParse(updateIRI))
- update.SetJSONLDId(updateID)
-
- return update
-}
-
func (suite *InboxPostTestSuite) newDelete(actorIRI string, objectIRI string, deleteIRI string) vocab.ActivityStreamsDelete {
// create a delete
delete := streams.NewActivityStreamsDelete()
@@ -225,7 +193,7 @@ func (suite *InboxPostTestSuite) newDelete(actorIRI string, objectIRI string, de
// Set the To of the delete as public
deleteTo := streams.NewActivityStreamsToProperty()
- deleteTo.AppendIRI(testrig.URLMustParse(pub.PublicActivityPubIRI))
+ deleteTo.AppendIRI(ap.PublicURI())
delete.SetActivityStreamsTo(deleteTo)
// set some random-ass ID for the activity
@@ -329,7 +297,6 @@ func (suite *InboxPostTestSuite) TestPostUpdate() {
var (
requestingAccount = new(gtsmodel.Account)
targetAccount = suite.testAccounts["local_account_1"]
- activityID = "http://fossbros-anonymous.io/72cc96a3-f742-4daf-b9f5-3407667260c5"
updatedDisplayName = "updated display name!"
)
@@ -348,11 +315,19 @@ func (suite *InboxPostTestSuite) TestPostUpdate() {
requestingAccount.Emojis = []*gtsmodel.Emoji{testEmoji}
// Create an update from the account.
- asAccount, err := suite.tc.AccountToAS(context.Background(), requestingAccount)
+ accountable, err := suite.tc.AccountToAS(context.Background(), requestingAccount)
+ if err != nil {
+ suite.FailNow(err.Error())
+ }
+ update, err := suite.tc.WrapAccountableInUpdate(accountable)
if err != nil {
suite.FailNow(err.Error())
}
- update := suite.newUpdatePerson(asAccount, targetAccount.URI, activityID)
+
+ // Set the ID to something from fossbros anonymous.
+ idProp := streams.NewJSONLDIdProperty()
+ idProp.SetIRI(testrig.URLMustParse("https://fossbros-anonymous.io/updates/waaaaaaaaaaaaaaaaa"))
+ update.SetJSONLDId(idProp)
// Update.
suite.inboxPost(
@@ -540,17 +515,20 @@ func (suite *InboxPostTestSuite) TestPostFromBlockedAccount() {
var (
requestingAccount = suite.testAccounts["remote_account_1"]
targetAccount = suite.testAccounts["local_account_2"]
- activityID = requestingAccount.URI + "/some-new-activity/01FG9C441MCTW3R2W117V2PQK3"
)
- person, err := suite.tc.AccountToAS(context.Background(), requestingAccount)
+ // Create an update from the account.
+ accountable, err := suite.tc.AccountToAS(context.Background(), requestingAccount)
+ if err != nil {
+ suite.FailNow(err.Error())
+ }
+ update, err := suite.tc.WrapAccountableInUpdate(accountable)
if err != nil {
suite.FailNow(err.Error())
}
- // Post an update from foss satan to turtle, who blocks him.
- update := suite.newUpdatePerson(person, targetAccount.URI, activityID)
-
+ // Post an update from foss satan
+ // to turtle, who blocks him.
suite.inboxPost(
update,
requestingAccount,
diff --git a/internal/federation/federator_test.go b/internal/federation/federator_test.go
index e10c7576c..a4f8c4683 100644
--- a/internal/federation/federator_test.go
+++ b/internal/federation/federator_test.go
@@ -75,12 +75,12 @@ func (suite *FederatorStandardTestSuite) SetupTest() {
// Ensure it's possible to deref
// main key of foss satan.
- fossSatanPerson, err := suite.typeconverter.AccountToAS(context.Background(), suite.testAccounts["remote_account_1"])
+ fossSatanAS, err := suite.typeconverter.AccountToAS(context.Background(), suite.testAccounts["remote_account_1"])
if err != nil {
suite.FailNow(err.Error())
}
- suite.httpClient = testrig.NewMockHTTPClient(nil, "../../testrig/media", fossSatanPerson)
+ suite.httpClient = testrig.NewMockHTTPClient(nil, "../../testrig/media", fossSatanAS)
suite.httpClient.TestRemotePeople = testrig.NewTestFediPeople()
suite.httpClient.TestRemoteStatuses = testrig.NewTestFediStatuses()
diff --git a/internal/processing/fedi/user.go b/internal/processing/fedi/user.go
index bf14554cf..79c1b4fdb 100644
--- a/internal/processing/fedi/user.go
+++ b/internal/processing/fedi/user.go
@@ -23,7 +23,6 @@ import (
"fmt"
"net/url"
- "github.com/superseriousbusiness/activity/streams/vocab"
"github.com/superseriousbusiness/gotosocial/internal/ap"
"github.com/superseriousbusiness/gotosocial/internal/db"
"github.com/superseriousbusiness/gotosocial/internal/gtserror"
@@ -72,7 +71,7 @@ func (p *Processor) UserGet(ctx context.Context, requestedUsername string, reque
}
// Auth passed, generate the proper AP representation.
- person, err := p.converter.AccountToAS(ctx, receiver)
+ accountable, err := p.converter.AccountToAS(ctx, receiver)
if err != nil {
err := gtserror.Newf("error converting account: %w", err)
return nil, gtserror.NewErrorInternalError(err)
@@ -91,7 +90,7 @@ func (p *Processor) UserGet(ctx context.Context, requestedUsername string, reque
// Instead, we end up in an 'I'll show you mine if you show me
// yours' situation, where we sort of agree to reveal each
// other's profiles at the same time.
- return data(person)
+ return data(accountable)
}
// Get requester from auth.
@@ -107,13 +106,13 @@ func (p *Processor) UserGet(ctx context.Context, requestedUsername string, reque
return nil, gtserror.NewErrorForbidden(errors.New(text))
}
- return data(person)
+ return data(accountable)
}
-func data(requestedPerson vocab.ActivityStreamsPerson) (interface{}, gtserror.WithCode) {
- data, err := ap.Serialize(requestedPerson)
+func data(accountable ap.Accountable) (interface{}, gtserror.WithCode) {
+ data, err := ap.Serialize(accountable)
if err != nil {
- err := gtserror.Newf("error serializing person: %w", err)
+ err := gtserror.Newf("error serializing accountable: %w", err)
return nil, gtserror.NewErrorInternalError(err)
}
diff --git a/internal/processing/workers/federate.go b/internal/processing/workers/federate.go
index 8c08c42b7..d6dec6691 100644
--- a/internal/processing/workers/federate.go
+++ b/internal/processing/workers/federate.go
@@ -21,7 +21,6 @@ import (
"context"
"net/url"
- "github.com/superseriousbusiness/activity/pub"
"github.com/superseriousbusiness/activity/streams"
"github.com/superseriousbusiness/activity/streams/vocab"
"github.com/superseriousbusiness/gotosocial/internal/ap"
@@ -93,11 +92,6 @@ func (f *federate) DeleteAccount(ctx context.Context, account *gtsmodel.Account)
return err
}
- publicIRI, err := parseURI(pub.PublicActivityPubIRI)
- if err != nil {
- return err
- }
-
// Create a new delete.
// todo: tc.AccountToASDelete
delete := streams.NewActivityStreamsDelete()
@@ -121,7 +115,7 @@ func (f *federate) DeleteAccount(ctx context.Context, account *gtsmodel.Account)
// Address the delete CC public.
deleteCC := streams.NewActivityStreamsCcProperty()
- deleteCC.AppendIRI(publicIRI)
+ deleteCC.AppendIRI(ap.PublicURI())
delete.SetActivityStreamsCc(deleteCC)
// Send the Delete via the Actor's outbox.
@@ -877,14 +871,14 @@ func (f *federate) UpdateAccount(ctx context.Context, account *gtsmodel.Account)
return err
}
- // Convert account to ActivityStreams Person.
- person, err := f.converter.AccountToAS(ctx, account)
+ // Convert account to Accountable.
+ accountable, err := f.converter.AccountToAS(ctx, account)
if err != nil {
return gtserror.Newf("error converting account to Person: %w", err)
}
- // Use ActivityStreams Person as Object of Update.
- update, err := f.converter.WrapPersonInUpdate(person, account)
+ // Use Accountable as Object of Update.
+ update, err := f.converter.WrapAccountableInUpdate(accountable)
if err != nil {
return gtserror.Newf("error wrapping Person in Update: %w", err)
}
@@ -1089,11 +1083,6 @@ func (f *federate) MoveAccount(ctx context.Context, account *gtsmodel.Account) e
return err
}
- publicIRI, err := parseURI(pub.PublicActivityPubIRI)
- if err != nil {
- return err
- }
-
// Create a new move.
move := streams.NewActivityStreamsMove()
@@ -1115,7 +1104,7 @@ func (f *federate) MoveAccount(ctx context.Context, account *gtsmodel.Account) e
ap.AppendTo(move, followersIRI)
// Address the move CC public.
- ap.AppendCc(move, publicIRI)
+ ap.AppendCc(move, ap.PublicURI())
// Send the Move via the Actor's outbox.
if _, err := f.FederatingActor().Send(
diff --git a/internal/typeutils/internaltoas.go b/internal/typeutils/internaltoas.go
index de1badb5c..ce5187bde 100644
--- a/internal/typeutils/internaltoas.go
+++ b/internal/typeutils/internaltoas.go
@@ -36,12 +36,24 @@ import (
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
"github.com/superseriousbusiness/gotosocial/internal/log"
"github.com/superseriousbusiness/gotosocial/internal/uris"
+ "github.com/superseriousbusiness/gotosocial/internal/util"
"github.com/superseriousbusiness/gotosocial/internal/util/xslices"
)
-// AccountToAS converts a gts model account into an activity streams person, suitable for federation
-func (c *Converter) AccountToAS(ctx context.Context, a *gtsmodel.Account) (vocab.ActivityStreamsPerson, error) {
- person := streams.NewActivityStreamsPerson()
+// AccountToAS converts a gts model account
+// into an activity streams person or service.
+func (c *Converter) AccountToAS(
+ ctx context.Context,
+ a *gtsmodel.Account,
+) (ap.Accountable, error) {
+ // accountable is a service if this
+ // is a bot account, otherwise a person.
+ var accountable ap.Accountable
+ if util.PtrOrZero(a.Bot) {
+ accountable = streams.NewActivityStreamsService()
+ } else {
+ accountable = streams.NewActivityStreamsPerson()
+ }
// id should be the activitypub URI of this user
// something like https://example.org/users/example_user
@@ -51,13 +63,13 @@ func (c *Converter) AccountToAS(ctx context.Context, a *gtsmodel.Account) (vocab
}
idProp := streams.NewJSONLDIdProperty()
idProp.SetIRI(profileIDURI)
- person.SetJSONLDId(idProp)
+ accountable.SetJSONLDId(idProp)
// published
// The moment when the account was created.
publishedProp := streams.NewActivityStreamsPublishedProperty()
publishedProp.Set(a.CreatedAt)
- person.SetActivityStreamsPublished(publishedProp)
+ accountable.SetActivityStreamsPublished(publishedProp)
// following
// The URI for retrieving a list of accounts this user is following
@@ -67,7 +79,7 @@ func (c *Converter) AccountToAS(ctx context.Context, a *gtsmodel.Account) (vocab
}
followingProp := streams.NewActivityStreamsFollowingProperty()
followingProp.SetIRI(followingURI)
- person.SetActivityStreamsFollowing(followingProp)
+ accountable.SetActivityStreamsFollowing(followingProp)
// followers
// The URI for retrieving a list of this user's followers
@@ -77,7 +89,7 @@ func (c *Converter) AccountToAS(ctx context.Context, a *gtsmodel.Account) (vocab
}
followersProp := streams.NewActivityStreamsFollowersProperty()
followersProp.SetIRI(followersURI)
- person.SetActivityStreamsFollowers(followersProp)
+ accountable.SetActivityStreamsFollowers(followersProp)
// inbox
// the activitypub inbox of this user for accepting messages
@@ -87,7 +99,7 @@ func (c *Converter) AccountToAS(ctx context.Context, a *gtsmodel.Account) (vocab
}
inboxProp := streams.NewActivityStreamsInboxProperty()
inboxProp.SetIRI(inboxURI)
- person.SetActivityStreamsInbox(inboxProp)
+ accountable.SetActivityStreamsInbox(inboxProp)
// shared inbox -- only add this if we know for sure it has one
if a.SharedInboxURI != nil && *a.SharedInboxURI != "" {
@@ -101,7 +113,7 @@ func (c *Converter) AccountToAS(ctx context.Context, a *gtsmodel.Account) (vocab
sharedInboxProp.SetIRI(sharedInboxURI)
endpoints.SetActivityStreamsSharedInbox(sharedInboxProp)
endpointsProp.AppendActivityStreamsEndpoints(endpoints)
- person.SetActivityStreamsEndpoints(endpointsProp)
+ accountable.SetActivityStreamsEndpoints(endpointsProp)
}
// outbox
@@ -112,7 +124,7 @@ func (c *Converter) AccountToAS(ctx context.Context, a *gtsmodel.Account) (vocab
}
outboxProp := streams.NewActivityStreamsOutboxProperty()
outboxProp.SetIRI(outboxURI)
- person.SetActivityStreamsOutbox(outboxProp)
+ accountable.SetActivityStreamsOutbox(outboxProp)
// featured posts
// Pinned posts.
@@ -122,7 +134,7 @@ func (c *Converter) AccountToAS(ctx context.Context, a *gtsmodel.Account) (vocab
}
featuredProp := streams.NewTootFeaturedProperty()
featuredProp.SetIRI(featuredURI)
- person.SetTootFeatured(featuredProp)
+ accountable.SetTootFeatured(featuredProp)
// featuredTags
// NOT IMPLEMENTED
@@ -131,7 +143,7 @@ func (c *Converter) AccountToAS(ctx context.Context, a *gtsmodel.Account) (vocab
// Used for Webfinger lookup. Must be unique on the domain, and must correspond to a Webfinger acct: URI.
preferredUsernameProp := streams.NewActivityStreamsPreferredUsernameProperty()
preferredUsernameProp.SetXMLSchemaString(a.Username)
- person.SetActivityStreamsPreferredUsername(preferredUsernameProp)
+ accountable.SetActivityStreamsPreferredUsername(preferredUsernameProp)
// name
// Used as profile display name.
@@ -141,14 +153,14 @@ func (c *Converter) AccountToAS(ctx context.Context, a *gtsmodel.Account) (vocab
} else {
nameProp.AppendXMLSchemaString(a.Username)
}
- person.SetActivityStreamsName(nameProp)
+ accountable.SetActivityStreamsName(nameProp)
// summary
// Used as profile bio.
if a.Note != "" {
summaryProp := streams.NewActivityStreamsSummaryProperty()
summaryProp.AppendXMLSchemaString(a.Note)
- person.SetActivityStreamsSummary(summaryProp)
+ accountable.SetActivityStreamsSummary(summaryProp)
}
// url
@@ -159,19 +171,19 @@ func (c *Converter) AccountToAS(ctx context.Context, a *gtsmodel.Account) (vocab
}
urlProp := streams.NewActivityStreamsUrlProperty()
urlProp.AppendIRI(profileURL)
- person.SetActivityStreamsUrl(urlProp)
+ accountable.SetActivityStreamsUrl(urlProp)
// manuallyApprovesFollowers
// Will be shown as a locked account.
manuallyApprovesFollowersProp := streams.NewActivityStreamsManuallyApprovesFollowersProperty()
manuallyApprovesFollowersProp.Set(*a.Locked)
- person.SetActivityStreamsManuallyApprovesFollowers(manuallyApprovesFollowersProp)
+ accountable.SetActivityStreamsManuallyApprovesFollowers(manuallyApprovesFollowersProp)
// discoverable
// Will be shown in the profile directory.
discoverableProp := streams.NewTootDiscoverableProperty()
discoverableProp.Set(*a.Discoverable)
- person.SetTootDiscoverable(discoverableProp)
+ accountable.SetTootDiscoverable(discoverableProp)
// devices
// NOT IMPLEMENTED, probably won't implement
@@ -189,7 +201,7 @@ func (c *Converter) AccountToAS(ctx context.Context, a *gtsmodel.Account) (vocab
alsoKnownAsURIs[i] = uri
}
- ap.SetAlsoKnownAs(person, alsoKnownAsURIs)
+ ap.SetAlsoKnownAs(accountable, alsoKnownAsURIs)
}
// movedTo
@@ -200,7 +212,7 @@ func (c *Converter) AccountToAS(ctx context.Context, a *gtsmodel.Account) (vocab
return nil, err
}
- ap.SetMovedTo(person, movedTo)
+ ap.SetMovedTo(accountable, movedTo)
}
// publicKey
@@ -241,7 +253,7 @@ func (c *Converter) AccountToAS(ctx context.Context, a *gtsmodel.Account) (vocab
publicKeyProp.AppendW3IDSecurityV1PublicKey(publicKey)
// set the public key property on the Person
- person.SetW3IDSecurityV1PublicKey(publicKeyProp)
+ accountable.SetW3IDSecurityV1PublicKey(publicKeyProp)
// tags
tagProp := streams.NewActivityStreamsTagProperty()
@@ -269,7 +281,7 @@ func (c *Converter) AccountToAS(ctx context.Context, a *gtsmodel.Account) (vocab
// tag -- hashtags
// TODO
- person.SetActivityStreamsTag(tagProp)
+ accountable.SetActivityStreamsTag(tagProp)
// attachment
// Used for profile fields.
@@ -290,7 +302,7 @@ func (c *Converter) AccountToAS(ctx context.Context, a *gtsmodel.Account) (vocab
attachmentProp.AppendSchemaPropertyValue(propertyValue)
}
- person.SetActivityStreamsAttachment(attachmentProp)
+ accountable.SetActivityStreamsAttachment(attachmentProp)
}
// endpoints
@@ -326,7 +338,7 @@ func (c *Converter) AccountToAS(ctx context.Context, a *gtsmodel.Account) (vocab
iconImage.SetActivityStreamsUrl(avatarURLProperty)
iconProperty.AppendActivityStreamsImage(iconImage)
- person.SetActivityStreamsIcon(iconProperty)
+ accountable.SetActivityStreamsIcon(iconProperty)
}
}
@@ -360,20 +372,32 @@ func (c *Converter) AccountToAS(ctx context.Context, a *gtsmodel.Account) (vocab
headerImage.SetActivityStreamsUrl(headerURLProperty)
headerProperty.AppendActivityStreamsImage(headerImage)
- person.SetActivityStreamsImage(headerProperty)
+ accountable.SetActivityStreamsImage(headerProperty)
}
}
- return person, nil
+ return accountable, nil
}
-// AccountToASMinimal converts a gts model account into an activity streams person, suitable for federation.
+// AccountToASMinimal converts a gts model account
+// into an activity streams person or service.
//
-// The returned account will just have the Type, Username, PublicKey, and ID properties set. This is
-// suitable for serving to requesters to whom we want to give as little information as possible because
-// we don't trust them (yet).
-func (c *Converter) AccountToASMinimal(ctx context.Context, a *gtsmodel.Account) (vocab.ActivityStreamsPerson, error) {
- person := streams.NewActivityStreamsPerson()
+// The returned account will just have the Type, Username,
+// PublicKey, and ID properties set. This is suitable for
+// serving to requesters to whom we want to give as little
+// information as possible because we don't trust them (yet).
+func (c *Converter) AccountToASMinimal(
+ ctx context.Context,
+ a *gtsmodel.Account,
+) (ap.Accountable, error) {
+ // accountable is a service if this
+ // is a bot account, otherwise a person.
+ var accountable ap.Accountable
+ if util.PtrOrZero(a.Bot) {
+ accountable = streams.NewActivityStreamsService()
+ } else {
+ accountable = streams.NewActivityStreamsPerson()
+ }
// id should be the activitypub URI of this user
// something like https://example.org/users/example_user
@@ -383,13 +407,13 @@ func (c *Converter) AccountToASMinimal(ctx context.Context, a *gtsmodel.Account)
}
idProp := streams.NewJSONLDIdProperty()
idProp.SetIRI(profileIDURI)
- person.SetJSONLDId(idProp)
+ accountable.SetJSONLDId(idProp)
// preferredUsername
// Used for Webfinger lookup. Must be unique on the domain, and must correspond to a Webfinger acct: URI.
preferredUsernameProp := streams.NewActivityStreamsPreferredUsernameProperty()
preferredUsernameProp.SetXMLSchemaString(a.Username)
- person.SetActivityStreamsPreferredUsername(preferredUsernameProp)
+ accountable.SetActivityStreamsPreferredUsername(preferredUsernameProp)
// publicKey
// Required for signatures.
@@ -429,9 +453,9 @@ func (c *Converter) AccountToASMinimal(ctx context.Context, a *gtsmodel.Account)
publicKeyProp.AppendW3IDSecurityV1PublicKey(publicKey)
// set the public key property on the Person
- person.SetW3IDSecurityV1PublicKey(publicKeyProp)
+ accountable.SetW3IDSecurityV1PublicKey(publicKeyProp)
- return person, nil
+ return accountable, nil
}
// StatusToAS converts a gts model status into an ActivityStreams Statusable implementation, suitable for federation
diff --git a/internal/typeutils/internaltoas_test.go b/internal/typeutils/internaltoas_test.go
index 344a42798..4d0d95641 100644
--- a/internal/typeutils/internaltoas_test.go
+++ b/internal/typeutils/internaltoas_test.go
@@ -27,6 +27,7 @@ import (
"github.com/superseriousbusiness/gotosocial/internal/ap"
"github.com/superseriousbusiness/gotosocial/internal/db"
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
+ "github.com/superseriousbusiness/gotosocial/internal/util"
"github.com/superseriousbusiness/gotosocial/testrig"
)
@@ -38,10 +39,10 @@ func (suite *InternalToASTestSuite) TestAccountToAS() {
testAccount := &gtsmodel.Account{}
*testAccount = *suite.testAccounts["local_account_1"] // take zork for this test
- asPerson, err := suite.typeconverter.AccountToAS(context.Background(), testAccount)
+ accountable, err := suite.typeconverter.AccountToAS(context.Background(), testAccount)
suite.NoError(err)
- ser, err := ap.Serialize(asPerson)
+ ser, err := ap.Serialize(accountable)
suite.NoError(err)
bytes, err := json.MarshalIndent(ser, "", " ")
@@ -94,14 +95,80 @@ func (suite *InternalToASTestSuite) TestAccountToAS() {
}`, string(bytes))
}
+func (suite *InternalToASTestSuite) TestAccountToASBot() {
+ testAccount := &gtsmodel.Account{}
+ *testAccount = *suite.testAccounts["local_account_1"] // take zork for this test
+
+ // Update zork to be a bot.
+ testAccount.Bot = util.Ptr(true)
+ if err := suite.state.DB.UpdateAccount(context.Background(), testAccount); err != nil {
+ suite.FailNow(err.Error())
+ }
+
+ accountable, err := suite.typeconverter.AccountToAS(context.Background(), testAccount)
+ suite.NoError(err)
+
+ ser, err := ap.Serialize(accountable)
+ suite.NoError(err)
+
+ bytes, err := json.MarshalIndent(ser, "", " ")
+ suite.NoError(err)
+
+ suite.Equal(`{
+ "@context": [
+ "https://w3id.org/security/v1",
+ "https://www.w3.org/ns/activitystreams",
+ {
+ "discoverable": "toot:discoverable",
+ "featured": {
+ "@id": "toot:featured",
+ "@type": "@id"
+ },
+ "manuallyApprovesFollowers": "as:manuallyApprovesFollowers",
+ "toot": "http://joinmastodon.org/ns#"
+ }
+ ],
+ "discoverable": true,
+ "featured": "http://localhost:8080/users/the_mighty_zork/collections/featured",
+ "followers": "http://localhost:8080/users/the_mighty_zork/followers",
+ "following": "http://localhost:8080/users/the_mighty_zork/following",
+ "icon": {
+ "mediaType": "image/jpeg",
+ "type": "Image",
+ "url": "http://localhost:8080/fileserver/01F8MH1H7YV1Z7D2C8K2730QBF/avatar/original/01F8MH58A357CV5K7R7TJMSH6S.jpg"
+ },
+ "id": "http://localhost:8080/users/the_mighty_zork",
+ "image": {
+ "mediaType": "image/jpeg",
+ "type": "Image",
+ "url": "http://localhost:8080/fileserver/01F8MH1H7YV1Z7D2C8K2730QBF/header/original/01PFPMWK2FF0D9WMHEJHR07C3Q.jpg"
+ },
+ "inbox": "http://localhost:8080/users/the_mighty_zork/inbox",
+ "manuallyApprovesFollowers": false,
+ "name": "original zork (he/they)",
+ "outbox": "http://localhost:8080/users/the_mighty_zork/outbox",
+ "preferredUsername": "the_mighty_zork",
+ "publicKey": {
+ "id": "http://localhost:8080/users/the_mighty_zork/main-key",
+ "owner": "http://localhost:8080/users/the_mighty_zork",
+ "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwXTcOAvM1Jiw5Ffpk0qn\nr0cwbNvFe/5zQ+Tp7tumK/ZnT37o7X0FUEXrxNi+dkhmeJ0gsaiN+JQGNUewvpSk\nPIAXKvi908aSfCGjs7bGlJCJCuDuL5d6m7hZnP9rt9fJc70GElPpG0jc9fXwlz7T\nlsPb2ecatmG05Y4jPwdC+oN4MNCv9yQzEvCVMzl76EJaM602kIHC1CISn0rDFmYd\n9rSN7XPlNJw1F6PbpJ/BWQ+pXHKw3OEwNTETAUNYiVGnZU+B7a7bZC9f6/aPbJuV\nt8Qmg+UnDvW1Y8gmfHnxaWG2f5TDBvCHmcYtucIZPLQD4trAozC4ryqlmCWQNKbt\n0wIDAQAB\n-----END PUBLIC KEY-----\n"
+ },
+ "published": "2022-05-20T11:09:18Z",
+ "summary": "\u003cp\u003ehey yo this is my profile!\u003c/p\u003e",
+ "tag": [],
+ "type": "Service",
+ "url": "http://localhost:8080/@the_mighty_zork"
+}`, string(bytes))
+}
+
func (suite *InternalToASTestSuite) TestAccountToASWithFields() {
testAccount := &gtsmodel.Account{}
*testAccount = *suite.testAccounts["local_account_2"]
- asPerson, err := suite.typeconverter.AccountToAS(context.Background(), testAccount)
+ accountable, err := suite.typeconverter.AccountToAS(context.Background(), testAccount)
suite.NoError(err)
- ser, err := ap.Serialize(asPerson)
+ ser, err := ap.Serialize(accountable)
suite.NoError(err)
bytes, err := json.MarshalIndent(ser, "", " ")
@@ -176,10 +243,10 @@ func (suite *InternalToASTestSuite) TestAccountToASAliasedAndMoved() {
suite.FailNow(err.Error())
}
- asPerson, err := suite.typeconverter.AccountToAS(context.Background(), testAccount)
+ accountable, err := suite.typeconverter.AccountToAS(context.Background(), testAccount)
suite.NoError(err)
- ser, err := ap.Serialize(asPerson)
+ ser, err := ap.Serialize(accountable)
suite.NoError(err)
bytes, err := json.MarshalIndent(ser, "", " ")
@@ -246,10 +313,10 @@ func (suite *InternalToASTestSuite) TestAccountToASWithOneField() {
*testAccount = *suite.testAccounts["local_account_2"]
testAccount.Fields = testAccount.Fields[0:1] // Take only one field.
- asPerson, err := suite.typeconverter.AccountToAS(context.Background(), testAccount)
+ accountable, err := suite.typeconverter.AccountToAS(context.Background(), testAccount)
suite.NoError(err)
- ser, err := ap.Serialize(asPerson)
+ ser, err := ap.Serialize(accountable)
suite.NoError(err)
bytes, err := json.MarshalIndent(ser, "", " ")
@@ -308,10 +375,10 @@ func (suite *InternalToASTestSuite) TestAccountToASWithEmoji() {
*testAccount = *suite.testAccounts["local_account_1"] // take zork for this test
testAccount.Emojis = []*gtsmodel.Emoji{suite.testEmojis["rainbow"]}
- asPerson, err := suite.typeconverter.AccountToAS(context.Background(), testAccount)
+ accountable, err := suite.typeconverter.AccountToAS(context.Background(), testAccount)
suite.NoError(err)
- ser, err := ap.Serialize(asPerson)
+ ser, err := ap.Serialize(accountable)
suite.NoError(err)
bytes, err := json.MarshalIndent(ser, "", " ")
@@ -381,10 +448,10 @@ func (suite *InternalToASTestSuite) TestAccountToASWithSharedInbox() {
sharedInbox := "http://localhost:8080/sharedInbox"
testAccount.SharedInboxURI = &sharedInbox
- asPerson, err := suite.typeconverter.AccountToAS(context.Background(), testAccount)
+ accountable, err := suite.typeconverter.AccountToAS(context.Background(), testAccount)
suite.NoError(err)
- ser, err := ap.Serialize(asPerson)
+ ser, err := ap.Serialize(accountable)
suite.NoError(err)
bytes, err := json.MarshalIndent(ser, "", " ")
diff --git a/internal/typeutils/wrap.go b/internal/typeutils/wrap.go
index 89bcdfc09..1230981d4 100644
--- a/internal/typeutils/wrap.go
+++ b/internal/typeutils/wrap.go
@@ -18,68 +18,45 @@
package typeutils
import (
- "net/url"
-
- "github.com/superseriousbusiness/activity/pub"
"github.com/superseriousbusiness/activity/streams"
"github.com/superseriousbusiness/activity/streams/vocab"
"github.com/superseriousbusiness/gotosocial/internal/ap"
- "github.com/superseriousbusiness/gotosocial/internal/gtserror"
- "github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
"github.com/superseriousbusiness/gotosocial/internal/id"
+ "github.com/superseriousbusiness/gotosocial/internal/log"
"github.com/superseriousbusiness/gotosocial/internal/uris"
)
-// WrapPersonInUpdate ...
-func (c *Converter) WrapPersonInUpdate(person vocab.ActivityStreamsPerson, originAccount *gtsmodel.Account) (vocab.ActivityStreamsUpdate, error) {
+// WrapAccountableInUpdate wraps the given accountable
+// in an Update activity with the accountable as the object.
+//
+// The Update will be addressed to Public and bcc followers.
+func (c *Converter) WrapAccountableInUpdate(accountable ap.Accountable) (vocab.ActivityStreamsUpdate, error) {
update := streams.NewActivityStreamsUpdate()
- // set the actor
- actorURI, err := url.Parse(originAccount.URI)
- if err != nil {
- return nil, gtserror.Newf("error parsing url %s: %w", originAccount.URI, err)
- }
- actorProp := streams.NewActivityStreamsActorProperty()
- actorProp.AppendIRI(actorURI)
- update.SetActivityStreamsActor(actorProp)
+ // Set actor IRI to this accountable's IRI.
+ ap.AppendActorIRIs(update, ap.GetJSONLDId(accountable))
- // set the ID
- newID, err := id.NewRandomULID()
- if err != nil {
- return nil, err
- }
+ // Set the update ID
+ updateURI := uris.GenerateURIForUpdate(ap.ExtractPreferredUsername(accountable), id.NewULID())
+ ap.MustSet(ap.SetJSONLDIdStr, ap.WithJSONLDId(update), updateURI)
- idString := uris.GenerateURIForUpdate(originAccount.Username, newID)
- idURI, err := url.Parse(idString)
- if err != nil {
- return nil, gtserror.Newf("error parsing url %s: %w", idString, err)
- }
- idProp := streams.NewJSONLDIdProperty()
- idProp.SetIRI(idURI)
- update.SetJSONLDId(idProp)
-
- // set the person as the object here
+ // Set the accountable as the object of the update.
objectProp := streams.NewActivityStreamsObjectProperty()
- objectProp.AppendActivityStreamsPerson(person)
+ switch t := accountable.(type) {
+ case vocab.ActivityStreamsPerson:
+ objectProp.AppendActivityStreamsPerson(t)
+ case vocab.ActivityStreamsService:
+ objectProp.AppendActivityStreamsService(t)
+ default:
+ log.Panicf(nil, "%T was neither person nor service", t)
+ }
update.SetActivityStreamsObject(objectProp)
- // to should be public
- toURI, err := url.Parse(pub.PublicActivityPubIRI)
- if err != nil {
- return nil, gtserror.Newf("error parsing url %s: %w", pub.PublicActivityPubIRI, err)
- }
- toProp := streams.NewActivityStreamsToProperty()
- toProp.AppendIRI(toURI)
- update.SetActivityStreamsTo(toProp)
+ // to should be public.
+ ap.AppendTo(update, ap.PublicURI())
- // bcc followers
- followersURI, err := url.Parse(originAccount.FollowersURI)
- if err != nil {
- return nil, gtserror.Newf("error parsing url %s: %w", originAccount.FollowersURI, err)
- }
- bccProp := streams.NewActivityStreamsBccProperty()
- bccProp.AppendIRI(followersURI)
- update.SetActivityStreamsBcc(bccProp)
+ // bcc should be followers.
+ ap.AppendBcc(update, ap.GetFollowers(accountable))
return update, nil
}
diff --git a/internal/typeutils/wrap_test.go b/internal/typeutils/wrap_test.go
index 1085c8c66..8c8af7506 100644
--- a/internal/typeutils/wrap_test.go
+++ b/internal/typeutils/wrap_test.go
@@ -139,6 +139,86 @@ func (suite *WrapTestSuite) TestWrapNoteInCreate() {
}`, string(bytes))
}
+func (suite *WrapTestSuite) TestWrapAccountableInUpdate() {
+ testAccount := suite.testAccounts["local_account_1"]
+
+ accountable, err := suite.typeconverter.AccountToAS(context.Background(), testAccount)
+ if err != nil {
+ suite.FailNow(err.Error())
+ }
+
+ create, err := suite.typeconverter.WrapAccountableInUpdate(accountable)
+ if err != nil {
+ suite.FailNow(err.Error())
+ }
+
+ createI, err := ap.Serialize(create)
+ if err != nil {
+ suite.FailNow(err.Error())
+ }
+
+ // Get the ID as it's not determinate.
+ createID := ap.GetJSONLDId(create)
+
+ bytes, err := json.MarshalIndent(createI, "", " ")
+ if err != nil {
+ suite.FailNow(err.Error())
+ }
+
+ suite.Equal(`{
+ "@context": [
+ "https://w3id.org/security/v1",
+ "https://www.w3.org/ns/activitystreams",
+ {
+ "discoverable": "toot:discoverable",
+ "featured": {
+ "@id": "toot:featured",
+ "@type": "@id"
+ },
+ "manuallyApprovesFollowers": "as:manuallyApprovesFollowers",
+ "toot": "http://joinmastodon.org/ns#"
+ }
+ ],
+ "actor": "http://localhost:8080/users/the_mighty_zork",
+ "bcc": "http://localhost:8080/users/the_mighty_zork/followers",
+ "id": "`+createID.String()+`",
+ "object": {
+ "discoverable": true,
+ "featured": "http://localhost:8080/users/the_mighty_zork/collections/featured",
+ "followers": "http://localhost:8080/users/the_mighty_zork/followers",
+ "following": "http://localhost:8080/users/the_mighty_zork/following",
+ "icon": {
+ "mediaType": "image/jpeg",
+ "type": "Image",
+ "url": "http://localhost:8080/fileserver/01F8MH1H7YV1Z7D2C8K2730QBF/avatar/original/01F8MH58A357CV5K7R7TJMSH6S.jpg"
+ },
+ "id": "http://localhost:8080/users/the_mighty_zork",
+ "image": {
+ "mediaType": "image/jpeg",
+ "type": "Image",
+ "url": "http://localhost:8080/fileserver/01F8MH1H7YV1Z7D2C8K2730QBF/header/original/01PFPMWK2FF0D9WMHEJHR07C3Q.jpg"
+ },
+ "inbox": "http://localhost:8080/users/the_mighty_zork/inbox",
+ "manuallyApprovesFollowers": false,
+ "name": "original zork (he/they)",
+ "outbox": "http://localhost:8080/users/the_mighty_zork/outbox",
+ "preferredUsername": "the_mighty_zork",
+ "publicKey": {
+ "id": "http://localhost:8080/users/the_mighty_zork/main-key",
+ "owner": "http://localhost:8080/users/the_mighty_zork",
+ "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwXTcOAvM1Jiw5Ffpk0qn\nr0cwbNvFe/5zQ+Tp7tumK/ZnT37o7X0FUEXrxNi+dkhmeJ0gsaiN+JQGNUewvpSk\nPIAXKvi908aSfCGjs7bGlJCJCuDuL5d6m7hZnP9rt9fJc70GElPpG0jc9fXwlz7T\nlsPb2ecatmG05Y4jPwdC+oN4MNCv9yQzEvCVMzl76EJaM602kIHC1CISn0rDFmYd\n9rSN7XPlNJw1F6PbpJ/BWQ+pXHKw3OEwNTETAUNYiVGnZU+B7a7bZC9f6/aPbJuV\nt8Qmg+UnDvW1Y8gmfHnxaWG2f5TDBvCHmcYtucIZPLQD4trAozC4ryqlmCWQNKbt\n0wIDAQAB\n-----END PUBLIC KEY-----\n"
+ },
+ "published": "2022-05-20T11:09:18Z",
+ "summary": "\u003cp\u003ehey yo this is my profile!\u003c/p\u003e",
+ "tag": [],
+ "type": "Person",
+ "url": "http://localhost:8080/@the_mighty_zork"
+ },
+ "to": "https://www.w3.org/ns/activitystreams#Public",
+ "type": "Update"
+}`, string(bytes))
+}
+
func TestWrapTestSuite(t *testing.T) {
suite.Run(t, new(WrapTestSuite))
}
diff --git a/testrig/testmodels.go b/testrig/testmodels.go
index 81c3a85c5..da4202eed 100644
--- a/testrig/testmodels.go
+++ b/testrig/testmodels.go
@@ -2853,7 +2853,7 @@ func NewTestActivities(accounts map[string]*gtsmodel.Account) map[string]Activit
"this is a public status, please forward it!",
"",
URLMustParse("http://example.org/users/Some_User"),
- []*url.URL{URLMustParse(pub.PublicActivityPubIRI)},
+ []*url.URL{ap.PublicURI()},
nil,
false,
[]vocab.ActivityStreamsMention{},
@@ -3207,7 +3207,7 @@ func NewTestFediStatuses() map[string]vocab.ActivityStreamsNote {
"this is a public status, please forward it!",
"",
URLMustParse("http://example.org/users/Some_User"),
- []*url.URL{URLMustParse(pub.PublicActivityPubIRI)},
+ []*url.URL{ap.PublicURI()},
nil,
false,
[]vocab.ActivityStreamsMention{},
@@ -3228,7 +3228,7 @@ func NewTestFediStatuses() map[string]vocab.ActivityStreamsNote {
"",
URLMustParse("https://unknown-instance.com/users/brand_new_person"),
[]*url.URL{
- URLMustParse(pub.PublicActivityPubIRI),
+ ap.PublicURI(),
},
[]*url.URL{},
false,
@@ -3244,7 +3244,7 @@ func NewTestFediStatuses() map[string]vocab.ActivityStreamsNote {
"",
URLMustParse("https://unknown-instance.com/users/brand_new_person"),
[]*url.URL{
- URLMustParse(pub.PublicActivityPubIRI),
+ ap.PublicURI(),
},
[]*url.URL{},
false,
@@ -3265,7 +3265,7 @@ func NewTestFediStatuses() map[string]vocab.ActivityStreamsNote {
"",
URLMustParse("https://unknown-instance.com/users/brand_new_person"),
[]*url.URL{
- URLMustParse(pub.PublicActivityPubIRI),
+ ap.PublicURI(),
},
[]*url.URL{},
false,
@@ -3286,7 +3286,7 @@ func NewTestFediStatuses() map[string]vocab.ActivityStreamsNote {
"",
URLMustParse("https://turnip.farm/users/turniplover6969"),
[]*url.URL{
- URLMustParse(pub.PublicActivityPubIRI),
+ ap.PublicURI(),
},
[]*url.URL{},
false,
@@ -3309,7 +3309,7 @@ func NewTestFediStatuses() map[string]vocab.ActivityStreamsNote {
"",
URLMustParse("http://fossbros-anonymous.io/users/foss_satan"),
[]*url.URL{
- URLMustParse(pub.PublicActivityPubIRI),
+ ap.PublicURI(),
},
[]*url.URL{},
false,
diff --git a/testrig/transportcontroller.go b/testrig/transportcontroller.go
index 3bc8752e0..b886e5c40 100644
--- a/testrig/transportcontroller.go
+++ b/testrig/transportcontroller.go
@@ -29,6 +29,7 @@ import (
"github.com/superseriousbusiness/activity/pub"
"github.com/superseriousbusiness/activity/streams"
"github.com/superseriousbusiness/activity/streams/vocab"
+ "github.com/superseriousbusiness/gotosocial/internal/ap"
apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model"
"github.com/superseriousbusiness/gotosocial/internal/federation"
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
@@ -81,7 +82,7 @@ type MockHTTPClient struct {
// to customize how the client is mocked.
//
// Note that you should never ever make ACTUAL http calls with this thing.
-func NewMockHTTPClient(do func(req *http.Request) (*http.Response, error), relativeMediaPath string, extraPeople ...vocab.ActivityStreamsPerson) *MockHTTPClient {
+func NewMockHTTPClient(do func(req *http.Request) (*http.Response, error), relativeMediaPath string, extraPeople ...ap.Accountable) *MockHTTPClient {
mockHTTPClient := &MockHTTPClient{}
if do != nil {