diff --git a/telegram/client.go b/telegram/client.go index 61d46aa..5cc15a4 100644 --- a/telegram/client.go +++ b/telegram/client.go @@ -53,6 +53,7 @@ type Client struct { Session *persistence.Session resources map[string]bool outbox map[string]string + editQueue map[ChatMessageId]bool content *config.TelegramContentConfig cache *cache.Cache online bool @@ -69,6 +70,7 @@ type clientLocks struct { chatMessageLocks map[int64]*sync.Mutex resourcesLock sync.Mutex outboxLock sync.Mutex + editQueueLock sync.Mutex } // NewClient instantiates a Telegram App @@ -125,6 +127,7 @@ func NewClient(conf config.TelegramConfig, jid string, component *xmpp.Component Session: session, resources: make(map[string]bool), outbox: make(map[string]string), + editQueue: make(map[ChatMessageId]bool), content: &conf.Content, cache: cache.NewCache(), options: options, diff --git a/telegram/handlers.go b/telegram/handlers.go index abc1f5d..93ac284 100644 --- a/telegram/handlers.go +++ b/telegram/handlers.go @@ -104,6 +104,13 @@ func (c *Client) updateHandler() { } c.updateNewMessage(typedUpdate) log.Debugf("%#v", typedUpdate.Message) + case client.TypeUpdateMessageEdited: + typedUpdate, ok := update.(*client.UpdateMessageEdited) + if !ok { + uhOh() + } + c.updateMessageEdited(typedUpdate) + log.Debugf("%#v", typedUpdate) case client.TypeUpdateMessageContent: typedUpdate, ok := update.(*client.UpdateMessageContent) if !ok { @@ -229,6 +236,11 @@ func (c *Client) updateNewMessage(update *client.UpdateNewMessage) { }() } +// message content edited +func (c *Client) updateMessageEdited(update *client.UpdateMessageEdited) { + c.addToEditQueue(update.ChatId, update.MessageId) +} + // message content updated func (c *Client) updateMessageContent(update *client.UpdateMessageContent) { markupFunction := formatter.EntityToXEP0393 @@ -244,6 +256,14 @@ func (c *Client) updateMessageContent(update *client.UpdateMessageContent) { } log.Infof("ignoredResource: %v", ignoredResource) + if !c.deleteFromEditQueue(update.ChatId, update.MessageId) { + log.WithFields(log.Fields{ + "chatId": update.ChatId, + "messageId": update.MessageId, + }).Infof("Content update with no preceding message edit, ignoring") + return + } + jids := c.getCarbonFullJids(true, ignoredResource) if len(jids) == 0 { log.Info("The only resource is ignored, aborting") diff --git a/telegram/utils.go b/telegram/utils.go index 9486349..da66189 100644 --- a/telegram/utils.go +++ b/telegram/utils.go @@ -24,6 +24,7 @@ import ( "github.com/zelenin/go-tdlib/client" ) +// VCardInfo contains intermediate data to produce a vCard type VCardInfo struct { Fn string Photo *client.File @@ -34,6 +35,12 @@ type VCardInfo struct { Info string } +// ChatMessageId uniquely identifies a Telegram message +type ChatMessageId struct { + ChatId int64 + MessageId int64 +} + var errOffline = errors.New("TDlib instance is offline") var spaceRegex = regexp.MustCompile(`\s+`) @@ -1384,3 +1391,29 @@ func (c *Client) getCarbonFullJids(isOutgoing bool, ignoredResource string) []st } return jids } + +func (c *Client) addToEditQueue(chatId, messageId int64) { + c.locks.editQueueLock.Lock() + defer c.locks.editQueueLock.Unlock() + + c.editQueue[ChatMessageId{ + ChatId: chatId, + MessageId: messageId, + }] = true +} + +func (c *Client) deleteFromEditQueue(chatId, messageId int64) bool { + c.locks.editQueueLock.Lock() + defer c.locks.editQueueLock.Unlock() + + key := ChatMessageId{ + ChatId: chatId, + MessageId: messageId, + } + _, ok := c.editQueue[key] + if ok { + delete(c.editQueue, key) + } + + return ok +}