aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--telegram/commands.go2
-rw-r--r--telegram/connect.go8
-rw-r--r--telegram/handlers.go4
-rw-r--r--telegram/utils.go99
-rw-r--r--telegram/utils_test.go62
-rw-r--r--xmpp/extensions/extensions.go18
-rw-r--r--xmpp/gateway/gateway.go31
-rw-r--r--xmpp/handlers.go2
8 files changed, 168 insertions, 58 deletions
diff --git a/telegram/commands.go b/telegram/commands.go
index 957c335..943d071 100644
--- a/telegram/commands.go
+++ b/telegram/commands.go
@@ -184,6 +184,7 @@ func (c *Client) unsubscribe(chatID int64) error {
func (c *Client) sendMessagesReverse(chatID int64, messages []*client.Message) {
for i := len(messages) - 1; i >= 0; i-- {
message := messages[i]
+ reply, _ := c.getMessageReply(message)
gateway.SendMessage(
c.jid,
@@ -191,6 +192,7 @@ func (c *Client) sendMessagesReverse(chatID int64, messages []*client.Message) {
c.formatMessage(0, 0, false, message),
strconv.FormatInt(message.Id, 10),
c.xmpp,
+ reply,
)
}
}
diff --git a/telegram/connect.go b/telegram/connect.go
index b4957b1..2633980 100644
--- a/telegram/connect.go
+++ b/telegram/connect.go
@@ -219,20 +219,20 @@ func (c *Client) interactor() {
if c.Session.Login != "" {
c.authorizer.PhoneNumber <- c.Session.Login
} else {
- gateway.SendMessage(c.jid, "", "Please, enter your Telegram login via /login 12345", "", c.xmpp)
+ gateway.SendServiceMessage(c.jid, "Please, enter your Telegram login via /login 12345", c.xmpp)
}
// stage 1: wait for auth code
case client.TypeAuthorizationStateWaitCode:
log.Warn("Waiting for authorization code...")
- gateway.SendMessage(c.jid, "", "Please, enter authorization code via /code 12345", "", c.xmpp)
+ gateway.SendServiceMessage(c.jid, "Please, enter authorization code via /code 12345", c.xmpp)
// stage 1b: wait for registration
case client.TypeAuthorizationStateWaitRegistration:
log.Warn("Waiting for full name...")
- gateway.SendMessage(c.jid, "", "This number is not registered yet! Please, enter your name via /setname John Doe", "", c.xmpp)
+ gateway.SendServiceMessage(c.jid, "This number is not registered yet! Please, enter your name via /setname John Doe", c.xmpp)
// stage 2: wait for 2fa
case client.TypeAuthorizationStateWaitPassword:
log.Warn("Waiting for 2FA password...")
- gateway.SendMessage(c.jid, "", "Please, enter 2FA passphrase via /password 12345", "", c.xmpp)
+ gateway.SendServiceMessage(c.jid, "Please, enter 2FA passphrase via /password 12345", c.xmpp)
}
}
}
diff --git a/telegram/handlers.go b/telegram/handlers.go
index 517fb54..307562a 100644
--- a/telegram/handlers.go
+++ b/telegram/handlers.go
@@ -242,7 +242,7 @@ func (c *Client) updateMessageContent(update *client.UpdateMessageContent) {
textContent.Text.Entities,
markupFunction,
))
- gateway.SendMessage(c.jid, strconv.FormatInt(update.ChatId, 10), text, "e" + strconv.FormatInt(update.MessageId, 10), c.xmpp)
+ gateway.SendMessage(c.jid, strconv.FormatInt(update.ChatId, 10), text, "e" + strconv.FormatInt(update.MessageId, 10), c.xmpp, nil)
}
}
@@ -256,7 +256,7 @@ func (c *Client) updateDeleteMessages(update *client.UpdateDeleteMessages) {
deleteChar = "✗ "
}
text := deleteChar + strings.Join(int64SliceToStringSlice(update.MessageIds), ",")
- gateway.SendMessage(c.jid, strconv.FormatInt(update.ChatId, 10), text, "", c.xmpp)
+ gateway.SendTextMessage(c.jid, strconv.FormatInt(update.ChatId, 10), text, c.xmpp)
}
}
diff --git a/telegram/utils.go b/telegram/utils.go
index e58f6bf..f06abd7 100644
--- a/telegram/utils.go
+++ b/telegram/utils.go
@@ -261,6 +261,46 @@ func (c *Client) formatContact(chatID int64) string {
return str
}
+func (c *Client) getSenderId(message *client.Message) (senderId int64) {
+ if message.SenderId != nil {
+ switch message.SenderId.MessageSenderType() {
+ case client.TypeMessageSenderUser:
+ senderUser, _ := message.SenderId.(*client.MessageSenderUser)
+ senderId = senderUser.UserId
+ case client.TypeMessageSenderChat:
+ senderChat, _ := message.SenderId.(*client.MessageSenderChat)
+ senderId = senderChat.ChatId
+ }
+ }
+
+ return
+}
+
+func (c *Client) formatSender(message *client.Message) string {
+ return c.formatContact(c.getSenderId(message))
+}
+
+func (c *Client) getMessageReply(message *client.Message) (reply *gateway.Reply, replyMsg *client.Message) {
+ if message.ReplyToMessageId != 0 {
+ var err error
+ replyMsg, err = c.client.GetMessage(&client.GetMessageRequest{
+ ChatId: message.ChatId,
+ MessageId: message.ReplyToMessageId,
+ })
+ if err != nil {
+ log.Errorf("<error fetching message: %s>", err.Error())
+ return
+ }
+
+ reply = &gateway.Reply {
+ Author: fmt.Sprintf("%v@%s", c.getSenderId(replyMsg), gateway.Jid.Full()),
+ Id: strconv.FormatInt(message.ReplyToMessageId, 10),
+ }
+ }
+
+ return
+}
+
func (c *Client) formatMessage(chatID int64, messageID int64, preview bool, message *client.Message) string {
var err error
if message == nil {
@@ -279,18 +319,7 @@ func (c *Client) formatMessage(chatID int64, messageID int64, preview bool, mess
var str strings.Builder
// add messageid and sender
- var senderId int64
- if message.SenderId != nil {
- switch message.SenderId.MessageSenderType() {
- case client.TypeMessageSenderUser:
- senderUser, _ := message.SenderId.(*client.MessageSenderUser)
- senderId = senderUser.UserId
- case client.TypeMessageSenderChat:
- senderChat, _ := message.SenderId.(*client.MessageSenderChat)
- senderId = senderChat.ChatId
- }
- }
- str.WriteString(fmt.Sprintf("%v | %s | ", message.Id, c.formatContact(senderId)))
+ str.WriteString(fmt.Sprintf("%v | %s | ", message.Id, c.formatSender(message)))
// add date
if !preview {
str.WriteString(
@@ -681,7 +710,7 @@ func (c *Client) contentToFile(content client.MessageContent) (*client.File, *cl
return nil, nil
}
-func (c *Client) messageToPrefix(message *client.Message, previewString string, fileString string) string {
+func (c *Client) messageToPrefix(message *client.Message, previewString string, fileString string, replyMsg *client.Message) string {
prefix := []string{}
// message direction
var directionChar string
@@ -700,21 +729,12 @@ func (c *Client) messageToPrefix(message *client.Message, previewString string,
}
prefix = append(prefix, directionChar+strconv.FormatInt(message.Id, 10))
// show sender in group chats
- if message.ChatId < 0 && message.SenderId != nil {
- var senderId int64
- switch message.SenderId.MessageSenderType() {
- case client.TypeMessageSenderUser:
- senderUser, _ := message.SenderId.(*client.MessageSenderUser)
- senderId = senderUser.UserId
- case client.TypeMessageSenderChat:
- senderChat, _ := message.SenderId.(*client.MessageSenderChat)
- senderId = senderChat.ChatId
- }
- prefix = append(prefix, c.formatContact(senderId))
+ if message.ChatId < 0 {
+ prefix = append(prefix, c.formatSender(message))
}
// reply to
if message.ReplyToMessageId != 0 {
- prefix = append(prefix, "reply: "+c.formatMessage(message.ChatId, message.ReplyToMessageId, true, nil))
+ prefix = append(prefix, "reply: "+c.formatMessage(message.ChatId, message.ReplyToMessageId, true, replyMsg))
}
if message.ForwardInfo != nil {
prefix = append(prefix, "fwd: "+c.formatForward(message.ForwardInfo))
@@ -750,6 +770,9 @@ func (c *Client) ensureDownloadFile(file *client.File) *client.File {
// 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, oob, auxText string
+
+ reply, replyMsg := c.getMessageReply(message)
+
content := message.Content
if content != nil && content.MessageContentType() == client.TypeMessageChatChangePhoto {
chat, err := c.client.GetChat(&client.GetChatRequest{
@@ -783,7 +806,7 @@ func (c *Client) ProcessIncomingMessage(chatId int64, message *client.Message) {
text = oob
} else if !c.Session.RawMessages {
var prefix strings.Builder
- prefix.WriteString(c.messageToPrefix(message, previewName, fileName))
+ prefix.WriteString(c.messageToPrefix(message, previewName, fileName, replyMsg))
if text != "" {
// \n if it is groupchat and message is not empty
if chatId < 0 {
@@ -808,9 +831,9 @@ func (c *Client) ProcessIncomingMessage(chatId int64, message *client.Message) {
// forward message to XMPP
sId := strconv.FormatInt(message.Id, 10)
sChatId := strconv.FormatInt(chatId, 10)
- gateway.SendMessageWithOOB(c.jid, sChatId, text, sId, c.xmpp, oob)
+ gateway.SendMessageWithOOB(c.jid, sChatId, text, sId, c.xmpp, reply, oob)
if auxText != "" {
- gateway.SendMessage(c.jid, sChatId, auxText, sId, c.xmpp)
+ gateway.SendMessage(c.jid, sChatId, auxText, sId, c.xmpp, reply)
}
}
@@ -825,7 +848,7 @@ func (c *Client) ProcessOutgoingMessage(chatID int64, text string, returnJid str
// try to execute commands
response, isCommand := c.ProcessChatCommand(chatID, text)
if response != "" {
- gateway.SendMessage(returnJid, strconv.FormatInt(chatID, 10), response, "", c.xmpp)
+ gateway.SendTextMessage(returnJid, strconv.FormatInt(chatID, 10), response, c.xmpp)
}
// do not send on success
if isCommand {
@@ -847,11 +870,10 @@ func (c *Client) ProcessOutgoingMessage(chatID int64, text string, returnJid str
if chatID != 0 && c.content.Upload != "" && strings.HasPrefix(text, c.content.Upload) {
response, err := http.Get(text)
if err != nil {
- gateway.SendMessage(
+ gateway.SendTextMessage(
returnJid,
strconv.FormatInt(chatID, 10),
fmt.Sprintf("Failed to fetch the uploaded file: %s", err.Error()),
- "",
c.xmpp,
)
return nil
@@ -860,11 +882,10 @@ func (c *Client) ProcessOutgoingMessage(chatID int64, text string, returnJid str
defer response.Body.Close()
if response.StatusCode != 200 {
- gateway.SendMessage(
+ gateway.SendTextMessage(
returnJid,
strconv.FormatInt(chatID, 10),
fmt.Sprintf("Received status code %v", response.StatusCode),
- "",
c.xmpp,
)
return nil
@@ -872,22 +893,20 @@ func (c *Client) ProcessOutgoingMessage(chatID int64, text string, returnJid str
tempDir, err := ioutil.TempDir("", "telegabber-*")
if err != nil {
- gateway.SendMessage(
+ gateway.SendTextMessage(
returnJid,
strconv.FormatInt(chatID, 10),
fmt.Sprintf("Failed to create a temporary directory: %s", err.Error()),
- "",
c.xmpp,
)
return nil
}
tempFile, err := os.Create(filepath.Join(tempDir, filepath.Base(text)))
if err != nil {
- gateway.SendMessage(
+ gateway.SendTextMessage(
returnJid,
strconv.FormatInt(chatID, 10),
fmt.Sprintf("Failed to create a temporary file: %s", err.Error()),
- "",
c.xmpp,
)
return nil
@@ -895,11 +914,10 @@ func (c *Client) ProcessOutgoingMessage(chatID int64, text string, returnJid str
_, err = io.Copy(tempFile, response.Body)
if err != nil {
- gateway.SendMessage(
+ gateway.SendTextMessage(
returnJid,
strconv.FormatInt(chatID, 10),
fmt.Sprintf("Failed to write a temporary file: %s", err.Error()),
- "",
c.xmpp,
)
return nil
@@ -946,11 +964,10 @@ func (c *Client) ProcessOutgoingMessage(chatID int64, text string, returnJid str
InputMessageContent: message,
})
if err != nil {
- gateway.SendMessage(
+ gateway.SendTextMessage(
returnJid,
strconv.FormatInt(chatID, 10),
fmt.Sprintf("Not sent: %s", err.Error()),
- "",
c.xmpp,
)
}
diff --git a/telegram/utils_test.go b/telegram/utils_test.go
index bfd6c49..03ab8bd 100644
--- a/telegram/utils_test.go
+++ b/telegram/utils_test.go
@@ -389,7 +389,7 @@ func TestMessageToPrefix1(t *testing.T) {
},
},
}
- prefix := (&Client{Session: &persistence.Session{}}).messageToPrefix(&message, "", "")
+ prefix := (&Client{Session: &persistence.Session{}}).messageToPrefix(&message, "", "", nil)
if prefix != "➡ 42 | fwd: ziz" {
t.Errorf("Wrong prefix: %v", prefix)
}
@@ -404,7 +404,7 @@ func TestMessageToPrefix2(t *testing.T) {
},
},
}
- prefix := (&Client{Session: &persistence.Session{}}).messageToPrefix(&message, "y.jpg", "")
+ prefix := (&Client{Session: &persistence.Session{}}).messageToPrefix(&message, "y.jpg", "", nil)
if prefix != "⬅ 56 | fwd: (zaz) | preview: y.jpg" {
t.Errorf("Wrong prefix: %v", prefix)
}
@@ -419,7 +419,7 @@ func TestMessageToPrefix3(t *testing.T) {
},
},
}
- prefix := (&Client{Session: &persistence.Session{AsciiArrows: true}}).messageToPrefix(&message, "", "a.jpg")
+ prefix := (&Client{Session: &persistence.Session{AsciiArrows: true}}).messageToPrefix(&message, "", "a.jpg", nil)
if prefix != "< 56 | fwd: (zuz) | file: a.jpg" {
t.Errorf("Wrong prefix: %v", prefix)
}
@@ -430,7 +430,7 @@ func TestMessageToPrefix4(t *testing.T) {
Id: 23,
IsOutgoing: true,
}
- prefix := (&Client{Session: &persistence.Session{AsciiArrows: true}}).messageToPrefix(&message, "", "")
+ prefix := (&Client{Session: &persistence.Session{AsciiArrows: true}}).messageToPrefix(&message, "", "", nil)
if prefix != "> 23" {
t.Errorf("Wrong prefix: %v", prefix)
}
@@ -445,8 +445,60 @@ func TestMessageToPrefix5(t *testing.T) {
},
},
}
- prefix := (&Client{Session: &persistence.Session{AsciiArrows: true}}).messageToPrefix(&message, "h.jpg", "a.jpg")
+ prefix := (&Client{Session: &persistence.Session{AsciiArrows: true}}).messageToPrefix(&message, "h.jpg", "a.jpg", nil)
if prefix != "< 560 | fwd: (zyz) | preview: h.jpg | file: a.jpg" {
t.Errorf("Wrong prefix: %v", prefix)
}
}
+
+func TestMessageToPrefix6(t *testing.T) {
+ message := client.Message{
+ Id: 23,
+ IsOutgoing: true,
+ ReplyToMessageId: 42,
+ }
+ reply := client.Message{
+ Id: 42,
+ Content: &client.MessageText{
+ Text: &client.FormattedText{
+ Text: "tist",
+ },
+ },
+ }
+ prefix := (&Client{Session: &persistence.Session{AsciiArrows: true}}).messageToPrefix(&message, "", "", &reply)
+ if prefix != "> 23 | reply: 42 | | tist" {
+ t.Errorf("Wrong prefix: %v", prefix)
+ }
+}
+
+func GetSenderIdEmpty(t *testing.T) {
+ message := client.Message{}
+ senderId := (&Client{}).getSenderId(&message)
+ if senderId != 0 {
+ t.Errorf("Wrong sender id: %v", senderId)
+ }
+}
+
+func GetSenderIdUser(t *testing.T) {
+ message := client.Message{
+ SenderId: &client.MessageSenderUser{
+ UserId: 42,
+ },
+ }
+ senderId := (&Client{}).getSenderId(&message)
+ if senderId != 42 {
+ t.Errorf("Wrong sender id: %v", senderId)
+ }
+}
+
+func GetSenderIdChat(t *testing.T) {
+ message := client.Message{
+ SenderId: &client.MessageSenderChat{
+ ChatId: -42,
+ },
+ }
+ senderId := (&Client{}).getSenderId(&message)
+ if senderId != -42 {
+ t.Errorf("Wrong sender id: %v", senderId)
+ }
+}
diff --git a/xmpp/extensions/extensions.go b/xmpp/extensions/extensions.go
index fac5e7b..ce27656 100644
--- a/xmpp/extensions/extensions.go
+++ b/xmpp/extensions/extensions.go
@@ -111,6 +111,13 @@ type IqVcardDesc struct {
Text string `xml:",chardata"`
}
+// Reply is from XEP-0461
+type Reply struct {
+ XMLName xml.Name `xml:"urn:xmpp:reply:0 reply"`
+ To string `xml:"to,attr"`
+ Id string `xml:"id,attr"`
+}
+
// Namespace is a namespace!
func (c PresenceNickExtension) Namespace() string {
return c.XMLName.Space
@@ -131,6 +138,11 @@ func (c IqVcardTemp) GetSet() *stanza.ResultSet {
return c.ResultSet
}
+// Namespace is a namespace!
+func (c Reply) Namespace() string {
+ return c.XMLName.Space
+}
+
func init() {
// presence nick
stanza.TypeRegistry.MapExtension(stanza.PKTPresence, xml.Name{
@@ -149,4 +161,10 @@ func init() {
"vcard-temp",
"vCard",
}, IqVcardTemp{})
+
+ // reply
+ stanza.TypeRegistry.MapExtension(stanza.PKTMessage, xml.Name{
+ "urn:xmpp:reply:0",
+ "reply",
+ }, Reply{})
}
diff --git a/xmpp/gateway/gateway.go b/xmpp/gateway/gateway.go
index daa8f8a..d309ade 100644
--- a/xmpp/gateway/gateway.go
+++ b/xmpp/gateway/gateway.go
@@ -13,6 +13,11 @@ import (
"gosrc.io/xmpp/stanza"
)
+type Reply struct {
+ Author string
+ Id string
+}
+
const NSNick string = "http://jabber.org/protocol/nick"
// Queue stores presences to send later
@@ -27,16 +32,26 @@ var Jid *stanza.Jid
var DirtySessions = false
// SendMessage creates and sends a message stanza
-func SendMessage(to string, from string, body string, id string, component *xmpp.Component) {
- sendMessageWrapper(to, from, body, id, component, "")
+func SendMessage(to string, from string, body string, id string, component *xmpp.Component, reply *Reply) {
+ sendMessageWrapper(to, from, body, id, component, reply, "")
+}
+
+// SendServiceMessage creates and sends a simple message stanza from transport
+func SendServiceMessage(to string, body string, component *xmpp.Component) {
+ sendMessageWrapper(to, "", body, "", component, nil, "")
+}
+
+// SendTextMessage creates and sends a simple message stanza
+func SendTextMessage(to string, from string, body string, component *xmpp.Component) {
+ sendMessageWrapper(to, from, body, "", component, nil, "")
}
// SendMessageWithOOB creates and sends a message stanza with OOB URL
-func SendMessageWithOOB(to string, from string, body string, id string, component *xmpp.Component, oob string) {
- sendMessageWrapper(to, from, body, id, component, oob)
+func SendMessageWithOOB(to string, from string, body string, id string, component *xmpp.Component, reply *Reply, oob string) {
+ sendMessageWrapper(to, from, body, id, component, reply, oob)
}
-func sendMessageWrapper(to string, from string, body string, id string, component *xmpp.Component, oob string) {
+func sendMessageWrapper(to string, from string, body string, id string, component *xmpp.Component, reply *Reply, oob string) {
componentJid := Jid.Full()
var logFrom string
@@ -69,6 +84,12 @@ func sendMessageWrapper(to string, from string, body string, id string, componen
URL: oob,
})
}
+ if reply != nil {
+ message.Extensions = append(message.Extensions, extensions.Reply{
+ To: reply.Author,
+ Id: reply.Id,
+ })
+ }
sendMessage(&message, component)
}
diff --git a/xmpp/handlers.go b/xmpp/handlers.go
index d83fef4..b023bc5 100644
--- a/xmpp/handlers.go
+++ b/xmpp/handlers.go
@@ -106,7 +106,7 @@ func HandleMessage(s xmpp.Sender, p stanza.Packet) {
if err == nil && toJid.Bare() == gatewayJid && (strings.HasPrefix(msg.Body, "/") || strings.HasPrefix(msg.Body, "!")) {
response := session.ProcessTransportCommand(msg.Body, resource)
if response != "" {
- gateway.SendMessage(msg.From, "", response, "", component)
+ gateway.SendServiceMessage(msg.From, response, component)
}
return
}