From 608f67551297a14e2e23603413bbce66f6ad5cd9 Mon Sep 17 00:00:00 2001
From: Bohdan Horbeshko <bodqhrohro@gmail.com>
Date: Wed, 2 Aug 2023 16:41:18 -0400
Subject: Revert sending carbons for outgoing messages to other resources (they
 duplicate what clients already send to each other)

---
 Makefile             |  2 +-
 telegabber.go        |  2 +-
 telegram/commands.go |  2 +-
 telegram/handlers.go | 19 ++++++++-----------
 telegram/utils.go    | 11 +++--------
 xmpp/handlers.go     |  1 -
 6 files changed, 14 insertions(+), 23 deletions(-)

diff --git a/Makefile b/Makefile
index 2eb17ac..6732740 100644
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,7 @@
 
 COMMIT := $(shell git rev-parse --short HEAD)
 TD_COMMIT := "8517026415e75a8eec567774072cbbbbb52376c1"
-VERSION := "v1.7.2"
+VERSION := "v1.7.3"
 MAKEOPTS := "-j4"
 
 all:
diff --git a/telegabber.go b/telegabber.go
index 9ce070f..3d7d2ea 100644
--- a/telegabber.go
+++ b/telegabber.go
@@ -15,7 +15,7 @@ import (
 	goxmpp "gosrc.io/xmpp"
 )
 
-var version string = "1.7.2"
+var version string = "1.7.3"
 var commit string
 
 var sm *goxmpp.StreamManager
diff --git a/telegram/commands.go b/telegram/commands.go
index e164ce1..206e049 100644
--- a/telegram/commands.go
+++ b/telegram/commands.go
@@ -658,7 +658,7 @@ func (c *Client) ProcessChatCommand(chatID int64, cmdline string) (string, bool)
 		}
 		if messages != nil && messages.Messages != nil {
 			for _, message := range messages.Messages {
-				c.ProcessIncomingMessage(targetChatId, message, "")
+				c.ProcessIncomingMessage(targetChatId, message)
 			}
 		}
 	// print vCard
diff --git a/telegram/handlers.go b/telegram/handlers.go
index cedea63..0d1cda9 100644
--- a/telegram/handlers.go
+++ b/telegram/handlers.go
@@ -205,27 +205,24 @@ func (c *Client) updateChatLastMessage(update *client.UpdateChatLastMessage) {
 func (c *Client) updateNewMessage(update *client.UpdateNewMessage) {
 	chatId := update.Message.ChatId
 
-	c.SendMessageLock.Lock()
-	c.SendMessageLock.Unlock()
-	xmppId, err := gateway.IdsDB.GetByTgIds(c.Session.Login, c.jid, chatId, update.Message.Id)
-	var ignoredResource string
-	if err == nil {
-		ignoredResource = c.popFromOutbox(xmppId)
-	} else {
-		log.Infof("Couldn't retrieve XMPP message ids for %v, an echo may happen", update.Message.Id)
-	}
-
 	// guarantee sequential message delivering per chat
 	lock := c.getChatMessageLock(chatId)
 	go func() {
 		lock.Lock()
 		defer lock.Unlock()
 
+		// ignore self outgoing messages
+		if update.Message.IsOutgoing &&
+			update.Message.SendingState != nil &&
+			update.Message.SendingState.MessageSendingStateType() == client.TypeMessageSendingStatePending {
+			return
+		}
+
 		log.WithFields(log.Fields{
 			"chat_id": chatId,
 		}).Warn("New message from chat")
 
-		c.ProcessIncomingMessage(chatId, update.Message, ignoredResource)
+		c.ProcessIncomingMessage(chatId, update.Message)
 
 		c.updateLastMessageHash(update.Message.ChatId, update.Message.Id, update.Message.Content)
 	}()
diff --git a/telegram/utils.go b/telegram/utils.go
index cd25c22..62ce945 100644
--- a/telegram/utils.go
+++ b/telegram/utils.go
@@ -911,7 +911,7 @@ 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, ignoredResource string) {
+func (c *Client) ProcessIncomingMessage(chatId int64, message *client.Message) {
 	var isPM bool
 	var err error
 	if gateway.MessageOutgoingPermission && c.Session.Carbons {
@@ -921,13 +921,8 @@ func (c *Client) ProcessIncomingMessage(chatId int64, message *client.Message, i
 		}
 	}
 
-	isOutgoing := message.IsOutgoing
-	isCarbon := isPM && isOutgoing
-	jids := c.getCarbonFullJids(isOutgoing, ignoredResource)
-	if len(jids) == 0 {
-		log.Info("The only resource is ignored, aborting")
-		return
-	}
+	isCarbon := isPM && message.IsOutgoing
+	jids := c.getCarbonFullJids(isCarbon, "")
 
 	var text, oob, auxText string
 
diff --git a/xmpp/handlers.go b/xmpp/handlers.go
index fd1afad..4e3354e 100644
--- a/xmpp/handlers.go
+++ b/xmpp/handlers.go
@@ -183,7 +183,6 @@ func HandleMessage(s xmpp.Sender, p stanza.Packet) {
 					if err != nil {
 						log.Errorf("Failed to save ids %v/%v %v", toID, tgMessageId, msg.Id)
 					}
-					session.AddToOutbox(msg.Id, resource)
 				}
 			} else {
 				/*
-- 
cgit v1.2.3


From c03ccfdfb713d4fcb089600d9fd91f03e469daca Mon Sep 17 00:00:00 2001
From: Bohdan Horbeshko <bodqhrohro@gmail.com>
Date: Wed, 2 Aug 2023 17:08:06 -0400
Subject: Support urn:xmpp:privilege:2

---
 Makefile                      |  2 +-
 telegabber.go                 |  2 +-
 telegram/commands.go          |  2 +-
 telegram/utils.go             |  4 ++--
 xmpp/extensions/extensions.go | 26 ++++++++++++++++++++++----
 xmpp/gateway/gateway.go       | 22 +++++++++++++++-------
 xmpp/handlers.go              | 21 ++++++++++++++++-----
 7 files changed, 58 insertions(+), 21 deletions(-)

diff --git a/Makefile b/Makefile
index 6732740..7857e17 100644
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,7 @@
 
 COMMIT := $(shell git rev-parse --short HEAD)
 TD_COMMIT := "8517026415e75a8eec567774072cbbbbb52376c1"
-VERSION := "v1.7.3"
+VERSION := "v1.7.4"
 MAKEOPTS := "-j4"
 
 all:
diff --git a/telegabber.go b/telegabber.go
index 3d7d2ea..df13dd6 100644
--- a/telegabber.go
+++ b/telegabber.go
@@ -15,7 +15,7 @@ import (
 	goxmpp "gosrc.io/xmpp"
 )
 
-var version string = "1.7.3"
+var version string = "1.7.4"
 var commit string
 
 var sm *goxmpp.StreamManager
diff --git a/telegram/commands.go b/telegram/commands.go
index 206e049..0c83945 100644
--- a/telegram/commands.go
+++ b/telegram/commands.go
@@ -384,7 +384,7 @@ func (c *Client) ProcessTransportCommand(cmdline string, resource string) string
 		}
 	case "config":
 		if len(args) > 1 {
-			if !gateway.MessageOutgoingPermission && args[0] == "carbons" && args[1] == "true" {
+			if gateway.MessageOutgoingPermissionVersion == 0 && args[0] == "carbons" && args[1] == "true" {
 				return "The server did not allow to enable carbons"
 			}
 
diff --git a/telegram/utils.go b/telegram/utils.go
index 62ce945..4caf88c 100644
--- a/telegram/utils.go
+++ b/telegram/utils.go
@@ -842,7 +842,7 @@ func (c *Client) messageToPrefix(message *client.Message, previewString string,
 	prefix := []string{}
 	// message direction
 	var directionChar string
-	if !isPM || !gateway.MessageOutgoingPermission || !c.Session.Carbons {
+	if !isPM || gateway.MessageOutgoingPermissionVersion == 0 || !c.Session.Carbons {
 		if c.Session.AsciiArrows {
 			if message.IsOutgoing {
 				directionChar = "> "
@@ -914,7 +914,7 @@ func (c *Client) ensureDownloadFile(file *client.File) *client.File {
 func (c *Client) ProcessIncomingMessage(chatId int64, message *client.Message) {
 	var isPM bool
 	var err error
-	if gateway.MessageOutgoingPermission && c.Session.Carbons {
+	if gateway.MessageOutgoingPermissionVersion > 0 && c.Session.Carbons {
 		isPM, err = c.IsPM(chatId)
 		if err != nil {
 			log.Errorf("Could not determine if chat is PM: %v", err)
diff --git a/xmpp/extensions/extensions.go b/xmpp/extensions/extensions.go
index 2d547af..192b630 100644
--- a/xmpp/extensions/extensions.go
+++ b/xmpp/extensions/extensions.go
@@ -154,12 +154,19 @@ type CarbonSent struct {
 }
 
 // ComponentPrivilege is from XEP-0356
-type ComponentPrivilege struct {
+type ComponentPrivilege1 struct {
 	XMLName   xml.Name         `xml:"urn:xmpp:privilege:1 privilege"`
 	Perms     []ComponentPerm  `xml:"perm"`
 	Forwarded stanza.Forwarded `xml:"urn:xmpp:forward:0 forwarded"`
 }
 
+// ComponentPrivilege is from XEP-0356
+type ComponentPrivilege2 struct {
+	XMLName   xml.Name         `xml:"urn:xmpp:privilege:2 privilege"`
+	Perms     []ComponentPerm  `xml:"perm"`
+	Forwarded stanza.Forwarded `xml:"urn:xmpp:forward:0 forwarded"`
+}
+
 // ComponentPerm is from XEP-0356
 type ComponentPerm struct {
 	XMLName xml.Name `xml:"perm"`
@@ -227,7 +234,12 @@ func (c CarbonSent) Namespace() string {
 }
 
 // Namespace is a namespace!
-func (c ComponentPrivilege) Namespace() string {
+func (c ComponentPrivilege1) Namespace() string {
+	return c.XMLName.Space
+}
+
+// Namespace is a namespace!
+func (c ComponentPrivilege2) Namespace() string {
 	return c.XMLName.Space
 }
 
@@ -297,11 +309,17 @@ func init() {
 		"sent",
 	}, CarbonSent{})
 
-	// component privilege
+	// component privilege v1
 	stanza.TypeRegistry.MapExtension(stanza.PKTMessage, xml.Name{
 		"urn:xmpp:privilege:1",
 		"privilege",
-	}, ComponentPrivilege{})
+	}, ComponentPrivilege1{})
+
+	// component privilege v2
+	stanza.TypeRegistry.MapExtension(stanza.PKTMessage, xml.Name{
+		"urn:xmpp:privilege:2",
+		"privilege",
+	}, ComponentPrivilege2{})
 
 	// message edit
 	stanza.TypeRegistry.MapExtension(stanza.PKTMessage, xml.Name{
diff --git a/xmpp/gateway/gateway.go b/xmpp/gateway/gateway.go
index 1be2fca..7a2500e 100644
--- a/xmpp/gateway/gateway.go
+++ b/xmpp/gateway/gateway.go
@@ -38,8 +38,8 @@ var IdsDB badger.IdsDB
 // were changed and need to be re-flushed to the YamlDB
 var DirtySessions = false
 
-// MessageOutgoingPermission allows to fake outgoing messages by foreign JIDs
-var MessageOutgoingPermission = false
+// MessageOutgoingPermissionVersion contains a XEP-0356 version to fake outgoing messages by foreign JIDs
+var MessageOutgoingPermissionVersion = 0
 
 // SendMessage creates and sends a message stanza
 func SendMessage(to string, from string, body string, id string, component *xmpp.Component, reply *Reply, isCarbon bool) {
@@ -142,11 +142,19 @@ func sendMessageWrapper(to string, from string, body string, id string, componen
 				To:   toJid.Domain,
 			},
 		}
-		privilegeMessage.Extensions = append(privilegeMessage.Extensions, extensions.ComponentPrivilege{
-			Forwarded: stanza.Forwarded{
-				Stanza: carbonMessage,
-			},
-		})
+		if MessageOutgoingPermissionVersion == 2 {
+			privilegeMessage.Extensions = append(privilegeMessage.Extensions, extensions.ComponentPrivilege2{
+				Forwarded: stanza.Forwarded{
+					Stanza: carbonMessage,
+				},
+			})
+		} else {
+			privilegeMessage.Extensions = append(privilegeMessage.Extensions, extensions.ComponentPrivilege1{
+				Forwarded: stanza.Forwarded{
+					Stanza: carbonMessage,
+				},
+			})
+		}
 		sendMessage(&privilegeMessage, component)
 	} else {
 		sendMessage(&message, component)
diff --git a/xmpp/handlers.go b/xmpp/handlers.go
index 4e3354e..6679a72 100644
--- a/xmpp/handlers.go
+++ b/xmpp/handlers.go
@@ -209,14 +209,25 @@ func HandleMessage(s xmpp.Sender, p stanza.Packet) {
 	}
 
 	if msg.Body == "" {
-		var privilege extensions.ComponentPrivilege
-		if ok := msg.Get(&privilege); ok {
-			log.Debugf("privilege: %#v", privilege)
+		var privilege1 extensions.ComponentPrivilege1
+		if ok := msg.Get(&privilege1); ok {
+			log.Debugf("privilege1: %#v", privilege1)
 		}
 
-		for _, perm := range privilege.Perms {
+		for _, perm := range privilege1.Perms {
 			if perm.Access == "message" && perm.Type == "outgoing" {
-				gateway.MessageOutgoingPermission = true
+				gateway.MessageOutgoingPermissionVersion = 1
+			}
+		}
+
+		var privilege2 extensions.ComponentPrivilege2
+		if ok := msg.Get(&privilege2); ok {
+			log.Debugf("privilege2: %#v", privilege2)
+		}
+
+		for _, perm := range privilege2.Perms {
+			if perm.Access == "message" && perm.Type == "outgoing" {
+				gateway.MessageOutgoingPermissionVersion = 2
 			}
 		}
 	}
-- 
cgit v1.2.3


From 9377d7a15538a6c0af97937806ecd55eb112beb3 Mon Sep 17 00:00:00 2001
From: Bohdan Horbeshko <bodqhrohro@gmail.com>
Date: Sun, 6 Aug 2023 20:04:49 -0400
Subject: Save/read unavailable presence type in cache

---
 Makefile                |  2 +-
 telegabber.go           |  2 +-
 telegram/cache/cache.go | 10 ++++++++++
 telegram/utils.go       | 40 ++++++++++++++++++++++++++++++++++++----
 xmpp/handlers.go        | 14 +++++++++++---
 5 files changed, 59 insertions(+), 9 deletions(-)

diff --git a/Makefile b/Makefile
index 7857e17..33bedad 100644
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,7 @@
 
 COMMIT := $(shell git rev-parse --short HEAD)
 TD_COMMIT := "8517026415e75a8eec567774072cbbbbb52376c1"
-VERSION := "v1.7.4"
+VERSION := "v1.7.5"
 MAKEOPTS := "-j4"
 
 all:
diff --git a/telegabber.go b/telegabber.go
index df13dd6..37d5890 100644
--- a/telegabber.go
+++ b/telegabber.go
@@ -15,7 +15,7 @@ import (
 	goxmpp "gosrc.io/xmpp"
 )
 
-var version string = "1.7.4"
+var version string = "1.7.5"
 var commit string
 
 var sm *goxmpp.StreamManager
diff --git a/telegram/cache/cache.go b/telegram/cache/cache.go
index 3d9608d..6847d3e 100644
--- a/telegram/cache/cache.go
+++ b/telegram/cache/cache.go
@@ -133,3 +133,13 @@ func (cache *Cache) SetStatus(id int64, show string, status string) {
 		Description: status,
 	}
 }
+
+// Destruct splits a cached status into show, description and type
+func (status *Status) Destruct() (show, description, typ string) {
+	show, description = status.XMPP, status.Description
+	if show == "unavailable" {
+		typ = show
+		show = ""
+	}
+	return
+}
diff --git a/telegram/utils.go b/telegram/utils.go
index 4caf88c..2578671 100644
--- a/telegram/utils.go
+++ b/telegram/utils.go
@@ -243,15 +243,33 @@ func (c *Client) ProcessStatusUpdate(chatID int64, status string, show string, o
 	cachedStatus, ok := c.cache.GetStatus(chatID)
 	if status == "" {
 		if ok {
-			show, status = cachedStatus.XMPP, cachedStatus.Description
+			var typ string
+			show, status, typ = cachedStatus.Destruct()
+			if presenceType == "" {
+				presenceType = typ
+			}
+			log.WithFields(log.Fields{
+				"show": show,
+				"status": status,
+				"presenceType": presenceType,
+			}).Debug("Cached status")
 		} else if user != nil && user.Status != nil {
 			show, status, presenceType = c.userStatusToText(user.Status, chatID)
+			log.WithFields(log.Fields{
+				"show": show,
+				"status": status,
+				"presenceType": presenceType,
+			}).Debug("Status to text")
 		} else {
 			show, status = "chat", chat.Title
 		}
 	}
 
-	c.cache.SetStatus(chatID, show, status)
+	cacheShow := show
+	if presenceType == "unavailable" {
+		cacheShow = presenceType
+	}
+	c.cache.SetStatus(chatID, cacheShow, status)
 
 	newArgs := []args.V{
 		gateway.SPFrom(strconv.FormatInt(chatID, 10)),
@@ -1366,12 +1384,26 @@ func (c *Client) UpdateChatNicknames() {
 	for _, id := range c.cache.ChatsKeys() {
 		chat, ok := c.cache.GetChat(id)
 		if ok {
+			newArgs := []args.V{
+				gateway.SPFrom(strconv.FormatInt(id, 10)),
+				gateway.SPNickname(chat.Title),
+			}
+
+			cachedStatus, ok := c.cache.GetStatus(id)
+			if ok {
+				show, status, typ := cachedStatus.Destruct()
+				newArgs = append(newArgs, gateway.SPShow(show), gateway.SPStatus(status))
+				if typ != "" {
+					newArgs = append(newArgs, gateway.SPType(typ))
+				}
+			}
+
 			gateway.SendPresence(
 				c.xmpp,
 				c.jid,
-				gateway.SPFrom(strconv.FormatInt(id, 10)),
-				gateway.SPNickname(chat.Title),
+				newArgs...,
 			)
+
 			gateway.SetNickname(c.jid, strconv.FormatInt(id, 10), chat.Title, c.xmpp)
 		}
 	}
diff --git a/xmpp/handlers.go b/xmpp/handlers.go
index 6679a72..e85dfc9 100644
--- a/xmpp/handlers.go
+++ b/xmpp/handlers.go
@@ -15,6 +15,7 @@ import (
 	"dev.narayana.im/narayana/telegabber/xmpp/gateway"
 
 	log "github.com/sirupsen/logrus"
+	"github.com/soheilhy/args"
 	"gosrc.io/xmpp"
 	"gosrc.io/xmpp/stanza"
 )
@@ -349,11 +350,18 @@ func handlePresence(s xmpp.Sender, p stanza.Presence) {
 				log.Error(errors.Wrap(err, "TDlib connection failure"))
 			} else {
 				for status := range session.StatusesRange() {
+					show, description, typ := status.Destruct()
+					newArgs := []args.V{
+						gateway.SPImmed(false),
+					}
+					if typ != "" {
+						newArgs = append(newArgs, gateway.SPType(typ))
+					}
 					go session.ProcessStatusUpdate(
 						status.ID,
-						status.Description,
-						status.XMPP,
-						gateway.SPImmed(false),
+						description,
+						show,
+						newArgs...,
 					)
 				}
 				session.UpdateChatNicknames()
-- 
cgit v1.2.3


From 64515e2c666067953e3a9680b4f0db84f3838498 Mon Sep 17 00:00:00 2001
From: Bohdan Horbeshko <bodqhrohro@gmail.com>
Date: Tue, 8 Aug 2023 00:54:24 -0400
Subject: Fix replies to messages with non-ASCII characters

---
 Makefile         | 2 +-
 telegabber.go    | 2 +-
 xmpp/handlers.go | 7 ++++++-
 3 files changed, 8 insertions(+), 3 deletions(-)

diff --git a/Makefile b/Makefile
index 33bedad..ef6aef4 100644
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,7 @@
 
 COMMIT := $(shell git rev-parse --short HEAD)
 TD_COMMIT := "8517026415e75a8eec567774072cbbbbb52376c1"
-VERSION := "v1.7.5"
+VERSION := "v1.7.6"
 MAKEOPTS := "-j4"
 
 all:
diff --git a/telegabber.go b/telegabber.go
index 37d5890..3802764 100644
--- a/telegabber.go
+++ b/telegabber.go
@@ -15,7 +15,7 @@ import (
 	goxmpp "gosrc.io/xmpp"
 )
 
-var version string = "1.7.5"
+var version string = "1.7.6"
 var commit string
 
 var sm *goxmpp.StreamManager
diff --git a/xmpp/handlers.go b/xmpp/handlers.go
index e85dfc9..36f9cf9 100644
--- a/xmpp/handlers.go
+++ b/xmpp/handlers.go
@@ -149,7 +149,12 @@ func HandleMessage(s xmpp.Sender, p stanza.Packet) {
 							"end": body.End,
 						}).Warn(errors.Wrap(err, "Failed to parse fallback end!"))
 					}
-					text = text[:start] + text[end:]
+
+					fullRunes := []rune(text)
+					cutRunes := make([]rune, 0, len(text)-int(end-start))
+					cutRunes = append(cutRunes, fullRunes[:start]...)
+					cutRunes = append(cutRunes, fullRunes[end:]...)
+					text = string(cutRunes)
 				}
 			}
 			var replaceId int64
-- 
cgit v1.2.3