fix: display name/nickname/ens which includes dash is not resolved in the chat when mentioned (#3516)
This commit is contained in:
parent
8c90353bc0
commit
75864528b1
|
@ -35,7 +35,7 @@ const (
|
||||||
var (
|
var (
|
||||||
specialCharsRegex = regexp.MustCompile("[@~\\\\*_\n>`]{1}")
|
specialCharsRegex = regexp.MustCompile("[@~\\\\*_\n>`]{1}")
|
||||||
endingCharsRegex = regexp.MustCompile(endingChars)
|
endingCharsRegex = regexp.MustCompile(endingChars)
|
||||||
wordRegex = regexp.MustCompile("^[\\w\\d]*" + endingChars + "|^[\\S]*$")
|
wordRegex = regexp.MustCompile("^[\\w\\d\\-]*" + endingChars + "|^[\\S]*$")
|
||||||
)
|
)
|
||||||
|
|
||||||
type specialCharLocation struct {
|
type specialCharLocation struct {
|
||||||
|
@ -60,12 +60,15 @@ type textMeta struct {
|
||||||
newlineIndexes []int
|
newlineIndexes []int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type searchablePhrase struct {
|
||||||
|
originalName string
|
||||||
|
phrase string
|
||||||
|
}
|
||||||
|
|
||||||
type MentionableUser struct {
|
type MentionableUser struct {
|
||||||
*Contact
|
*Contact
|
||||||
|
|
||||||
primaryName string
|
searchablePhrases []searchablePhrase
|
||||||
secondaryName string
|
|
||||||
searchablePhrases []string
|
|
||||||
|
|
||||||
Key string // a unique identifier of a mentionable user
|
Key string // a unique identifier of a mentionable user
|
||||||
Match string
|
Match string
|
||||||
|
@ -107,20 +110,6 @@ func (c *MentionableUser) MarshalJSON() ([]byte, error) {
|
||||||
return json.Marshal(contactJSON)
|
return json.Marshal(contactJSON)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *MentionableUser) PrimaryName() string {
|
|
||||||
if c.primaryName != "" {
|
|
||||||
return c.primaryName
|
|
||||||
}
|
|
||||||
return c.Contact.PrimaryName()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *MentionableUser) SecondaryName() string {
|
|
||||||
if c.secondaryName != "" {
|
|
||||||
return c.secondaryName
|
|
||||||
}
|
|
||||||
return c.Contact.SecondaryName()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *MentionableUser) GetDisplayName() string {
|
func (c *MentionableUser) GetDisplayName() string {
|
||||||
if c.ENSVerified && c.EnsName != "" {
|
if c.ENSVerified && c.EnsName != "" {
|
||||||
return c.EnsName
|
return c.EnsName
|
||||||
|
@ -649,8 +638,6 @@ func getUserSuggestions(users map[string]*MentionableUser, searchedText string,
|
||||||
match := findMatch(user, searchedText)
|
match := findMatch(user, searchedText)
|
||||||
if match != "" {
|
if match != "" {
|
||||||
result[pk] = &MentionableUser{
|
result[pk] = &MentionableUser{
|
||||||
primaryName: user.PrimaryName(),
|
|
||||||
secondaryName: user.SecondaryName(),
|
|
||||||
searchablePhrases: user.searchablePhrases,
|
searchablePhrases: user.searchablePhrases,
|
||||||
Contact: user.Contact,
|
Contact: user.Contact,
|
||||||
Key: pk,
|
Key: pk,
|
||||||
|
@ -677,9 +664,9 @@ func findMatch(user *MentionableUser, searchedText string) string {
|
||||||
func findMatchInPhrases(user *MentionableUser, searchedText string) string {
|
func findMatchInPhrases(user *MentionableUser, searchedText string) string {
|
||||||
var match string
|
var match string
|
||||||
|
|
||||||
for _, phrase := range user.searchablePhrases {
|
for _, p := range user.searchablePhrases {
|
||||||
if searchedText == "" || strings.HasPrefix(strings.ToLower(phrase), searchedText) {
|
if searchedText == "" || strings.HasPrefix(strings.ToLower(p.phrase), searchedText) {
|
||||||
match = primaryOrSecondaryName(user)
|
match = p.originalName
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -690,13 +677,11 @@ func findMatchInPhrases(user *MentionableUser, searchedText string) string {
|
||||||
// findMatchInNames searches for a matching phrase in MentionableUser's primary and secondary names.
|
// findMatchInNames searches for a matching phrase in MentionableUser's primary and secondary names.
|
||||||
func findMatchInNames(user *MentionableUser, searchedText string) string {
|
func findMatchInNames(user *MentionableUser, searchedText string) string {
|
||||||
var match string
|
var match string
|
||||||
|
for _, name := range user.names() {
|
||||||
if hasMatchingPrefix(user.PrimaryName(), searchedText) {
|
if hasMatchingPrefix(name, searchedText) {
|
||||||
match = primaryOrSecondaryName(user)
|
match = name
|
||||||
} else if hasMatchingPrefix(user.SecondaryName(), searchedText) {
|
}
|
||||||
match = user.SecondaryName()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return match
|
return match
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -705,18 +690,15 @@ func hasMatchingPrefix(text, searchedText string) bool {
|
||||||
return text != "" && (searchedText == "" || strings.HasPrefix(strings.ToLower(text), searchedText))
|
return text != "" && (searchedText == "" || strings.HasPrefix(strings.ToLower(text), searchedText))
|
||||||
}
|
}
|
||||||
|
|
||||||
// primaryOrSecondaryName returns the primary name if it is not empty, otherwise returns the secondary name.
|
|
||||||
func primaryOrSecondaryName(user *MentionableUser) string {
|
|
||||||
if primaryName := user.PrimaryName(); primaryName != "" {
|
|
||||||
return primaryName
|
|
||||||
}
|
|
||||||
return user.SecondaryName()
|
|
||||||
}
|
|
||||||
|
|
||||||
func isMentioned(user *MentionableUser, text string) bool {
|
func isMentioned(user *MentionableUser, text string) bool {
|
||||||
lCasePName := strings.ToLower(user.PrimaryName())
|
regexStr := ""
|
||||||
lCaseSName := strings.ToLower(user.SecondaryName())
|
for i, name := range user.names() {
|
||||||
regexStr := "^" + lCasePName + endingChars + "|" + "^" + lCasePName + "$" + "|" + "^" + lCaseSName + endingChars + "|" + "^" + lCaseSName + "$"
|
name = strings.ToLower(name)
|
||||||
|
if i != 0 {
|
||||||
|
regexStr += "|"
|
||||||
|
}
|
||||||
|
regexStr += "^" + name + endingChars + "|" + "^" + name + "$"
|
||||||
|
}
|
||||||
regex := regexp.MustCompile(regexStr)
|
regex := regexp.MustCompile(regexStr)
|
||||||
lCaseText := strings.ToLower(text)
|
lCaseText := strings.ToLower(text)
|
||||||
return regex.MatchString(lCaseText)
|
return regex.MatchString(lCaseText)
|
||||||
|
@ -797,12 +779,16 @@ func replaceMentions(text string, users map[string]*MentionableUser, idxs []int,
|
||||||
|
|
||||||
func addSearchablePhrases(user *MentionableUser) *MentionableUser {
|
func addSearchablePhrases(user *MentionableUser) *MentionableUser {
|
||||||
if !user.Blocked {
|
if !user.Blocked {
|
||||||
searchablePhrases := []string{user.PrimaryName(), user.SecondaryName()}
|
searchablePhrases := user.names()
|
||||||
for _, s := range searchablePhrases {
|
for _, s := range searchablePhrases {
|
||||||
if s != "" {
|
if s != "" {
|
||||||
newWords := []string{s}
|
newWords := []string{s}
|
||||||
newWords = append(newWords, strings.Split(s, " ")[1:]...)
|
newWords = append(newWords, strings.Split(s, " ")[1:]...)
|
||||||
user.searchablePhrases = append(user.searchablePhrases, newWords...)
|
var phrases []searchablePhrase
|
||||||
|
for _, w := range newWords {
|
||||||
|
phrases = append(phrases, searchablePhrase{s, w})
|
||||||
|
}
|
||||||
|
user.searchablePhrases = append(user.searchablePhrases, phrases...)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return user
|
return user
|
||||||
|
|
|
@ -84,23 +84,34 @@ func TestRePos(t *testing.T) {
|
||||||
func TestReplaceMentions(t *testing.T) {
|
func TestReplaceMentions(t *testing.T) {
|
||||||
users := map[string]*MentionableUser{
|
users := map[string]*MentionableUser{
|
||||||
"0xpk1": {
|
"0xpk1": {
|
||||||
primaryName: "User Number One",
|
|
||||||
Contact: &Contact{
|
Contact: &Contact{
|
||||||
ID: "0xpk1",
|
ID: "0xpk1",
|
||||||
|
LocalNickname: "User Number One",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"0xpk2": {
|
"0xpk2": {
|
||||||
primaryName: "user2",
|
|
||||||
secondaryName: "User Number Two",
|
|
||||||
Contact: &Contact{
|
Contact: &Contact{
|
||||||
ID: "0xpk2",
|
ID: "0xpk2",
|
||||||
|
LocalNickname: "user2",
|
||||||
|
ENSVerified: true,
|
||||||
|
EnsName: "User Number Two",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"0xpk3": {
|
"0xpk3": {
|
||||||
primaryName: "user3",
|
|
||||||
secondaryName: "User Number Three",
|
|
||||||
Contact: &Contact{
|
Contact: &Contact{
|
||||||
ID: "0xpk3",
|
ID: "0xpk3",
|
||||||
|
LocalNickname: "user3",
|
||||||
|
ENSVerified: true,
|
||||||
|
EnsName: "User Number Three",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"0xpk4": {
|
||||||
|
Contact: &Contact{
|
||||||
|
ID: "0xpk4",
|
||||||
|
EnsName: "ens-user-4.eth",
|
||||||
|
ENSVerified: true,
|
||||||
|
DisplayName: "display-name-user-4",
|
||||||
|
LocalNickname: "primary-name-user-4",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -163,6 +174,8 @@ func TestReplaceMentions(t *testing.T) {
|
||||||
{"code case 4", "` ` @user2 ``", "` ` @0xpk2 ``"},
|
{"code case 4", "` ` @user2 ``", "` ` @0xpk2 ``"},
|
||||||
|
|
||||||
{"double @", "@ @user2", "@ @0xpk2"},
|
{"double @", "@ @user2", "@ @0xpk2"},
|
||||||
|
|
||||||
|
{"user name contains dash", "@display-name-user-4 ", "@0xpk4 "},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
|
@ -693,9 +706,9 @@ func TestMentionSuggestionSpecialChars(t *testing.T) {
|
||||||
func TestMentionSuggestionAtSignSpaceCases(t *testing.T) {
|
func TestMentionSuggestionAtSignSpaceCases(t *testing.T) {
|
||||||
mentionableUserMap, chatID, mentionManager := setupMentionSuggestionTest(t, map[string]*MentionableUser{
|
mentionableUserMap, chatID, mentionManager := setupMentionSuggestionTest(t, map[string]*MentionableUser{
|
||||||
"0xpk1": {
|
"0xpk1": {
|
||||||
primaryName: "User Number One",
|
|
||||||
Contact: &Contact{
|
Contact: &Contact{
|
||||||
ID: "0xpk1",
|
ID: "0xpk1",
|
||||||
|
LocalNickname: "User Number One",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
@ -768,23 +781,25 @@ func setupMentionSuggestionTest(t *testing.T, mentionableUserMapInput map[string
|
||||||
func getDefaultMentionableUserMap() map[string]*MentionableUser {
|
func getDefaultMentionableUserMap() map[string]*MentionableUser {
|
||||||
return map[string]*MentionableUser{
|
return map[string]*MentionableUser{
|
||||||
"0xpk1": {
|
"0xpk1": {
|
||||||
primaryName: "User Number One",
|
|
||||||
Contact: &Contact{
|
Contact: &Contact{
|
||||||
ID: "0xpk1",
|
ID: "0xpk1",
|
||||||
|
LocalNickname: "User Number One",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"0xpk2": {
|
"0xpk2": {
|
||||||
primaryName: "u2",
|
|
||||||
secondaryName: "User Number Two",
|
|
||||||
Contact: &Contact{
|
Contact: &Contact{
|
||||||
ID: "0xpk2",
|
ID: "0xpk2",
|
||||||
|
LocalNickname: "u2",
|
||||||
|
ENSVerified: true,
|
||||||
|
EnsName: "User Number Two",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"0xpk3": {
|
"0xpk3": {
|
||||||
primaryName: "u3",
|
|
||||||
secondaryName: "User Number Three",
|
|
||||||
Contact: &Contact{
|
Contact: &Contact{
|
||||||
ID: "0xpk3",
|
ID: "0xpk3",
|
||||||
|
LocalNickname: "u3",
|
||||||
|
ENSVerified: true,
|
||||||
|
EnsName: "User Number Three",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue