mirror of
https://github.com/superseriousbusiness/gotosocial.git
synced 2025-10-29 01:22:26 -05:00
[feature] Support incoming avatar/header descriptions (#4275)
Signed-off-by: nicole mikołajczyk <git@mkljczk.pl> # Description Follow-up to #4270 Closes https://codeberg.org/superseriousbusiness/gotosocial/issues/3450 ## Checklist - [x] I/we have read the [GoToSocial contribution guidelines](https://codeberg.org/superseriousbusiness/gotosocial/src/branch/main/CONTRIBUTING.md). - [ ] I/we have discussed the proposed changes already, either in an issue on the repository, or in the Matrix chat. - [x] I/we have not leveraged AI to create the proposed changes. - [x] I/we have performed a self-review of added code. - [x] I/we have written code that is legible and maintainable by others. - [x] I/we have commented the added code, particularly in hard-to-understand areas. - [ ] I/we have made any necessary changes to documentation. - [x] I/we have added tests that cover new code. - [x] I/we have run tests and they pass locally with the changes. - [x] I/we have run `go fmt ./...` and `golangci-lint run`. Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4275 Co-authored-by: nicole mikołajczyk <git@mkljczk.pl> Co-committed-by: nicole mikołajczyk <git@mkljczk.pl>
This commit is contained in:
parent
29d481d769
commit
bfc8c31e5f
5 changed files with 238 additions and 6 deletions
|
|
@ -370,6 +370,54 @@ func ExtractIconURI(i WithIcon) (*url.URL, error) {
|
||||||
return nil, gtserror.New("could not extract valid image URI from icon")
|
return nil, gtserror.New("could not extract valid image URI from icon")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ExtractIconDescription extracts the name property from
|
||||||
|
// the given WithIcon which links to a supported image file,
|
||||||
|
// or returns an empty string.
|
||||||
|
// Input will look something like this:
|
||||||
|
//
|
||||||
|
// "icon": {
|
||||||
|
// "mediaType": "image/jpeg",
|
||||||
|
// "name": "some description",
|
||||||
|
// "type": "Image",
|
||||||
|
// "url": "http://example.org/path/to/some/file.jpeg"
|
||||||
|
// },
|
||||||
|
func ExtractIconDescription(i WithIcon) string {
|
||||||
|
iconProp := i.GetActivityStreamsIcon()
|
||||||
|
if iconProp == nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// Icon can potentially contain multiple entries,
|
||||||
|
// so we iterate through all of them here in order
|
||||||
|
// to find the first one that meets these criteria:
|
||||||
|
//
|
||||||
|
// 1. Is an image.
|
||||||
|
// 2. Has a URL that we can use to derefereince it.
|
||||||
|
for iter := iconProp.Begin(); iter != iconProp.End(); iter = iter.Next() {
|
||||||
|
if !iter.IsActivityStreamsImage() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
image := iter.GetActivityStreamsImage()
|
||||||
|
if image == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
imageURL := GetURL(image)
|
||||||
|
if len(imageURL) == 0 {
|
||||||
|
// Nothing here.
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
imageDescription := ExtractName(image)
|
||||||
|
|
||||||
|
// Got a hit.
|
||||||
|
return imageDescription
|
||||||
|
}
|
||||||
|
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
// ExtractImageURI extracts the first URI it can find from
|
// ExtractImageURI extracts the first URI it can find from
|
||||||
// the given WithImage which links to a supported image file.
|
// the given WithImage which links to a supported image file.
|
||||||
// Input will look something like this:
|
// Input will look something like this:
|
||||||
|
|
@ -416,6 +464,54 @@ func ExtractImageURI(i WithImage) (*url.URL, error) {
|
||||||
return nil, gtserror.New("could not extract valid image URI from image")
|
return nil, gtserror.New("could not extract valid image URI from image")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ExtractImageDescription extracts the name property from
|
||||||
|
// the given WithImage which links to a supported image file,
|
||||||
|
// or returns an empty string.
|
||||||
|
// Input will look something like this:
|
||||||
|
//
|
||||||
|
// "image": {
|
||||||
|
// "mediaType": "image/jpeg",
|
||||||
|
// "name": "some description",
|
||||||
|
// "type": "Image",
|
||||||
|
// "url": "http://example.org/path/to/some/file.jpeg"
|
||||||
|
// },
|
||||||
|
func ExtractImageDescription(i WithImage) string {
|
||||||
|
imageProp := i.GetActivityStreamsImage()
|
||||||
|
if imageProp == nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// Image can potentially contain multiple entries,
|
||||||
|
// so we iterate through all of them here in order
|
||||||
|
// to find the first one that meets these criteria:
|
||||||
|
//
|
||||||
|
// 1. Is an image.
|
||||||
|
// 2. Has a URL that we can use to derefereince it.
|
||||||
|
for iter := imageProp.Begin(); iter != imageProp.End(); iter = iter.Next() {
|
||||||
|
if !iter.IsActivityStreamsImage() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
image := iter.GetActivityStreamsImage()
|
||||||
|
if image == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
imageURL := GetURL(image)
|
||||||
|
if len(imageURL) == 0 {
|
||||||
|
// Nothing here.
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
imageDescription := ExtractName(image)
|
||||||
|
|
||||||
|
// Got a hit.
|
||||||
|
return imageDescription
|
||||||
|
}
|
||||||
|
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
// ExtractSummary extracts the summary/content warning of
|
// ExtractSummary extracts the summary/content warning of
|
||||||
// the given WithSummary interface. Will return an empty
|
// the given WithSummary interface. Will return an empty
|
||||||
// string if no summary/content warning was present.
|
// string if no summary/content warning was present.
|
||||||
|
|
|
||||||
|
|
@ -807,12 +807,12 @@ func (d *Dereferencer) enrichAccount(
|
||||||
latestAcc.UpdatedAt = now
|
latestAcc.UpdatedAt = now
|
||||||
|
|
||||||
// Ensure the account's avatar media is populated, passing in existing to check for chages.
|
// Ensure the account's avatar media is populated, passing in existing to check for chages.
|
||||||
if err := d.fetchAccountAvatar(ctx, requestUser, account, latestAcc); err != nil {
|
if err := d.fetchAccountAvatar(ctx, requestUser, account, latestAcc, apubAcc); err != nil {
|
||||||
log.Errorf(ctx, "error fetching remote avatar for account %s: %v", uri, err)
|
log.Errorf(ctx, "error fetching remote avatar for account %s: %v", uri, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure the account's avatar media is populated, passing in existing to check for chages.
|
// Ensure the account's avatar media is populated, passing in existing to check for chages.
|
||||||
if err := d.fetchAccountHeader(ctx, requestUser, account, latestAcc); err != nil {
|
if err := d.fetchAccountHeader(ctx, requestUser, account, latestAcc, apubAcc); err != nil {
|
||||||
log.Errorf(ctx, "error fetching remote header for account %s: %v", uri, err)
|
log.Errorf(ctx, "error fetching remote header for account %s: %v", uri, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -854,6 +854,7 @@ func (d *Dereferencer) fetchAccountAvatar(
|
||||||
requestUser string,
|
requestUser string,
|
||||||
existingAcc *gtsmodel.Account,
|
existingAcc *gtsmodel.Account,
|
||||||
latestAcc *gtsmodel.Account,
|
latestAcc *gtsmodel.Account,
|
||||||
|
apubAcc ap.Accountable,
|
||||||
) error {
|
) error {
|
||||||
if latestAcc.AvatarRemoteURL == "" {
|
if latestAcc.AvatarRemoteURL == "" {
|
||||||
// No avatar set on newest model, leave
|
// No avatar set on newest model, leave
|
||||||
|
|
@ -861,6 +862,8 @@ func (d *Dereferencer) fetchAccountAvatar(
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
avatarDescription := ap.ExtractIconDescription(apubAcc)
|
||||||
|
|
||||||
// Check for an existing stored media attachment
|
// Check for an existing stored media attachment
|
||||||
// specifically with unchanged remote URL we can use.
|
// specifically with unchanged remote URL we can use.
|
||||||
if existingAcc.AvatarMediaAttachmentID != "" &&
|
if existingAcc.AvatarMediaAttachmentID != "" &&
|
||||||
|
|
@ -883,6 +886,18 @@ func (d *Dereferencer) fetchAccountAvatar(
|
||||||
nil,
|
nil,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if existing.Description != avatarDescription {
|
||||||
|
existing.Description = avatarDescription
|
||||||
|
if err := d.state.DB.UpdateAttachment(
|
||||||
|
ctx,
|
||||||
|
existing,
|
||||||
|
"description",
|
||||||
|
); err != nil {
|
||||||
|
err := gtserror.Newf("db error updating existing avatar description: %w", err)
|
||||||
|
return gtserror.NewErrorInternalError(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf(ctx, "error updating existing attachment: %v", err)
|
log.Errorf(ctx, "error updating existing attachment: %v", err)
|
||||||
|
|
||||||
|
|
@ -906,8 +921,9 @@ func (d *Dereferencer) fetchAccountAvatar(
|
||||||
latestAcc.ID,
|
latestAcc.ID,
|
||||||
latestAcc.AvatarRemoteURL,
|
latestAcc.AvatarRemoteURL,
|
||||||
media.AdditionalMediaInfo{
|
media.AdditionalMediaInfo{
|
||||||
Avatar: util.Ptr(true),
|
Avatar: util.Ptr(true),
|
||||||
RemoteURL: &latestAcc.AvatarRemoteURL,
|
RemoteURL: &latestAcc.AvatarRemoteURL,
|
||||||
|
Description: &avatarDescription,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -931,6 +947,7 @@ func (d *Dereferencer) fetchAccountHeader(
|
||||||
requestUser string,
|
requestUser string,
|
||||||
existingAcc *gtsmodel.Account,
|
existingAcc *gtsmodel.Account,
|
||||||
latestAcc *gtsmodel.Account,
|
latestAcc *gtsmodel.Account,
|
||||||
|
apubAcc ap.Accountable,
|
||||||
) error {
|
) error {
|
||||||
if latestAcc.HeaderRemoteURL == "" {
|
if latestAcc.HeaderRemoteURL == "" {
|
||||||
// No header set on newest model, leave
|
// No header set on newest model, leave
|
||||||
|
|
@ -938,6 +955,8 @@ func (d *Dereferencer) fetchAccountHeader(
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
headerDescription := ap.ExtractImageDescription(apubAcc)
|
||||||
|
|
||||||
// Check for an existing stored media attachment
|
// Check for an existing stored media attachment
|
||||||
// specifically with unchanged remote URL we can use.
|
// specifically with unchanged remote URL we can use.
|
||||||
if existingAcc.HeaderMediaAttachmentID != "" &&
|
if existingAcc.HeaderMediaAttachmentID != "" &&
|
||||||
|
|
@ -951,6 +970,18 @@ func (d *Dereferencer) fetchAccountHeader(
|
||||||
return gtserror.Newf("error getting attachment %s: %w", existingAcc.HeaderMediaAttachmentID, err)
|
return gtserror.Newf("error getting attachment %s: %w", existingAcc.HeaderMediaAttachmentID, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if existing.Description != headerDescription {
|
||||||
|
existing.Description = headerDescription
|
||||||
|
if err := d.state.DB.UpdateAttachment(
|
||||||
|
ctx,
|
||||||
|
existing,
|
||||||
|
"description",
|
||||||
|
); err != nil {
|
||||||
|
err := gtserror.Newf("db error updating existing header description: %w", err)
|
||||||
|
return gtserror.NewErrorInternalError(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if existing != nil {
|
if existing != nil {
|
||||||
// Ensuring existing attachment is up-to-date
|
// Ensuring existing attachment is up-to-date
|
||||||
// and any recaching is performed if required.
|
// and any recaching is performed if required.
|
||||||
|
|
@ -983,8 +1014,9 @@ func (d *Dereferencer) fetchAccountHeader(
|
||||||
latestAcc.ID,
|
latestAcc.ID,
|
||||||
latestAcc.HeaderRemoteURL,
|
latestAcc.HeaderRemoteURL,
|
||||||
media.AdditionalMediaInfo{
|
media.AdditionalMediaInfo{
|
||||||
Header: util.Ptr(true),
|
Header: util.Ptr(true),
|
||||||
RemoteURL: &latestAcc.HeaderRemoteURL,
|
RemoteURL: &latestAcc.HeaderRemoteURL,
|
||||||
|
Description: &headerDescription,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@ import (
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
|
@ -473,6 +474,49 @@ func (suite *AccountTestSuite) TestRefreshFederatedRemoteAccountWithKeyChange()
|
||||||
suite.True(updatedAcc.PublicKey.Equal(fetchingAcc.PublicKey))
|
suite.True(updatedAcc.PublicKey.Equal(fetchingAcc.PublicKey))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (suite *AccountTestSuite) TestDereferenceRemoteAccountWithAvatarDescription() {
|
||||||
|
ctx, cncl := context.WithCancel(suite.T().Context())
|
||||||
|
defer cncl()
|
||||||
|
|
||||||
|
fetchingAcc := suite.testAccounts["local_account_1"]
|
||||||
|
remoteURI := "https://shrimpnet.example.org/users/shrimp"
|
||||||
|
description := "me scrolling fedi on a laptop, there's a monster ultra white and another fedi user on my right."
|
||||||
|
|
||||||
|
// Fetch the remote account to load into the database.
|
||||||
|
remoteAcc, _, err := suite.dereferencer.GetAccountByURI(ctx,
|
||||||
|
fetchingAcc.Username,
|
||||||
|
testrig.URLMustParse(remoteURI),
|
||||||
|
false,
|
||||||
|
)
|
||||||
|
suite.NoError(err)
|
||||||
|
suite.NotNil(remoteAcc)
|
||||||
|
|
||||||
|
suite.Equal(remoteAcc.AvatarMediaAttachment.Description, description)
|
||||||
|
|
||||||
|
remotePerson := suite.client.TestRemotePeople[remoteURI]
|
||||||
|
|
||||||
|
description = strings.TrimSuffix(description, ".")
|
||||||
|
|
||||||
|
icon := remotePerson.GetActivityStreamsIcon()
|
||||||
|
image := icon.Begin().GetActivityStreamsImage()
|
||||||
|
nameProp := streams.NewActivityStreamsNameProperty()
|
||||||
|
nameProp.AppendXMLSchemaString(description)
|
||||||
|
image.SetActivityStreamsName(nameProp)
|
||||||
|
icon.SetActivityStreamsImage(0, image)
|
||||||
|
remotePerson.SetActivityStreamsIcon(icon)
|
||||||
|
|
||||||
|
updatedAcc, apAcc, err := suite.dereferencer.RefreshAccount(ctx,
|
||||||
|
fetchingAcc.Username,
|
||||||
|
remoteAcc,
|
||||||
|
remotePerson,
|
||||||
|
nil,
|
||||||
|
)
|
||||||
|
|
||||||
|
suite.NoError(err)
|
||||||
|
suite.NotNil(apAcc)
|
||||||
|
suite.Equal(updatedAcc.AvatarMediaAttachment.Description, description)
|
||||||
|
}
|
||||||
|
|
||||||
func TestAccountTestSuite(t *testing.T) {
|
func TestAccountTestSuite(t *testing.T) {
|
||||||
suite.Run(t, new(AccountTestSuite))
|
suite.Run(t, new(AccountTestSuite))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3578,6 +3578,12 @@ func NewTestFediPeople() map[string]vocab.ActivityStreamsPerson {
|
||||||
}
|
}
|
||||||
someUserPub := &someUserPriv.PublicKey
|
someUserPub := &someUserPriv.PublicKey
|
||||||
|
|
||||||
|
shrimpPriv, err := rsa.GenerateKey(rand.Reader, 2048)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
shrimpPub := &shrimpPriv.PublicKey
|
||||||
|
|
||||||
return map[string]vocab.ActivityStreamsPerson{
|
return map[string]vocab.ActivityStreamsPerson{
|
||||||
"https://unknown-instance.com/users/brand_new_person": newAPPerson(
|
"https://unknown-instance.com/users/brand_new_person": newAPPerson(
|
||||||
URLMustParse("https://unknown-instance.com/users/brand_new_person"),
|
URLMustParse("https://unknown-instance.com/users/brand_new_person"),
|
||||||
|
|
@ -3599,7 +3605,9 @@ func NewTestFediPeople() map[string]vocab.ActivityStreamsPerson {
|
||||||
nil,
|
nil,
|
||||||
"image/jpeg",
|
"image/jpeg",
|
||||||
nil,
|
nil,
|
||||||
|
nil,
|
||||||
"image/png",
|
"image/png",
|
||||||
|
nil,
|
||||||
false,
|
false,
|
||||||
),
|
),
|
||||||
"https://turnip.farm/users/turniplover6969": newAPPerson(
|
"https://turnip.farm/users/turniplover6969": newAPPerson(
|
||||||
|
|
@ -3622,7 +3630,9 @@ func NewTestFediPeople() map[string]vocab.ActivityStreamsPerson {
|
||||||
nil,
|
nil,
|
||||||
"image/jpeg",
|
"image/jpeg",
|
||||||
nil,
|
nil,
|
||||||
|
nil,
|
||||||
"image/png",
|
"image/png",
|
||||||
|
nil,
|
||||||
false,
|
false,
|
||||||
),
|
),
|
||||||
"http://example.org/users/Some_User": newAPPerson(
|
"http://example.org/users/Some_User": newAPPerson(
|
||||||
|
|
@ -3645,7 +3655,34 @@ func NewTestFediPeople() map[string]vocab.ActivityStreamsPerson {
|
||||||
nil,
|
nil,
|
||||||
"image/jpeg",
|
"image/jpeg",
|
||||||
nil,
|
nil,
|
||||||
|
nil,
|
||||||
"image/png",
|
"image/png",
|
||||||
|
nil,
|
||||||
|
false,
|
||||||
|
),
|
||||||
|
"https://shrimpnet.example.org/users/shrimp": newAPPerson(
|
||||||
|
URLMustParse("https://shrimpnet.example.org/users/shrimp"),
|
||||||
|
URLMustParse("https://shrimpnet.example.org/users/shrimp/following"),
|
||||||
|
URLMustParse("https://shrimpnet.example.org/users/shrimp/followers"),
|
||||||
|
URLMustParse("https://shrimpnet.example.org/users/shrimp/inbox"),
|
||||||
|
URLMustParse("https://shrimpnet.example.org/inbox"),
|
||||||
|
URLMustParse("https://shrimpnet.example.org/users/shrimp/outbox"),
|
||||||
|
URLMustParse("https://shrimpnet.example.org/users/shrimp/collections/featured"),
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
"shrimp",
|
||||||
|
"Shrimp",
|
||||||
|
"",
|
||||||
|
URLMustParse("https://shrimpnet.example.org/@shrimp"),
|
||||||
|
true,
|
||||||
|
URLMustParse("https://shrimpnet.example.org/users/shrimp#main-key"),
|
||||||
|
shrimpPub,
|
||||||
|
URLMustParse("https://shrimpnet.example.org/files/public-1c8468b8-eb2d-485f-9967-f4238ded95e7.webp"),
|
||||||
|
"image/jpeg",
|
||||||
|
util.Ptr("me scrolling fedi on a laptop, there's a monster ultra white and another fedi user on my right."),
|
||||||
|
nil,
|
||||||
|
"image/png",
|
||||||
|
nil,
|
||||||
false,
|
false,
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
|
@ -4398,8 +4435,10 @@ func newAPPerson(
|
||||||
pkey *rsa.PublicKey,
|
pkey *rsa.PublicKey,
|
||||||
avatarURL *url.URL,
|
avatarURL *url.URL,
|
||||||
avatarContentType string,
|
avatarContentType string,
|
||||||
|
avatarDescription *string,
|
||||||
headerURL *url.URL,
|
headerURL *url.URL,
|
||||||
headerContentType string,
|
headerContentType string,
|
||||||
|
headerDescription *string,
|
||||||
manuallyApprovesFollowers bool,
|
manuallyApprovesFollowers bool,
|
||||||
) vocab.ActivityStreamsPerson {
|
) vocab.ActivityStreamsPerson {
|
||||||
person := streams.NewActivityStreamsPerson()
|
person := streams.NewActivityStreamsPerson()
|
||||||
|
|
@ -4564,6 +4603,11 @@ func newAPPerson(
|
||||||
avatarURLProperty := streams.NewActivityStreamsUrlProperty()
|
avatarURLProperty := streams.NewActivityStreamsUrlProperty()
|
||||||
avatarURLProperty.AppendIRI(avatarURL)
|
avatarURLProperty.AppendIRI(avatarURL)
|
||||||
iconImage.SetActivityStreamsUrl(avatarURLProperty)
|
iconImage.SetActivityStreamsUrl(avatarURLProperty)
|
||||||
|
if avatarDescription != nil {
|
||||||
|
nameProp := streams.NewActivityStreamsNameProperty()
|
||||||
|
nameProp.AppendXMLSchemaString(*avatarDescription)
|
||||||
|
iconImage.SetActivityStreamsName(nameProp)
|
||||||
|
}
|
||||||
iconProperty.AppendActivityStreamsImage(iconImage)
|
iconProperty.AppendActivityStreamsImage(iconImage)
|
||||||
person.SetActivityStreamsIcon(iconProperty)
|
person.SetActivityStreamsIcon(iconProperty)
|
||||||
|
|
||||||
|
|
@ -4577,6 +4621,11 @@ func newAPPerson(
|
||||||
headerURLProperty := streams.NewActivityStreamsUrlProperty()
|
headerURLProperty := streams.NewActivityStreamsUrlProperty()
|
||||||
headerURLProperty.AppendIRI(headerURL)
|
headerURLProperty.AppendIRI(headerURL)
|
||||||
headerImage.SetActivityStreamsUrl(headerURLProperty)
|
headerImage.SetActivityStreamsUrl(headerURLProperty)
|
||||||
|
if headerDescription != nil {
|
||||||
|
nameProp := streams.NewActivityStreamsNameProperty()
|
||||||
|
nameProp.AppendXMLSchemaString(*headerDescription)
|
||||||
|
headerImage.SetActivityStreamsName(nameProp)
|
||||||
|
}
|
||||||
headerProperty.AppendActivityStreamsImage(headerImage)
|
headerProperty.AppendActivityStreamsImage(headerImage)
|
||||||
person.SetActivityStreamsImage(headerProperty)
|
person.SetActivityStreamsImage(headerProperty)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -566,6 +566,17 @@ func WebfingerResponse(req *http.Request) (
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
case "https://shrimpnet.example.org/.well-known/webfinger?resource=acct%3Ashrimp%40shrimpnet.example.org":
|
||||||
|
wfr = &apimodel.WellKnownResponse{
|
||||||
|
Subject: "acct:shrimp@shrimpnet.example.org",
|
||||||
|
Links: []apimodel.Link{
|
||||||
|
{
|
||||||
|
Rel: "self",
|
||||||
|
Type: applicationActivityJSON,
|
||||||
|
Href: "https://shrimpnet.example.org/users/shrimp",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
case "https://misconfigured-instance.com/.weird-webfinger-location/webfinger?resource=acct%3Asomeone%40misconfigured-instance.com":
|
case "https://misconfigured-instance.com/.weird-webfinger-location/webfinger?resource=acct%3Asomeone%40misconfigured-instance.com":
|
||||||
wfr = &apimodel.WellKnownResponse{
|
wfr = &apimodel.WellKnownResponse{
|
||||||
Subject: "acct:someone@misconfigured-instance.com",
|
Subject: "acct:someone@misconfigured-instance.com",
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue