Avoid webpage preview updates being sent as message edits (by hash matching)
This commit is contained in:
parent
eadef987be
commit
748366ad6a
|
@ -2,6 +2,7 @@ package telegram
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
"hash/maphash"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strconv"
|
"strconv"
|
||||||
"sync"
|
"sync"
|
||||||
|
@ -60,6 +61,9 @@ type Client struct {
|
||||||
DelayedStatuses map[int64]*DelayedStatus
|
DelayedStatuses map[int64]*DelayedStatus
|
||||||
DelayedStatusesLock sync.Mutex
|
DelayedStatusesLock sync.Mutex
|
||||||
|
|
||||||
|
lastMsgHashes map[int64]uint64
|
||||||
|
msgHashSeed maphash.Seed
|
||||||
|
|
||||||
locks clientLocks
|
locks clientLocks
|
||||||
SendMessageLock sync.Mutex
|
SendMessageLock sync.Mutex
|
||||||
}
|
}
|
||||||
|
@ -69,6 +73,7 @@ type clientLocks struct {
|
||||||
chatMessageLocks map[int64]*sync.Mutex
|
chatMessageLocks map[int64]*sync.Mutex
|
||||||
resourcesLock sync.Mutex
|
resourcesLock sync.Mutex
|
||||||
outboxLock sync.Mutex
|
outboxLock sync.Mutex
|
||||||
|
lastMsgHashesLock sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewClient instantiates a Telegram App
|
// NewClient instantiates a Telegram App
|
||||||
|
@ -129,6 +134,8 @@ func NewClient(conf config.TelegramConfig, jid string, component *xmpp.Component
|
||||||
cache: cache.NewCache(),
|
cache: cache.NewCache(),
|
||||||
options: options,
|
options: options,
|
||||||
DelayedStatuses: make(map[int64]*DelayedStatus),
|
DelayedStatuses: make(map[int64]*DelayedStatus),
|
||||||
|
lastMsgHashes: make(map[int64]uint64),
|
||||||
|
msgHashSeed: maphash.MakeSeed(),
|
||||||
locks: clientLocks{
|
locks: clientLocks{
|
||||||
chatMessageLocks: make(map[int64]*sync.Mutex),
|
chatMessageLocks: make(map[int64]*sync.Mutex),
|
||||||
},
|
},
|
||||||
|
|
|
@ -226,6 +226,8 @@ func (c *Client) updateNewMessage(update *client.UpdateNewMessage) {
|
||||||
}).Warn("New message from chat")
|
}).Warn("New message from chat")
|
||||||
|
|
||||||
c.ProcessIncomingMessage(chatId, update.Message, ignoredResource)
|
c.ProcessIncomingMessage(chatId, update.Message, ignoredResource)
|
||||||
|
|
||||||
|
c.updateLastMessageHash(update.Message.ChatId, update.Message.Id, update.Message.Content)
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -233,6 +235,8 @@ func (c *Client) updateNewMessage(update *client.UpdateNewMessage) {
|
||||||
func (c *Client) updateMessageContent(update *client.UpdateMessageContent) {
|
func (c *Client) updateMessageContent(update *client.UpdateMessageContent) {
|
||||||
markupFunction := formatter.EntityToXEP0393
|
markupFunction := formatter.EntityToXEP0393
|
||||||
|
|
||||||
|
defer c.updateLastMessageHash(update.ChatId, update.MessageId, update.NewContent)
|
||||||
|
|
||||||
c.SendMessageLock.Lock()
|
c.SendMessageLock.Lock()
|
||||||
c.SendMessageLock.Unlock()
|
c.SendMessageLock.Unlock()
|
||||||
xmppId, err := gateway.IdsDB.GetByTgIds(c.Session.Login, c.jid, update.ChatId, update.MessageId)
|
xmppId, err := gateway.IdsDB.GetByTgIds(c.Session.Login, c.jid, update.ChatId, update.MessageId)
|
||||||
|
@ -250,7 +254,7 @@ func (c *Client) updateMessageContent(update *client.UpdateMessageContent) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if update.NewContent.MessageContentType() == client.TypeMessageText {
|
if update.NewContent.MessageContentType() == client.TypeMessageText && c.hasLastMessageHashChanged(update.ChatId, update.MessageId, update.NewContent) {
|
||||||
textContent := update.NewContent.(*client.MessageText)
|
textContent := update.NewContent.(*client.MessageText)
|
||||||
var editChar string
|
var editChar string
|
||||||
if c.Session.AsciiArrows {
|
if c.Session.AsciiArrows {
|
||||||
|
|
|
@ -2,8 +2,10 @@ package telegram
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/sha1"
|
"crypto/sha1"
|
||||||
|
"encoding/binary"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
"hash/maphash"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
@ -1384,3 +1386,58 @@ func (c *Client) getCarbonFullJids(isOutgoing bool, ignoredResource string) []st
|
||||||
}
|
}
|
||||||
return jids
|
return jids
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Client) calculateMessageHash(messageId int64, content client.MessageContent) uint64 {
|
||||||
|
var h maphash.Hash
|
||||||
|
h.SetSeed(c.msgHashSeed)
|
||||||
|
|
||||||
|
buf8 := make([]byte, 8)
|
||||||
|
binary.BigEndian.PutUint64(buf8, uint64(messageId))
|
||||||
|
h.Write(buf8)
|
||||||
|
|
||||||
|
if content != nil && content.MessageContentType() == client.TypeMessageText {
|
||||||
|
textContent, ok := content.(*client.MessageText)
|
||||||
|
if !ok {
|
||||||
|
uhOh()
|
||||||
|
}
|
||||||
|
|
||||||
|
if textContent.Text != nil {
|
||||||
|
h.WriteString(textContent.Text.Text)
|
||||||
|
for _, entity := range textContent.Text.Entities {
|
||||||
|
buf4 := make([]byte, 4)
|
||||||
|
binary.BigEndian.PutUint32(buf4, uint32(entity.Offset))
|
||||||
|
h.Write(buf4)
|
||||||
|
binary.BigEndian.PutUint32(buf4, uint32(entity.Length))
|
||||||
|
h.Write(buf4)
|
||||||
|
h.WriteString(entity.Type.TextEntityTypeType())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return h.Sum64()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) updateLastMessageHash(chatId, messageId int64, content client.MessageContent) {
|
||||||
|
c.locks.lastMsgHashesLock.Lock()
|
||||||
|
defer c.locks.lastMsgHashesLock.Unlock()
|
||||||
|
|
||||||
|
c.lastMsgHashes[chatId] = c.calculateMessageHash(messageId, content)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) hasLastMessageHashChanged(chatId, messageId int64, content client.MessageContent) bool {
|
||||||
|
c.locks.lastMsgHashesLock.Lock()
|
||||||
|
defer c.locks.lastMsgHashesLock.Unlock()
|
||||||
|
|
||||||
|
oldHash, ok := c.lastMsgHashes[chatId]
|
||||||
|
newHash := c.calculateMessageHash(messageId, content)
|
||||||
|
|
||||||
|
if !ok {
|
||||||
|
log.Warnf("Last message hash for chat %v does not exist", chatId)
|
||||||
|
}
|
||||||
|
log.WithFields(log.Fields{
|
||||||
|
"old hash": oldHash,
|
||||||
|
"new hash": newHash,
|
||||||
|
}).Info("Message hashes")
|
||||||
|
|
||||||
|
return !ok || oldHash != newHash
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue