From 3b01b1de700a42071b751a073707c92731aca3e7 Mon Sep 17 00:00:00 2001 From: Bohdan Horbeshko Date: Sat, 5 Jul 2025 12:43:38 -0400 Subject: [PATCH] Support /history command in MUCs --- telegram/handlers.go | 4 +- telegram/utils.go | 109 +++++++++++++++++++++++++++---------------- 2 files changed, 70 insertions(+), 43 deletions(-) diff --git a/telegram/handlers.go b/telegram/handlers.go index dfbc8f0..3369496 100644 --- a/telegram/handlers.go +++ b/telegram/handlers.go @@ -274,7 +274,7 @@ func (c *Client) updateMessageContent(update *client.UpdateMessageContent) { var jids []string if isMUC { - _, jids = c.getMUCJoinedJIDs(update.ChatId) + _, jids = c.getMUCJoinedJIDs(update.ChatId, nil, true) } else { c.getCarbonFullJids(true, ignoredResource) } @@ -408,7 +408,7 @@ func (c *Client) updateDeleteMessages(update *client.UpdateDeleteMessages) { var jids []string if isGroupchat { fromJid = gateway.MUCJID(update.ChatId) - _, jids = c.getMUCJoinedJIDs(update.ChatId) + _, jids = c.getMUCJoinedJIDs(update.ChatId, nil, true) } else { fromJid = gateway.CHATNODE(update.ChatId) c.getCarbonFullJids(true, "") diff --git a/telegram/utils.go b/telegram/utils.go index abfd394..c5d7274 100644 --- a/telegram/utils.go +++ b/telegram/utils.go @@ -872,19 +872,23 @@ func (c *Client) MUCHasResource(chatID int64, resource string) bool { return ok } -func (c *Client) getMUCJoinedJIDs(chatId int64) (bool, []string) { - c.locks.mucCacheLock.Lock() - defer c.locks.mucCacheLock.Unlock() +func (c *Client) getMUCJoinedJIDs(chatId int64, mucState *MUCState, lock bool) (bool, []string) { + if lock { + c.locks.mucCacheLock.Lock() + defer c.locks.mucCacheLock.Unlock() + } groupChatTos := []string{} - mucState, ok := c.mucCache[chatId] - if !ok || mucState == nil { + if mucState == nil { + mucState, _ = c.mucCache[chatId] + } + if mucState == nil { return false, nil - } else { - for resource := range mucState.Resources { - groupChatTos = append(groupChatTos, c.jid + "/" + resource) - } + } + + for resource := range mucState.Resources { + groupChatTos = append(groupChatTos, c.jid + "/" + resource) } return true, groupChatTos @@ -1099,7 +1103,7 @@ func (c *Client) getMessageReply(message *client.Message, preview bool, noConten return } -func (c *Client) formatMessage(chatID int64, messageID int64, preview bool, message *client.Message) string { +func (c *Client) formatMessage(chatID int64, messageID int64, preview bool, sender bool, message *client.Message) string { var err error if message == nil { message, err = c.client.GetMessage(&client.GetMessageRequest{ @@ -1115,16 +1119,18 @@ func (c *Client) formatMessage(chatID int64, messageID int64, preview bool, mess return "" } - return c.formatMessageContent(preview, c.messageToStub(message, preview, "")) + return c.formatMessageContent(preview, c.messageToStub(message, preview, ""), sender) } -func (c *Client) formatMessageContent(preview bool, message *messageStub) string { +func (c *Client) formatMessageContent(preview bool, message *messageStub, sender bool) string { var str strings.Builder // add messageid and sender if message.MessageId != 0 { str.WriteString(fmt.Sprintf("%v | ", message.MessageId)) } - str.WriteString(fmt.Sprintf("%s | ", message.Sender)) + if sender { + str.WriteString(fmt.Sprintf("%s | ", message.Sender)) + } // add date if !preview { str.WriteString( @@ -1354,7 +1360,7 @@ func (c *Client) messageContentToText(content client.MessageContent, chatId int6 return "kicked " + c.FormatContact(deleteMember.UserId) case client.TypeMessagePinMessage: pinMessage, _ := content.(*client.MessagePinMessage) - return "pinned message: " + c.formatMessage(chatId, pinMessage.MessageId, preview, nil) + return "pinned message: " + c.formatMessage(chatId, pinMessage.MessageId, preview, true, nil) case client.TypeMessageChatChangeTitle: changeTitle, _ := content.(*client.MessageChatChangeTitle) return "chat title set to: " + changeTitle.Title @@ -1648,7 +1654,7 @@ func (c *Client) messageToPrefix(message *client.Message, previewString string, replyStart = c.countCharsInLines(&prefix) + (len(prefix)-1)*len(messageHeaderSeparator) } - replyLine := "reply: " + c.formatMessageContent(preview, tgReply) + replyLine := "reply: " + c.formatMessageContent(preview, tgReply, true) prefix = append(prefix, replyLine) replyEnd = replyStart + utf8.RuneCountInString(replyLine) @@ -1750,7 +1756,7 @@ func (c *Client) ProcessIncomingMessage(chatId int64, message *client.Message) { groupChatFrom = gateway.MUCJID(chatId) + "/" + c.GetMUCNickname(senderId) var ok bool - ok, groupChatTos = c.getMUCJoinedJIDs(chatId) + ok, groupChatTos = c.getMUCJoinedJIDs(chatId, nil, true) if !ok { safeToSend = false } @@ -2604,9 +2610,20 @@ func (c *Client) TgMemberToMUCOccupant(member *client.ChatMember, chat *client.C func (c *Client) sendMessagesReverse(chatID int64, messages []*client.Message, plain bool, toJid string) { sChatId := gateway.CHATNODE(chatID) - var mucJid string - if toJid != "" { - mucJid = gateway.MUCJID(chatID) + mucJid := gateway.MUCJID(chatID) + var plainTos []string + + var isMUC bool + if plain { + chat, err := c.GetChatByID(chatID, nil) + if err == nil { + isMUC = c.Session.MUC && c.IsGroup(chat) + } + } + if isMUC { + _, plainTos = c.getMUCJoinedJIDs(chatID, nil, true) + } else { + plainTos = []string{c.jid} } for i := len(messages) - 1; i >= 0; i-- { @@ -2614,23 +2631,37 @@ func (c *Client) sendMessagesReverse(chatID int64, messages []*client.Message, p if plain { reply, _ := c.getMessageReply(message, false, true) - sId := strconv.FormatInt(message.Id, 10) - gateway.SendMessage( - c.jid, - sChatId, - c.formatMessage(0, 0, false, message), - sId, - c.xmpp, - reply, - 0, - "", - false, - false, - false, - "", - "", - ) + + var originalFrom string + var from string + if isMUC { + senderId := c.getMessageSenderId(message) + if senderId != 0 { + originalFrom = gateway.CHATJID(senderId, true) + } + from = mucJid + "/" + c.GetMUCNickname(senderId) + } else { + from = sChatId + } + + for _, to := range plainTos { + gateway.SendMessage( + to, + from, + c.formatMessage(0, 0, false, !isMUC, message), + sId, + c.xmpp, + reply, + 0, + "", + false, + isMUC, + false, + originalFrom, + "", + ) + } } else { msgId, _ := gateway.IdsDB.GetByTgIds(c.Session.Login, c.jid, chatID, message.Id) c.SendMessageToGateway( @@ -2764,6 +2795,7 @@ func (c *Client) leaveChat(chatID int64) error { return c.unsubscribe(chatID) } +// achtung: assuming a locked mucState context func (c *Client) kickMeFromMUC(chatID int64, statusCodes []uint16, destroy bool, mucState *MUCState) error { var myJid string if c.me != nil { @@ -2778,12 +2810,7 @@ func (c *Client) kickMeFromMUC(chatID int64, statusCodes []uint16, destroy bool, gateway.SPMUCStatusCodes(statusCodes), } if destroy { - var toResources []string - if mucState != nil { - for resource := range mucState.Resources { - toResources = append(toResources, resource) - } - } + _, toResources := c.getMUCJoinedJIDs(chatID, mucState, false) args = append( args, gateway.SPMUCDestroy(""),