Filter available commands by chat type
This commit is contained in:
parent
dc6f99dc3c
commit
9b5fee8826
|
@ -50,56 +50,60 @@ var permissionsMember = client.ChatPermissions{
|
||||||
var permissionsReadonly = client.ChatPermissions{}
|
var permissionsReadonly = client.ChatPermissions{}
|
||||||
|
|
||||||
var transportCommands = map[string]command{
|
var transportCommands = map[string]command{
|
||||||
"help": command{0, []string{}, "help"},
|
"help": command{0, []string{}, "help", nil},
|
||||||
"login": command{1, []string{"phone"}, "sign in"},
|
"login": command{1, []string{"phone"}, "sign in", nil},
|
||||||
"logout": command{0, []string{}, "sign out"},
|
"logout": command{0, []string{}, "sign out", nil},
|
||||||
"cancelauth": command{0, []string{}, "quit the signin wizard"},
|
"cancelauth": command{0, []string{}, "quit the signin wizard", nil},
|
||||||
"code": command{1, []string{"xxxxx"}, "check one-time code"},
|
"code": command{1, []string{"xxxxx"}, "check one-time code", nil},
|
||||||
"password": command{1, []string{"********"}, "check 2fa password"},
|
"password": command{1, []string{"********"}, "check 2fa password", nil},
|
||||||
"setusername": command{0, []string{"@username"}, "update @username"},
|
"setusername": command{0, []string{"@username"}, "update @username", nil},
|
||||||
"setname": command{1, []string{"first", "last"}, "update name"},
|
"setname": command{1, []string{"first", "last"}, "update name", nil},
|
||||||
"setbio": command{0, []string{"Lorem ipsum"}, "update about"},
|
"setbio": command{0, []string{"Lorem ipsum"}, "update about", nil},
|
||||||
"setpassword": command{0, []string{"old", "new"}, "set or remove password"},
|
"setpassword": command{0, []string{"old", "new"}, "set or remove password", nil},
|
||||||
"config": command{0, []string{"param", "value"}, "view or update configuration options"},
|
"config": command{0, []string{"param", "value"}, "view or update configuration options", nil},
|
||||||
"report": command{2, []string{"chat", "comment"}, "report a chat by id or @username"},
|
"report": command{2, []string{"chat", "comment"}, "report a chat by id or @username", nil},
|
||||||
"add": command{1, []string{"@username"}, "add @username to your chat list"},
|
"add": command{1, []string{"@username"}, "add @username to your chat list", nil},
|
||||||
"join": command{1, []string{"https://t.me/invite_link"}, "join to chat via invite link or @publicname"},
|
"join": command{1, []string{"https://t.me/invite_link"}, "join to chat via invite link or @publicname", nil},
|
||||||
"supergroup": command{1, []string{"title", "description"}, "create new supergroup «title» with «description»"},
|
"supergroup": command{1, []string{"title", "description"}, "create new supergroup «title» with «description»", nil},
|
||||||
"channel": command{1, []string{"title", "description"}, "create new channel «title» with «description»"},
|
"channel": command{1, []string{"title", "description"}, "create new channel «title» with «description»", nil},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var notForGroups = []ChatType{ChatTypeBasicGroup, ChatTypeSupergroup, ChatTypeChannel}
|
||||||
|
var notForPM = []ChatType{ChatTypePrivate, ChatTypeSecret}
|
||||||
|
var onlyForSecret = []ChatType{ChatTypePrivate, ChatTypeBasicGroup, ChatTypeSupergroup, ChatTypeChannel}
|
||||||
|
|
||||||
var chatCommands = map[string]command{
|
var chatCommands = map[string]command{
|
||||||
"help": command{0, []string{}, "help"},
|
"help": command{0, []string{}, "help", nil},
|
||||||
"d": command{0, []string{"n"}, "delete your last message(s)"},
|
"d": command{0, []string{"n"}, "delete your last message(s)", nil},
|
||||||
"s": command{1, []string{"edited message"}, "edit your last message"},
|
"s": command{1, []string{"edited message"}, "edit your last message", nil},
|
||||||
"silent": command{1, []string{"message"}, "send a message without sound"},
|
"silent": command{1, []string{"message"}, "send a message without sound", nil},
|
||||||
"schedule": command{2, []string{"{online | 2006-01-02T15:04:05 | 15:04:05}", "message"}, "schedules a message either to timestamp or to whenever the user goes online"},
|
"schedule": command{2, []string{"{online | 2006-01-02T15:04:05 | 15:04:05}", "message"}, "schedules a message either to timestamp or to whenever the user goes online", nil},
|
||||||
"forward": command{2, []string{"message_id", "target_chat"}, "forwards a message"},
|
"forward": command{2, []string{"message_id", "target_chat"}, "forwards a message", nil},
|
||||||
"vcard": command{0, []string{}, "print vCard as text"},
|
"vcard": command{0, []string{}, "print vCard as text", nil},
|
||||||
"add": command{1, []string{"@username"}, "add @username to your chat list"},
|
"add": command{1, []string{"@username"}, "add @username to your chat list", nil},
|
||||||
"join": command{1, []string{"https://t.me/invite_link"}, "join to chat via invite link or @publicname"},
|
"join": command{1, []string{"https://t.me/invite_link"}, "join to chat via invite link or @publicname", nil},
|
||||||
"group": command{1, []string{"title"}, "create groupchat «title» with current user"},
|
"group": command{1, []string{"title"}, "create groupchat «title» with current user", ¬ForGroups},
|
||||||
"supergroup": command{1, []string{"title", "description"}, "create new supergroup «title» with «description»"},
|
"supergroup": command{1, []string{"title", "description"}, "create new supergroup «title» with «description»", nil},
|
||||||
"channel": command{1, []string{"title", "description"}, "create new channel «title» with «description»"},
|
"channel": command{1, []string{"title", "description"}, "create new channel «title» with «description»", nil},
|
||||||
"secret": command{0, []string{}, "create secretchat with current user"},
|
"secret": command{0, []string{}, "create secretchat with current user", ¬ForGroups},
|
||||||
"search": command{0, []string{"string", "[limit]"}, "search <string> in current chat"},
|
"search": command{0, []string{"string", "[limit]"}, "search <string> in current chat", nil},
|
||||||
"history": command{0, []string{"limit"}, "get last [limit] messages from current chat"},
|
"history": command{0, []string{"limit"}, "get last [limit] messages from current chat", nil},
|
||||||
"block": command{0, []string{}, "blacklist current user"},
|
"block": command{0, []string{}, "blacklist current user", ¬ForGroups},
|
||||||
"unblock": command{0, []string{}, "unblacklist current user"},
|
"unblock": command{0, []string{}, "unblacklist current user", ¬ForGroups},
|
||||||
"invite": command{1, []string{"id or @username"}, "add user to current chat"},
|
"invite": command{1, []string{"id or @username"}, "add user to current chat", ¬ForPM},
|
||||||
"link": command{0, []string{}, "get invite link for current chat"},
|
"link": command{0, []string{}, "get invite link for current chat", ¬ForPM},
|
||||||
"kick": command{1, []string{"id or @username"}, "remove user to current chat"},
|
"kick": command{1, []string{"id or @username"}, "remove user from current chat", ¬ForPM},
|
||||||
"mute": command{1, []string{"id or @username", "hours"}, "mute user in current chat"},
|
"mute": command{1, []string{"id or @username", "hours"}, "mute user in current chat", ¬ForPM},
|
||||||
"unmute": command{1, []string{"id or @username"}, "unrestrict user from current chat"},
|
"unmute": command{1, []string{"id or @username"}, "unrestrict user from current chat", ¬ForPM},
|
||||||
"ban": command{1, []string{"id or @username", "hours"}, "restrict @username from current chat for [hours] or forever"},
|
"ban": command{1, []string{"id or @username", "hours"}, "restrict @username from current chat for [hours] or forever", ¬ForPM},
|
||||||
"unban": command{1, []string{"id or @username"}, "unbans @username in current chat (and devotes from admins)"},
|
"unban": command{1, []string{"id or @username"}, "unbans @username in current chat (and devotes from admins)", ¬ForPM},
|
||||||
"promote": command{1, []string{"id or @username", "title"}, "promote user to admin in current chat"},
|
"promote": command{1, []string{"id or @username", "title"}, "promote user to admin in current chat", ¬ForPM},
|
||||||
"leave": command{0, []string{}, "leave current chat"},
|
"leave": command{0, []string{}, "leave current chat", ¬ForPM},
|
||||||
"leave!": command{0, []string{}, "leave current chat (for owners)"},
|
"leave!": command{0, []string{}, "leave current chat (for owners)", ¬ForPM},
|
||||||
"ttl": command{0, []string{"seconds"}, "set secret chat messages TTL before self-destroying"},
|
"ttl": command{0, []string{"seconds"}, "set secret chat messages TTL before self-destroying", &onlyForSecret},
|
||||||
"close": command{0, []string{}, "close current secret chat"},
|
"close": command{0, []string{}, "close current secret chat", &onlyForSecret},
|
||||||
"delete": command{0, []string{}, "delete current chat from chat list"},
|
"delete": command{0, []string{}, "delete current chat from chat list", nil},
|
||||||
"members": command{0, []string{"query"}, "search members [by optional query] in current chat (requires admin rights)"},
|
"members": command{0, []string{"query"}, "search members [by optional query] in current chat (requires admin rights)", nil},
|
||||||
}
|
}
|
||||||
|
|
||||||
var transportConfigurationOptions = map[string]configurationOption{
|
var transportConfigurationOptions = map[string]configurationOption{
|
||||||
|
@ -112,6 +116,7 @@ type command struct {
|
||||||
RequiredArgs int
|
RequiredArgs int
|
||||||
Arguments []string
|
Arguments []string
|
||||||
Description string
|
Description string
|
||||||
|
NotFor *[]ChatType
|
||||||
}
|
}
|
||||||
type configurationOption struct {
|
type configurationOption struct {
|
||||||
arguments string
|
arguments string
|
||||||
|
@ -185,14 +190,31 @@ func CommandToHelpString(name string, cmd command) string {
|
||||||
return str.String()
|
return str.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
func helpString(typ CommandType) string {
|
// IsCommandFor checks the suitability of a command for a chat type
|
||||||
|
func IsCommandForChatType(cmd command, chatType ChatType) bool {
|
||||||
|
if cmd.NotFor != nil {
|
||||||
|
for _, typ := range *cmd.NotFor {
|
||||||
|
if chatType == typ {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) helpString(typ CommandType, chatId int64) string {
|
||||||
var str strings.Builder
|
var str strings.Builder
|
||||||
|
|
||||||
commandMap := GetCommands(typ)
|
commandMap := GetCommands(typ)
|
||||||
|
chatType, chatTypeErr := c.GetChatType(chatId)
|
||||||
|
|
||||||
str.WriteString("Available commands:\n")
|
str.WriteString("Available commands:\n")
|
||||||
for _, name := range SortedCommandKeys(commandMap) {
|
for _, name := range SortedCommandKeys(commandMap) {
|
||||||
command := commandMap[name]
|
command := commandMap[name]
|
||||||
|
if chatTypeErr == nil && !IsCommandForChatType(command, chatType) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
str.WriteString(CommandToHelpString(name, command))
|
str.WriteString(CommandToHelpString(name, command))
|
||||||
str.WriteString("\n")
|
str.WriteString("\n")
|
||||||
}
|
}
|
||||||
|
@ -502,7 +524,7 @@ func (c *Client) ProcessTransportCommand(cmdline string, resource string) string
|
||||||
case "channel":
|
case "channel":
|
||||||
return c.cmdChannel(args, cmdline)
|
return c.cmdChannel(args, cmdline)
|
||||||
case "help":
|
case "help":
|
||||||
return helpString(CommandTypeTransport)
|
return c.helpString(CommandTypeTransport, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
return ""
|
return ""
|
||||||
|
@ -524,6 +546,11 @@ func (c *Client) ProcessChatCommand(chatID int64, cmdline string) (string, bool)
|
||||||
return notEnoughArguments, true
|
return notEnoughArguments, true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
chatType, chatTypeErr := c.GetChatType(chatID)
|
||||||
|
if chatTypeErr == nil && !IsCommandForChatType(command, chatType) {
|
||||||
|
return "Not applicable for this chat type", true
|
||||||
|
}
|
||||||
|
|
||||||
switch cmd {
|
switch cmd {
|
||||||
// delete message
|
// delete message
|
||||||
case "d":
|
case "d":
|
||||||
|
@ -1103,7 +1130,7 @@ func (c *Client) ProcessChatCommand(chatID int64, cmdline string) (string, bool)
|
||||||
|
|
||||||
return strings.Join(entries, "\n"), true
|
return strings.Join(entries, "\n"), true
|
||||||
case "help":
|
case "help":
|
||||||
return helpString(CommandTypeChat), true
|
return c.helpString(CommandTypeChat, chatID), true
|
||||||
default:
|
default:
|
||||||
return "", false
|
return "", false
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,6 +53,18 @@ var replyRegex = regexp.MustCompile("\\A>>? ?([0-9]+)\\n")
|
||||||
const newlineChar string = "\n"
|
const newlineChar string = "\n"
|
||||||
const messageHeaderSeparator string = " | " // no hrunicode allowed here yet
|
const messageHeaderSeparator string = " | " // no hrunicode allowed here yet
|
||||||
|
|
||||||
|
// ChatType is an enum of chat types, roughly corresponding to TDLib's one but better
|
||||||
|
type ChatType int
|
||||||
|
|
||||||
|
const (
|
||||||
|
ChatTypeUnknown ChatType = iota
|
||||||
|
ChatTypePrivate
|
||||||
|
ChatTypeBasicGroup
|
||||||
|
ChatTypeSupergroup
|
||||||
|
ChatTypeSecret
|
||||||
|
ChatTypeChannel
|
||||||
|
)
|
||||||
|
|
||||||
// GetContactByUsername resolves username to user id retrieves user and chat information
|
// GetContactByUsername resolves username to user id retrieves user and chat information
|
||||||
func (c *Client) GetContactByUsername(username string) (*client.Chat, *client.User, error) {
|
func (c *Client) GetContactByUsername(username string) (*client.Chat, *client.User, error) {
|
||||||
if !c.Online() {
|
if !c.Online() {
|
||||||
|
@ -130,10 +142,10 @@ func (c *Client) GetContactByID(id int64, chat *client.Chat) (*client.Chat, *cli
|
||||||
return chat, user, nil
|
return chat, user, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsPM checks if a chat is PM
|
// GetChatType obtains chat type from its information
|
||||||
func (c *Client) IsPM(id int64) (bool, error) {
|
func (c *Client) GetChatType(id int64) (ChatType, error) {
|
||||||
if !c.Online() || id == 0 {
|
if !c.Online() || id == 0 {
|
||||||
return false, errOffline
|
return ChatTypeUnknown, errOffline
|
||||||
}
|
}
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
|
@ -144,14 +156,38 @@ func (c *Client) IsPM(id int64) (bool, error) {
|
||||||
ChatId: id,
|
ChatId: id,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return ChatTypeUnknown, err
|
||||||
}
|
}
|
||||||
|
|
||||||
c.cache.SetChat(id, chat)
|
c.cache.SetChat(id, chat)
|
||||||
}
|
}
|
||||||
|
|
||||||
chatType := chat.Type.ChatTypeType()
|
chatType := chat.Type.ChatTypeType()
|
||||||
if chatType == client.TypeChatTypePrivate || chatType == client.TypeChatTypeSecret {
|
if chatType == client.TypeChatTypePrivate {
|
||||||
|
return ChatTypePrivate, nil
|
||||||
|
} else if chatType == client.TypeChatTypeBasicGroup {
|
||||||
|
return ChatTypeBasicGroup, nil
|
||||||
|
} else if chatType == client.TypeChatTypeSupergroup {
|
||||||
|
supergroup, _ := chat.Type.(*client.ChatTypeSupergroup)
|
||||||
|
if supergroup.IsChannel {
|
||||||
|
return ChatTypeChannel, nil
|
||||||
|
}
|
||||||
|
return ChatTypeSupergroup, nil
|
||||||
|
} else if chatType == client.TypeChatTypeSecret {
|
||||||
|
return ChatTypeSecret, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return ChatTypeUnknown, errors.New("Unknown chat type")
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsPM checks if a chat is PM
|
||||||
|
func (c *Client) IsPM(id int64) (bool, error) {
|
||||||
|
typ, err := c.GetChatType(id)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if typ == ChatTypePrivate || typ == ChatTypeSecret {
|
||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
return false, nil
|
return false, nil
|
||||||
|
|
|
@ -475,6 +475,21 @@ func handleGetVcardIq(s xmpp.Sender, iq *stanza.IQ, typ byte) {
|
||||||
_ = gateway.ResumableSend(component, &answer)
|
_ = gateway.ResumableSend(component, &answer)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getTelegramChatType(from string, to string) (telegram.ChatType, error) {
|
||||||
|
toId, ok := toToID(to)
|
||||||
|
if ok {
|
||||||
|
bare, _, ok := gateway.SplitJID(from)
|
||||||
|
if ok {
|
||||||
|
session, ok := sessions[bare]
|
||||||
|
if ok {
|
||||||
|
return session.GetChatType(toId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return telegram.ChatTypeUnknown, errors.New("Unknown chat type")
|
||||||
|
}
|
||||||
|
|
||||||
func handleGetDiscoInfo(s xmpp.Sender, iq *stanza.IQ, di *stanza.DiscoInfo) {
|
func handleGetDiscoInfo(s xmpp.Sender, iq *stanza.IQ, di *stanza.DiscoInfo) {
|
||||||
answer, err := stanza.NewIQ(stanza.Attrs{
|
answer, err := stanza.NewIQ(stanza.Attrs{
|
||||||
Type: stanza.IQTypeResult,
|
Type: stanza.IQTypeResult,
|
||||||
|
@ -501,6 +516,8 @@ func handleGetDiscoInfo(s xmpp.Sender, iq *stanza.IQ, di *stanza.DiscoInfo) {
|
||||||
}
|
}
|
||||||
disco.AddFeatures(NSCommand)
|
disco.AddFeatures(NSCommand)
|
||||||
} else {
|
} else {
|
||||||
|
chatType, chatTypeErr := getTelegramChatType(iq.From, iq.To)
|
||||||
|
|
||||||
var cmdType telegram.CommandType
|
var cmdType telegram.CommandType
|
||||||
if ok {
|
if ok {
|
||||||
cmdType = telegram.CommandTypeChat
|
cmdType = telegram.CommandTypeChat
|
||||||
|
@ -510,6 +527,9 @@ func handleGetDiscoInfo(s xmpp.Sender, iq *stanza.IQ, di *stanza.DiscoInfo) {
|
||||||
|
|
||||||
for name, command := range telegram.GetCommands(cmdType) {
|
for name, command := range telegram.GetCommands(cmdType) {
|
||||||
if di.Node == name {
|
if di.Node == name {
|
||||||
|
if chatTypeErr == nil && !telegram.IsCommandForChatType(command, chatType) {
|
||||||
|
break
|
||||||
|
}
|
||||||
answer.Payload = di
|
answer.Payload = di
|
||||||
di.AddIdentity(telegram.CommandToHelpString(name, command), "automation", "command-node")
|
di.AddIdentity(telegram.CommandToHelpString(name, command), "automation", "command-node")
|
||||||
di.AddFeatures(NSCommand, "jabber:x:data")
|
di.AddFeatures(NSCommand, "jabber:x:data")
|
||||||
|
@ -549,6 +569,8 @@ func handleGetDiscoItems(s xmpp.Sender, iq *stanza.IQ, di *stanza.DiscoItems) {
|
||||||
if di.Node == NSCommand {
|
if di.Node == NSCommand {
|
||||||
answer.Payload = di
|
answer.Payload = di
|
||||||
|
|
||||||
|
chatType, chatTypeErr := getTelegramChatType(iq.From, iq.To)
|
||||||
|
|
||||||
var cmdType telegram.CommandType
|
var cmdType telegram.CommandType
|
||||||
if ok {
|
if ok {
|
||||||
cmdType = telegram.CommandTypeChat
|
cmdType = telegram.CommandTypeChat
|
||||||
|
@ -559,6 +581,9 @@ func handleGetDiscoItems(s xmpp.Sender, iq *stanza.IQ, di *stanza.DiscoItems) {
|
||||||
commands := telegram.GetCommands(cmdType)
|
commands := telegram.GetCommands(cmdType)
|
||||||
for _, name := range telegram.SortedCommandKeys(commands) {
|
for _, name := range telegram.SortedCommandKeys(commands) {
|
||||||
command := commands[name]
|
command := commands[name]
|
||||||
|
if chatTypeErr == nil && !telegram.IsCommandForChatType(command, chatType) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
di.AddItem(iq.To, name, telegram.CommandToHelpString(name, command))
|
di.AddItem(iq.To, name, telegram.CommandToHelpString(name, command))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
Loading…
Reference in a new issue