1
0
зеркало из https://github.com/glebtv/telegram-bot.git synced 2026-08-28 15:26:18 +03:00
Files
telegram-bot/lib/telegram/bot/updates_controller.rb
Max Melentiev 37a63f7b23 v0.1.0
2016-02-22 23:19:38 +06:00

106 строки
3.2 KiB
Ruby

require 'abstract_controller'
require 'active_support/callbacks'
module Telegram
class Bot
class UpdatesController < AbstractController::Base
include AbstractController::Callbacks
include AbstractController::Translation
require 'telegram/bot/updates_controller/log_subscriber'
require 'telegram/bot/updates_controller/instrumentation'
prepend Instrumentation
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)")
abstract!
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