зеркало из
https://github.com/glebtv/telegram-bot.git
synced 2026-08-28 15:26:18 +03:00
106 строки
3.2 KiB
Ruby
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
|