diff options
Diffstat (limited to 'telegram/commands.go')
-rw-r--r-- | telegram/commands.go | 328 |
1 files changed, 212 insertions, 116 deletions
diff --git a/telegram/commands.go b/telegram/commands.go index bd9f0f8..87fff72 100644 --- a/telegram/commands.go +++ b/telegram/commands.go @@ -15,11 +15,11 @@ import ( ) 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 TelegramAuthDone string = "Authorization is done already" const notOnline string = "Not online" -var permissionsAdmin = client.ChatMemberStatusAdministrator{ - CanBeEdited: true, +var permissionsAdmin = client.ChatAdministratorRights{ CanChangeInfo: true, CanPostMessages: true, CanEditMessages: true, @@ -30,20 +30,27 @@ var permissionsAdmin = client.ChatMemberStatusAdministrator{ CanPromoteMembers: false, } var permissionsMember = client.ChatPermissions{ - CanSendMessages: true, - CanSendMediaMessages: true, + CanSendBasicMessages: true, + CanSendAudios: true, + CanSendDocuments: true, + CanSendPhotos: true, + CanSendVideos: true, + CanSendVideoNotes: true, + CanSendVoiceNotes: true, CanSendPolls: true, CanSendOtherMessages: true, CanAddWebPagePreviews: true, CanChangeInfo: true, CanInviteUsers: true, CanPinMessages: true, + CanManageTopics: true, } var permissionsReadonly = client.ChatPermissions{} var transportCommands = map[string]command{ "login": command{"phone", "sign in"}, "logout": command{"", "sign out"}, + "cancelauth": command{"", "quit the signin wizard"}, "code": command{"", "check one-time code"}, "password": command{"", "check 2fa password"}, "setusername": command{"", "update @username"}, @@ -52,6 +59,10 @@ var transportCommands = map[string]command{ "setpassword": command{"[old] [new]", "set or remove password"}, "config": command{"[param] [value]", "view or update configuration options"}, "report": command{"[chat] [comment]", "report a chat by id or @username"}, + "add": command{"@username", "add @username to your chat list"}, + "join": command{"https://t.me/invite_link", "join to chat via invite link or @publicname"}, + "supergroup": command{"title description", "create new supergroup «title» with «description»"}, + "channel": command{"title description", "create new channel «title» with «description»"}, } var chatCommands = map[string]command{ @@ -60,6 +71,7 @@ var chatCommands = map[string]command{ "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"}, + "vcard": command{"", "print vCard as text"}, "add": command{"@username", "add @username to your chat list"}, "join": command{"https://t.me/invite_link", "join to chat via invite link or @publicname"}, "group": command{"title", "create groupchat «title» with current user"}, @@ -168,6 +180,10 @@ func rawCmdArguments(cmdline string, start uint8) string { return "" } +func keyValueString(key, value string) string { + return fmt.Sprintf("%s: %s", key, value) +} + func (c *Client) unsubscribe(chatID int64) error { return gateway.SendPresence( c.xmpp, @@ -179,11 +195,17 @@ 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, strconv.FormatInt(chatID, 10), - c.formatMessage(0, 0, false, messages[i]), + c.formatMessage(0, 0, false, message), + strconv.FormatInt(message.Id, 10), c.xmpp, + reply, + false, ) } } @@ -215,7 +237,7 @@ func (c *Client) ProcessTransportCommand(cmdline string, resource string) string switch cmd { case "login", "code", "password": if cmd == "login" && c.Session.Login != "" { - return "" + return "Phone number already provided, use /cancelauth to start over" } if len(args) < 1 { @@ -223,36 +245,35 @@ func (c *Client) ProcessTransportCommand(cmdline string, resource string) string } if cmd == "login" { - wasSessionLoginEmpty := c.Session.Login == "" - c.Session.Login = args[0] - - if wasSessionLoginEmpty && c.authorizer == nil { - go func() { - err := c.Connect(resource) - if err != nil { - log.Error(errors.Wrap(err, "TDlib connection failure")) - } - }() - // a quirk for authorizer to become ready. If it's still not, - // nothing bad: the command just needs to be resent again - time.Sleep(1e5) + err := c.TryLogin(resource, args[0]) + if err != nil { + return err.Error() } - } - if c.authorizer == nil { - return telegramNotInitialized - } + c.locks.authorizerWriteLock.Lock() + defer c.locks.authorizerWriteLock.Unlock() - switch cmd { - // sign in - case "login": c.authorizer.PhoneNumber <- args[0] - // check auth code - case "code": - c.authorizer.Code <- args[0] - // check auth password - case "password": - c.authorizer.Password <- args[0] + } else { + c.locks.authorizerWriteLock.Lock() + defer c.locks.authorizerWriteLock.Unlock() + + if c.authorizer == nil { + return TelegramNotInitialized + } + + if c.authorizer.isClosed { + return TelegramAuthDone + } + + switch cmd { + // check auth code + case "code": + c.authorizer.Code <- args[0] + // check auth password + case "password": + c.authorizer.Password <- args[0] + } } // sign out case "logout": @@ -271,6 +292,13 @@ func (c *Client) ProcessTransportCommand(cmdline string, resource string) string } c.Session.Login = "" + // cancel auth + case "cancelauth": + if c.Online() { + return "Not allowed when online, use /logout instead" + } + c.cancelAuth() + return "Cancelled" // set @username case "setusername": if !c.Online() { @@ -290,25 +318,36 @@ func (c *Client) ProcessTransportCommand(cmdline string, resource string) string } // set My Name case "setname": - if !c.Online() { - return notOnline - } - var firstname string var lastname string if len(args) > 0 { firstname = args[0] } + if firstname == "" { + return "The name should contain at least one character" + } if len(args) > 1 { - lastname = args[1] + lastname = rawCmdArguments(cmdline, 1) } - _, err := c.client.SetName(&client.SetNameRequest{ - FirstName: firstname, - LastName: lastname, - }) - if err != nil { - return errors.Wrap(err, "Couldn't set name").Error() + c.locks.authorizerWriteLock.Lock() + if c.authorizer != nil && !c.authorizer.isClosed { + c.authorizer.FirstName <- firstname + c.authorizer.LastName <- lastname + c.locks.authorizerWriteLock.Unlock() + } else { + c.locks.authorizerWriteLock.Unlock() + if !c.Online() { + return notOnline + } + + _, err := c.client.SetName(&client.SetNameRequest{ + FirstName: firstname, + LastName: lastname, + }) + if err != nil { + return errors.Wrap(err, "Couldn't set name").Error() + } } // set About case "setbio": @@ -344,6 +383,10 @@ func (c *Client) ProcessTransportCommand(cmdline string, resource string) string } case "config": if len(args) > 1 { + if gateway.MessageOutgoingPermissionVersion == 0 && args[0] == "carbons" && args[1] == "true" { + return "The server did not allow to enable carbons" + } + value, err := c.Session.Set(args[0], args[1]) if err != nil { return err.Error() @@ -387,6 +430,14 @@ func (c *Client) ProcessTransportCommand(cmdline string, resource string) string } else { return "Reported" } + case "add": + return c.cmdAdd(args) + case "join": + return c.cmdJoin(args) + case "supergroup": + return c.cmdSupergroup(args, cmdline) + case "channel": + return c.cmdChannel(args, cmdline) case "help": return helpString(helpTypeTransport) } @@ -463,14 +514,17 @@ func (c *Client) ProcessChatCommand(chatID int64, cmdline string) (string, bool) return "Last message is empty", true } - content := c.ProcessOutgoingMessage(0, rawCmdArguments(cmdline, 0), "") + content := c.PrepareOutgoingMessageContent(rawCmdArguments(cmdline, 0)) if content != nil { - c.client.EditMessageText(&client.EditMessageTextRequest{ + _, err = c.client.EditMessageText(&client.EditMessageTextRequest{ ChatId: chatID, MessageId: message.Id, InputMessageContent: content, }) + if err != nil { + return "Message editing error", true + } } else { return "Message processing error", true } @@ -480,7 +534,7 @@ func (c *Client) ProcessChatCommand(chatID int64, cmdline string) (string, bool) return "Not enough arguments", true } - content := c.ProcessOutgoingMessage(0, rawCmdArguments(cmdline, 0), "") + content := c.PrepareOutgoingMessageContent(rawCmdArguments(cmdline, 0)) if content != nil { _, err := c.client.SendMessage(&client.SendMessageRequest{ @@ -559,7 +613,7 @@ func (c *Client) ProcessChatCommand(chatID int64, cmdline string) (string, bool) } } - content := c.ProcessOutgoingMessage(0, rawCmdArguments(cmdline, 1), "") + content := c.PrepareOutgoingMessageContent(rawCmdArguments(cmdline, 1)) if content != nil { _, err := c.client.SendMessage(&client.SendMessageRequest{ @@ -606,80 +660,33 @@ func (c *Client) ProcessChatCommand(chatID int64, cmdline string) (string, bool) c.ProcessIncomingMessage(targetChatId, message) } } - // add @contact - case "add": - if len(args) < 1 { - return notEnoughArguments, true - } - - chat, err := c.client.SearchPublicChat(&client.SearchPublicChatRequest{ - Username: args[0], - }) + // print vCard + case "vcard": + info, err := c.GetVcardInfo(chatID) if err != nil { return err.Error(), true } - if chat == nil { - return "No error, but chat is nil", true + _, link := c.PermastoreFile(info.Photo, true) + entries := []string{ + keyValueString("Chat title", info.Fn), + keyValueString("Photo", link), + keyValueString("Usernames", c.usernamesToString(info.Nicknames)), + keyValueString("Full name", info.Given+" "+info.Family), + keyValueString("Phone number", info.Tel), } - - c.subscribeToID(chat.Id, chat) + return strings.Join(entries, "\n"), true + // add @contact + case "add": + return c.cmdAdd(args), true // join https://t.me/publichat or @publicchat case "join": - if len(args) < 1 { - return notEnoughArguments, true - } - - if strings.HasPrefix(args[0], "@") { - chat, err := c.client.SearchPublicChat(&client.SearchPublicChatRequest{ - Username: args[0], - }) - if err != nil { - return err.Error(), true - } - if chat == nil { - return "No error, but chat is nil", true - } - _, err = c.client.JoinChat(&client.JoinChatRequest{ - ChatId: chat.Id, - }) - if err != nil { - return err.Error(), true - } - } else { - _, err := c.client.JoinChatByInviteLink(&client.JoinChatByInviteLinkRequest{ - InviteLink: args[0], - }) - if err != nil { - return err.Error(), true - } - } + return c.cmdJoin(args), true // create new supergroup case "supergroup": - if len(args) < 1 { - return notEnoughArguments, true - } - - _, err := c.client.CreateNewSupergroupChat(&client.CreateNewSupergroupChatRequest{ - Title: args[0], - Description: rawCmdArguments(cmdline, 1), - }) - if err != nil { - return err.Error(), true - } + return c.cmdSupergroup(args, cmdline), true // create new channel case "channel": - if len(args) < 1 { - return notEnoughArguments, true - } - - _, err := c.client.CreateNewSupergroupChat(&client.CreateNewSupergroupChatRequest{ - Title: args[0], - Description: rawCmdArguments(cmdline, 1), - IsChannel: true, - }) - if err != nil { - return err.Error(), true - } + return c.cmdChannel(args, cmdline), true // create new secret chat with current user case "secret": _, err := c.client.CreateNewSecretChat(&client.CreateNewSecretChatRequest{ @@ -880,7 +887,10 @@ func (c *Client) ProcessChatCommand(chatID int64, cmdline string) (string, bool) } // clone the permissions - status := permissionsAdmin + status := client.ChatMemberStatusAdministrator{ + CanBeEdited: true, + Rights: &permissionsAdmin, + } if len(args) > 1 { status.CustomTitle = args[1] @@ -930,9 +940,9 @@ func (c *Client) ProcessChatCommand(chatID int64, cmdline string) (string, bool) return "Invalid TTL", true } } - _, err = c.client.SetChatMessageTtl(&client.SetChatMessageTtlRequest{ - ChatId: chatID, - Ttl: int32(ttl), + _, err = c.client.SetChatMessageAutoDeleteTime(&client.SetChatMessageAutoDeleteTimeRequest{ + ChatId: chatID, + MessageAutoDeleteTime: int32(ttl), }) if err != nil { @@ -1076,3 +1086,89 @@ func (c *Client) ProcessChatCommand(chatID int64, cmdline string) (string, bool) return "", true } + +func (c *Client) cmdAdd(args []string) string { + if len(args) < 1 { + return notEnoughArguments + } + + chat, err := c.client.SearchPublicChat(&client.SearchPublicChatRequest{ + Username: args[0], + }) + if err != nil { + return err.Error() + } + if chat == nil { + return "No error, but chat is nil" + } + + c.subscribeToID(chat.Id, chat) + + return "" +} + +func (c *Client) cmdJoin(args []string) string { + if len(args) < 1 { + return notEnoughArguments + } + + if strings.HasPrefix(args[0], "@") { + chat, err := c.client.SearchPublicChat(&client.SearchPublicChatRequest{ + Username: args[0], + }) + if err != nil { + return err.Error() + } + if chat == nil { + return "No error, but chat is nil" + } + _, err = c.client.JoinChat(&client.JoinChatRequest{ + ChatId: chat.Id, + }) + if err != nil { + return err.Error() + } + } else { + _, err := c.client.JoinChatByInviteLink(&client.JoinChatByInviteLinkRequest{ + InviteLink: args[0], + }) + if err != nil { + return err.Error() + } + } + + return "" +} + +func (c *Client) cmdSupergroup(args []string, cmdline string) string { + if len(args) < 1 { + return notEnoughArguments + } + + _, err := c.client.CreateNewSupergroupChat(&client.CreateNewSupergroupChatRequest{ + Title: args[0], + Description: rawCmdArguments(cmdline, 1), + }) + if err != nil { + return err.Error() + } + + return "" +} + +func (c *Client) cmdChannel(args []string, cmdline string) string { + if len(args) < 1 { + return notEnoughArguments + } + + _, err := c.client.CreateNewSupergroupChat(&client.CreateNewSupergroupChatRequest{ + Title: args[0], + Description: rawCmdArguments(cmdline, 1), + IsChannel: true, + }) + if err != nil { + return err.Error() + } + + return "" +} |