From 022a12ce3174ebc53ad7be712fd37077145aaffc Mon Sep 17 00:00:00 2001
From: Bohdan Horbeshko <bodqhrohro@gmail.com>
Date: Sat, 12 Mar 2022 12:25:53 -0500
Subject: Add /forward command

---
 telegram/commands.go | 31 ++++++++++++++++++++++++++++++
 telegram/handlers.go | 50 +------------------------------------------------
 telegram/utils.go    | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 85 insertions(+), 49 deletions(-)

(limited to 'telegram')

diff --git a/telegram/commands.go b/telegram/commands.go
index 58f4db3..17d212f 100644
--- a/telegram/commands.go
+++ b/telegram/commands.go
@@ -59,6 +59,7 @@ var chatCommands = map[string]command{
 	"s":          command{"edited message", "edit your last message"},
 	"silent":     command{"message", "send a message without sound"},
 	"schedule":   command{"{online | 2006-01-02T15:04:05 | 15:04:05} message", "schedules a message either to timestamp or to whenever the user goes online"},
+	"forward":    command{"message_id target_chat", "forwards a message"},
 	"add":        command{"@username", "add @username to your chat list"},
 	"join":       command{"https://t.me/invite_link", "join to chat via invite link"},
 	"group":      command{"title", "create groupchat «title» with current user"},
@@ -575,6 +576,36 @@ func (c *Client) ProcessChatCommand(chatID int64, cmdline string) (string, bool)
 		} else {
 			return "Message processing error", true
 		}
+	// forward a message to chat
+	case "forward":
+		if len(args) < 2 {
+			return notEnoughArguments, true
+		}
+
+		messageId, err := strconv.ParseInt(args[0], 10, 64)
+		if err != nil {
+			return "Cannot parse message ID", true
+		}
+
+		targetChatParts := strings.Split(args[1], "@") // full JIDs are supported too
+		targetChatId, err := strconv.ParseInt(targetChatParts[0], 10, 64)
+		if err != nil {
+			return "Cannot parse target chat ID", true
+		}
+
+		messages, err := c.client.ForwardMessages(&client.ForwardMessagesRequest{
+			ChatId:     targetChatId,
+			FromChatId: chatID,
+			MessageIds: []int64{messageId},
+		})
+		if err != nil {
+			return err.Error(), true
+		}
+		if messages != nil && messages.Messages != nil {
+			for _, message := range messages.Messages {
+				c.ProcessIncomingMessage(targetChatId, message)
+			}
+		}
 	// add @contact
 	case "add":
 		if len(args) < 1 {
diff --git a/telegram/handlers.go b/telegram/handlers.go
index a4fa39f..45f10fd 100644
--- a/telegram/handlers.go
+++ b/telegram/handlers.go
@@ -192,55 +192,7 @@ func (c *Client) updateNewMessage(update *client.UpdateNewMessage) {
 			"chat_id": chatId,
 		}).Warn("New message from chat")
 
-		var text string
-		content := update.Message.Content
-		if content != nil && content.MessageContentType() == client.TypeMessageChatChangePhoto {
-			chat, err := c.client.GetChat(&client.GetChatRequest{
-				ChatId: chatId,
-			})
-			if err == nil {
-				c.cache.SetChat(chatId, chat)
-				go c.ProcessStatusUpdate(chatId, "", "", gateway.SPImmed(true))
-				text = "<Chat photo has changed>"
-			}
-		} else {
-			text = c.messageToText(update.Message, false)
-			file := c.contentToFile(content)
-
-			// download file (if one)
-			if file != nil {
-				newFile, err := c.DownloadFile(file.Id, 1, true)
-				if err == nil {
-					file = newFile
-				}
-			}
-			// OTR support (I do not know why would you need it, seriously)
-			if !(strings.HasPrefix(text, "?OTR") || c.Session.RawMessages) {
-				var prefix strings.Builder
-				prefix.WriteString(c.messageToPrefix(update.Message, c.formatFile(file)))
-				if text != "" {
-					// \n if it is groupchat and message is not empty
-					if chatId < 0 {
-						prefix.WriteString("\n")
-					} else if chatId > 0 {
-						prefix.WriteString(" | ")
-					}
-
-					prefix.WriteString(text)
-				}
-
-				text = prefix.String()
-			}
-		}
-
-		// mark message as read
-		c.client.ViewMessages(&client.ViewMessagesRequest{
-			ChatId:     chatId,
-			MessageIds: []int64{update.Message.Id},
-			ForceRead:  true,
-		})
-		// forward message to XMPP
-		gateway.SendMessage(c.jid, strconv.FormatInt(chatId, 10), text, c.xmpp)
+		c.ProcessIncomingMessage(chatId, update.Message)
 	}()
 }
 
diff --git a/telegram/utils.go b/telegram/utils.go
index 9b72242..3511de0 100644
--- a/telegram/utils.go
+++ b/telegram/utils.go
@@ -694,6 +694,59 @@ func (c *Client) messageToPrefix(message *client.Message, fileString string) str
 	return strings.Join(prefix, " | ")
 }
 
+// ProcessIncomingMessage transfers a message to XMPP side and marks it as read on Telegram side
+func (c *Client) ProcessIncomingMessage(chatId int64, message *client.Message) {
+	var text string
+	content := message.Content
+	if content != nil && content.MessageContentType() == client.TypeMessageChatChangePhoto {
+		chat, err := c.client.GetChat(&client.GetChatRequest{
+			ChatId: chatId,
+		})
+		if err == nil {
+			c.cache.SetChat(chatId, chat)
+			go c.ProcessStatusUpdate(chatId, "", "", gateway.SPImmed(true))
+			text = "<Chat photo has changed>"
+		}
+	} else {
+		text = c.messageToText(message, false)
+		file := c.contentToFile(content)
+
+		// download file (if one)
+		if file != nil {
+			newFile, err := c.DownloadFile(file.Id, 1, true)
+			if err == nil {
+				file = newFile
+			}
+		}
+		// OTR support (I do not know why would you need it, seriously)
+		if !(strings.HasPrefix(text, "?OTR") || c.Session.RawMessages) {
+			var prefix strings.Builder
+			prefix.WriteString(c.messageToPrefix(message, c.formatFile(file)))
+			if text != "" {
+				// \n if it is groupchat and message is not empty
+				if chatId < 0 {
+					prefix.WriteString("\n")
+				} else if chatId > 0 {
+					prefix.WriteString(" | ")
+				}
+
+				prefix.WriteString(text)
+			}
+
+			text = prefix.String()
+		}
+	}
+
+	// mark message as read
+	c.client.ViewMessages(&client.ViewMessagesRequest{
+		ChatId:     chatId,
+		MessageIds: []int64{message.Id},
+		ForceRead:  true,
+	})
+	// forward message to XMPP
+	gateway.SendMessage(c.jid, strconv.FormatInt(chatId, 10), text, c.xmpp)
+}
+
 // ProcessOutgoingMessage executes commands or sends messages to mapped chats
 func (c *Client) ProcessOutgoingMessage(chatID int64, text string, returnJid string) client.InputMessageContent {
 	if !c.Online() {
-- 
cgit v1.2.3