{"id":13878085,"url":"https://github.com/telegram-bot-rb/telegram-bot","last_synced_at":"2025-05-14T02:06:20.992Z","repository":{"id":38916498,"uuid":"52291766","full_name":"telegram-bot-rb/telegram-bot","owner":"telegram-bot-rb","description":"Ruby gem for building Telegram Bot with optional Rails integration","archived":false,"fork":false,"pushed_at":"2025-01-15T03:57:48.000Z","size":380,"stargazers_count":650,"open_issues_count":10,"forks_count":118,"subscribers_count":18,"default_branch":"master","last_synced_at":"2025-04-14T03:57:22.362Z","etag":null,"topics":["async","bot","controller","hot-reload","poller","rails","ruby","telegram","telegram-bot","webhook"],"latest_commit_sha":null,"homepage":"","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/telegram-bot-rb.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-02-22T17:34:31.000Z","updated_at":"2025-03-25T18:55:00.000Z","dependencies_parsed_at":"2023-02-09T19:31:33.756Z","dependency_job_id":"e7568aeb-1b48-4529-b85b-f4ff5fda885c","html_url":"https://github.com/telegram-bot-rb/telegram-bot","commit_stats":{"total_commits":186,"total_committers":16,"mean_commits":11.625,"dds":"0.11827956989247312","last_synced_commit":"be74094c9051f59a124112e369f4d2c3e5ffeca3"},"previous_names":[],"tags_count":48,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/telegram-bot-rb%2Ftelegram-bot","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/telegram-bot-rb%2Ftelegram-bot/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/telegram-bot-rb%2Ftelegram-bot/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/telegram-bot-rb%2Ftelegram-bot/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/telegram-bot-rb","download_url":"https://codeload.github.com/telegram-bot-rb/telegram-bot/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254052697,"owners_count":22006716,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["async","bot","controller","hot-reload","poller","rails","ruby","telegram","telegram-bot","webhook"],"created_at":"2024-08-06T08:01:39.465Z","updated_at":"2025-05-14T02:06:15.854Z","avatar_url":"https://github.com/telegram-bot-rb.png","language":"Ruby","funding_links":[],"categories":["Ruby","Telegram Libraries"],"sub_categories":["Ruby"],"readme":"# Telegram::Bot\n\n[![Gem Version](https://badge.fury.io/rb/telegram-bot.svg)](http://badge.fury.io/rb/telegram-bot)\n[![Code Climate](https://codeclimate.com/github/telegram-bot-rb/telegram-bot/badges/gpa.svg)](https://codeclimate.com/github/telegram-bot-rb/telegram-bot)\n[![Lint \u0026 Test](https://github.com/telegram-bot-rb/telegram-bot/actions/workflows/ci.yml/badge.svg)](https://github.com/telegram-bot-rb/telegram-bot/actions/workflows/ci.yml)\n\nTools for developing Telegram bots. Best used with Rails, but can be used in\n[standalone app](https://github.com/telegram-bot-rb/telegram-bot/wiki/Not-rails-application).\nSupposed to be used in webhook-mode in production, and poller-mode\nin development, but you can use poller in production if you want.\n\nPackage contains:\n\n- Lightweight client for bot API (with fast and thread-safe\n  [httpclient](https://github.com/nahi/httpclient) under the hood).\n- Controller with message parser: define methods for commands, not `case` branches.\n- Middleware and routes helpers for production env.\n- Poller with automatic source-reloader for development env.\n- Rake tasks to update webhook urls.\n- __[Async mode](#async-mode)__.\n  Let the queue adapter handle network errors!\n\nHere is sample [telegram_bot_app](https://github.com/telegram-bot-rb/telegram_bot_app)\nwith session, keyboards and inline queries.\nRun it on your local machine in 1 minute!\n\nAnd here is [app template](https://github.com/telegram-bot-rb/rails_template)\nto generate new rails app in seconds.\n\nSee examples and cookbook in [the wiki](https://github.com/telegram-bot-rb/telegram-bot/wiki).\n\n## Table of Contents\n\n* [Installation](#installation)\n* [Usage](#usage)\n  * [Configuration](#configuration)\n  * [Configuration in Rails app](#configuration-in-rails-app)\n  * [Client](#client)\n    * [Typed responses](#typed-responses)\n  * [Controller](#controller)\n    * [Reply helpers](#reply-helpers)\n    * [Optional typecasting](#optional-typecasting)\n    * [Session](#session)\n    * [Message context](#message-context)\n    * [Callback queries](#callback-queries)\n  * [Routes in Rails app](#routes-in-rails-app)\n    * [Processing updates](#processing-updates)\n  * [Development \u0026 Debugging](#development--debugging)\n  * [Testing](#testing)\n  * [Deployment](#deployment)\n  * [Async mode](#async-mode)\n    * [Limitations](#limitations)\n* [Development](#development)\n* [Contributing](#contributing)\n\n## Installation\n\nAdd this line to your application's Gemfile:\n\n```ruby\ngem 'telegram-bot'\n```\n\nAnd then execute:\n\n```\nbundle\n```\n\nOr install it yourself as:\n\n```\ngem install telegram-bot\n```\n\nRequire if necessary:\n\n```ruby\nrequire 'telegram/bot'\n```\n\n## Usage\n\n### Configuration\n\nWhile clients can be instantiated explicitly, there is `Telegram.bots_config=` method\nto configure app-wide clients, which are accessible via `Telegram.bots`.\nIt accepts hash of `{bot_id: bot_config}`, and there is special id `:default`\nwhich is used for `Telegram.bot`.\n\n```ruby\nTelegram.bots_config = {\n  default: DEFAULT_BOT_TOKEN,\n  chat: {\n    token: CHAT_BOT_TOKEN,\n    username: 'ChatBot', # to support commands with mentions (/help@ChatBot)\n    server: 'http://local.bot.api.server', # for Local Bot API Server\n  },\n}\n\nTelegram.bot.get_updates\nTelegram.bot == Telegram.bots[:default] # true\nTelegram.bots[:chat].send_message(...)\n```\n\n### Configuration in Rails app\n\nIn Rails app `Telegram.bots_config` is read from `secrets.yml` automatically\nfrom `telegram` section:\n\n```yml\ndevelopment:\n  telegram:\n    # Single bot can be specified like this\n    bot: TOKEN\n    # or\n    bot:\n      token: TOKEN\n      username: SomeBot\n      server: http://local.bot.api.server\n\n    # For multiple bots in single app use hash of `internal_bot_id =\u003e settings`\n    bots:\n      # just set the bot token\n      chat: TOKEN_1\n      # or add username to support commands with mentions (/help@ChatBot)\n      auction:\n        token: TOKEN_2\n        username: ChatBot\n```\n\nFor Rails \u003e= 5.2 `Telegram::Bot` searches for config first in credentials and then in secrets.\nTo use credentials as config store, add telegram section to credentials instead of secrets using\n`rails credentials:edit`. In this case be aware of that [Rails \u003c 6.0 may not load\ncredentials in dev environment by default](https://github.com/telegram-bot-rb/telegram-bot/issues/74#issuecomment-384205609).\nIn Rails \u003e= 6.0 run `rails credentials:edit --environment development` to configure bot\nin each environment.\n\nI suggest not using Rails 5.2 credentials because it can lead to leakage of sensitive data\nand it's more difficult to use in multiple environments. See\n[secure_credentials](https://github.com/printercu/secure_credentials) gem for better option.\n\nFrom now clients will be accessible with `Telegram.bots[:chat]` or `Telegram.bots[:auction]`.\nSingle bot can be accessed with `Telegram.bot` or `Telegram.bots[:default]`.\n\n### Client\n\nClient is instantiated with `Telegram::Bot::Client.new(token, username)`.\nUsername is optional and used only to parse commands with mentions.\n\nThere is `request(path_suffix, body)` method to perform any query.\nAnd there are shortcuts for all available requests in underscored style\n(`answer_inline_query(params)` instead of `answerInlineQuery`).\n\n```ruby\nbot.request(:getMe) or bot.get_me\nbot.request(:getupdates, offset: 1) or bot.get_updates(offset: 1)\nbot.send_message(chat_id: chat_id, text: 'Test')\n```\n\nThere is no magic, they just pass params as is and set `path_suffix`.\nSee [list of available methods](https://github.com/telegram-bot-rb/telegram-bot/blob/master/lib/telegram/bot/client/api_methods.txt)\nfetched from [API docs](https://core.telegram.org/bots/api).\nPlease open PR or issue if it misses methods from new API versions.\n\nAny API request error will raise `Telegram::Bot::Error` with description in its message.\nSpecial `Telegram::Bot::Forbidden` is raised when bot can't post messages to the chat anymore.\n\n#### Typed responses\n\nBy default client will return parsed json responses. You can enable\nresponse typecasting to virtus models using\n[`telegram-bot-types`](https://github.com/telegram-bot-rb/telegram-bot-types) gem:\n\n```ruby\n# Add to your gemfile:\ngem 'telegram-bot-types', '~\u003e x.x.x'\n# Enable typecasting:\nTelegram::Bot::Client.typed_response!\n# or for single instance:\nbot.extend Telegram::Bot::Client::TypedResponse\n\nbot.get_me.class # =\u003e Telegram::Bot::Types::User\n```\n\n### Controller\n\nController makes it easy to keep bot's code readable.\nIt does nothing more than finding out action name for update and invoking it.\nSo there is almost no overhead comparing to large `switch`, while you\ncan represent actions as separate methods keeping source much more readable and supportable.\n\nNew instance of controller is instantiated for each update.\nThis way every update is processed in isolation from others.\n\nBot controllers like usual rails controllers provides features like callbacks,\n`rescue_from` and instrumentation.\n\n```ruby\nclass Telegram::WebhookController \u003c Telegram::Bot::UpdatesController\n  # use callbacks like in any other controller\n  around_action :with_locale\n\n  # Every update has one of: message, inline_query, chosen_inline_result,\n  # callback_query, etc.\n  # Define method with the same name to handle this type of update.\n  def message(message)\n    # store_message(message['text'])\n  end\n\n  # For the following types of updates commonly used params are passed as arguments,\n  # full payload object is available with `payload` instance method.\n  #\n  #   message(payload)\n  #   inline_query(query, offset)\n  #   chosen_inline_result(result_id, query)\n  #   callback_query(data)\n\n  # Define public methods ending with `!` to handle commands.\n  # Command arguments will be parsed and passed to the method.\n  # Be sure to use splat args and default values to not get errors when\n  # someone passed more or less arguments in the message.\n  def start!(word = nil, *other_words)\n    # do_smth_with(word)\n\n    # full message object is also available via `payload` instance method:\n    # process_raw_message(payload['text'])\n\n    # There are `chat` \u0026 `from` shortcut methods.\n    # For callback queries `chat` is taken from `message` when it's available.\n    response = from ? \"Hello #{from['username']}!\" : 'Hi there!'\n\n    # There is `respond_with` helper to set `chat_id` from received message:\n    respond_with :message, text: response\n\n    # `reply_with` also sets `reply_to_message_id`:\n    reply_with :photo, photo: File.open('party.jpg')\n  end\n\n  private\n\n  def with_locale(\u0026block)\n    I18n.with_locale(locale_for_update, \u0026block)\n  end\n\n  def locale_for_update\n    if from\n      # locale for user\n    elsif chat\n      # locale for chat\n    end\n  end\nend\n```\n\n#### Reply helpers\n\nThere are helpers for basic responses. They just set chat/message/query\nidentifiers from the update. See\n[`ReplyHelpers`](https://github.com/telegram-bot-rb/telegram-bot/blob/master/lib/telegram/bot/updates_controller/reply_helpers.rb)\nmodule for more information. Here are these methods signatures:\n\n```ruby\ndef respond_with(type, params); end\ndef reply_with(type, params); end\ndef answer_inline_query(results, params = {}); end\ndef answer_callback_query(text, params = {}); end\ndef edit_message(type, params = {}); end\ndef answer_pre_checkout_query(ok, params = {}); end\ndef answer_shipping_query(ok, params = {}); end\n```\n\n#### Optional typecasting\n\nYou can enable typecasting of `update` with `telegram-bot-types` by including\n`Telegram::Bot::UpdatesController::TypedUpdate`:\n\n```ruby\nclass Telegram::WebhookController \u003c Telegram::Bot::UpdatesController\n  include Telegram::Bot::UpdatesController::TypedUpdate\n\n  def message(message)\n    message.class # =\u003e Telegram::Bot::Types::Message\n  end\nend\n```\n\n#### Session\n\nThis API is very close to ActiveController's session API, but works different\nunder the hood. Cookies can not be used to store session id or\nwhole session (like CookieStore does). So it uses key-value store and `session_key`\nmethod to build identifier from update.\n\nStore can be one of numerous `ActiveSupport::Cache` stores.\nWhile `:file_store` is suitable for development and single-server deployments\nwithout heavy load, it doesn't scale well. Key-value databases with persistance\nlike Redis are more appropriate for production use.\n\n```ruby\n# In rails app store can be configured in env files:\nconfig.telegram_updates_controller.session_store = :redis_store, {expires_in: 1.month}\n\n# In other app it can be done for all controllers with:\nTelegram::Bot::UpdatesController.session_store = :redis_store, {expires_in: 1.month}\n# or for specific one:\nOneOfUpdatesController.session_store = :redis_store, {expires_in: 1.month}\n```\n\nDefault session id is made from bot's username and `(from || chat)['id']`.\nIt means that session will be the same for updates from user in every chat,\nand different for every user in the same group chat.\nTo change this behavior you can override `session_key` method, or even\ndefine [multiple sessions](https://github.com/telegram-bot-rb/telegram-bot/wiki/Multiple-session-objects)\nin single controller. For details see `Session` module.\n\n```ruby\nclass Telegram::WebhookController \u003c Telegram::Bot::UpdatesController\n  include Telegram::Bot::UpdatesController::Session\n  # or just shortcut:\n  use_session!\n\n  # You can override global config for this controller.\n  self.session_store = :file_store\n\n  def write!(text = nil, *)\n    session[:text] = text\n  end\n\n  def read!(*)\n    respond_with :message, text: session[:text]\n  end\n\n  private\n\n  # In this case session will persist for user only in specific chat.\n  # Same user in other chat will have different session.\n  def session_key\n    \"#{bot.username}:#{chat['id']}:#{from['id']}\" if chat \u0026\u0026 from\n  end\nend\n```\n\n#### Message context\n\nIt's usual to support chain of messages like BotFather: after receiving command\nit asks you for additional argument. There is `MessageContext` for this:\n\n```ruby\nclass Telegram::WebhookController \u003c Telegram::Bot::UpdatesController\n  include Telegram::Bot::UpdatesController::MessageContext\n\n  def rename!(*)\n    # set context for the next message\n    save_context :rename_from_message\n    respond_with :message, text: 'What name do you like?'\n  end\n\n  # register context handlers to handle this context\n  def rename_from_message(*words)\n    update_name words[0]\n    respond_with :message, text: 'Renamed!'\n  end\n\n  # You can use same action name as context name:\n  def rename!(name = nil, *)\n    if name\n      update_name name\n      respond_with :message, text: 'Renamed!'\n    else\n      save_context :rename!\n      respond_with :message, text: 'What name do you like?'\n    end\n  end\nend\n```\n\n#### Callback queries\n\nYou can include `CallbackQueryContext` module to split `#callback_query` into\nseveral methods. It doesn't require session support, and takes context from\ndata: if data has a prefix with colon like this `my_ctx:smth...` it invokes\n`my_ctx_callback_query('smth...')` when such action method is defined. Otherwise\nit invokes `callback_query('my_ctx:smth...')` as usual.\nCallback queries without prefix stay untouched.\n\n```ruby\n# This one handles `set_value:%{something}`.\ndef set_value_callback_query(new_value = nil, *)\n  save_this(value)\n  answer_callback_query('Saved!')\nend\n\n# And this one is for `make_cool:%{something}`\ndef make_cool_callback_query(thing = nil, *)\n  do_it(thing)\n  answer_callback_query(\"#{thing} is cool now! Like a callback query context.\")\nend\n```\n\n### Routes in Rails app\n\nThere is `telegram_webhook` helper for rails app to define routes for webhooks.\nIt defines routes at `telegram/#{hash_of(bot.token)}` and connects bots with controller.\n\n```ruby\n# Most off apps would require\ntelegram_webhook TelegramController\n# which is same as\ntelegram_webhook TelegramController, :default\n\n# Use different controllers for each bot:\ntelegram_webhook TelegramChatController, :chat\ntelegram_webhook TelegramAuctionController, :auction\n\n# Defined route is named and its name depends on `Telegram.bots`.\n# For single bot it will use 'telegram_webhook',\n# for multiple bots it uses bot's key in the `Telegram.bots` as prefix\n# (eg. `chat_telegram_webhook`).\n# You can override this with `as` option:\ntelegram_webhook TelegramController, as: :custom_telegram_webhook\n```\n\n#### Processing updates\n\nTo process update with controller call `.dispatch(bot, update)` on it.\nThere are several options to run it automatically:\n\n- Use webhooks with routes helper (described above).\n- Use `Telegram::Bot::Middleware` with rack ([example in wiki](https://github.com/telegram-bot-rb/telegram-bot/wiki/Not-rails-application)).\n- Use poller (described in the next section).\n\nWhen controller runs in webhook mode `Telegram::Bot::Middleware` passes\n`ActionDispatch::Request` object to the `.dispatch` method.\nIt's available via `#webhook_request` controller method.\n\nTo run action without update (ex., send notifications from jobs),\nyou can call `#process` directly. In this case controller can be initialized\nwith `:from` and/or `:chat` options instead of `update` object:\n\n```ruby\ncontroller = ControllerClass.new(bot, from: telegram_user, chat: telegram_chat)\ncontroller.process(:welcome, *args)\n```\n\n### Development \u0026 Debugging\n\nUse `rake telegram:bot:poller` to run poller in rails app. It automatically loads\nchanges without restart in development env.\nOptionally pass bot id in `BOT` envvar (`BOT=chat`) to specify bot to run poller for.\n\nThis task requires `telegram_webhook` helper to be used as it connects bots with controller.\nTo run poller in other cases use:\n\n```ruby\nTelegram::Bot::UpdatesPoller.start(bot, controller_class)\n```\n\n### Testing\n\nThere is a `Telegram::Bot::ClientStub` class to stub client for tests.\nInstead of performing API requests it stores them in a `requests` hash.\n\nTo stub all possible clients use `Telegram::Bot::ClientStub.stub_all!` before\ninitializing clients. Here is a template for RSpec:\n\n```ruby\n# environments/test.rb\n# Make sure to run it before defining routes or accessing any bot in the app!\nTelegram.reset_bots\nTelegram::Bot::ClientStub.stub_all!\n\n# rails_helper.rb\nRSpec.configure do |config|\n  # ...\n  config.after { Telegram.bot.reset }\n  # or for multiple bots:\n  config.after { Telegram.bots.each_value(\u0026:reset) }\n  # ...\nend\n```\n\nRSpec contexts and helpers are included automatically for groups and examples with matching\ntags. In RSpec \u003c 3.4 it's required to use `include_context` explicitly.\nSee [list of available helpers](https://github.com/telegram-bot-rb/telegram-bot/tree/master/lib/telegram/bot/rspec)\nfor details.\n\nThere are 3 types of integration tests:\n\n- `:rails` - for testing bot in webhooks-mode in Rails application.\n  It simulates webhook requests POSTing data to controller's endpoint.\n  It works on the top of requests specs, so `rspec-rails` gem is required.\n- `:rack` - For testing bot in webhooks-mode in non-Rails application.\n  It uses `rack-test` gem to POST requests to bot's endpoint.\n- `:poller` - Calls `.dispatch` directly on controller class.\n\nPick the appropriate one, then require `telegram/bot/rspec/integration/#{type}`\nand mark spec group with tag `telegram_bot: type`. See configuration options\nfor each type in\n[telegram/bot/rspec/integration/](https://github.com/telegram-bot-rb/telegram-bot/tree/master/lib/telegram/bot/rspec/integration).\n\nHere is an example test for a Rails app:\n\n```ruby\n# spec/requests/telegram_webhooks_spec.rb\nrequire 'telegram/bot/rspec/integration/rails'\n\nRSpec.describe TelegramWebhooksController, telegram_bot: :rails do\n  # for old RSpec:\n  # include_context 'telegram/bot/integration/rails'\n\n  # Main method is #dispatch(update). Some helpers are:\n  #   dispatch_message(text, options = {})\n  #   dispatch_command(cmd, *args)\n\n  # Available matchers can be found in Telegram::Bot::RSpec::ClientMatchers.\n  it 'shows usage of basic matchers' do\n    # The most basic one is #make_telegram_request(bot, action).\n    # It works similar to `receive` matcher and supports chaining `.with(args).exactly(n).times`.\n    expect { dispatch_command(:start) }.to make_telegram_request(bot, :sendMessage).\n      with(hash_including(text: 'msg text'))\n\n    # There are some shortcuts for dispatching basic updates and testing responses.\n    expect { dispatch_message('Hi') }.to send_telegram_message(bot, /msg regexp/, some: :option)\n  end\n\n  describe '#start!' do\n    subject { -\u003e { dispatch_command :start } }\n    # Using built in matcher for `respond_to`:\n    it { should respond_with_message 'Hi there!' }\n  end\n\n  # There is context for callback queries with related matchers,\n  # use :callback_query tag to include it.\n  describe '#hey_callback_query', :callback_query do\n    let(:data) { \"hey:#{name}\" }\n    let(:name) { 'Joe' }\n    it { should answer_callback_query('Hey Joe') }\n    it { should edit_current_message :text, text: 'Done' }\n  end\nend\n```\n\nThere is a context for testing bot controller in the way similar to Rails controller tests.\nIt's supposed to be a low-level alternative for integration tests. Among the differences is\nthat controller tests use a single controller instance for all dispatches in specific example,\nsession is stubbed (does not use configured store engine), and update is not serialized\nso it also supports mocks. This can be useful for unit testing, but should not be used as\nthe default way to test the bot.\n\n```ruby\nrequire 'telegram/bot/updates_controller/rspec_helpers'\nRSpec.describe TelegramWebhooksController, type: :telegram_bot_controller do\n  # for old RSpec:\n  # include_context 'telegram/bot/updates_controller'\n\n  # Same helpers and matchers like dispatch_command, answer_callback_query are available here.\nend\n```\n\nSee sample app for more examples.\n\n### Deployment\n\nWhile webhooks-mode is prefered, poller still can be used in production.\nSee [comparison and examples](https://github.com/telegram-bot-rb/telegram-bot/wiki/Deployment)\nfor details.\n\n### Async mode\n\nThere is built in support for async requests using ActiveJob. Without Rails\nyou can implement your own worker class to handle such requests. This allows:\n\n- Process updates very fast, without waiting for telegram responses.\n- Handle and retry network and other errors with queue adapter.\n- ???\n\nInstead of performing request instantly client serializes it, pushes to queue,\nand immediately return control back. The job is then fetched with a worker\nand real API request is performed. And this all is absolutely transparent for the app.\n\nTo enable this mode add `async: true` to bot's config.\nFor more information and custom configuration check out\n[docs](http://www.rubydoc.info/github/telegram-bot-rb/telegram-bot/master/Telegram/Bot/Async) or\n[source](https://github.com/telegram-bot-rb/telegram-bot/blob/master/lib/telegram/bot/async.rb).\n\nIf you want async mode, but don't want to setup queue, know that Rails 5 are shipped\nwith Async adapter by default, and there is\n[Sucker Punch](https://github.com/brandonhilkert/sucker_punch) for Rails 4.\n\nTo disable async mode for the block of code use `bot.async(false) { bot.send_photo }`.\nYes, it's threadsafe too.\n\n#### Limitations\n\n- Client will not return API response.\n- Sending files is not available in async mode, because they can not be serialized.\n\n## Development\n\nAfter checking out the repo, run `bin/setup` to install dependencies and git hooks.\nThen, run `appraisal rake spec` to run the tests.\nYou can also run `bin/console` for an interactive prompt that will allow you to experiment.\n\nTo install this gem onto your local machine, run `bundle exec rake install`.\nTo release a new version, update the version number in `version.rb`,\nand then run `bundle exec rake release`, which will create a git tag for the version,\npush git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).\n\nUse `bin/fetch-telegram-methods` to update API methods list from Telegram website.\n\n## Contributing\n\nBug reports and pull requests are welcome on GitHub at https://github.com/telegram-bot-rb/telegram-bot.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftelegram-bot-rb%2Ftelegram-bot","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftelegram-bot-rb%2Ftelegram-bot","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftelegram-bot-rb%2Ftelegram-bot/lists"}