Skip to content

Multiple controllers for single bot

printercu edited this page Jun 7, 2018 · 5 revisions

You may want to split controller into multiple ones if it gets too large, or just to keep separate logic of different chats. The easiest way is to define custom .dispatch and forward update to other controller:

class TelegramWebhooksController < Telegram::Bot::UpdatesController
  require_dependency 'telegram_webhooks_controller/group_chat_controller'

  class << self
    # Use GroupChatController for group chats.
    def dispatch(bot, update)
      message = update['message'] || update['channel_post'] ||
        update.dig('callback_query', 'message')
      chat_type = message && message.dig('chat', 'type')
      if chat_type && chat_type != 'private'
        GroupChatController.dispatch(bot, update)
      else
        super
      end
    end
  end

  def start!(*)
    respond_with :message, text: 'Hi user!'
  end
end

# app/controllers/telegram_webhooks_controller/group_chat_controller.rb
class TelegramWebhooksController
  class GroupChatController < Telegram::Bot::UpdatesController
    def start!(*)
      respond_with :message, text: 'Hi group!'
    end
  end
end

Note that GroupChatController is not inherited from TelegramWebhooksController. To use inheritance, prepend .dispatch with this lines to prevent call loop:

return super if self != TelegramWebhooksController

Other approach is to define separate router module with .dispatch method and use this module as usual bot controller.

module TelegramWebhooksRouter
  module_function

  def dispatch(bot, update)
    if something
      TelegramGroupChatController.dispatch(bot, update)
    else
      TelegramPrivateChatController.dispatch(bot, update)
    end
  end
end

# routes.rb
Rails.application.routes.draw do
  telegram_webhooks TelegramWebhooksRouter
end

If you want to have access to session or other controller methods, you can override #dispatch instance-method instead of class-level one.

Clone this wiki locally