Skip to content

Instantly share code, notes, and snippets.

@alexkutsan
Created January 4, 2023 17:01
Show Gist options
  • Save alexkutsan/b4578bcff1f0118cf10e75da269acb2a to your computer and use it in GitHub Desktop.
Save alexkutsan/b4578bcff1f0118cf10e75da269acb2a to your computer and use it in GitHub Desktop.
module Tourmaline
module Handlers
class CommandHandler < EventHandler
ANNOTATION = Command
# Commands (without prefix) that this handler should respond to.
property commands : Array(String)
# Prefixes that commands should start with.
property prefixes : Array(String)
# User API: if true, this command will only be activated by an outgoing message.
property outgoing : Bool
# If true, this handler will only respond if the command is sent in private.
property private_only : Bool
# If true, this handler will only respond if the command is sent in a group.
property group_only : Bool
# If true, this handler will also run (or re-run) when messages are edited.
property on_edit : Bool
# Register this command with BotFather. Only works is `prefixes` contains `/` (as
# it does by default), as non-botcommands can't be registed with BotFather.
property register : Bool
# By default the first command in `commands` will be selected as the command name
# to register. If this property is set, it will be used instead.
property register_as : String?
# Used when registering the command with BotFather. If `register` is true, but this
# is not set, the command will not be registered.
property description : String?
# Create a new `CommandHandler` instance using the provided `commands`. `commands` can
# be a single command string, or an array of possible commands.
#
# !!! warning
# If `#admin_only` is true, `get_chat_adminstrators` will be run every time the
# handler is invoked. This should be fine in testing, but in production it's
# recommended to cache admins and do your own guarding.
def initialize(commands,
prefix = nil,
@outgoing = true,
@private_only = false,
@group_only = false,
@on_edit = false,
@register = false,
@register_as = nil,
@description = nil,
&block : Context ->)
super()
if prefix
@prefixes = prefix.is_a?(Array) ? prefix : [prefix]
else
@prefixes = Tourmaline::Client.default_command_prefixes
end
commands = commands.is_a?(Array) ? commands : [commands]
@commands = commands.map(&.to_s)
@proc = block
end
def call(update : Update)
if (message = update.message || update.channel_post) || (@on_edit && (message = update.edited_message || update.edited_channel_post))
return if message.outgoing? unless @outgoing
if ((raw_text = message.raw_text) && (text = message.text)) ||
(raw_text = message.raw_caption && (text = message.caption))
return if private_only && message.chat.private?
return if group_only && message.chat.private?
text = text.to_s
raw_text = raw_text.to_s
tokens = text.split(/\s+/)
tokens = tokens.size > 1 ? text.split(/\s+/, 2) : [tokens[0], ""]
Log.debug { "CommandHandler Checking command #{tokens} against #{commands}" }
raw_tokens = raw_text.split(/\s+/)
Log.debug { "CommandHandler raw_tokens #{raw_tokens}" }
return if tokens.empty?
command = raw_tokens[0]
text = tokens[1]
if command.starts_with?('/') && command.includes?("@")
command, botname = command.split("@", 2)
Log.debug { "CommandHandler command, botname #{command}, #{botname}" }
return unless botname.downcase == client.bot.username.to_s.downcase
end
prefix_re = /^#{@prefixes.map(&->Regex.escape(String)).join('|')}/
Log.debug { "CommandHandler prefix_re #{prefix_re}" }
return unless command.match(prefix_re)
command = command.sub(prefix_re, "")
Log.debug { "CommandHandler command #{command}" }
return unless @commands.includes?(command)
context = Context.new(update, update.context, message, command, text, raw_text, !!botname, !!update.edited_message)
@proc.call(context)
return true
end
end
end
record Context,
update : Update,
context : Middleware::Context,
message : Message,
command : String,
text : String,
raw_text : String,
botname : Bool,
edit : Bool
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment