Map MUC subject changes to new pinned messages in Telegram

This commit is contained in:
Bohdan Horbeshko 2025-05-25 22:35:26 -04:00
parent 29a76e342e
commit 2c8c7f029d
4 changed files with 83 additions and 0 deletions

View file

@ -69,6 +69,7 @@ type Client struct {
outbox map[string]string
editOutbox map[string]string
pinOutbox map[int64]chan int64
DelayedStatuses map[int64]*DelayedStatus
DelayedStatusesLock sync.Mutex
@ -98,6 +99,7 @@ type clientLocks struct {
outboxLock sync.Mutex
mucCacheLock sync.Mutex
editOutboxLock sync.Mutex
pinOutboxLock sync.Mutex
lastMsgHashesLock sync.Mutex
lastMsgIdsLock sync.RWMutex
@ -167,6 +169,7 @@ func NewClient(conf config.TelegramConfig, jid string, component *xmpp.Component
cache: cache.NewCache(),
outbox: make(map[string]string),
editOutbox: make(map[string]string),
pinOutbox: make(map[int64]chan int64),
mucCache: make(map[int64]*MUCState),
options: options,
DelayedStatuses: make(map[int64]*DelayedStatus),

View file

@ -452,6 +452,13 @@ func (c *Client) updateAuthorizationState(update *client.UpdateAuthorizationStat
}
func (c *Client) updateMessageSendSucceeded(update *client.UpdateMessageSendSucceeded) {
c.locks.pinOutboxLock.Lock()
ch, chOk := c.pinOutbox[update.OldMessageId]
if chOk {
ch <-update.Message.Id
}
c.locks.pinOutboxLock.Unlock()
// replace message ID in local database
log.Debugf("replace message %v with %v", update.OldMessageId, update.Message.Id)
if err := gateway.IdsDB.ReplaceTgId(c.Session.Login, c.jid, update.Message.ChatId, update.OldMessageId, update.Message.Id); err != nil {
@ -469,6 +476,13 @@ func (c *Client) updateMessageSendSucceeded(update *client.UpdateMessageSendSucc
}
}
func (c *Client) updateMessageSendFailed(update *client.UpdateMessageSendFailed) {
c.locks.pinOutboxLock.Lock()
ch, chOk := c.pinOutbox[update.OldMessageId]
if chOk {
ch <-0
}
c.locks.pinOutboxLock.Unlock()
// clean uploaded files
file, _ := c.contentToFile(update.Message.Content)
if file != nil && file.Local != nil {

View file

@ -808,6 +808,44 @@ func (c *Client) GetMyMUCNickname(chatID int64) (string, bool) {
return member.Nickname, true
}
// NewPinnedMessage sends a text message and pins it right away
func (c *Client) NewPinnedMessage(chatID int64, text, returnJid string) bool {
c.locks.pinOutboxLock.Lock()
msg := c.ProcessOutgoingMessage(chatID, text, returnJid, 0, 0, true, true)
if msg == nil {
c.locks.pinOutboxLock.Unlock()
return false
}
ch := make(chan int64)
c.pinOutbox[msg.Id] = ch
c.locks.pinOutboxLock.Unlock()
newId := <-ch
c.locks.pinOutboxLock.Lock()
delete(c.pinOutbox, msg.Id)
c.locks.pinOutboxLock.Unlock()
if newId == 0 {
return false
}
ok, err := c.client.PinChatMessage(&client.PinChatMessageRequest{
ChatId: chatID,
MessageId: newId,
})
if err != nil {
log.Errorf("failed to pin message: %v", err.Error())
c.client.DeleteMessages(&client.DeleteMessagesRequest{
ChatId: chatID,
MessageIds: []int64{msg.Id},
Revoke: true,
})
}
return ok != nil
}
// FormatContact retrieves a complete "full name (@usernames)" string for display
func (c *Client) FormatContact(chatID int64) string {
if chatID == 0 {

View file

@ -342,6 +342,34 @@ func HandleMessage(s xmpp.Sender, p stanza.Packet) {
}
return
}
if msg.Thread == "" && msg.Subject != "" && msg.Type == "groupchat" {
log.Debugf("MUC subject change: %#v", msg)
bare, _, ok := gateway.SplitJID(msg.From)
if !ok {
return
}
session, ok := sessions[bare]
if !ok {
return
}
toID, ok, isGroup := toToID(msg.To)
if !ok || !isGroup {
return
}
_, resource, ok := gateway.SplitJID(msg.To)
if ok && resource != "" {
return
}
go func() {
pinOk := session.NewPinnedMessage(toID, msg.Subject, msg.From)
if !pinOk {
gateway.SendErrorMessage(msg.From, gateway.MUCJID(toID), "", 406, true, component)
}
}()
}
}
if msg.Type == "error" {