1
0
зеркало из https://github.com/glebtv/telegram-bot.git synced 2026-09-02 09:26:17 +03:00
Files
telegram-bot/lib/telegram/bot/updates_controller.rb
2016-02-28 21:51:59 +06:00

122 строки
3.9 KiB
Ruby

require 'abstract_controller'
require 'active_support/callbacks'
require 'active_support/version'
module Telegram
module Bot
class UpdatesController < AbstractController::Base
abstract!
require 'telegram/bot/updates_controller/session'
require 'telegram/bot/updates_controller/log_subscriber'
require 'telegram/bot/updates_controller/instrumentation'
include AbstractController::Callbacks
# Redefine callbacks with default terminator.
if ActiveSupport.gem_version >= Gem::Version.new('5')
define_callbacks :process_action,
skip_after_callbacks_if_terminated: true
else
define_callbacks :process_action,
terminator: ->(_, result) { result == false },
skip_after_callbacks_if_terminated: true
end
include AbstractController::Translation
prepend Instrumentation
extend Session::ConfigMethods
autoload :TypedUpdate, 'telegram/bot/updates_controller/typed_update'
PAYLOAD_TYPES = %w(
message
inline_query
chosen_inline_result
).freeze
CMD_REGEX = %r{\A/([a-z\d_]{,31})(@(\S+))?(\s|$)}i
CONFLICT_CMD_REGEX = Regexp.new("^(#{PAYLOAD_TYPES.join('|')}|\\d)")
class << self
def dispatch(*args)
new(*args).dispatch
end
# Overrid it to filter or transform commands.
# Default implementation is to convert to downcase and add `on_` prefix
# for conflicting commands.
def action_for_command(cmd)
cmd.downcase!
cmd.match(CONFLICT_CMD_REGEX) ? "on_#{cmd}" : cmd
end
# Fetches command from text message. All subsequent words are returned
# as arguments.
# If command has mention (eg. `/test@SomeBot`), it returns commands only
# for specified username. Set `username` to `true` to accept
# any commands.
def command_from_text(text, username = nil)
return unless text
match = text.match CMD_REGEX
return unless match
return if match[3] && username != true && match[3] != username
[match[1], text.split(' ').drop(1)]
end
end
attr_internal_reader :update, :bot, :payload, :payload_type, :is_command
alias_method :command?, :is_command
delegate :username, to: :bot, prefix: true, allow_nil: true
def initialize(bot = nil, update = nil)
@_update = update
@_bot = bot
update && PAYLOAD_TYPES.find do |type|
item = update[type]
next unless item
@_payload = item
@_payload_type = type
end
end
def dispatch
@_is_command, action, args = action_for_payload
process(action, *args)
end
# Calculates action name and args for payload.
# If payload is a message with command, then returned action is an
# action for this command. Otherwise it's the same as payload type.
# Returns array `[is_command?, action, args]`.
def action_for_payload
case payload_type
when 'message'
cmd, args = self.class.command_from_text(payload['text'], bot_username)
cmd &&= self.class.action_for_command(cmd)
[true, cmd, args] if cmd
end || [false, payload_type, [payload]]
end
# Silently ignore unsupported messages.
# Params are `action, *args`.
def action_missing(*)
end
%w(chat from).each do |field|
define_method(field) { payload[field] }
end
def reply_with(type, params)
method = "send_#{type}"
params = params.merge(
chat_id: chat['id'],
reply_to_message: payload['message_id'],
)
bot.public_send(method, params)
end
ActiveSupport.run_load_hooks('telegram.bot.updates_controller', self)
end
end
end