Telegram::BotManager

Gem Version

This gem is based on https://github.com/telegram-bot-rb/telegram-bot. Follow this link for advanced usage of this gem

Installation

Add this line to your application's Gemfile:

gem 'telegram-bot_manager'

And then execute:

$ bundle

Or install it yourself as:

$ gem install telegram-bot_manager

Require if necessary:

require 'telegram/bot_manager'

Usage

Configuration

Configure you gem in config/telegram_bot_manager.rb for example

Telegram::BotManager.configure do |config|
  config.controller_logging = true
  config.show_config_message = true
  config.telegram_app_owner_id = ENV['TELEGRAM_APP_OWNER_ID']
end

Bot configuration

You can configure you main bot file with basic configuration Create file 'my_bot.rb' in libs/ folder:

require_relative 'you lib module dependencies here'

module MyBot
  include Telegram::BotManager::BotClassMethods

  configure do |config|
    config.app_name = 'MyBot'
    config.locale = 'my_bot' # Do not forget to create 'locales/my_bot.yml' file
    config.localizer = Telegram::BotManager::Localizer.new(locale)
    config.logger = Telegram::BotManager::BotLogger.new(app_name)
    config.bot = Telegram.bots[:my_bot] # Place here your bot using 'telegram-bot' gem
  end
end

All this config methods will be available for calling on your module

MyBot.app_name # => 'MyBot'
MyBot.localizer.pick('start_message.greeting', some_param: some_value)
MyBot.logger.info('Info message that will be shown in console and writed to log file')
MyBot.bot.send_message(...)

Application file

Create your application file in apps/my_bot/application.rb and inherit it from Telegram::BotManager::Application

module MyBot
  class Application < Telegram::BotManager::Application

    def configure
      # Configure your app here
      # And don't forget to call 'super'
      super
    end

    private

    def controller
      # specify your bot controller
      MyBot::Controller
    end

    def configuration_message
      # Change config message here

      # By default, it will show you main bot configuration info
      # such as app name, telegram bot username and specified locale file 
    end

    def startup_message
      # by default will be shown '[MyBot] Application is listening messages...'
    end

    def handle_exception(exception)
      # Any exception handling here
      # You can send telegram message with exception if you want

      # Telegram::BotManager::Message
      #  .new(Telegram.bots[:my_bot], exception.full_message.truncate(4000))
      #  .send_to_app_owner

      # By default gem will raise exception
    end
  end
end

Init and run application

Create my_bot file in bin/ directory and init the application. Then run

MyBot::Application.new(MyBot.configuration).run

Controller

All methods reused from telegram-bot gem. Basic example:

module MyBot
  class Controller < Telegram::BotManager::Controller

  # Specify redis url if you want to use 'session' feature like `session[:user_id] = user_id`
  self.session_store = :redis_cache_store, { url: REDIS.id, namespace: MyBot.bot.username }

  # use callbacks like in any other controllers
  around_action :with_locale
  before_action :sync_chat

  # Every update can have one of: message, inline_query, chosen_inline_result,
  # callback_query, etc.
  # Define method with same name to respond to this updates.
  def message(message)
    message == self.payload # true
  end

  # Specify telegram bot commands
  # Do not forget to use '!' at the end of method name
  def start!
  end

  private

  def with_locale
    # 'around_action' callback code
    # Use 'throw :abort' to exit from action
  end

  def sync_chat
    # 'before_action' callback code
    # Use 'throw :abort' to exit from action
  end
end

Views

Create folder apps/my_bot/views and place here files that is responsible for building telegram message

module MyBot
  module Views
    class StartMessage < Telegram::BotManager::View

    def main_keyboard
      # Specify your telegram bot keyboard data here
      # Also you can use method `callback_data` to automaticaly build your callback string

      markup = { inline_keyboard: [[
          { text: 'First button',   callback_data: callback_data(bot: 'my_bot', action: 'start!') },
          { text: 'Second button',  callback_data: callback_data(any_key: 'any value') }
        ]]
      }
    end

    def text
      # Add message parts to 'content' attribute
      content << title
    end

    def title
      # Place any string here you want to add to message content
      'Hello, this is start message'
    end

    def username
      # Also you can append string to base content here
      # all content will be shown if you call '#message' method
      content << 'some string'
    end

    def greeting
      # You can use translations based on I18n gem here
      ::MyBot.localizer.pick('start_message.greeting', user: params[:user])
    end

    def useful_links
      callback_data(any_key: 'any value')
    end

  end
end

And then use it in your controller actions:

def start!
  start_message_view = MyBotBot::Views::StartMessage.new(any_key: any_value)

  # start_message_view.content => Will return 'content' attribute and all appended strings
  # start_message_view.text => Will call 'text' method of your view
  # start_message_view.markup => Will return data from 'markup' attribute
end

Localizer

Use localizer to pick some sample message for different variations by translator key. By default, this gem uses 'I18n' gem with some wrapper-methods

The main convention is to write hyphenated translations so that an array of strings will be accessible by translation key. Follow this example:

Create file my_bot.yml in locales/ folder of your project. Then define main key with name of your bot (the same as your file name) and write translator key with array of strings, so localizer will choose random variant:

my_bot:
  start_message:
    - "First variant %{param}"
    - "Second variat %{param}"
    - "Third variant %{param}"
  title:
    - "Translation #1"
    - "..."

And then you can get random translation from your locale file by using

::MyBot.localizer.pick('start_message', param: some_value) # Will pick random translation
::MyBot.localizer.samples('start_message', param: some_value) # Will return array with all translations by this key

Logger

This gem includes custom logger with ability to write log entries both to console and log file

# Use BotLogger to write bot logs
logger = Telegram::BotManager::BotLogger.new('MyBot', **args) # => Will create 'MyBot.log' file in 'log/' folder and will write to STDOUT
logger.info('Bot info log message')

# Use Logger if you just want to have ability to write to STDOUT and file
logger = Telegram::BotManager::Logger.new(log_file: 'custom_logfile', **args)

Messages

Here is present a Message class that gives you ability to choose destionation of message by calling corresponding method

message = Telegram::BotManager::Message.new(Telegram.bots[:my_bot], 'Any message text here')

message.send_to_app_owner # will send message to user whose telegram id is specified in `Telegram::BotManager.configuration.telegram_app_owner_id`
message.edit(message_id: 123, chat_id: 456, **params)
message.edit_inline(inline_message_id: 123, **params) # => Will update message with inline keyboard
message.reply(to_message_id: 123, chat_id: 456, **params)
message.send_to_chat(123, **params)

Callback query

Its just JSON parser and JSON generator for your params that you pass in initialize method as hash All your hash keys and values will be transformed to JSON string like '{"first_key":"first_value","second_key":"second_value"}' because telegram allows to pass only strings between actions on inline keyboards

new_query = Telegram::BotManager::CallbackQuery.new(first_key: 'first_value', second_key: 'second_value')
new_query.build # => 'first_key:first_value,second_key:second_value'

received_query = Telegram::BotManager::CallbackQuery.parse('{"first_key":"first_value"}"')
received_query.params # => { first_key: first_value }

You can use callback query objects in your controller. Example:

# controller:
def callback_query(query)
  query = Telegram::BotManager::CallbackQuery.parse(query)

  case query.params[:bot]
  when 'first_bot'  then first_bot(query)
  when 'second_bot' then second_bot(query)
  end
end

def first_bot(query)
  case query.params[:action]
  when 'start!'     then first_bot_start!
  when 'author!'    then first_bot_author!
  end
end

Development

After checking out the repo, run bin/setup to install dependencies. You can also run bin/console for an interactive prompt that will allow you to experiment.

To install this gem onto your local machine, run bundle exec rake install. To release a new version, update the version number in version.rb, and then run bundle exec rake release, which will create a git tag for the version, push git commits and tags, and push the .gem file to rubygems.org.

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/vrtsev/Gem-Telegram-Bot-Manager. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the Contributor Covenant code of conduct.

License

The gem is available as open source under the terms of the MIT License.

Code of Conduct

Everyone interacting in the BotManager project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the code of conduct.