Migrate to TDLib 1.8.14 (multiple usernames support)

This commit is contained in:
Bohdan Horbeshko 2023-07-31 21:25:24 -04:00
parent 748366ad6a
commit ef831fc972
9 changed files with 138 additions and 44 deletions

1
go.mod
View file

@ -34,3 +34,4 @@ require (
) )
replace gosrc.io/xmpp => dev.narayana.im/narayana/go-xmpp v0.0.0-20220524203317-306b4ff58e8f replace gosrc.io/xmpp => dev.narayana.im/narayana/go-xmpp v0.0.0-20220524203317-306b4ff58e8f
replace github.com/zelenin/go-tdlib => dev.narayana.im/narayana/go-tdlib v0.0.0-20230730021136-47da33180615

2
go.sum
View file

@ -1,4 +1,6 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
dev.narayana.im/narayana/go-tdlib v0.0.0-20230730021136-47da33180615 h1:RRUZJSro+k8FkazNx7QEYLVoO4wZtchvsd0Y2RBWjeU=
dev.narayana.im/narayana/go-tdlib v0.0.0-20230730021136-47da33180615/go.mod h1:Xs8fXbk5n7VaPyrSs9DP7QYoBScWYsjX+lUcWmx1DIU=
dev.narayana.im/narayana/go-xmpp v0.0.0-20220524203317-306b4ff58e8f h1:6249ajbMjgYz53Oq0IjTvjHXbxTfu29Mj1J/6swRHs4= dev.narayana.im/narayana/go-xmpp v0.0.0-20220524203317-306b4ff58e8f h1:6249ajbMjgYz53Oq0IjTvjHXbxTfu29Mj1J/6swRHs4=
dev.narayana.im/narayana/go-xmpp v0.0.0-20220524203317-306b4ff58e8f/go.mod h1:L3NFMqYOxyLz3JGmgFyWf7r9htE91zVGiK40oW4RwdY= dev.narayana.im/narayana/go-xmpp v0.0.0-20220524203317-306b4ff58e8f/go.mod h1:L3NFMqYOxyLz3JGmgFyWf7r9htE91zVGiK40oW4RwdY=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=

View file

@ -45,7 +45,7 @@ type DelayedStatus struct {
type Client struct { type Client struct {
client *client.Client client *client.Client
authorizer *clientAuthorizer authorizer *clientAuthorizer
parameters *client.TdlibParameters parameters *client.SetTdlibParametersRequest
options []client.Option options []client.Option
me *client.User me *client.User
@ -100,7 +100,7 @@ func NewClient(conf config.TelegramConfig, jid string, component *xmpp.Component
datadir = "./sessions/" // ye olde defaute datadir = "./sessions/" // ye olde defaute
} }
parameters := client.TdlibParameters{ parameters := client.SetTdlibParametersRequest{
UseTestDc: false, UseTestDc: false,
DatabaseDirectory: filepath.Join(datadir, jid), DatabaseDirectory: filepath.Join(datadir, jid),

View file

@ -18,8 +18,7 @@ const notEnoughArguments string = "Not enough arguments"
const telegramNotInitialized string = "Telegram connection is not initialized yet" const telegramNotInitialized string = "Telegram connection is not initialized yet"
const notOnline string = "Not online" const notOnline string = "Not online"
var permissionsAdmin = client.ChatMemberStatusAdministrator{ var permissionsAdmin = client.ChatAdministratorRights{
CanBeEdited: true,
CanChangeInfo: true, CanChangeInfo: true,
CanPostMessages: true, CanPostMessages: true,
CanEditMessages: true, CanEditMessages: true,
@ -30,14 +29,20 @@ var permissionsAdmin = client.ChatMemberStatusAdministrator{
CanPromoteMembers: false, CanPromoteMembers: false,
} }
var permissionsMember = client.ChatPermissions{ var permissionsMember = client.ChatPermissions{
CanSendMessages: true, CanSendBasicMessages: true,
CanSendMediaMessages: true, CanSendAudios: true,
CanSendDocuments: true,
CanSendPhotos: true,
CanSendVideos: true,
CanSendVideoNotes: true,
CanSendVoiceNotes: true,
CanSendPolls: true, CanSendPolls: true,
CanSendOtherMessages: true, CanSendOtherMessages: true,
CanAddWebPagePreviews: true, CanAddWebPagePreviews: true,
CanChangeInfo: true, CanChangeInfo: true,
CanInviteUsers: true, CanInviteUsers: true,
CanPinMessages: true, CanPinMessages: true,
CanManageTopics: true,
} }
var permissionsReadonly = client.ChatPermissions{} var permissionsReadonly = client.ChatPermissions{}
@ -666,7 +671,7 @@ func (c *Client) ProcessChatCommand(chatID int64, cmdline string) (string, bool)
entries := []string{ entries := []string{
keyValueString("Chat title", info.Fn), keyValueString("Chat title", info.Fn),
keyValueString("Photo", link), keyValueString("Photo", link),
keyValueString("Username", info.Nickname), keyValueString("Usernames", c.usernamesToString(info.Nicknames)),
keyValueString("Full name", info.Given+" "+info.Family), keyValueString("Full name", info.Given+" "+info.Family),
keyValueString("Phone number", info.Tel), keyValueString("Phone number", info.Tel),
} }
@ -883,7 +888,10 @@ func (c *Client) ProcessChatCommand(chatID int64, cmdline string) (string, bool)
} }
// clone the permissions // clone the permissions
status := permissionsAdmin status := client.ChatMemberStatusAdministrator{
CanBeEdited: true,
Rights: &permissionsAdmin,
}
if len(args) > 1 { if len(args) > 1 {
status.CustomTitle = args[1] status.CustomTitle = args[1]
@ -933,9 +941,9 @@ func (c *Client) ProcessChatCommand(chatID int64, cmdline string) (string, bool)
return "Invalid TTL", true return "Invalid TTL", true
} }
} }
_, err = c.client.SetChatMessageTtl(&client.SetChatMessageTtlRequest{ _, err = c.client.SetChatMessageAutoDeleteTime(&client.SetChatMessageAutoDeleteTimeRequest{
ChatId: chatID, ChatId: chatID,
Ttl: int32(ttl), MessageAutoDeleteTime: int32(ttl),
}) })
if err != nil { if err != nil {

View file

@ -13,7 +13,7 @@ import (
const chatsLimit int32 = 999 const chatsLimit int32 = 999
type clientAuthorizer struct { type clientAuthorizer struct {
TdlibParameters chan *client.TdlibParameters TdlibParameters chan *client.SetTdlibParametersRequest
PhoneNumber chan string PhoneNumber chan string
Code chan string Code chan string
State chan client.AuthorizationState State chan client.AuthorizationState
@ -31,13 +31,7 @@ func (stateHandler *clientAuthorizer) Handle(c *client.Client, state client.Auth
switch state.AuthorizationStateType() { switch state.AuthorizationStateType() {
case client.TypeAuthorizationStateWaitTdlibParameters: case client.TypeAuthorizationStateWaitTdlibParameters:
_, err := c.SetTdlibParameters(&client.SetTdlibParametersRequest{ _, err := c.SetTdlibParameters(<-stateHandler.TdlibParameters)
Parameters: <-stateHandler.TdlibParameters,
})
return err
case client.TypeAuthorizationStateWaitEncryptionKey:
_, err := c.CheckDatabaseEncryptionKey(&client.CheckDatabaseEncryptionKeyRequest{})
return err return err
case client.TypeAuthorizationStateWaitPhoneNumber: case client.TypeAuthorizationStateWaitPhoneNumber:
@ -116,7 +110,7 @@ func (c *Client) Connect(resource string) error {
log.Warn("Connecting to Telegram network...") log.Warn("Connecting to Telegram network...")
c.authorizer = &clientAuthorizer{ c.authorizer = &clientAuthorizer{
TdlibParameters: make(chan *client.TdlibParameters, 1), TdlibParameters: make(chan *client.SetTdlibParametersRequest, 1),
PhoneNumber: make(chan string, 1), PhoneNumber: make(chan string, 1),
Code: make(chan string, 1), Code: make(chan string, 1),
State: make(chan client.AuthorizationState, 10), State: make(chan client.AuthorizationState, 10),

View file

@ -233,7 +233,7 @@ func (c *Client) updateNewMessage(update *client.UpdateNewMessage) {
// message content updated // message content updated
func (c *Client) updateMessageContent(update *client.UpdateMessageContent) { func (c *Client) updateMessageContent(update *client.UpdateMessageContent) {
markupFunction := formatter.EntityToXEP0393 markupFunction := c.getFormatter()
defer c.updateLastMessageHash(update.ChatId, update.MessageId, update.NewContent) defer c.updateLastMessageHash(update.ChatId, update.MessageId, update.NewContent)

View file

@ -27,13 +27,13 @@ import (
) )
type VCardInfo struct { type VCardInfo struct {
Fn string Fn string
Photo *client.File Photo *client.File
Nickname string Nicknames []string
Given string Given string
Family string Family string
Tel string Tel string
Info string Info string
} }
var errOffline = errors.New("TDlib instance is offline") var errOffline = errors.New("TDlib instance is offline")
@ -286,12 +286,15 @@ func (c *Client) formatContact(chatID int64) string {
if chat != nil { if chat != nil {
str = fmt.Sprintf("%s (%v)", chat.Title, chat.Id) str = fmt.Sprintf("%s (%v)", chat.Title, chat.Id)
} else if user != nil { } else if user != nil {
username := user.Username var usernames string
if username == "" { if user.Usernames != nil {
username = strconv.FormatInt(user.Id, 10) usernames = c.usernamesToString(user.Usernames.ActiveUsernames)
}
if usernames == "" {
usernames = strconv.FormatInt(user.Id, 10)
} }
str = fmt.Sprintf("%s %s (%v)", user.FirstName, user.LastName, username) str = fmt.Sprintf("%s %s (%v)", user.FirstName, user.LastName, usernames)
} else { } else {
str = strconv.FormatInt(chatID, 10) str = strconv.FormatInt(chatID, 10)
} }
@ -566,7 +569,7 @@ func (c *Client) messageToText(message *client.Message, preview bool) string {
return "<empty message>" return "<empty message>"
} }
markupFunction := formatter.EntityToXEP0393 markupFunction := c.getFormatter()
switch message.Content.MessageContentType() { switch message.Content.MessageContentType() {
case client.TypeMessageSticker: case client.TypeMessageSticker:
sticker, _ := message.Content.(*client.MessageSticker) sticker, _ := message.Content.(*client.MessageSticker)
@ -737,6 +740,22 @@ func (c *Client) messageToText(message *client.Message, preview bool) string {
return strings.Join(rows, "\n") return strings.Join(rows, "\n")
} }
case client.TypeMessageChatSetMessageAutoDeleteTime:
ttl, _ := message.Content.(*client.MessageChatSetMessageAutoDeleteTime)
name := c.formatContact(ttl.FromUserId)
if name == "" {
if ttl.MessageAutoDeleteTime == 0 {
return "The self-destruct timer was disabled"
} else {
return fmt.Sprintf("The self-destruct timer was set to %v seconds", ttl.MessageAutoDeleteTime)
}
} else {
if ttl.MessageAutoDeleteTime == 0 {
return fmt.Sprintf("%s disabled the self-destruct timer", name)
} else {
return fmt.Sprintf("%s set the self-destruct timer to %v seconds", name, ttl.MessageAutoDeleteTime)
}
}
} }
return fmt.Sprintf("unknown message (%s)", message.Content.MessageContentType()) return fmt.Sprintf("unknown message (%s)", message.Content.MessageContentType())
@ -751,7 +770,7 @@ func (c *Client) contentToFile(content client.MessageContent) (*client.File, *cl
case client.TypeMessageSticker: case client.TypeMessageSticker:
sticker, _ := content.(*client.MessageSticker) sticker, _ := content.(*client.MessageSticker)
file := sticker.Sticker.Sticker file := sticker.Sticker.Sticker
if sticker.Sticker.IsAnimated && sticker.Sticker.Thumbnail != nil && sticker.Sticker.Thumbnail.File != nil { if sticker.Sticker.Format.StickerFormatType() != client.TypeStickerTypeRegular && sticker.Sticker.Thumbnail != nil && sticker.Sticker.Thumbnail.File != nil {
file = sticker.Sticker.Thumbnail.File file = sticker.Sticker.Thumbnail.File
} }
return file, nil return file, nil
@ -1192,7 +1211,7 @@ func (c *Client) roster(resource string) {
} }
// get last messages from specified chat // get last messages from specified chat
func (c *Client) getLastMessages(id int64, query string, from int64, count int32) (*client.Messages, error) { func (c *Client) getLastMessages(id int64, query string, from int64, count int32) (*client.FoundChatMessages, error) {
return c.client.SearchChatMessages(&client.SearchChatMessagesRequest{ return c.client.SearchChatMessages(&client.SearchChatMessagesRequest{
ChatId: id, ChatId: id,
Query: query, Query: query,
@ -1245,10 +1264,18 @@ func (c *Client) GetChatDescription(chat *client.Chat) string {
UserId: privateType.UserId, UserId: privateType.UserId,
}) })
if err == nil { if err == nil {
if fullInfo.Bio != "" { if fullInfo.Bio != nil && fullInfo.Bio.Text != "" {
return fullInfo.Bio return formatter.Format(
} else if fullInfo.Description != "" { fullInfo.Bio.Text,
return fullInfo.Description fullInfo.Bio.Entities,
c.getFormatter(),
)
} else if fullInfo.BotInfo != nil {
if fullInfo.BotInfo.ShortDescription != "" {
return fullInfo.BotInfo.ShortDescription
} else {
return fullInfo.BotInfo.Description
}
} }
} else { } else {
log.Warnf("Coudln't retrieve private chat info: %v", err.Error()) log.Warnf("Coudln't retrieve private chat info: %v", err.Error())
@ -1328,7 +1355,10 @@ func (c *Client) GetVcardInfo(toID int64) (VCardInfo, error) {
info.Info = c.GetChatDescription(chat) info.Info = c.GetChatDescription(chat)
} }
if user != nil { if user != nil {
info.Nickname = user.Username if user.Usernames != nil {
info.Nicknames = make([]string, len(user.Usernames.ActiveUsernames))
copy(info.Nicknames, user.Usernames.ActiveUsernames)
}
info.Given = user.FirstName info.Given = user.FirstName
info.Family = user.LastName info.Family = user.LastName
info.Tel = user.PhoneNumber info.Tel = user.PhoneNumber
@ -1441,3 +1471,15 @@ func (c *Client) hasLastMessageHashChanged(chatId, messageId int64, content clie
return !ok || oldHash != newHash return !ok || oldHash != newHash
} }
func (c *Client) getFormatter() func(*client.TextEntity) (*formatter.Insertion, *formatter.Insertion) {
return formatter.EntityToXEP0393
}
func (c *Client) usernamesToString(usernames []string) string {
var atUsernames []string
for _, username := range usernames {
atUsernames = append(atUsernames, "@"+username)
}
return strings.Join(atUsernames, ", ")
}

View file

@ -369,6 +369,53 @@ func TestMessageAnimation(t *testing.T) {
} }
} }
func TestMessageTtl1(t *testing.T) {
ttl := client.Message{
Content: &client.MessageChatSetMessageAutoDeleteTime{},
}
text := (&Client{}).messageToText(&ttl, false)
if text != "The self-destruct timer was disabled" {
t.Errorf("Wrong anonymous off ttl label: %v", text)
}
}
func TestMessageTtl2(t *testing.T) {
ttl := client.Message{
Content: &client.MessageChatSetMessageAutoDeleteTime{
MessageAutoDeleteTime: 3,
},
}
text := (&Client{}).messageToText(&ttl, false)
if text != "The self-destruct timer was set to 3 seconds" {
t.Errorf("Wrong anonymous ttl label: %v", text)
}
}
func TestMessageTtl3(t *testing.T) {
ttl := client.Message{
Content: &client.MessageChatSetMessageAutoDeleteTime{
FromUserId: 3,
},
}
text := (&Client{}).messageToText(&ttl, false)
if text != "unknown contact: TDlib instance is offline disabled the self-destruct timer" {
t.Errorf("Wrong off ttl label: %v", text)
}
}
func TestMessageTtl4(t *testing.T) {
ttl := client.Message{
Content: &client.MessageChatSetMessageAutoDeleteTime{
FromUserId: 3,
MessageAutoDeleteTime: 3,
},
}
text := (&Client{}).messageToText(&ttl, false)
if text != "unknown contact: TDlib instance is offline set the self-destruct timer to 3 seconds" {
t.Errorf("Wrong ttl label: %v", text)
}
}
func TestMessageUnknown(t *testing.T) { func TestMessageUnknown(t *testing.T) {
unknown := client.Message{ unknown := client.Message{
Content: &client.MessageExpiredPhoto{}, Content: &client.MessageExpiredPhoto{},

View file

@ -481,7 +481,7 @@ func makeVCardPayload(typ byte, id string, info telegram.VCardInfo, session *tel
vcard.Photo.Type.Text = "image/jpeg" vcard.Photo.Type.Text = "image/jpeg"
vcard.Photo.Binval.Text = base64Photo vcard.Photo.Binval.Text = base64Photo
} }
vcard.Nickname.Text = info.Nickname vcard.Nickname.Text = strings.Join(info.Nicknames, ",")
vcard.N.Given.Text = info.Given vcard.N.Given.Text = info.Given
vcard.N.Family.Text = info.Family vcard.N.Family.Text = info.Family
vcard.Tel.Number.Text = info.Tel vcard.Tel.Number.Text = info.Tel
@ -512,13 +512,13 @@ func makeVCardPayload(typ byte, id string, info telegram.VCardInfo, session *tel
}, },
}) })
} }
if info.Nickname != "" { for _, nickname := range info.Nicknames {
nodes = append(nodes, stanza.Node{ nodes = append(nodes, stanza.Node{
XMLName: xml.Name{Local: "nickname"}, XMLName: xml.Name{Local: "nickname"},
Nodes: []stanza.Node{ Nodes: []stanza.Node{
stanza.Node{ stanza.Node{
XMLName: xml.Name{Local: "text"}, XMLName: xml.Name{Local: "text"},
Content: info.Nickname, Content: nickname,
}, },
}, },
}, stanza.Node{ }, stanza.Node{
@ -526,7 +526,7 @@ func makeVCardPayload(typ byte, id string, info telegram.VCardInfo, session *tel
Nodes: []stanza.Node{ Nodes: []stanza.Node{
stanza.Node{ stanza.Node{
XMLName: xml.Name{Local: "uri"}, XMLName: xml.Name{Local: "uri"},
Content: "https://t.me/" + info.Nickname, Content: "https://t.me/" + nickname,
}, },
}, },
}) })