@@ -51,17 +51,19 @@ func interface2Struct(in interface{}, out interface{}) error {
|
|||||||
return json.Unmarshal(jsonObj, out)
|
return json.Unmarshal(jsonObj, out)
|
||||||
}
|
}
|
||||||
|
|
||||||
// getDisplayName retrieves the displayName for mxid, querying the homserver if the mxid is not in the cache.
|
// getDisplayName retrieves the displayName for mxid, querying the homeserver if the mxid is not in the cache.
|
||||||
func (b *Bmatrix) getDisplayName(mxid string) string {
|
func (b *Bmatrix) getDisplayName(channelID string, mxid string) string {
|
||||||
if b.GetBool("UseUserName") {
|
if b.GetBool("UseUserName") {
|
||||||
return mxid[1:]
|
return mxid[1:]
|
||||||
}
|
}
|
||||||
|
|
||||||
b.RLock()
|
b.RLock()
|
||||||
if val, present := b.NicknameMap[mxid]; present {
|
if channel, channelPresent := b.NicknameMap[channelID]; channelPresent {
|
||||||
b.RUnlock()
|
if val, present := channel[mxid]; present {
|
||||||
|
b.RUnlock()
|
||||||
|
|
||||||
return val.displayName
|
return val.displayName
|
||||||
|
}
|
||||||
}
|
}
|
||||||
b.RUnlock()
|
b.RUnlock()
|
||||||
|
|
||||||
@@ -72,48 +74,54 @@ func (b *Bmatrix) getDisplayName(mxid string) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return b.cacheDisplayName(mxid, mxid[1:])
|
return b.cacheDisplayName(channelID, mxid, mxid[1:])
|
||||||
}
|
}
|
||||||
|
|
||||||
return b.cacheDisplayName(mxid, displayName.DisplayName)
|
return b.cacheDisplayName(channelID, mxid, displayName.DisplayName)
|
||||||
}
|
}
|
||||||
|
|
||||||
// cacheDisplayName stores the mapping between a mxid and a display name, to be reused later without performing a query to the homserver.
|
// cacheDisplayName stores the mapping between a mxid and a display name, to be reused later without performing a query to the homeserver.
|
||||||
// Note that old entries are cleaned when this function is called.
|
// Note that old entries are cleaned when this function is called.
|
||||||
func (b *Bmatrix) cacheDisplayName(mxid string, displayName string) string {
|
func (b *Bmatrix) cacheDisplayName(channelID string, mxid string, displayName string) string {
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
|
|
||||||
// scan to delete old entries, to stop memory usage from becoming too high with old entries.
|
// scan to delete old entries, to stop memory usage from becoming high with obsolete entries.
|
||||||
// In addition, we also detect if another user have the same username, and if so, we append their mxids to their usernames to differentiate them.
|
// In addition, we detect if another user have the same username, and if so, we append their mxids to their usernames to differentiate them.
|
||||||
toDelete := []string{}
|
toDelete := map[string]string{}
|
||||||
conflict := false
|
conflict := false
|
||||||
|
|
||||||
b.Lock()
|
b.Lock()
|
||||||
for mxid, v := range b.NicknameMap {
|
for channelIDIter, channelEntriesIter := range b.NicknameMap {
|
||||||
// to prevent username reuse across matrix servers - or even on the same server, append
|
for mxidIter, NicknameCacheIter := range channelEntriesIter {
|
||||||
// the mxid to the username when there is a conflict
|
// to prevent username reuse across matrix rooms - or even inside the same room, if a user uses multiple servers -
|
||||||
if v.displayName == displayName {
|
// append the mxid to the username when there is a conflict
|
||||||
conflict = true
|
if NicknameCacheIter.displayName == displayName {
|
||||||
// TODO: it would be nice to be able to rename previous messages from this user.
|
conflict = true
|
||||||
// The current behavior is that only users with clashing usernames and *that have spoken since the bridge last started* will get their mxids shown, and I don't know if that's the expected behavior.
|
// TODO: it would be nice to be able to rename previous messages from this user.
|
||||||
v.displayName = fmt.Sprintf("%s (%s)", displayName, mxid)
|
// The current behavior is that only users with clashing usernames and *that have spoken since the bridge last started* will get their mxids shown, and I don't know if that's the expected behavior.
|
||||||
b.NicknameMap[mxid] = v
|
NicknameCacheIter.displayName = fmt.Sprintf("%s (%s)", displayName, mxidIter)
|
||||||
}
|
b.NicknameMap[channelIDIter][mxidIter] = NicknameCacheIter
|
||||||
|
}
|
||||||
|
|
||||||
if now.Sub(v.lastUpdated) > 10*time.Minute {
|
if now.Sub(NicknameCacheIter.lastUpdated) > 10*time.Minute {
|
||||||
toDelete = append(toDelete, mxid)
|
toDelete[channelIDIter] = mxidIter
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for channelIDIter, mxidIter := range toDelete {
|
||||||
|
delete(b.NicknameMap[channelIDIter], mxidIter)
|
||||||
|
}
|
||||||
|
|
||||||
if conflict {
|
if conflict {
|
||||||
displayName = fmt.Sprintf("%s (%s)", displayName, mxid)
|
displayName = fmt.Sprintf("%s (%s)", displayName, mxid)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, v := range toDelete {
|
if _, channelPresent := b.NicknameMap[channelID]; !channelPresent {
|
||||||
delete(b.NicknameMap, v)
|
b.NicknameMap[channelID] = make(map[string]NicknameCacheEntry)
|
||||||
}
|
}
|
||||||
|
|
||||||
b.NicknameMap[mxid] = NicknameCacheEntry{
|
b.NicknameMap[channelID][mxid] = NicknameCacheEntry{
|
||||||
displayName: displayName,
|
displayName: displayName,
|
||||||
lastUpdated: now,
|
lastUpdated: now,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,9 +26,10 @@ type NicknameCacheEntry struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Bmatrix struct {
|
type Bmatrix struct {
|
||||||
mc *matrix.Client
|
mc *matrix.Client
|
||||||
UserID string
|
UserID string
|
||||||
NicknameMap map[string]NicknameCacheEntry
|
// channelId -> mxid -> NickNameCacheEntry
|
||||||
|
NicknameMap map[string]map[string]NicknameCacheEntry
|
||||||
RoomMap map[string]string
|
RoomMap map[string]string
|
||||||
rateMutex sync.RWMutex
|
rateMutex sync.RWMutex
|
||||||
sync.RWMutex
|
sync.RWMutex
|
||||||
@@ -68,7 +69,7 @@ type EditedMessage struct {
|
|||||||
func New(cfg *bridge.Config) bridge.Bridger {
|
func New(cfg *bridge.Config) bridge.Bridger {
|
||||||
b := &Bmatrix{Config: cfg}
|
b := &Bmatrix{Config: cfg}
|
||||||
b.RoomMap = make(map[string]string)
|
b.RoomMap = make(map[string]string)
|
||||||
b.NicknameMap = make(map[string]NicknameCacheEntry)
|
b.NicknameMap = make(map[string]map[string]NicknameCacheEntry)
|
||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -342,7 +343,7 @@ func (b *Bmatrix) handleMemberChange(ev *matrix.Event) {
|
|||||||
// Update the displayname on join messages, according to https://matrix.org/docs/spec/client_server/r0.6.1#events-on-change-of-profile-information
|
// Update the displayname on join messages, according to https://matrix.org/docs/spec/client_server/r0.6.1#events-on-change-of-profile-information
|
||||||
if ev.Content["membership"] == "join" {
|
if ev.Content["membership"] == "join" {
|
||||||
if dn, ok := ev.Content["displayname"].(string); ok {
|
if dn, ok := ev.Content["displayname"].(string); ok {
|
||||||
b.cacheDisplayName(ev.Sender, dn)
|
b.cacheDisplayName(ev.RoomID, ev.Sender, dn)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -360,7 +361,7 @@ func (b *Bmatrix) handleEvent(ev *matrix.Event) {
|
|||||||
|
|
||||||
// Create our message
|
// Create our message
|
||||||
rmsg := config.Message{
|
rmsg := config.Message{
|
||||||
Username: b.getDisplayName(ev.Sender),
|
Username: b.getDisplayName(ev.RoomID, ev.Sender),
|
||||||
Channel: channel,
|
Channel: channel,
|
||||||
Account: b.Account,
|
Account: b.Account,
|
||||||
UserID: ev.Sender,
|
UserID: ev.Sender,
|
||||||
|
|||||||
Reference in New Issue
Block a user