電報用ボット。 レールウェイ

この投稿は、Telegram向けのボットを作成するためのTelegram -Botライブラリに関するものです。 作成中の主な目標には、ボットの開発、デバッグ、テストの利便性、インターフェイスを最小限に抑えながら拡張可能で、Railsアプリケーションとの統合が容易であり、ボットを作成するために必要なツールを提供することがあります。 含まれるものは次のとおりです。





面白い? インストールするには、 Gemfile



telegram-bot



を追加し、詳細をカットします。



ボットAPIのクライアント



クライアントの作成は簡単です: Telegram::Bot::Client.new(token, username)



username



値はオプションであり、呼び出し( /cmd@BotName



)およびKey-Valueストアのセッションキープレフィックス内のコマンドを解析するために使用されます。



基本的なクライアントメソッドはrequest(path_suffix, body)



。ドキュメントのすべてのチームには、Rubyスタイルのショートカットがあります-アンダースコア( .send_message(body)



answer_inline_query(body)



)。 これらのメソッドはすべて、目的のURLに渡されたパラメーターを使用してPOSTを実行するだけです。 body



ファイルはmultipart/form-data



で自動的に転送され、添付のハッシュはドキュメントで必要とされるようにjsonでエンコードされます。



 bot.request(:getMe) or bot.get_me bot.request(:getupdates, offset: 1) or bot.get_updates(offset: 1) bot.send_message chat_id: chat_id, text: 'Test' bot.send_photo chat_id: chat_id, photo: File.open(photo_filename)
      
      





すぐに使用できるように、クライアントは各リクエストに対して通常の分散jsonを返します。 telegram- telegram-bot-types



を使用して、出力でvirtus-modelsを取得できます。



 #   Gemfile: gem 'telegram-bot-types', '~> xxx' #  typecasting   : Telegram::Bot::Client.typed_response! #    : bot.extend Telegram::Bot::Client::TypedResponse bot.get_me.class # => Telegram::Bot::Types::User
      
      





カスタマイズ



gemは、アプリケーションに共通のクライアントをセットアップしてアクセスするためのメソッドをTelegram



モジュールに追加します(これらはスレッドセーフであり、複数のスレッドで問題はありません)。



 #   Telegram.bots_config = { #     default: 'bot_token', #    username chat: { token: 'other_token', username } } #     : Telegram.bots[:chat].send_message(params) Telegram.bots[:default].send_message(params) #  :default    (,   ): Telegram.bot.get_me
      
      





Railsアプリケーションの場合、 bots_config



を手動で設定せずに実行できます。設定はbots_config



から読み取られsecrets.yml







 development: telegram: bots: chat: TOKEN_1 default: token: TOKEN_2 username: ChatBot #     bots.default bot: token: TOKEN username: SomeBot
      
      





コントローラー



更新を処理するために、gemにはベースコントローラークラスがあります。 ActionController



と同様に、すべてのパブリックメソッドはコマンドを処理するためのアクションメソッドとして使用されます。 つまり、メッセージ/cmd arg 1 2



が到着すると、 cmd('arg', '1', '2')



メソッドcmd('arg', '1', '2')



が呼び出されます(定義されていてパブリックの場合)。 ActionControllerとは異なり、サポートされていないコマンドが到着した場合、ActionMissingエラーなしで単に無視されます。



コントローラーは参照付きのコマンドを処理できます。 これが発生すると、コマンドの名前username



ボットのusername



と比較されusername



。 一致する場合、コマンドが実行されます。一致しない場合、メッセージはプレーンテキストとして処理されます。



他の更新(メッセージではない)を処理するには、更新タイプの名前からpublicメソッドを定義する必要もあります(現在、3つのオプションが利用可能です: `message、inline_query、selected_inline_result ')。 これらのメソッドは、更新から対応するオブジェクトを引数として受け取ります。



通知に応答するために、受信した更新から受信者およびその他のフィールドを公開するreply_with(type, params)



およびanswer_inline_query(results, params)



ヘルパーがあります。



 class TelegramWebhookController < Telegram::Bot::UpdatesController def message(message) reply_with text: "Echo: #{message['text']}" end def start(*) #    chat  from: reply_with text: "Hello #{from['username']}!" if from #        payload: log { "Started at: #{payload['date']}" } end #       splat-  #  -,       #    ,     . def help(cmd = nil, *) message = if cmd help_for_cmd?(cmd) ? t(".cmd.#{cmd}") : t('.no_help') else t('.help') end reply_with text: message end end
      
      





ほとんどの場合、ボットはメッセージ間のチャットの状態を記憶する必要があります。 これを行うには、コントローラーでセッションを使用できます。 このインターフェースはActionControllerのセッションインターフェースに似ていますが、違いは保存方法です。 任意のActiveSupport ::キャッシュ互換ストレージ( redis-activesupport



など)をアダプターとして使用できます。



デフォルトでは、この値はセッションIDとして使用されます(メソッドをオーバーライドすることで変更できます)。



 def session_key "#{bot.username}:#{from ? "from:#{from['id']}" : "chat:#{chat['id']}"}" end
      
      





セッションを使用して、メッセージコンテキストを実装できます-複数のメッセージで送信されるコマンドのサポート:ユーザーは引数なしでコマンドを送信し、ボットは期待する引数を指定し、ユーザーは次のメッセージでそれらを送信します(たとえば、BotFatherが行うように)。 このような機能は、 Telegram::Bot::UpdatesController::MessageContext



利用できTelegram::Bot::UpdatesController::MessageContext







 class TelegramWebhookController < Telegram::Bot::UpdatesController include Telegram::Bot::UpdatesController::MessageContext def rename(*) #     : save_context :rename reply_with :message, text: 'What name do you like?' end #     : context_handler :rename do |message| update_name message[:text] reply_with :message, text: 'Renamed!' end #   -.  rename,      #   . def rename(name = nil, *) if name update_name name reply_with :message, text: 'Renamed!' else #    ,   : save_context :rename reply_with :message, text: 'What name do you like?' end end #          ,    . #      ,   ,     #  '/rename %text%' context_handler :rename #    ,  : context_to_action! #              . end
      
      





アプリケーション統合



コントローラーはいくつかの方法で使用できます。



 #   : ControllerClass.dispatch(bot, update) #   ,  . controller = ControllerClass.new(bot, from: telegram_user, chat: telegram_chat) controller.process(:help, *args)
      
      





フックを処理するためのラックエンドポイントがあります。 Railsアプリケーションにはルートヘルパーがあります。ボットトークンがパスサフィックスとして使用されます。 アプリケーションで単一のボットを使用する場合は、次を追加します。



 # routes.rb telegram_webhooks Telegram::WebhookController
      
      





このヘルパーを使用すると、タスクを使用して結果のURLを使用して、ボットのsetWebhook



を設定できます。



 rake telegram:bot:set_webhook RAILS_ENV=production
      
      





テスト中



gemには、テストでAPIクライアントを置き換えるTelegram::Bot::ClientStub



があります。 クエリを実行する代わりに、 #requests



ハッシュに保存します。 作成されたすべてのクライアントをストールさせ、テスト実行中にTelegramにリクエストを送信しないようにするには、次のように記述できます。



 RSpec.configure do |config| # ... Telegram.reset_bots Telegram::Bot::ClientStub.stub_all! config.after { Telegram.bot.reset } # ... end
      
      





ActionControllerと同じ方法でコントローラーをテストするためのヘルパーがあります。



 require 'telegram/bot/updates_controller/rspec_helpers' RSpec.describe TelegramWebhookController do include_context 'telegram/bot/updates_controller' describe '#rename' do subject { -> { dispatch_message "/rename #{new_name}" } } let(:new_name) { 'new_name' } it { should change { resource.reload.name }.to(new_name) } end end
      
      





開発とデバッグ



ローカルデバッグの場合、更新ポーラーを実行できます。 これを行うには、おそらく別のボットを作成する必要があります。 rake telegram:bot:poller



rake telegram:bot:poller



を起動します。 更新の処理時にコードの更新が自動的にダウンロードされるため、プロセスを再起動する必要はありません。



ソースコードと詳細な説明はgithubで入手できます。



素晴らしい開発を!




All Articles