mirror of
				https://github.com/superseriousbusiness/gotosocial.git
				synced 2025-11-02 20:02:25 -06:00 
			
		
		
		
	[chore] Add test for dereferencing Owncast service account (#613)
This commit is contained in:
		
					parent
					
						
							
								1cdc163276
							
						
					
				
			
			
				commit
				
					
						dc8cc7e364
					
				
			
		
					 5 changed files with 344 additions and 0 deletions
				
			
		| 
						 | 
				
			
			@ -51,6 +51,26 @@ func (suite *AccountTestSuite) TestDereferenceGroup() {
 | 
			
		|||
	suite.Equal(ap.ActorGroup, dbGroup.ActorType)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (suite *AccountTestSuite) TestDereferenceService() {
 | 
			
		||||
	fetchingAccount := suite.testAccounts["local_account_1"]
 | 
			
		||||
 | 
			
		||||
	serviceURL := testrig.URLMustParse("https://owncast.example.org/federation/user/rgh")
 | 
			
		||||
	service, err := suite.dereferencer.GetRemoteAccount(context.Background(), fetchingAccount.Username, serviceURL, false, false)
 | 
			
		||||
	suite.NoError(err)
 | 
			
		||||
	suite.NotNil(service)
 | 
			
		||||
	suite.NotNil(service)
 | 
			
		||||
 | 
			
		||||
	// service values should be set
 | 
			
		||||
	suite.Equal("https://owncast.example.org/federation/user/rgh", service.URI)
 | 
			
		||||
	suite.Equal("https://owncast.example.org/federation/user/rgh", service.URL)
 | 
			
		||||
 | 
			
		||||
	// service should be in the database
 | 
			
		||||
	dbService, err := suite.db.GetAccountByURI(context.Background(), service.URI)
 | 
			
		||||
	suite.NoError(err)
 | 
			
		||||
	suite.Equal(service.ID, dbService.ID)
 | 
			
		||||
	suite.Equal(ap.ActorService, dbService.ActorType)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestAccountTestSuite(t *testing.T) {
 | 
			
		||||
	suite.Run(t, new(AccountTestSuite))
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -46,6 +46,7 @@ type DereferencerStandardTestSuite struct {
 | 
			
		|||
	testRemoteStatuses    map[string]vocab.ActivityStreamsNote
 | 
			
		||||
	testRemotePeople      map[string]vocab.ActivityStreamsPerson
 | 
			
		||||
	testRemoteGroups      map[string]vocab.ActivityStreamsGroup
 | 
			
		||||
	testRemoteServices    map[string]vocab.ActivityStreamsService
 | 
			
		||||
	testRemoteAttachments map[string]testrig.RemoteAttachmentFile
 | 
			
		||||
	testAccounts          map[string]*gtsmodel.Account
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -60,6 +61,7 @@ func (suite *DereferencerStandardTestSuite) SetupTest() {
 | 
			
		|||
	suite.testRemoteStatuses = testrig.NewTestFediStatuses()
 | 
			
		||||
	suite.testRemotePeople = testrig.NewTestFediPeople()
 | 
			
		||||
	suite.testRemoteGroups = testrig.NewTestFediGroups()
 | 
			
		||||
	suite.testRemoteServices = testrig.NewTestFediServices()
 | 
			
		||||
	suite.testRemoteAttachments = testrig.NewTestFediAttachments("../../../testrig/media")
 | 
			
		||||
 | 
			
		||||
	suite.db = testrig.NewTestDB()
 | 
			
		||||
| 
						 | 
				
			
			@ -126,6 +128,19 @@ func (suite *DereferencerStandardTestSuite) mockTransportController() transport.
 | 
			
		|||
			responseType = "application/activity+json"
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if service, ok := suite.testRemoteServices[req.URL.String()]; ok {
 | 
			
		||||
			serviceI, err := streams.Serialize(service)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				panic(err)
 | 
			
		||||
			}
 | 
			
		||||
			serviceJson, err := json.Marshal(serviceI)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				panic(err)
 | 
			
		||||
			}
 | 
			
		||||
			responseBytes = serviceJson
 | 
			
		||||
			responseType = "application/activity+json"
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if attachment, ok := suite.testRemoteAttachments[req.URL.String()]; ok {
 | 
			
		||||
			responseBytes = attachment.Data
 | 
			
		||||
			responseType = attachment.ContentType
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -157,6 +157,49 @@ func (suite *ASToInternalTestSuite) TestParseReplyWithMention() {
 | 
			
		|||
	suite.Equal(gtsmodel.VisibilityUnlocked, status.Visibility)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (suite *ASToInternalTestSuite) TestParseOwncastService() {
 | 
			
		||||
	m := make(map[string]interface{})
 | 
			
		||||
	err := json.Unmarshal([]byte(owncastService), &m)
 | 
			
		||||
	suite.NoError(err)
 | 
			
		||||
 | 
			
		||||
	t, err := streams.ToType(context.Background(), m)
 | 
			
		||||
	suite.NoError(err)
 | 
			
		||||
 | 
			
		||||
	rep, ok := t.(ap.Accountable)
 | 
			
		||||
	suite.True(ok)
 | 
			
		||||
 | 
			
		||||
	acct, err := suite.typeconverter.ASRepresentationToAccount(context.Background(), rep, false)
 | 
			
		||||
	suite.NoError(err)
 | 
			
		||||
 | 
			
		||||
	suite.Equal("rgh", acct.Username)
 | 
			
		||||
	suite.Equal("owncast.example.org", acct.Domain)
 | 
			
		||||
	suite.Equal("https://owncast.example.org/logo/external", acct.AvatarRemoteURL)
 | 
			
		||||
	suite.Equal("https://owncast.example.org/logo/external", acct.HeaderRemoteURL)
 | 
			
		||||
	suite.Equal("Rob's Owncast Server", acct.DisplayName)
 | 
			
		||||
	suite.Equal("linux audio stuff ", acct.Note)
 | 
			
		||||
	suite.True(acct.Bot)
 | 
			
		||||
	suite.False(acct.Locked)
 | 
			
		||||
	suite.True(acct.Discoverable)
 | 
			
		||||
	suite.Equal("https://owncast.example.org/federation/user/rgh", acct.URI)
 | 
			
		||||
	suite.Equal("https://owncast.example.org/federation/user/rgh", acct.URL)
 | 
			
		||||
	suite.Equal("https://owncast.example.org/federation/user/rgh/inbox", acct.InboxURI)
 | 
			
		||||
	suite.Equal("https://owncast.example.org/federation/user/rgh/outbox", acct.OutboxURI)
 | 
			
		||||
	suite.Equal("https://owncast.example.org/federation/user/rgh/followers", acct.FollowersURI)
 | 
			
		||||
	suite.Equal("Service", acct.ActorType)
 | 
			
		||||
	suite.Equal("https://owncast.example.org/federation/user/rgh#main-key", acct.PublicKeyURI)
 | 
			
		||||
 | 
			
		||||
	acct.ID = "01G42D57DTCJQE8XT9KD4K88RK"
 | 
			
		||||
 | 
			
		||||
	apiAcct, err := suite.typeconverter.AccountToAPIAccountPublic(context.Background(), acct)
 | 
			
		||||
	suite.NoError(err)
 | 
			
		||||
	suite.NotNil(apiAcct)
 | 
			
		||||
 | 
			
		||||
	b, err := json.Marshal(apiAcct)
 | 
			
		||||
	suite.NoError(err)
 | 
			
		||||
 | 
			
		||||
	fmt.Printf("\n\n\n%s\n\n\n", string(b))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestASToInternalTestSuite(t *testing.T) {
 | 
			
		||||
	suite.Run(t, new(ASToInternalTestSuite))
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -414,6 +414,57 @@ const (
 | 
			
		|||
		}
 | 
			
		||||
	  }	  
 | 
			
		||||
	`
 | 
			
		||||
	owncastService = `
 | 
			
		||||
	{
 | 
			
		||||
		"@context": [
 | 
			
		||||
		  "https://www.w3.org/ns/activitystreams",
 | 
			
		||||
		  "http://joinmastodon.org/ns",
 | 
			
		||||
		  "https://w3id.org/security/v1"
 | 
			
		||||
		],
 | 
			
		||||
		"attachment": {
 | 
			
		||||
		  "name": "Stream",
 | 
			
		||||
		  "type": "PropertyValue",
 | 
			
		||||
		  "value": "<a href=\"https://owncast.example.org\" rel=\"me nofollow noopener noreferrer\" target=\"_blank\">https://owncast.example.org</a>"
 | 
			
		||||
		},
 | 
			
		||||
		"discoverable": true,
 | 
			
		||||
		"followers": "https://owncast.example.org/federation/user/rgh/followers",
 | 
			
		||||
		"icon": {
 | 
			
		||||
		  "type": "Image",
 | 
			
		||||
		  "url": "https://owncast.example.org/logo/external"
 | 
			
		||||
		},
 | 
			
		||||
		"id": "https://owncast.example.org/federation/user/rgh",
 | 
			
		||||
		"image": {
 | 
			
		||||
		  "type": "Image",
 | 
			
		||||
		  "url": "https://owncast.example.org/logo/external"
 | 
			
		||||
		},
 | 
			
		||||
		"inbox": "https://owncast.example.org/federation/user/rgh/inbox",
 | 
			
		||||
		"manuallyApprovesFollowers": false,
 | 
			
		||||
		"name": "Rob's Owncast Server",
 | 
			
		||||
		"outbox": "https://owncast.example.org/federation/user/rgh/outbox",
 | 
			
		||||
		"preferredUsername": "rgh",
 | 
			
		||||
		"publicKey": {
 | 
			
		||||
		  "id": "https://owncast.example.org/federation/user/rgh#main-key",
 | 
			
		||||
		  "owner": "https://owncast.example.org/federation/user/rgh",
 | 
			
		||||
		  "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAurN+lUNwcGV2poLNtaoT\naRtJzN6s4SDcBmIFk82lxhdMKC6/Nssm+hvDuxWGqL0+dHwSvrG11rA6irGuSzRk\niHjYyVwYe/p1CxqJxzUfZVJAWdsCFWy+HtDrTWs5sggj1MiL59uGxvkCep+OYBuG\nBI8CvSOMLrDp8soCg3EY+zSgpXtGMuRaaUukavsfuglApShB61ny7W8LG252iKC5\nmyO8L7l8TNa5BrIi/pRHLzvv9aWiCa8VKtvmqj+mClEhpkRhImSk5GPJXgouTTgl\ntT28NYYciSf9YYgZ0SNWHdLUCdkMF592j4+BbkPvdgzc70G4yyu2GcWnTzBuvF5X\nYwIDAQAB\n-----END PUBLIC KEY-----\n"
 | 
			
		||||
		},
 | 
			
		||||
		"published": "2022-05-22T18:44:57Z",
 | 
			
		||||
		"summary": "linux audio stuff ",
 | 
			
		||||
		"tag": [
 | 
			
		||||
		  {
 | 
			
		||||
			"href": "https://directory.owncast.online/tags/owncast",
 | 
			
		||||
			"name": "#owncast",
 | 
			
		||||
			"type": "Hashtag"
 | 
			
		||||
		  },
 | 
			
		||||
		  {
 | 
			
		||||
			"href": "https://directory.owncast.online/tags/streaming",
 | 
			
		||||
			"name": "#streaming",
 | 
			
		||||
			"type": "Hashtag"
 | 
			
		||||
		  }
 | 
			
		||||
		],
 | 
			
		||||
		"type": "Service",
 | 
			
		||||
		"url": "https://owncast.example.org/federation/user/rgh"
 | 
			
		||||
	} 
 | 
			
		||||
`
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type TypeUtilsTestSuite struct {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1821,6 +1821,37 @@ func NewTestFediGroups() map[string]vocab.ActivityStreamsGroup {
 | 
			
		|||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewTestFediServices() map[string]vocab.ActivityStreamsService {
 | 
			
		||||
	newService1Priv, err := rsa.GenerateKey(rand.Reader, 2048)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		panic(err)
 | 
			
		||||
	}
 | 
			
		||||
	newService1Pub := &newService1Priv.PublicKey
 | 
			
		||||
 | 
			
		||||
	return map[string]vocab.ActivityStreamsService{
 | 
			
		||||
		"https://owncast.example.org/federation/user/rgh": newAPService(
 | 
			
		||||
			URLMustParse("https://owncast.example.org/federation/user/rgh"),
 | 
			
		||||
			nil,
 | 
			
		||||
			URLMustParse("https://owncast.example.org/federation/user/rgh/followers"),
 | 
			
		||||
			URLMustParse("https://owncast.example.org/federation/user/rgh/inbox"),
 | 
			
		||||
			URLMustParse("https://owncast.example.org/federation/user/rgh/outbox"),
 | 
			
		||||
			nil,
 | 
			
		||||
			"rgh",
 | 
			
		||||
			"linux audio stuff ",
 | 
			
		||||
			"",
 | 
			
		||||
			URLMustParse("https://owncast.example.org/federation/user/rgh"),
 | 
			
		||||
			true,
 | 
			
		||||
			URLMustParse("https://owncast.example.org/federation/user/rgh#main-key"),
 | 
			
		||||
			newService1Pub,
 | 
			
		||||
			nil,
 | 
			
		||||
			"image/jpeg",
 | 
			
		||||
			nil,
 | 
			
		||||
			"image/png",
 | 
			
		||||
			false,
 | 
			
		||||
		),
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RemoteAttachmentFile mimics a remote (federated) attachment
 | 
			
		||||
type RemoteAttachmentFile struct {
 | 
			
		||||
	Data        []byte
 | 
			
		||||
| 
						 | 
				
			
			@ -2459,6 +2490,190 @@ func newAPGroup(
 | 
			
		|||
	return group
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func newAPService(
 | 
			
		||||
	profileIDURI *url.URL,
 | 
			
		||||
	followingURI *url.URL,
 | 
			
		||||
	followersURI *url.URL,
 | 
			
		||||
	inboxURI *url.URL,
 | 
			
		||||
	outboxURI *url.URL,
 | 
			
		||||
	featuredURI *url.URL,
 | 
			
		||||
	username string,
 | 
			
		||||
	displayName string,
 | 
			
		||||
	note string,
 | 
			
		||||
	profileURL *url.URL,
 | 
			
		||||
	discoverable bool,
 | 
			
		||||
	publicKeyURI *url.URL,
 | 
			
		||||
	pkey *rsa.PublicKey,
 | 
			
		||||
	avatarURL *url.URL,
 | 
			
		||||
	avatarContentType string,
 | 
			
		||||
	headerURL *url.URL,
 | 
			
		||||
	headerContentType string,
 | 
			
		||||
	manuallyApprovesFollowers bool,
 | 
			
		||||
) vocab.ActivityStreamsService {
 | 
			
		||||
	service := streams.NewActivityStreamsService()
 | 
			
		||||
 | 
			
		||||
	// id should be the activitypub URI of this group
 | 
			
		||||
	// something like https://example.org/users/example_group
 | 
			
		||||
	idProp := streams.NewJSONLDIdProperty()
 | 
			
		||||
	idProp.SetIRI(profileIDURI)
 | 
			
		||||
	service.SetJSONLDId(idProp)
 | 
			
		||||
 | 
			
		||||
	// following
 | 
			
		||||
	// The URI for retrieving a list of accounts this group is following
 | 
			
		||||
	followingProp := streams.NewActivityStreamsFollowingProperty()
 | 
			
		||||
	followingProp.SetIRI(followingURI)
 | 
			
		||||
	service.SetActivityStreamsFollowing(followingProp)
 | 
			
		||||
 | 
			
		||||
	// followers
 | 
			
		||||
	// The URI for retrieving a list of this user's followers
 | 
			
		||||
	followersProp := streams.NewActivityStreamsFollowersProperty()
 | 
			
		||||
	followersProp.SetIRI(followersURI)
 | 
			
		||||
	service.SetActivityStreamsFollowers(followersProp)
 | 
			
		||||
 | 
			
		||||
	// inbox
 | 
			
		||||
	// the activitypub inbox of this user for accepting messages
 | 
			
		||||
	inboxProp := streams.NewActivityStreamsInboxProperty()
 | 
			
		||||
	inboxProp.SetIRI(inboxURI)
 | 
			
		||||
	service.SetActivityStreamsInbox(inboxProp)
 | 
			
		||||
 | 
			
		||||
	// outbox
 | 
			
		||||
	// the activitypub outbox of this user for serving messages
 | 
			
		||||
	outboxProp := streams.NewActivityStreamsOutboxProperty()
 | 
			
		||||
	outboxProp.SetIRI(outboxURI)
 | 
			
		||||
	service.SetActivityStreamsOutbox(outboxProp)
 | 
			
		||||
 | 
			
		||||
	// featured posts
 | 
			
		||||
	// Pinned posts.
 | 
			
		||||
	featuredProp := streams.NewTootFeaturedProperty()
 | 
			
		||||
	featuredProp.SetIRI(featuredURI)
 | 
			
		||||
	service.SetTootFeatured(featuredProp)
 | 
			
		||||
 | 
			
		||||
	// featuredTags
 | 
			
		||||
	// NOT IMPLEMENTED
 | 
			
		||||
 | 
			
		||||
	// preferredUsername
 | 
			
		||||
	// Used for Webfinger lookup. Must be unique on the domain, and must correspond to a Webfinger acct: URI.
 | 
			
		||||
	preferredUsernameProp := streams.NewActivityStreamsPreferredUsernameProperty()
 | 
			
		||||
	preferredUsernameProp.SetXMLSchemaString(username)
 | 
			
		||||
	service.SetActivityStreamsPreferredUsername(preferredUsernameProp)
 | 
			
		||||
 | 
			
		||||
	// name
 | 
			
		||||
	// Used as profile display name.
 | 
			
		||||
	nameProp := streams.NewActivityStreamsNameProperty()
 | 
			
		||||
	if displayName != "" {
 | 
			
		||||
		nameProp.AppendXMLSchemaString(displayName)
 | 
			
		||||
	} else {
 | 
			
		||||
		nameProp.AppendXMLSchemaString(username)
 | 
			
		||||
	}
 | 
			
		||||
	service.SetActivityStreamsName(nameProp)
 | 
			
		||||
 | 
			
		||||
	// summary
 | 
			
		||||
	// Used as profile bio.
 | 
			
		||||
	if note != "" {
 | 
			
		||||
		summaryProp := streams.NewActivityStreamsSummaryProperty()
 | 
			
		||||
		summaryProp.AppendXMLSchemaString(note)
 | 
			
		||||
		service.SetActivityStreamsSummary(summaryProp)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// url
 | 
			
		||||
	// Used as profile link.
 | 
			
		||||
	urlProp := streams.NewActivityStreamsUrlProperty()
 | 
			
		||||
	urlProp.AppendIRI(profileURL)
 | 
			
		||||
	service.SetActivityStreamsUrl(urlProp)
 | 
			
		||||
 | 
			
		||||
	// manuallyApprovesFollowers
 | 
			
		||||
	manuallyApprovesFollowersProp := streams.NewActivityStreamsManuallyApprovesFollowersProperty()
 | 
			
		||||
	manuallyApprovesFollowersProp.Set(manuallyApprovesFollowers)
 | 
			
		||||
	service.SetActivityStreamsManuallyApprovesFollowers(manuallyApprovesFollowersProp)
 | 
			
		||||
 | 
			
		||||
	// discoverable
 | 
			
		||||
	// Will be shown in the profile directory.
 | 
			
		||||
	discoverableProp := streams.NewTootDiscoverableProperty()
 | 
			
		||||
	discoverableProp.Set(discoverable)
 | 
			
		||||
	service.SetTootDiscoverable(discoverableProp)
 | 
			
		||||
 | 
			
		||||
	// devices
 | 
			
		||||
	// NOT IMPLEMENTED, probably won't implement
 | 
			
		||||
 | 
			
		||||
	// alsoKnownAs
 | 
			
		||||
	// Required for Move activity.
 | 
			
		||||
	// TODO: NOT IMPLEMENTED **YET** -- this needs to be added as an activitypub extension to https://github.com/go-fed/activity, see https://github.com/go-fed/activity/tree/master/astool
 | 
			
		||||
 | 
			
		||||
	// publicKey
 | 
			
		||||
	// Required for signatures.
 | 
			
		||||
	publicKeyProp := streams.NewW3IDSecurityV1PublicKeyProperty()
 | 
			
		||||
 | 
			
		||||
	// create the public key
 | 
			
		||||
	publicKey := streams.NewW3IDSecurityV1PublicKey()
 | 
			
		||||
 | 
			
		||||
	// set ID for the public key
 | 
			
		||||
	publicKeyIDProp := streams.NewJSONLDIdProperty()
 | 
			
		||||
	publicKeyIDProp.SetIRI(publicKeyURI)
 | 
			
		||||
	publicKey.SetJSONLDId(publicKeyIDProp)
 | 
			
		||||
 | 
			
		||||
	// set owner for the public key
 | 
			
		||||
	publicKeyOwnerProp := streams.NewW3IDSecurityV1OwnerProperty()
 | 
			
		||||
	publicKeyOwnerProp.SetIRI(profileIDURI)
 | 
			
		||||
	publicKey.SetW3IDSecurityV1Owner(publicKeyOwnerProp)
 | 
			
		||||
 | 
			
		||||
	// set the pem key itself
 | 
			
		||||
	encodedPublicKey, err := x509.MarshalPKIXPublicKey(pkey)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		panic(err)
 | 
			
		||||
	}
 | 
			
		||||
	publicKeyBytes := pem.EncodeToMemory(&pem.Block{
 | 
			
		||||
		Type:  "PUBLIC KEY",
 | 
			
		||||
		Bytes: encodedPublicKey,
 | 
			
		||||
	})
 | 
			
		||||
	publicKeyPEMProp := streams.NewW3IDSecurityV1PublicKeyPemProperty()
 | 
			
		||||
	publicKeyPEMProp.Set(string(publicKeyBytes))
 | 
			
		||||
	publicKey.SetW3IDSecurityV1PublicKeyPem(publicKeyPEMProp)
 | 
			
		||||
 | 
			
		||||
	// append the public key to the public key property
 | 
			
		||||
	publicKeyProp.AppendW3IDSecurityV1PublicKey(publicKey)
 | 
			
		||||
 | 
			
		||||
	// set the public key property on the Person
 | 
			
		||||
	service.SetW3IDSecurityV1PublicKey(publicKeyProp)
 | 
			
		||||
 | 
			
		||||
	// tag
 | 
			
		||||
	// TODO: Any tags used in the summary of this profile
 | 
			
		||||
 | 
			
		||||
	// attachment
 | 
			
		||||
	// Used for profile fields.
 | 
			
		||||
	// TODO: The PropertyValue type has to be added: https://schema.org/PropertyValue
 | 
			
		||||
 | 
			
		||||
	// endpoints
 | 
			
		||||
	// NOT IMPLEMENTED -- this is for shared inbox which we don't use
 | 
			
		||||
 | 
			
		||||
	// icon
 | 
			
		||||
	// Used as profile avatar.
 | 
			
		||||
	iconProperty := streams.NewActivityStreamsIconProperty()
 | 
			
		||||
	iconImage := streams.NewActivityStreamsImage()
 | 
			
		||||
	mediaType := streams.NewActivityStreamsMediaTypeProperty()
 | 
			
		||||
	mediaType.Set(avatarContentType)
 | 
			
		||||
	iconImage.SetActivityStreamsMediaType(mediaType)
 | 
			
		||||
	avatarURLProperty := streams.NewActivityStreamsUrlProperty()
 | 
			
		||||
	avatarURLProperty.AppendIRI(avatarURL)
 | 
			
		||||
	iconImage.SetActivityStreamsUrl(avatarURLProperty)
 | 
			
		||||
	iconProperty.AppendActivityStreamsImage(iconImage)
 | 
			
		||||
	service.SetActivityStreamsIcon(iconProperty)
 | 
			
		||||
 | 
			
		||||
	// image
 | 
			
		||||
	// Used as profile header.
 | 
			
		||||
	headerProperty := streams.NewActivityStreamsImageProperty()
 | 
			
		||||
	headerImage := streams.NewActivityStreamsImage()
 | 
			
		||||
	headerMediaType := streams.NewActivityStreamsMediaTypeProperty()
 | 
			
		||||
	mediaType.Set(headerContentType)
 | 
			
		||||
	headerImage.SetActivityStreamsMediaType(headerMediaType)
 | 
			
		||||
	headerURLProperty := streams.NewActivityStreamsUrlProperty()
 | 
			
		||||
	headerURLProperty.AppendIRI(headerURL)
 | 
			
		||||
	headerImage.SetActivityStreamsUrl(headerURLProperty)
 | 
			
		||||
	headerProperty.AppendActivityStreamsImage(headerImage)
 | 
			
		||||
	service.SetActivityStreamsImage(headerProperty)
 | 
			
		||||
 | 
			
		||||
	return service
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func newAPMention(uri *url.URL, namestring string) vocab.ActivityStreamsMention {
 | 
			
		||||
	mention := streams.NewActivityStreamsMention()
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue