diff --git a/internal/text/common.go b/internal/text/common.go index a3ec15e46b..d57e577543 100644 --- a/internal/text/common.go +++ b/internal/text/common.go @@ -90,26 +90,38 @@ func (f *formatter) ReplaceTags(ctx context.Context, in string, tags []*gtsmodel } func (f *formatter) ReplaceMentions(ctx context.Context, in string, mentions []*gtsmodel.Mention) string { - for _, menchie := range mentions { - // make sure we have a target account, either by getting one pinned on the mention, - // or by pulling it from the database - var targetAccount *gtsmodel.Account - if menchie.OriginAccount != nil { - // got it from the mention - targetAccount = menchie.OriginAccount - } else { - a, err := f.db.GetAccountByID(ctx, menchie.TargetAccountID) - if err == nil { - // got it from the db - targetAccount = a - } else { - // couldn't get it so we can't do replacement - return in + return regexes.MentionFinder.ReplaceAllStringFunc(in, func(match string) string { + // we have a match + matchTrimmed := strings.TrimSpace(match) + // check through mentions to find what we're matching + for _, menchie := range mentions { + if strings.EqualFold(matchTrimmed, menchie.NameString) { + // make sure we have an account attached to this mention + if menchie.TargetAccount == nil { + a, err := f.db.GetAccountByID(ctx, menchie.TargetAccountID) + if err != nil { + f.log.Errorf("error getting account with id %s from the db: %s", menchie.TargetAccountID, err) + return match + } + menchie.TargetAccount = a + } + targetAccount := menchie.TargetAccount + + // replace the mention with the formatted mention content + mentionContent := fmt.Sprintf(`@%s`, targetAccount.URL, targetAccount.Username) + + // in case the match picked up any previous space or newlines (thanks to the regex), include them as well + if strings.HasPrefix(match, " ") { + mentionContent = " " + mentionContent + } else if strings.HasPrefix(match, "\n") { + mentionContent = "\n" + mentionContent + } + + // done + return mentionContent } } - - mentionContent := fmt.Sprintf(`@%s`, targetAccount.URL, targetAccount.Username) - in = strings.ReplaceAll(in, menchie.NameString, mentionContent) - } - return in + // the match wasn't in the list of mentions for whatever reason, so just return the match as we found it so nothing changes + return match + }) } diff --git a/internal/text/common_test.go b/internal/text/common_test.go index 174b791771..6d21a07191 100644 --- a/internal/text/common_test.go +++ b/internal/text/common_test.go @@ -21,8 +21,8 @@ package text_test import ( "context" "testing" + "time" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/suite" "github.com/superseriousbusiness/gotosocial/internal/gtsmodel" "github.com/superseriousbusiness/gotosocial/internal/text" @@ -52,6 +52,22 @@ Text` Text` + + replaceMentionsWithLinkString = `Another test @foss_satan@fossbros-anonymous.io + +https://fossbros-anonymous.io/@foss_satan/statuses/6675ee73-fccc-4562-a46a-3e8cd9798060` + + replaceMentionsWithLinkStringExpected = `Another test @foss_satan + +https://fossbros-anonymous.io/@foss_satan/statuses/6675ee73-fccc-4562-a46a-3e8cd9798060` + + replaceMentionsWithLinkSelfString = `Mentioning myself: @the_mighty_zork + +and linking to my own status: https://localhost:8080/@the_mighty_zork/statuses/01FGXKJRX2PMERJQ9EQF8Y6HCR` + + replaceMemtionsWithLinkSelfExpected = `Mentioning myself: @the_mighty_zork + +and linking to my own status: https://localhost:8080/@the_mighty_zork/statuses/01FGXKJRX2PMERJQ9EQF8Y6HCR` ) type CommonTestSuite struct { @@ -89,7 +105,7 @@ func (suite *CommonTestSuite) TestReplaceMentions() { } f := suite.formatter.ReplaceMentions(context.Background(), replaceMentionsString, foundMentions) - assert.Equal(suite.T(), replaceMentionsExpected, f) + suite.Equal(replaceMentionsExpected, f) } func (suite *CommonTestSuite) TestReplaceHashtags() { @@ -99,7 +115,7 @@ func (suite *CommonTestSuite) TestReplaceHashtags() { f := suite.formatter.ReplaceTags(context.Background(), replaceMentionsString, foundTags) - assert.Equal(suite.T(), replaceHashtagsExpected, f) + suite.Equal(replaceHashtagsExpected, f) } func (suite *CommonTestSuite) TestReplaceHashtagsAfterReplaceMentions() { @@ -109,7 +125,37 @@ func (suite *CommonTestSuite) TestReplaceHashtagsAfterReplaceMentions() { f := suite.formatter.ReplaceTags(context.Background(), replaceMentionsExpected, foundTags) - assert.Equal(suite.T(), replaceHashtagsAfterMentionsExpected, f) + suite.Equal(replaceHashtagsAfterMentionsExpected, f) +} + +func (suite *CommonTestSuite) TestReplaceMentionsWithLink() { + foundMentions := []*gtsmodel.Mention{ + suite.testMentions["zork_mention_foss_satan"], + } + + f := suite.formatter.ReplaceMentions(context.Background(), replaceMentionsWithLinkString, foundMentions) + suite.Equal(replaceMentionsWithLinkStringExpected, f) +} + +func (suite *CommonTestSuite) TestReplaceMentionsWithLinkSelf() { + mentioningAccount := suite.testAccounts["local_account_1"] + + foundMentions := []*gtsmodel.Mention{ + { + ID: "01FGXKN5F815DVFVD53PN9NYM6", + CreatedAt: time.Now(), + UpdatedAt: time.Now(), + StatusID: "01FGXKP0S5THQXFC1D9R141DDR", + OriginAccountID: mentioningAccount.ID, + TargetAccountID: mentioningAccount.ID, + NameString: "@the_mighty_zork", + TargetAccountURI: mentioningAccount.URI, + TargetAccountURL: mentioningAccount.URL, + }, + } + + f := suite.formatter.ReplaceMentions(context.Background(), replaceMentionsWithLinkSelfString, foundMentions) + suite.Equal(replaceMemtionsWithLinkSelfExpected, f) } func TestCommonTestSuite(t *testing.T) {