mirror of
https://github.com/superseriousbusiness/gotosocial
synced 2025-06-05 21:59:39 +02:00
[feature] Hashtag federation (in/out), hashtag client API endpoints (#2032)
* update go-fed * do the things * remove unused columns from tags * update to latest lingo from main * further tag shenanigans * serve stub page at tag endpoint * we did it lads * tests, oh tests, ohhh tests, oh tests (doo doo doo doo) * swagger docs * document hashtag usage + federation * instanceGet * don't bother parsing tag href * rename whereStartsWith -> whereStartsLike * remove GetOrCreateTag * dont cache status tag timelineability
This commit is contained in:
@@ -1760,26 +1760,20 @@ func NewTestStatuses() map[string]*gtsmodel.Status {
|
||||
func NewTestTags() map[string]*gtsmodel.Tag {
|
||||
return map[string]*gtsmodel.Tag{
|
||||
"welcome": {
|
||||
ID: "01F8MHA1A2NF9MJ3WCCQ3K8BSZ",
|
||||
URL: "http://localhost:8080/tags/welcome",
|
||||
Name: "welcome",
|
||||
FirstSeenFromAccountID: "",
|
||||
CreatedAt: TimeMustParse("2022-05-14T13:21:09+02:00"),
|
||||
UpdatedAt: TimeMustParse("2022-05-14T13:21:09+02:00"),
|
||||
Useable: TrueBool(),
|
||||
Listable: TrueBool(),
|
||||
LastStatusAt: TimeMustParse("2022-05-14T13:21:09+02:00"),
|
||||
ID: "01F8MHA1A2NF9MJ3WCCQ3K8BSZ",
|
||||
Name: "welcome",
|
||||
CreatedAt: TimeMustParse("2022-05-14T13:21:09+02:00"),
|
||||
UpdatedAt: TimeMustParse("2022-05-14T13:21:09+02:00"),
|
||||
Useable: TrueBool(),
|
||||
Listable: TrueBool(),
|
||||
},
|
||||
"Hashtag": {
|
||||
ID: "01FCT9SGYA71487N8D0S1M638G",
|
||||
URL: "http://localhost:8080/tags/Hashtag",
|
||||
Name: "Hashtag",
|
||||
FirstSeenFromAccountID: "",
|
||||
CreatedAt: TimeMustParse("2022-05-14T13:21:09+02:00"),
|
||||
UpdatedAt: TimeMustParse("2022-05-14T13:21:09+02:00"),
|
||||
Useable: TrueBool(),
|
||||
Listable: TrueBool(),
|
||||
LastStatusAt: TimeMustParse("2022-05-14T13:21:09+02:00"),
|
||||
ID: "01FCT9SGYA71487N8D0S1M638G",
|
||||
Name: "hashtag",
|
||||
CreatedAt: TimeMustParse("2022-05-14T13:21:09+02:00"),
|
||||
UpdatedAt: TimeMustParse("2022-05-14T13:21:09+02:00"),
|
||||
Useable: TrueBool(),
|
||||
Listable: TrueBool(),
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -2092,6 +2086,7 @@ func NewTestActivities(accounts map[string]*gtsmodel.Account) map[string]Activit
|
||||
nil,
|
||||
true,
|
||||
[]vocab.ActivityStreamsMention{},
|
||||
[]vocab.TootHashtag{},
|
||||
nil,
|
||||
)
|
||||
createDmForZork := WrapAPNoteInCreate(
|
||||
@@ -2115,6 +2110,7 @@ func NewTestActivities(accounts map[string]*gtsmodel.Account) map[string]Activit
|
||||
URLMustParse("http://localhost:8080/users/1happyturtle"),
|
||||
"@1happyturtle@localhost:8080",
|
||||
)},
|
||||
[]vocab.TootHashtag{},
|
||||
nil,
|
||||
)
|
||||
createReplyToTurtle := WrapAPNoteInCreate(
|
||||
@@ -2136,6 +2132,7 @@ func NewTestActivities(accounts map[string]*gtsmodel.Account) map[string]Activit
|
||||
nil,
|
||||
false,
|
||||
[]vocab.ActivityStreamsMention{},
|
||||
[]vocab.TootHashtag{},
|
||||
[]vocab.ActivityStreamsImage{
|
||||
newAPImage(
|
||||
URLMustParse("http://example.org/users/Some_User/statuses/afaba698-5740-4e32-a702-af61aa543bc1/attachment1.jpg"),
|
||||
@@ -2483,6 +2480,7 @@ func NewTestFediStatuses() map[string]vocab.ActivityStreamsNote {
|
||||
nil,
|
||||
false,
|
||||
[]vocab.ActivityStreamsMention{},
|
||||
[]vocab.TootHashtag{},
|
||||
[]vocab.ActivityStreamsImage{
|
||||
newAPImage(
|
||||
URLMustParse("http://example.org/users/Some_User/statuses/afaba698-5740-4e32-a702-af61aa543bc1/attachment1.jpg"),
|
||||
@@ -2504,6 +2502,7 @@ func NewTestFediStatuses() map[string]vocab.ActivityStreamsNote {
|
||||
[]*url.URL{},
|
||||
false,
|
||||
nil,
|
||||
[]vocab.TootHashtag{},
|
||||
nil,
|
||||
),
|
||||
"https://unknown-instance.com/users/brand_new_person/statuses/01FE5Y30E3W4P7TRE0R98KAYQV": NewAPNote(
|
||||
@@ -2524,6 +2523,28 @@ func NewTestFediStatuses() map[string]vocab.ActivityStreamsNote {
|
||||
"@the_mighty_zork@localhost:8080",
|
||||
),
|
||||
},
|
||||
[]vocab.TootHashtag{},
|
||||
nil,
|
||||
),
|
||||
"https://unknown-instance.com/users/brand_new_person/statuses/01H641QSRS3TCXSVC10X4GPKW7": NewAPNote(
|
||||
URLMustParse("https://unknown-instance.com/users/brand_new_person/statuses/01H641QSRS3TCXSVC10X4GPKW7"),
|
||||
URLMustParse("https://unknown-instance.com/users/@brand_new_person/01H641QSRS3TCXSVC10X4GPKW7"),
|
||||
TimeMustParse("2023-04-12T12:13:12+02:00"),
|
||||
"<p>Babe are you okay, you've hardly touched your <a href=\"https://unknown-instance.com/tags/piss\" class=\"mention hashtag\" rel=\"tag nofollow noreferrer noopener\" target=\"_blank\">#<span>piss</span></a></p>",
|
||||
"",
|
||||
URLMustParse("https://unknown-instance.com/users/brand_new_person"),
|
||||
[]*url.URL{
|
||||
URLMustParse(pub.PublicActivityPubIRI),
|
||||
},
|
||||
[]*url.URL{},
|
||||
false,
|
||||
[]vocab.ActivityStreamsMention{},
|
||||
[]vocab.TootHashtag{
|
||||
newAPHashtag(
|
||||
URLMustParse("https://unknown-instance.com/tags/piss"),
|
||||
"#piss",
|
||||
),
|
||||
},
|
||||
nil,
|
||||
),
|
||||
"https://turnip.farm/users/turniplover6969/statuses/70c53e54-3146-42d5-a630-83c8b6c7c042": NewAPNote(
|
||||
@@ -2539,6 +2560,7 @@ func NewTestFediStatuses() map[string]vocab.ActivityStreamsNote {
|
||||
[]*url.URL{},
|
||||
false,
|
||||
nil,
|
||||
[]vocab.TootHashtag{},
|
||||
[]vocab.ActivityStreamsImage{
|
||||
newAPImage(
|
||||
URLMustParse("https://turnip.farm/attachments/f17843c7-015e-4251-9b5a-91389c49ee57.jpg"),
|
||||
@@ -2566,6 +2588,7 @@ func NewTestFediStatuses() map[string]vocab.ActivityStreamsNote {
|
||||
"@the_mighty_zork@localhost:8080",
|
||||
),
|
||||
},
|
||||
[]vocab.TootHashtag{},
|
||||
nil,
|
||||
),
|
||||
}
|
||||
@@ -3349,6 +3372,20 @@ func newAPMention(uri *url.URL, namestring string) vocab.ActivityStreamsMention
|
||||
return mention
|
||||
}
|
||||
|
||||
func newAPHashtag(href *url.URL, name string) vocab.TootHashtag {
|
||||
hashtag := streams.NewTootHashtag()
|
||||
|
||||
hrefProp := streams.NewActivityStreamsHrefProperty()
|
||||
hrefProp.SetIRI(href)
|
||||
hashtag.SetActivityStreamsHref(hrefProp)
|
||||
|
||||
nameProp := streams.NewActivityStreamsNameProperty()
|
||||
nameProp.AppendXMLSchemaString(name)
|
||||
hashtag.SetActivityStreamsName(nameProp)
|
||||
|
||||
return hashtag
|
||||
}
|
||||
|
||||
func newAPImage(url *url.URL, mediaType string, imageDescription string, blurhash string) vocab.ActivityStreamsImage {
|
||||
image := streams.NewActivityStreamsImage()
|
||||
|
||||
@@ -3413,6 +3450,7 @@ func NewAPNote(
|
||||
noteCC []*url.URL,
|
||||
noteSensitive bool,
|
||||
noteMentions []vocab.ActivityStreamsMention,
|
||||
noteTags []vocab.TootHashtag,
|
||||
noteAttachments []vocab.ActivityStreamsImage,
|
||||
) vocab.ActivityStreamsNote {
|
||||
// create the note itself
|
||||
@@ -3475,13 +3513,20 @@ func NewAPNote(
|
||||
note.SetActivityStreamsCc(cc)
|
||||
}
|
||||
|
||||
// mentions
|
||||
// Tag entries
|
||||
tag := streams.NewActivityStreamsTagProperty()
|
||||
|
||||
// mentions
|
||||
for _, m := range noteMentions {
|
||||
tag.AppendActivityStreamsMention(m)
|
||||
}
|
||||
note.SetActivityStreamsTag(tag)
|
||||
|
||||
// hashtags
|
||||
for _, t := range noteTags {
|
||||
tag.AppendTootHashtag(t)
|
||||
}
|
||||
|
||||
// append any attachments as ActivityStreamsImage
|
||||
if noteAttachments != nil {
|
||||
attachmentProperty := streams.NewActivityStreamsAttachmentProperty()
|
||||
|
Reference in New Issue
Block a user