TelegramSupportBot is a Ruby gem designed to enhance customer support through Telegram, allowing
for the management of queries directly from a designated chat while ensuring privacy and
confidentiality.
- Forward messages between users and a support chat
- Supports various message types (text, images, videos, documents, audio, stickers)
- Auto-away messages for off-hours
- Simple configuration and deployment
Add to your Gemfile:
gem 'telegram-support-bot'- Create Your Bot via BotFather on Telegram to get your bot token.
- Deploy Your Application and set up a controller action for webhook callbacks, directing them
to
TelegramSupportBot.process_update(orTelegramSupportBot.process_update(update, bot: :your_key)for keyed bots). - Set the Webhook URL using the Telegram Bot API to your controller action.
- Add Your Bot to a Support Chat and obtain the
support_chat_idby sending the/startcommand to the bot inside the support chat. - Configure Your Bot in your Ruby application with the token and
support_chat_id, and set a welcome message.
TelegramSupportBot.configure do |config|
config.adapter = :telegram_bot
config.adapter_options = { token: 'YOUR_TELEGRAM_BOT_TOKEN' }
config.support_chat_id = 'YOUR_SUPPORT_CHAT_ID'
config.welcome_message = 'Hi! How can we help you?'
# Support-chat noise control:
# true (default) -> ignore non-command messages in support chat
# false -> reply with non_command_message_response
config.ignore_non_command_messages = true
config.non_command_message_response = 'I only respond to commands. Please use /start.'
# Optional: ask users to share their phone once for account lookup.
config.request_contact_on_start = true
# Optional: forward the user's first /start message to support chat.
config.forward_start_to_support = false
# Optional: block forwarding until contact is shared.
config.require_contact_for_support = false
# Optional: deduplicate repeated Telegram deliveries by update_id.
# Keep > 0 (default: 24h) to avoid repeated /start replies/forwards on retries.
config.processed_update_ttl_seconds = 24 * 60 * 60
# Optional callback to persist/lookup user profile in your app.
config.on_contact_received = ->(profile) { YourUserMatcher.sync_from_telegram(profile) }
# Optional callback for user-chat commands other than /start.
# Return true to mark the command as handled (it will not be forwarded).
config.on_user_command = ->(command:, args:, chat_id:, message:, bot_username: nil) { false }
# Recommended in Kubernetes/multi-pod setup:
# config.state_store = :redis
# config.state_store_options = { url: ENV.fetch('REDIS_URL'), namespace: 'telegram_support_bot' }
endUse keyed configuration when one app process serves multiple Telegram bots/chats:
TelegramSupportBot.configure(:default) do |config|
config.adapter_options = { token: ENV.fetch('TELEGRAM_DEFAULT_TOKEN') }
config.support_chat_id = ENV.fetch('TELEGRAM_DEFAULT_SUPPORT_CHAT_ID')
end
TelegramSupportBot.configure(:partners) do |config|
config.adapter_options = { token: ENV.fetch('TELEGRAM_PARTNERS_TOKEN') }
config.support_chat_id = ENV.fetch('TELEGRAM_PARTNERS_SUPPORT_CHAT_ID')
end
# Route incoming webhook to the matching bot key:
TelegramSupportBot.process_update(update, bot: :partners)Backward compatibility is preserved:
TelegramSupportBot.configure { ... }configures:defaultTelegramSupportBot.process_update(update)processes with:default
Typical webhook routing in Rails:
# legacy/default bot
post '/v2/telegram/support' => 'api/v2/telegram#support'
# keyed bot
post '/v2/telegram/:bot_key/support' => 'api/v2/telegram#support'def support
update = JSON.parse(request.body.read)
bot_key = params[:bot_key].presence&.to_sym || :default
TelegramSupportBot.process_update(update, bot: bot_key)
head :ok
endWhen using Redis state store, non-default bot keys are namespaced automatically
(telegram_support_bot:<bot_key>:...) so mappings/profiles do not leak across bots.
- Interact with Users: Messages to your bot will be forwarded to the support chat, and replies in the chat will be sent back to the users.
TelegramSupportBot supports integration through adapters. Currently, telegram-bot
and telegram-bot-ruby are supported.
Configuration is pretty much the same for both gems:
TelegramSupportBot.configure do |config|
config.adapter = :telegram_bot
config.adapter_options = { token: 'YOUR_TELEGRAM_BOT_TOKEN' }
endTelegramSupportBot.configure do |config|
config.adapter = :telegram_bot_ruby
config.adapter_options = { token: 'YOUR_TELEGRAM_BOT_TOKEN' }
endBasically, just make sure you call TelegramSupportBot.process_update somewhere in you workflow
cycle and pass it a parsed json update received from Telegram servers.
If you're using the telegram-bot gem, set up a Rails controller to handle incoming webhook
requests. Here's an example of how you might implement such a controller:
class TelegramWebhooksController < ApplicationController
def webhook
update = JSON.parse(request.body.read)
TelegramSupportBot.process_update(update)
head :ok
end
endMake sure to configure your routes to direct webhook callbacks to this controller action.
For those utilizing telegram-bot-ruby, you can set up a simple listener loop to process incoming messages. This approach is more suited for polling rather than webhooks: require 'telegram/bot'
token = 'YOUR_TELEGRAM_BOT_TOKEN'
Telegram::Bot::Client.run(token) do |bot|
bot.listen do |message|
TelegramSupportBot.process_update(update.to_h)
end
endImplement custom adapters by inheriting from TelegramSupportBot::Adapter::Base and defining
message sending and forwarding methods.
If you want support agents to identify users quickly in your CRM, you can request phone sharing once:
TelegramSupportBot.configure do |config|
config.request_contact_on_start = true
config.require_contact_for_support = false
config.contact_request_message = 'Please share your phone number so we can identify your account.'
config.contact_received_message = 'Thanks! We have saved your phone number.'
config.on_contact_received = ->(profile) do
# profile keys:
# :chat_id, :user_id, :phone_number, :first_name, :last_name, :username, :language_code
UserIdentitySync.call(profile)
end
endIf you set require_contact_for_support = true, the bot will ask for contact and will not forward
other user messages until contact is shared.
Support replies are routed by internal message mapping, so users do not need to change Telegram forwarding privacy settings to receive replies.
You can handle user-chat commands in your app before they are forwarded to support:
TelegramSupportBot.configure do |config|
config.on_user_command = lambda do |command:, args:, chat_id:, message:, bot_username: nil|
case command
when '/help'
TelegramSupportBot.adapter.send_message(chat_id: chat_id, text: 'How can we help?')
true
else
false
end
end
endBehavior:
- Triggered only for user-chat commands that start with
/and are not/start. - Receives
command(normalized to lowercase),bot_username(if present), andargs(text after command). - Return
trueto stop forwarding to support chat; returnfalse/nilto keep default forwarding. /startcan be forwarded once per user to support chat whenforward_start_to_support = true.
By default, runtime state is stored in-memory (state_store = :memory). This is fine for local
development or a single process.
For Kubernetes / multiple pods, configure Redis so message mappings, reaction state, and user profiles are shared:
TelegramSupportBot.configure do |config|
config.state_store = :redis
config.state_store_options = {
url: ENV.fetch('REDIS_URL'),
namespace: 'telegram_support_bot'
}
# Optional TTL tuning:
# config.mapping_ttl_seconds = 30 * 24 * 60 * 60
# config.reaction_count_ttl_seconds = 7 * 24 * 60 * 60
# config.user_profile_ttl_seconds = nil
# config.processed_update_ttl_seconds = 24 * 60 * 60
end- Run
bin/setupto install dependencies. - Use
rake specfor tests andbin/consolefor an interactive prompt. - To install locally, use
bundle exec rake install. - For releases, update
lib/telegram_support_bot/version.rbandCHANGELOG.md, then runbundle exec rake release.
You can run the bot locally without a Rails app by using the included script:
Prerequisites:
- Add the bot as an administrator in the support chat if you want support-side reactions to be delivered as updates.
- Bots can set only one reaction per message via Bot API, so only one mirrored reaction is applied when multiple are present.
- Export required environment variables:
export TELEGRAM_BOT_TOKEN=your_bot_token
export SUPPORT_CHAT_ID=your_support_chat_id
# optional; defaults to telegram_bot
export TSB_ADAPTER=telegram_bot
# optional; used by telegram_bot adapter
export TELEGRAM_BOT_USERNAME=your_bot_username- Disable webhook mode for that bot token (polling and webhooks cannot be used together):
curl -s "https://api.telegram.org/bot$TELEGRAM_BOT_TOKEN/deleteWebhook" > /dev/null- Start the local poller:
bundle exec ruby script/dev_poll.rb- In Telegram, verify:
- user message is forwarded to support chat
- support reply is sent back to user
- reactions are mirrored in both directions
If you want to test with telegram_bot_ruby adapter, set TSB_ADAPTER=telegram_bot_ruby and add
the telegram-bot-ruby gem in your environment.
After polling tests, set your webhook again:
curl -X POST "https://api.telegram.org/bot$TELEGRAM_BOT_TOKEN/setWebhook" \
-H "Content-Type: application/json" \
-d '{"url":"https://YOUR_PUBLIC_HOST/telegram/webhook","allowed_updates":["message","message_reaction","message_reaction_count","my_chat_member"]}'Contributions are welcome via GitHub, adhering to the code of conduct.
Available under the MIT License.
Follow the project's code of conduct.