-
-
Notifications
You must be signed in to change notification settings - Fork 351
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[bugfix] Relax
Mention
parsing, allowing either href or name (#2320)
- Loading branch information
1 parent
dd4b024
commit 51d0a0b
Showing
6 changed files
with
317 additions
and
40 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -427,3 +427,58 @@ With just one tag, the `tag` property will be an object rather than an array, wh | |
The `href` URL provided by GoToSocial in outgoing tags points to a web URL that serves `text/html`. | ||
|
||
GoToSocial makes no guarantees whatsoever about what the content of the given `text/html` will be, and remote servers should not interpret the URL as a canonical ActivityPub ID/URI property. The `href` URL is provided merely as an endpoint which *might* contain more information about the given hashtag. | ||
|
||
## Mentions | ||
|
||
GoToSocial users can Mention other users in their posts, using the common `@[username]@[domain]` format. For example, if a GoToSocial user wanted to mention user `someone` on instance `example.org`, they could do this by including `@[email protected]` in their post somewhere. | ||
|
||
!!! info "Mentions and activity addressing" | ||
|
||
Mentions are not just aesthetic, they affect addressing of Activities as well. | ||
|
||
If a GoToSocial user explicitly mentions another user in a Note, the URI of that user will always be included in the `To` or `Cc` property of the Note's Create activity. | ||
|
||
If the Note is direct (ie., not `To` public or followers), each mention target URI will be in the `To` property of the wrapping Activity | ||
|
||
In all other cases, mentions will be included in the `Cc` property of the wrapping Activity. | ||
|
||
### Outgoing | ||
|
||
When a GoToSocial user Mentions another account, the Mention is included in outgoing federated messages as an entry in the `tag` property. | ||
|
||
For example, say a user on a GoToSocial instance Mentions `@[email protected]`, the `tag` property of the outgoing Note might look like the following: | ||
|
||
```json | ||
"tag": { | ||
"href": "http://example.org/users/someone", | ||
"name": "@[email protected]", | ||
"type": "Mention" | ||
} | ||
``` | ||
|
||
If a user Mentions a local user they share an instance with, the full `name` of the local user will still be included. | ||
|
||
For example, a GoToSocial user on domain `some.gotosocial.instance` mentions another user on the same instance called `user2`. They also mention `@[email protected]` as above. The `tag` property of the outgoing Note would look like the following: | ||
|
||
```json | ||
"tag": [ | ||
{ | ||
"href": "http://example.org/users/someone", | ||
"name": "@[email protected]", | ||
"type": "Mention" | ||
}, | ||
{ | ||
"href": "http://some.gotosocial.instance/users/user2", | ||
"name": "@[email protected]", | ||
"type": "Mention" | ||
} | ||
] | ||
``` | ||
|
||
For the convenience of remote servers, GoToSocial will always provide both the `href` and the `name` properties on outgoing Mentions. The `href` property used by GoToSocial will always be the ActivityPub ID/URI of the target account, not the web URL. | ||
|
||
### Incoming | ||
|
||
GoToSocial tries to parse incoming Mentions in the same way it sends them out: as a `Mention` type entry in the `tag` property. However, when parsing incoming Mentions it's a bit more relaxed with regards to which properties must be set. | ||
|
||
GoToSocial will prefer the `href` property, which can be either the ActivityPub ID/URI or the web URL of the target; if `href` is not present, it will fall back to using the `name` property. If neither property is present, the mention will be considered invalid and discarded. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -32,7 +32,6 @@ import ( | |
"github.com/superseriousbusiness/gotosocial/internal/gtserror" | ||
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel" | ||
"github.com/superseriousbusiness/gotosocial/internal/text" | ||
"github.com/superseriousbusiness/gotosocial/internal/util" | ||
) | ||
|
||
// ExtractObjects will extract object vocab.Types from given implementing interface. | ||
|
@@ -841,27 +840,27 @@ func ExtractMentions(i WithTag) ([]*gtsmodel.Mention, error) { | |
|
||
// ExtractMention extracts a minimal gtsmodel.Mention from a Mentionable. | ||
func ExtractMention(i Mentionable) (*gtsmodel.Mention, error) { | ||
// See if a name has been set in the | ||
// format `@[email protected]`. | ||
nameString := ExtractName(i) | ||
if nameString == "" { | ||
return nil, gtserror.New("name prop empty") | ||
} | ||
|
||
// Ensure namestring is valid so we | ||
// can handle it properly later on. | ||
if _, _, err := util.ExtractNamestringParts(nameString); err != nil { | ||
return nil, err | ||
} | ||
|
||
// The href prop should be the AP URI | ||
// of the target account. | ||
// of the target account; it could also | ||
// be the URL, but we'll check this later. | ||
var href string | ||
hrefProp := i.GetActivityStreamsHref() | ||
if hrefProp == nil || !hrefProp.IsIRI() { | ||
return nil, gtserror.New("no href prop") | ||
if hrefProp != nil && hrefProp.IsIRI() { | ||
href = hrefProp.GetIRI().String() | ||
} | ||
|
||
// One of nameString and hrefProp must be set. | ||
if nameString == "" && href == "" { | ||
return nil, gtserror.Newf("neither Name nor Href were set") | ||
} | ||
|
||
return >smodel.Mention{ | ||
NameString: nameString, | ||
TargetAccountURI: hrefProp.GetIRI().String(), | ||
TargetAccountURI: href, | ||
}, nil | ||
} | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -21,14 +21,16 @@ import ( | |
"testing" | ||
|
||
"github.com/stretchr/testify/suite" | ||
"github.com/superseriousbusiness/activity/streams" | ||
"github.com/superseriousbusiness/gotosocial/internal/ap" | ||
"github.com/superseriousbusiness/gotosocial/testrig" | ||
) | ||
|
||
type ExtractMentionsTestSuite struct { | ||
APTestSuite | ||
} | ||
|
||
func (suite *ExtractMentionsTestSuite) TestExtractMentions() { | ||
func (suite *ExtractMentionsTestSuite) TestExtractMentionsFromNote() { | ||
note := suite.noteWithMentions1 | ||
|
||
mentions, err := ap.ExtractMentions(note) | ||
|
@@ -44,6 +46,101 @@ func (suite *ExtractMentionsTestSuite) TestExtractMentions() { | |
suite.Equal("https://gts.superseriousbusiness.org/users/f0x", m2.TargetAccountURI) | ||
} | ||
|
||
func (suite *ExtractMentionsTestSuite) TestExtractMentions() { | ||
newMention := func(nameString string, href string) ap.Mentionable { | ||
mention := streams.NewActivityStreamsMention() | ||
|
||
if nameString != "" { | ||
nameProp := streams.NewActivityStreamsNameProperty() | ||
nameProp.AppendXMLSchemaString(nameString) | ||
mention.SetActivityStreamsName(nameProp) | ||
} | ||
|
||
if href != "" { | ||
hrefProp := streams.NewActivityStreamsHrefProperty() | ||
hrefProp.SetIRI(testrig.URLMustParse(href)) | ||
mention.SetActivityStreamsHref(hrefProp) | ||
} | ||
|
||
return mention | ||
} | ||
|
||
type test struct { | ||
nameString string | ||
href string | ||
expectedNameString string | ||
expectedHref string | ||
expectedErr string | ||
} | ||
|
||
for i, t := range []test{ | ||
{ | ||
// Mention with both Name and Href set, should be fine. | ||
nameString: "@[email protected]", | ||
href: "https://example.org/@someone", | ||
expectedNameString: "@[email protected]", | ||
expectedHref: "https://example.org/@someone", | ||
expectedErr: "", | ||
}, | ||
{ | ||
// Mention with just Href set, should be fine. | ||
nameString: "", | ||
href: "https://example.org/@someone", | ||
expectedNameString: "", | ||
expectedHref: "https://example.org/@someone", | ||
expectedErr: "", | ||
}, | ||
{ | ||
// Mention with just Name set, should be fine. | ||
nameString: "@[email protected]", | ||
href: "", | ||
expectedNameString: "@[email protected]", | ||
expectedHref: "", | ||
expectedErr: "", | ||
}, | ||
{ | ||
// Mention with nothing set, not fine! | ||
nameString: "", | ||
href: "", | ||
expectedNameString: "", | ||
expectedHref: "", | ||
expectedErr: "ExtractMention: neither Name nor Href were set", | ||
}, | ||
} { | ||
apMention := newMention(t.nameString, t.href) | ||
mention, err := ap.ExtractMention(apMention) | ||
|
||
if err != nil { | ||
if errString := err.Error(); errString != t.expectedErr { | ||
suite.Fail("", | ||
"test %d expected error %s, got %s", | ||
i+1, t.expectedErr, errString, | ||
) | ||
} | ||
continue | ||
} else if t.expectedErr != "" { | ||
suite.Fail("", | ||
"test %d expected error %s, got no error", | ||
i+1, t.expectedErr, | ||
) | ||
} | ||
|
||
if mention.NameString != t.expectedNameString { | ||
suite.Fail("", | ||
"test %d expected nameString %s, got %s", | ||
i+1, t.expectedNameString, mention.NameString, | ||
) | ||
} | ||
|
||
if mention.TargetAccountURI != t.expectedHref { | ||
suite.Fail("", | ||
"test %d expected href %s, got %s", | ||
i+1, t.expectedHref, mention.TargetAccountURI, | ||
) | ||
} | ||
} | ||
} | ||
|
||
func TestExtractMentionsTestSuite(t *testing.T) { | ||
suite.Run(t, &ExtractMentionsTestSuite{}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.