// mautrix-telegram - A Matrix-Telegram puppeting bridge. // Copyright (C) 2025 Sumner Evans // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. // // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . package connector import ( "errors" "slices" "strings" "maunium.net/go/mautrix/bridgev2" "maunium.net/go/mautrix/bridgev2/commands" "maunium.net/go/mautrix/bridgev2/networkid" "maunium.net/go/mautrix/format" "go.mau.fi/mautrix-telegram/pkg/connector/ids" ) var cmdSyncChats = &commands.FullHandler{ Func: fnSyncChats, Name: "sync-chats", Help: commands.HelpMeta{ Section: commands.HelpSectionChats, Description: "Synchronize your chats", Args: "[_login ID_]", }, RequiresLogin: true, } func fnSyncChats(ce *commands.Event) { logins := ce.User.GetUserLogins() if len(ce.Args) > 0 { logins = slices.DeleteFunc(logins, func(login *bridgev2.UserLogin) bool { return !slices.Contains(ce.Args, string(login.ID)) }) if len(logins) == 0 { ce.Reply("No matching logins found with provided ID(s)") return } } for _, login := range logins { client := login.Client.(*TelegramClient) if err := client.syncChats(ce.Ctx, 0, false, true); err != nil { ce.Reply("Failed to synchronize chats for %s: %v", format.SafeMarkdownCode(login.ID), err) } else { ce.Reply("Successfully synchronized chats for %s", format.SafeMarkdownCode(login.ID)) } } } var cmdUpgrade = &commands.FullHandler{ Func: fnUpgrade, Name: "upgrade", Help: commands.HelpMeta{ Section: commands.HelpSectionChats, Description: "Upgrade a minigroup to a supergroup on Telegram", }, RequiresPortal: true, } func fnUpgrade(ce *commands.Event) { login, _, err := ce.Portal.FindPreferredLogin(ce.Ctx, ce.User, false) if errors.Is(err, bridgev2.ErrNotLoggedIn) { ce.Reply("No logins found to upgrade the chat.") } else if err != nil { ce.Log.Err(err).Msg("Failed to find preferred login for upgrade command") ce.Reply("Failed to find a login to upgrade the chat.") } else if peerType, chatID, _, err := ids.ParsePortalID(ce.Portal.ID); err != nil { ce.Log.Err(err).Str("portal_id", string(ce.Portal.ID)).Msg("Failed to parse portal ID for upgrade command") ce.Reply("Failed to parse portal ID") } else if peerType == ids.PeerTypeChannel { ce.Reply("Only minigroups can be upgraded (this is already a channel/supergroup).") } else if peerType == ids.PeerTypeUser { ce.Reply("Only minigroups can be upgraded (this is direct chat).") } else if resp, err := login.Client.(*TelegramClient).client.API().MessagesMigrateChat(ce.Ctx, chatID); err != nil { ce.Log.Err(err).Int64("chat_id", chatID).Msg("Failed to upgrade chat") ce.Reply("Failed to upgrade chat: %v", err) } else { ce.Log.Trace().Any("response", resp).Msg("Updates from chat upgrade") ce.Log.Info().Int64("old_chat_id", chatID).Msg("Successfully upgraded chat") ce.React("\u2705\ufe0f") err = login.Client.(*TelegramClient).dispatcher.Handle(ce.Ctx, resp) if err != nil { ce.Log.Err(err).Msg("Failed to handle updates from chat upgrade") } else { ce.Log.Debug().Msg("Finished handling updates from chat upgrade") } } } var cmdEmojiPack = &commands.FullHandler{ Func: fnEmojiPack, Name: "emoji-pack", Aliases: []string{"pack", "sticker-pack", "emojipack", "stickerpack"}, Help: commands.HelpMeta{ Section: commands.HelpSectionChats, Description: "Bridge emoji packs between Matrix and Telegram.", Args: " [args...]", }, RequiresLogin: true, } const emojiPackHelp = `This command can be used to transfer emoji packs between Matrix and Telegram. * $cmdprefix emoji-pack upload - Transfer a pack from Matrix to Telegram. * $cmdprefix emoji-pack download - Transfer a pack from Telegram to Matrix. * $cmdprefix emoji-pack list - List your current emoji packs on Telegram. * $cmdprefix emoji-pack help - Show this help message.` func fnEmojiPack(ce *commands.Event) { var login *bridgev2.UserLogin if len(ce.Args) > 0 { targetLogin := ce.Bridge.GetCachedUserLoginByID(networkid.UserLoginID(ce.Args[0])) if targetLogin != nil && targetLogin.UserMXID == ce.User.MXID { ce.Args = ce.Args[1:] login = targetLogin } } var command string if len(ce.Args) > 0 { command = strings.ToLower(ce.Args[0]) ce.Args = ce.Args[1:] } if login == nil { login = ce.User.GetDefaultLogin() if login == nil { ce.Reply("You're not logged in.") return } } client := login.Client.(*TelegramClient) switch command { case "help", "": ce.Reply(emojiPackHelp) case "list": client.fnListEmojiPacks(ce) case "upload": client.fnUploadEmojiPack(ce) case "download": client.fnDownloadEmojiPack(ce) default: ce.Reply("Usage: `$cmdprefix emoji-pack [args...]`") } }