diff --git a/.rubocop.yml b/.rubocop.yml index f4d1051..53ce884 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -40,6 +40,7 @@ Style/IfUnlessModifier: {Enabled: false} # Consistent to other definitions. Style/EmptyMethod: {EnforcedStyle: expanded} +Style/Lambda: {EnforcedStyle: literal} Style/ModuleFunction: {Enabled: false} Style/NestedParenthesizedCalls: {Enabled: false} Style/SignalException: {EnforcedStyle: only_raise} diff --git a/CHANGELOG.md b/CHANGELOG.md index 926fccc..bb175b4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ - Add `:path` option to `telegram_webhook` route helper. - __Breaking change!__ Default route is generated using hashed bot token. Please reconfigure webhook after update (`rake telegram:bot:set_webhook`). +- Update to Bot API 5.0, add rake tasks for `deleteWebhook`, `close` & `logOut`. # 0.14.4 diff --git a/bin/fetch-telegram-methods b/bin/fetch-telegram-methods index 0092284..193d19a 100755 --- a/bin/fetch-telegram-methods +++ b/bin/fetch-telegram-methods @@ -25,7 +25,7 @@ method_list = headers. map { |g| g.reject { |x| x.match?(NOT_METHOD_REGEXP) } }. reject(&:empty?) -api_version = doc.text.match(/^(Bot API ([\d\.]+))\.?$/) +api_version = doc.text.match(/^(?:Introducing )?(Bot API ([\d\.]+))\.?$/) result = ['# Generated with bin/fetch-telegram-methods'] result << "# #{api_version[1]}" if api_version diff --git a/lib/tasks/telegram-bot.rake b/lib/tasks/telegram-bot.rake index 2ee40e8..01c5cd9 100644 --- a/lib/tasks/telegram-bot.rake +++ b/lib/tasks/telegram-bot.rake @@ -14,15 +14,22 @@ namespace :telegram do desc 'Set webhook urls for all bots' task set_webhook: :environment do - routes = Rails.application.routes.url_helpers - cert_file = ENV['CERT'] - cert = File.open(cert_file) if cert_file - Telegram.bots.each do |key, bot| - route_name = Telegram::Bot::RoutesHelper.route_name_for_bot(bot) - url = routes.send("#{route_name}_url") - puts "Setting webhook for #{key}..." - bot.async(false) { bot.set_webhook(url: url, certificate: cert) } - end + Telegram::Bot::Tasks.set_webhook + end + + desc 'Delete webhooks for all or specific BOT' + task :delete_webhook do + Telegram::Bot::Tasks.delete_webhook + end + + desc 'Perform logOut command for all or specific BOT' + task :log_out do + Telegram::Bot::Tasks.log_out + end + + desc 'Perform `close` command for all or specific BOT' + task :close do + Telegram::Bot::Tasks.close end end end diff --git a/lib/telegram/bot.rb b/lib/telegram/bot.rb index c3792e0..f6c1ffc 100644 --- a/lib/telegram/bot.rb +++ b/lib/telegram/bot.rb @@ -28,6 +28,7 @@ module Telegram autoload :Initializers, 'telegram/bot/initializers' autoload :Middleware, 'telegram/bot/middleware' autoload :RSpec, 'telegram/bot/rspec' + autoload :Tasks, 'telegram/bot/tasks' autoload :UpdatesController, 'telegram/bot/updates_controller' autoload :UpdatesPoller, 'telegram/bot/updates_poller' end diff --git a/lib/telegram/bot/client/api_methods.txt b/lib/telegram/bot/client/api_methods.txt index 24b1ffc..eee297a 100644 --- a/lib/telegram/bot/client/api_methods.txt +++ b/lib/telegram/bot/client/api_methods.txt @@ -1,5 +1,5 @@ # Generated with bin/fetch-telegram-methods -# Bot API 4.7 +# Bot API 5.0 getUpdates setWebhook @@ -7,8 +7,11 @@ deleteWebhook getWebhookInfo getMe +logOut +close sendMessage forwardMessage +copyMessage sendPhoto sendAudio sendDocument @@ -40,6 +43,7 @@ setChatTitle setChatDescription pinChatMessage unpinChatMessage +unpinAllChatMessages leaveChat getChat getChatAdministrators diff --git a/lib/telegram/bot/tasks.rb b/lib/telegram/bot/tasks.rb new file mode 100644 index 0000000..2bd1787 --- /dev/null +++ b/lib/telegram/bot/tasks.rb @@ -0,0 +1,63 @@ +# frozen_string_literal: true + +module Telegram + module Bot + module Tasks + extend self + + def set_webhook + routes = Rails.application.routes.url_helpers + cert_file = ENV['CERT'] + cert = File.open(cert_file) if cert_file + each_bot do |key, bot| + route_name = RoutesHelper.route_name_for_bot(bot) + url = routes.send("#{route_name}_url") + say("Setting webhook for #{key}...") + bot.set_webhook( + url: url, + certificate: cert, + ip_address: ENV['IP_ADDRESS'], + drop_pending_updates: drop_pending_updates, + ) + end + end + + def delete_webhook + each_bot do |key, bot| + say("Deleting webhook for #{key}...") + bot.delete_webhook(drop_pending_updates: drop_pending_updates) + end + end + + def log_out + each_bot do |key, bot| + say("Logging out #{key}...") + bot.log_out + end + end + + def close + each_bot do |key, bot| + say("Closing #{key}...") + bot.close + end + end + + private + + def say(text) + puts(text) unless Rails.env.test? # rubocop:disable Rails/Output + end + + def each_bot(&block) + id = ENV['BOT'].try!(:to_sym) + bots = id ? {id => Client.by_id(id)} : Telegram.bots + bots.each { |key, bot| bot.async(false) { block[key, bot] } } + end + + def drop_pending_updates + ENV['DROP_PENDING_UPDATES'].try!(:downcase) == 'true' + end + end + end +end diff --git a/spec/integration/tasks_spec.rb b/spec/integration/tasks_spec.rb new file mode 100644 index 0000000..39b2d35 --- /dev/null +++ b/spec/integration/tasks_spec.rb @@ -0,0 +1,74 @@ +# frozen_string_literal: true + +require 'integration_helper' + +RSpec.describe Telegram::Bot::Tasks, type: :request do + include Telegram::Bot::RSpec::ClientMatchers + + def stub_env(new_values) + new_values.stringify_keys! + old_values = ENV.to_h.slice(new_values.keys) + new_values.each { |k, v| ENV[k] = v.to_s } + yield + ensure + new_values.each_key { |k| ENV[k] = old_values[k] } + end + + shared_examples 'uses BOT envar' do |bot_matcher| + it 'runs for all bots by default' do + matcher = Telegram.bots.values.map { |x| instance_exec(x, &bot_matcher) }.reduce(&:and) + expect(subject).to matcher + end + + context 'when BOT specified' do + around { |ex| stub_env(BOT: :other) { ex.run } } + + it 'runs for this bot only' do + expect(subject).to instance_exec(Telegram.bots[:other], &bot_matcher) + end + end + end + + describe '#log_out' do + subject { -> { described_class.log_out } } + include_examples 'uses BOT envar', ->(bot) { make_telegram_request(bot, :logOut) } + end + + describe '#close' do + subject { -> { described_class.close } } + include_examples 'uses BOT envar', ->(bot) { make_telegram_request(bot, :close) } + end + + describe '#set_webhook' do + subject { -> { described_class.set_webhook } } + include_examples 'uses BOT envar', ->(bot) { make_telegram_request(bot, :setWebhook) } + + context 'with options in env' do + around do |ex| + stub_env(IP_ADDRESS: '1.2.3.4', DROP_PENDING_UPDATES: 'TrUe') do + ex.run + end + end + include_examples 'uses BOT envar', ->(bot) { + make_telegram_request(bot, :setWebhook).with(hash_including( + ip_address: '1.2.3.4', + drop_pending_updates: true, + )) + } + end + end + + describe '#delete_webhook' do + subject { -> { described_class.delete_webhook } } + include_examples 'uses BOT envar', ->(bot) { make_telegram_request(bot, :deleteWebhook) } + + context 'with options in env' do + around { |ex| stub_env(DROP_PENDING_UPDATES: 'TrUe') { ex.run } } + include_examples 'uses BOT envar', ->(bot) { + make_telegram_request(bot, :deleteWebhook).with(hash_including( + drop_pending_updates: true, + )) + } + end + end +end diff --git a/spec/integration_helper.rb b/spec/integration_helper.rb index dcd91f5..e876124 100644 --- a/spec/integration_helper.rb +++ b/spec/integration_helper.rb @@ -14,6 +14,7 @@ class TestApplication < Rails::Application config.eager_load = false config.log_level = :debug config.action_dispatch.show_exceptions = false + routes.default_url_options = {host: 'test.rpsec'} telegram_config = { bot: 'default_token',