Make /s replace the whole message; fix replies and whitespace corruption

This commit is contained in:
Bohdan Horbeshko 2022-01-08 05:59:57 -05:00
parent ee6653c0c6
commit 9f04ed51bd
3 changed files with 84 additions and 78 deletions

View file

@ -3,10 +3,10 @@ package telegram
import ( import (
"fmt" "fmt"
"github.com/pkg/errors" "github.com/pkg/errors"
"regexp"
"strconv" "strconv"
"strings" "strings"
"time" "time"
"unicode"
"dev.narayana.im/narayana/telegabber/xmpp/gateway" "dev.narayana.im/narayana/telegabber/xmpp/gateway"
@ -114,6 +114,24 @@ func parseCommand(cmdline string) (string, []string) {
return bodyFields[0][1:], bodyFields[1:] 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) { func (c *Client) unsubscribe(chatID int64) {
gateway.SendPresence( gateway.SendPresence(
c.xmpp, c.xmpp,
@ -263,7 +281,7 @@ func (c *Client) ProcessTransportCommand(cmdline string, resource string) string
} }
_, err := c.client.SetBio(&client.SetBioRequest{ _, err := c.client.SetBio(&client.SetBioRequest{
Bio: strings.Join(args, " "), Bio: rawCmdArguments(cmdline, 0),
}) })
if err != nil { if err != nil {
return errors.Wrap(err, "Couldn't set bio").Error() 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 { if c.me == nil {
return "@me is not initialized", true return "@me is not initialized", true
} }
if len(args) < 2 { if len(args) < 1 {
return "Not enough arguments", true 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) messages, err := c.getLastMessages(chatID, "", c.me.ID, 1)
if err != nil { if err != nil {
@ -392,13 +406,17 @@ func (c *Client) ProcessChatCommand(chatID int64, cmdline string) (string, bool)
return "Last message is empty", true return "Last message is empty", true
} }
messageText, ok := message.Content.(*client.MessageText) content := c.ProcessOutgoingMessage(0, rawCmdArguments(cmdline, 0), "")
if !ok {
return "Last message is not a text!", true
}
text := regex.ReplaceAllString(messageText.Text.Text, strings.Join(args[1:], " ")) if content != nil {
c.ProcessOutgoingMessage(chatID, text, message.ID, "") c.client.EditMessageText(&client.EditMessageTextRequest{
ChatID: chatID,
MessageID: message.ID,
InputMessageContent: content,
})
} else {
return "Message processing error", true
}
// add @contact // add @contact
case "add": case "add":
if len(args) < 1 { if len(args) < 1 {
@ -441,7 +459,7 @@ func (c *Client) ProcessChatCommand(chatID int64, cmdline string) (string, bool)
_, err := c.client.CreateNewSupergroupChat(&client.CreateNewSupergroupChatRequest{ _, err := c.client.CreateNewSupergroupChat(&client.CreateNewSupergroupChatRequest{
Title: args[0], Title: args[0],
Description: strings.Join(args[1:], " "), Description: rawCmdArguments(cmdline, 1),
}) })
if err != nil { if err != nil {
return err.Error(), true return err.Error(), true
@ -454,7 +472,7 @@ func (c *Client) ProcessChatCommand(chatID int64, cmdline string) (string, bool)
_, err := c.client.CreateNewSupergroupChat(&client.CreateNewSupergroupChatRequest{ _, err := c.client.CreateNewSupergroupChat(&client.CreateNewSupergroupChatRequest{
Title: args[0], Title: args[0],
Description: strings.Join(args[1:], " "), Description: rawCmdArguments(cmdline, 1),
IsChannel: true, IsChannel: true,
}) })
if err != nil { if err != nil {

View file

@ -25,7 +25,7 @@ import (
var errOffline = errors.New("TDlib instance is offline") var errOffline = errors.New("TDlib instance is offline")
var spaceRegex = regexp.MustCompile(`\s+`) var spaceRegex = regexp.MustCompile(`\s+`)
var replyRegex = regexp.MustCompile("> ?([0-9]{10,})") var replyRegex = regexp.MustCompile("\\A>>? ?([0-9]+)\\n")
const newlineChar string = "\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 // ProcessOutgoingMessage executes commands or sends messages to mapped chats
func (c *Client) ProcessOutgoingMessage(chatID int64, text string, messageID int64, returnJid string) { func (c *Client) ProcessOutgoingMessage(chatID int64, text string, returnJid string) client.InputMessageContent {
if messageID == 0 && strings.HasPrefix(text, "/") { if !c.Online() {
// try to execute a command // we're offline
return nil
}
if returnJid != "" && strings.HasPrefix(text, "/") {
// try to execute commands
response, isCommand := c.ProcessChatCommand(chatID, text) response, isCommand := c.ProcessChatCommand(chatID, text)
if response != "" { if response != "" {
gateway.SendMessage(returnJid, strconv.FormatInt(chatID, 10), response, c.xmpp) gateway.SendMessage(returnJid, strconv.FormatInt(chatID, 10), response, c.xmpp)
} }
// do not send on success // do not send on success
if isCommand { if isCommand {
return return nil
} }
} }
if !c.Online() { log.Warnf("Sending message to chat %v", chatID)
// we're offline
return // 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) // attach a file
var file *client.InputFileRemote
if messageID != 0 { if chatID != 0 && c.content.Upload != "" && strings.HasPrefix(text, c.content.Upload) {
formattedText := &client.FormattedText{ file = &client.InputFileRemote{
Text: text, 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 // compile our message
message := &client.InputMessageText{ message = &client.InputMessageText{
Text: formattedText, Text: formattedText,
} }
}
c.client.EditMessageText(&client.EditMessageTextRequest{ if chatID != 0 {
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,
}
}
_, err := c.client.SendMessage(&client.SendMessageRequest{ _, err := c.client.SendMessage(&client.SendMessageRequest{
ChatID: chatID, ChatID: chatID,
ReplyToMessageID: reply, ReplyToMessageID: reply,
@ -569,10 +554,13 @@ func (c *Client) ProcessOutgoingMessage(chatID int64, text string, messageID int
gateway.SendMessage( gateway.SendMessage(
returnJid, returnJid,
strconv.FormatInt(chatID, 10), strconv.FormatInt(chatID, 10),
fmt.Sprintf("Message not sent: %s", err.Error()), fmt.Sprintf("Not sent: %s", err.Error()),
c.xmpp, c.xmpp,
) )
} }
return nil
} else {
return message
} }
} }

View file

@ -77,7 +77,7 @@ func HandleMessage(s xmpp.Sender, p stanza.Packet) {
if len(toParts) > 1 { if len(toParts) > 1 {
toIDInt, err := strconv.ParseInt(toID, 10, 64) toIDInt, err := strconv.ParseInt(toID, 10, 64)
if err == nil { if err == nil {
session.ProcessOutgoingMessage(toIDInt, msg.Body, 0, msg.From) session.ProcessOutgoingMessage(toIDInt, msg.Body, msg.From)
return return
} }
log.WithFields(log.Fields{ log.WithFields(log.Fields{