From 9f04ed51bd26923afec70f086bdeba934fec32ba Mon Sep 17 00:00:00 2001 From: Bohdan Horbeshko Date: Sat, 8 Jan 2022 05:59:57 -0500 Subject: [PATCH] Make /s replace the whole message; fix replies and whitespace corruption --- telegram/commands.go | 48 +++++++++++++------ telegram/utils.go | 112 +++++++++++++++++++------------------------ xmpp/handlers.go | 2 +- 3 files changed, 84 insertions(+), 78 deletions(-) diff --git a/telegram/commands.go b/telegram/commands.go index cf4ebc8..8baf068 100644 --- a/telegram/commands.go +++ b/telegram/commands.go @@ -3,10 +3,10 @@ package telegram import ( "fmt" "github.com/pkg/errors" - "regexp" "strconv" "strings" "time" + "unicode" "dev.narayana.im/narayana/telegabber/xmpp/gateway" @@ -114,6 +114,24 @@ func parseCommand(cmdline string) (string, []string) { return bodyFields[0][1:], bodyFields[1:] } +func rawCmdArguments(cmdline string, start uint8) (string) { + var state uint + // /cmd ababa galamaga + // 01 2 3 45 + startState := uint(3 + 2 * start) + for i, r := range cmdline { + isOdd := state % 2 == 1 + isSpace := unicode.IsSpace(r) + if (!isOdd && !isSpace) || (isOdd && isSpace) { + state += 1 + } + if state == startState { + return cmdline[i:] + } + } + return "" +} + func (c *Client) unsubscribe(chatID int64) { gateway.SendPresence( c.xmpp, @@ -263,7 +281,7 @@ func (c *Client) ProcessTransportCommand(cmdline string, resource string) string } _, err := c.client.SetBio(&client.SetBioRequest{ - Bio: strings.Join(args, " "), + Bio: rawCmdArguments(cmdline, 0), }) if err != nil { return errors.Wrap(err, "Couldn't set bio").Error() @@ -371,13 +389,9 @@ func (c *Client) ProcessChatCommand(chatID int64, cmdline string) (string, bool) if c.me == nil { return "@me is not initialized", true } - if len(args) < 2 { + if len(args) < 1 { return "Not enough arguments", true } - regex, err := regexp.Compile(args[0]) - if err != nil { - return err.Error(), true - } messages, err := c.getLastMessages(chatID, "", c.me.ID, 1) if err != nil { @@ -392,13 +406,17 @@ func (c *Client) ProcessChatCommand(chatID int64, cmdline string) (string, bool) return "Last message is empty", true } - messageText, ok := message.Content.(*client.MessageText) - if !ok { - return "Last message is not a text!", true - } + content := c.ProcessOutgoingMessage(0, rawCmdArguments(cmdline, 0), "") - text := regex.ReplaceAllString(messageText.Text.Text, strings.Join(args[1:], " ")) - c.ProcessOutgoingMessage(chatID, text, message.ID, "") + if content != nil { + c.client.EditMessageText(&client.EditMessageTextRequest{ + ChatID: chatID, + MessageID: message.ID, + InputMessageContent: content, + }) + } else { + return "Message processing error", true + } // add @contact case "add": if len(args) < 1 { @@ -441,7 +459,7 @@ func (c *Client) ProcessChatCommand(chatID int64, cmdline string) (string, bool) _, err := c.client.CreateNewSupergroupChat(&client.CreateNewSupergroupChatRequest{ Title: args[0], - Description: strings.Join(args[1:], " "), + Description: rawCmdArguments(cmdline, 1), }) if err != nil { return err.Error(), true @@ -454,7 +472,7 @@ func (c *Client) ProcessChatCommand(chatID int64, cmdline string) (string, bool) _, err := c.client.CreateNewSupergroupChat(&client.CreateNewSupergroupChatRequest{ Title: args[0], - Description: strings.Join(args[1:], " "), + Description: rawCmdArguments(cmdline, 1), IsChannel: true, }) if err != nil { diff --git a/telegram/utils.go b/telegram/utils.go index bddffc8..7cc6256 100644 --- a/telegram/utils.go +++ b/telegram/utils.go @@ -25,7 +25,7 @@ import ( var errOffline = errors.New("TDlib instance is offline") var spaceRegex = regexp.MustCompile(`\s+`) -var replyRegex = regexp.MustCompile("> ?([0-9]{10,})") +var replyRegex = regexp.MustCompile("\\A>>? ?([0-9]+)\\n") const newlineChar string = "\n" @@ -483,83 +483,68 @@ func (c *Client) messageToPrefix(message *client.Message, fileString string) str } // ProcessOutgoingMessage executes commands or sends messages to mapped chats -func (c *Client) ProcessOutgoingMessage(chatID int64, text string, messageID int64, returnJid string) { - if messageID == 0 && strings.HasPrefix(text, "/") { - // try to execute a command +func (c *Client) ProcessOutgoingMessage(chatID int64, text string, returnJid string) client.InputMessageContent { + if !c.Online() { + // we're offline + return nil + } + + if returnJid != "" && strings.HasPrefix(text, "/") { + // try to execute commands response, isCommand := c.ProcessChatCommand(chatID, text) if response != "" { gateway.SendMessage(returnJid, strconv.FormatInt(chatID, 10), response, c.xmpp) } // do not send on success if isCommand { - return + return nil } } - if !c.Online() { - // we're offline - return + log.Warnf("Sending message to chat %v", chatID) + + // quotations + var reply int64 + replySlice := replyRegex.FindStringSubmatch(text) + if len(replySlice) > 1 { + reply, _ = strconv.ParseInt(replySlice[1], 10, 64) } - log.Warnf("Send message to chat %v", chatID) - - if messageID != 0 { - formattedText := &client.FormattedText{ - Text: text, + // attach a file + var file *client.InputFileRemote + if chatID != 0 && c.content.Upload != "" && strings.HasPrefix(text, c.content.Upload) { + file = &client.InputFileRemote{ + ID: text, } + } + // remove first line from text + if file != nil || reply != 0 { + newlinePos := strings.Index(text, newlineChar) + if newlinePos != -1 { + text = text[newlinePos+1:] + } + } + + formattedText := &client.FormattedText{ + Text: text, + } + + var message client.InputMessageContent + if file != nil { + // we can try to send a document + message = &client.InputMessageDocument{ + Document: file, + Caption: formattedText, + } + } else { // compile our message - message := &client.InputMessageText{ + message = &client.InputMessageText{ Text: formattedText, } + } - c.client.EditMessageText(&client.EditMessageTextRequest{ - ChatID: chatID, - MessageID: messageID, - InputMessageContent: message, - }) - } else { - // quotations - var reply int64 - replySlice := replyRegex.FindStringSubmatch(text) - if len(replySlice) > 1 { - reply, _ = strconv.ParseInt(replySlice[1], 10, 64) - } - - // attach a file - var file *client.InputFileRemote - if c.content.Upload != "" && strings.HasPrefix(text, c.content.Upload) { - file = &client.InputFileRemote{ - ID: text, - } - } - - // remove first line from text - if file != nil || reply != 0 { - newlinePos := strings.Index(text, newlineChar) - if newlinePos != -1 { - text = text[newlinePos+1:] - } - } - - formattedText := &client.FormattedText{ - Text: text, - } - - var message client.InputMessageContent - if file != nil { - // we can try to send a document - message = &client.InputMessageDocument{ - Document: file, - Caption: formattedText, - } - } else { - // compile our message - message = &client.InputMessageText{ - Text: formattedText, - } - } - + if chatID != 0 { _, err := c.client.SendMessage(&client.SendMessageRequest{ ChatID: chatID, ReplyToMessageID: reply, @@ -569,10 +554,13 @@ func (c *Client) ProcessOutgoingMessage(chatID int64, text string, messageID int gateway.SendMessage( returnJid, strconv.FormatInt(chatID, 10), - fmt.Sprintf("Message not sent: %s", err.Error()), + fmt.Sprintf("Not sent: %s", err.Error()), c.xmpp, ) } + return nil + } else { + return message } } diff --git a/xmpp/handlers.go b/xmpp/handlers.go index 1b4f6a3..07c30ec 100644 --- a/xmpp/handlers.go +++ b/xmpp/handlers.go @@ -77,7 +77,7 @@ func HandleMessage(s xmpp.Sender, p stanza.Packet) { if len(toParts) > 1 { toIDInt, err := strconv.ParseInt(toID, 10, 64) if err == nil { - session.ProcessOutgoingMessage(toIDInt, msg.Body, 0, msg.From) + session.ProcessOutgoingMessage(toIDInt, msg.Body, msg.From) return } log.WithFields(log.Fields{