mirror of
https://dev.narayana.im/narayana/telegabber.git
synced 2026-08-05 04:07:07 +00:00
Track updated message ids for more reliable message edit check
This commit is contained in:
parent
5650850be9
commit
eee277e36e
3 changed files with 158 additions and 47 deletions
|
|
@ -27,6 +27,41 @@ type HashedAvatar struct {
|
|||
File int32
|
||||
}
|
||||
|
||||
// NewId stores message ids and timestamps of their additions so old ones can be truncated to save memory
|
||||
type newId struct {
|
||||
Id int64
|
||||
Ts int64
|
||||
lock sync.Mutex
|
||||
ownLock sync.Mutex
|
||||
locked bool
|
||||
fired bool
|
||||
}
|
||||
|
||||
func newNewId() *newId {
|
||||
return &newId{Ts: time.Now().Unix()}
|
||||
}
|
||||
|
||||
func (i *newId) Lock() {
|
||||
i.ownLock.Lock()
|
||||
if i.fired {
|
||||
i.ownLock.Unlock()
|
||||
return
|
||||
}
|
||||
i.locked = true
|
||||
i.ownLock.Unlock()
|
||||
i.lock.Lock()
|
||||
}
|
||||
|
||||
func (i *newId) Unlock() {
|
||||
i.ownLock.Lock()
|
||||
if i.locked {
|
||||
i.lock.Unlock()
|
||||
i.locked = false
|
||||
i.fired = true
|
||||
}
|
||||
i.ownLock.Unlock()
|
||||
}
|
||||
|
||||
// Client stores the metadata for lazily invoked TDlib instance
|
||||
type Client struct {
|
||||
client *client.Client
|
||||
|
|
@ -64,6 +99,9 @@ type Client struct {
|
|||
AvatarHashes map[int64]*HashedAvatar
|
||||
AvatarHashesLock sync.Mutex
|
||||
|
||||
MessageIdChanges map[int64]map[int64]*newId
|
||||
MessageIdChangesLock sync.Mutex
|
||||
|
||||
locks clientLocks
|
||||
SendMessageLock sync.Mutex
|
||||
}
|
||||
|
|
@ -149,6 +187,7 @@ func NewClient(conf config.TelegramConfig, jid string, component *xmpp.Component
|
|||
lastMsgIds: make(map[int64]string),
|
||||
XmppClientFeatures: make(map[string]*[]string),
|
||||
AvatarHashes: make(map[int64]*HashedAvatar),
|
||||
MessageIdChanges: make(map[int64]map[int64]*newId),
|
||||
locks: clientLocks{
|
||||
chatMessageLocks: make(map[int64]*sync.Mutex),
|
||||
},
|
||||
|
|
|
|||
|
|
@ -312,21 +312,48 @@ func (c *Client) updateMessageContent(update *client.UpdateMessageContent) {
|
|||
sId := strconv.FormatInt(update.MessageId, 10)
|
||||
var isCarbon bool
|
||||
|
||||
go func() {
|
||||
message, messageErr := c.client.GetMessage(&client.GetMessageRequest{
|
||||
ChatId: update.ChatId,
|
||||
MessageId: update.MessageId,
|
||||
})
|
||||
if messageErr != nil {
|
||||
// odnako za vremya puti
|
||||
// sobaka mogla podrasti
|
||||
c.MessageIdChangesLock.Lock()
|
||||
idsMap, idsMapOk := c.MessageIdChanges[update.ChatId]
|
||||
hadNoId := false
|
||||
if idsMapOk {
|
||||
newId, newIdOk := idsMap[update.MessageId]
|
||||
if newIdOk {
|
||||
if newId.Id == 0 {
|
||||
hadNoId = true
|
||||
c.MessageIdChangesLock.Unlock()
|
||||
newId.Lock()
|
||||
}
|
||||
log.Infof("falling back to updated message id: %v/%v->%v", update.ChatId, update.MessageId, newId.Id)
|
||||
message, messageErr = c.client.GetMessage(&client.GetMessageRequest{
|
||||
ChatId: update.ChatId,
|
||||
MessageId: newId.Id,
|
||||
})
|
||||
}
|
||||
}
|
||||
if !hadNoId {
|
||||
c.MessageIdChangesLock.Unlock()
|
||||
}
|
||||
}
|
||||
var prefix string
|
||||
if messageErr == nil {
|
||||
if message.EditDate == 0 {
|
||||
return
|
||||
}
|
||||
log.Debugf("editDate: %v", message.EditDate)
|
||||
|
||||
isCarbon = c.isCarbonsEnabled() && message.IsOutgoing
|
||||
// reply correction support in clients is suboptimal yet, so cut them out for now
|
||||
prefix, _ = c.messageToPrefix(message, "", "", true)
|
||||
} else {
|
||||
log.Errorf("No message %v/%v found, cannot reliably determine if it is a carbon and if it is edited", update.ChatId, update.MessageId)
|
||||
log.Errorf("No message %v/%v found, cannot reliably determine if it is a carbon and if it is edited: %v", update.ChatId, update.MessageId, messageErr.Error())
|
||||
}
|
||||
|
||||
// use XEP-0308 edits only if the last message is edited for sure, fallback otherwise
|
||||
|
|
@ -367,12 +394,17 @@ func (c *Client) updateMessageContent(update *client.UpdateMessageContent) {
|
|||
for _, jid := range jids {
|
||||
gateway.SendMessage(jid, sChatId, text.String(), "e"+sId, c.xmpp, nil, replaceId, isCarbon, false)
|
||||
}
|
||||
}()
|
||||
}
|
||||
}
|
||||
|
||||
// message(s) deleted
|
||||
func (c *Client) updateDeleteMessages(update *client.UpdateDeleteMessages) {
|
||||
if update.IsPermanent {
|
||||
for _, deleteId := range update.MessageIds {
|
||||
c.tryUnlockMessageId(update.ChatId, deleteId)
|
||||
}
|
||||
|
||||
if c.Session.IsChatIgnored(update.ChatId) {
|
||||
return
|
||||
}
|
||||
|
|
@ -411,6 +443,20 @@ func (c *Client) updateMessageSendSucceeded(update *client.UpdateMessageSendSucc
|
|||
log.Errorf("failed to replace %v with %v: %v", update.OldMessageId, update.Message.Id, err.Error())
|
||||
}
|
||||
|
||||
c.MessageIdChangesLock.Lock()
|
||||
idsMap, ok := c.MessageIdChanges[update.Message.ChatId]
|
||||
if !ok {
|
||||
idsMap = make(map[int64]*newId)
|
||||
c.MessageIdChanges[update.Message.ChatId] = idsMap
|
||||
}
|
||||
id, ok := idsMap[update.OldMessageId]
|
||||
if !ok {
|
||||
id = newNewId()
|
||||
idsMap[update.OldMessageId] = id
|
||||
}
|
||||
id.Id = update.Message.Id
|
||||
c.MessageIdChangesLock.Unlock()
|
||||
|
||||
c.sendMarker(update.Message.ChatId, update.Message.Id, gateway.MarkerTypeReceived)
|
||||
|
||||
// clean uploaded files
|
||||
|
|
@ -420,6 +466,8 @@ func (c *Client) updateMessageSendSucceeded(update *client.UpdateMessageSendSucc
|
|||
}
|
||||
}
|
||||
func (c *Client) updateMessageSendFailed(update *client.UpdateMessageSendFailed) {
|
||||
c.tryUnlockMessageId(update.Message.ChatId, update.OldMessageId)
|
||||
|
||||
// clean uploaded files
|
||||
file, _ := c.contentToFile(update.Message.Content)
|
||||
if file != nil && file.Local != nil {
|
||||
|
|
@ -446,3 +494,15 @@ func (c *Client) updateChatTitle(update *client.UpdateChatTitle) {
|
|||
func (c *Client) updateChatReadOutbox(update *client.UpdateChatReadOutbox) {
|
||||
c.sendMarker(update.ChatId, update.LastReadOutboxMessageId, gateway.MarkerTypeDisplayed)
|
||||
}
|
||||
|
||||
func (c *Client) tryUnlockMessageId(chatId, messageId int64) {
|
||||
c.MessageIdChangesLock.Lock()
|
||||
idsMap, ok := c.MessageIdChanges[chatId]
|
||||
if ok {
|
||||
id, ok := idsMap[messageId]
|
||||
if ok {
|
||||
id.Unlock()
|
||||
}
|
||||
}
|
||||
c.MessageIdChangesLock.Unlock()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -148,6 +148,18 @@ func heartbeat(component *xmpp.Component) {
|
|||
}
|
||||
}
|
||||
session.DelayedStatusesLock.Unlock()
|
||||
|
||||
// shrink message id maps
|
||||
session.MessageIdChangesLock.Lock()
|
||||
for _, idsMap := range session.MessageIdChanges {
|
||||
for oldMessageId, newId := range idsMap {
|
||||
if newId.Ts < now - 60 {
|
||||
newId.Unlock()
|
||||
delete(idsMap, oldMessageId)
|
||||
}
|
||||
}
|
||||
}
|
||||
session.MessageIdChangesLock.Unlock()
|
||||
}
|
||||
sessionLock.Unlock()
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue