1
0
зеркало из https://github.com/glebtv/telegram-bot.git synced 2026-09-03 17:55:52 +03:00

Сравнить коммиты

..

16 Коммитов

Автор SHA1 Сообщение Дата
Max Melentiev
995cde5607 v0.8.0 2016-06-02 21:36:05 +03:00
Max Melentiev
9ba5a817cd Fixed doubled instrumentation for reply_with 2016-06-02 21:19:27 +03:00
Max Melentiev
0205891985 Controller#respond_with to reply without reply_to_message_id 2016-06-02 21:07:15 +03:00
printercu
7393b1a1f3 Merge pull request #7 from telegram-bot-rb/rails5
Rails5 compatibility
2016-06-02 20:34:09 +03:00
Max Melentiev
43b519c5e8 fixed controller's callbacks for rails5 2016-06-02 20:30:35 +03:00
Max Melentiev
93ff9851f6 Add rails 5 to travis matrix 2016-06-02 19:48:19 +03:00
Max Melentiev
7c1f1b5b63 Middleware is rails5-compatible 2016-06-02 19:38:29 +03:00
printercu
028849a617 Merge pull request #5 from dreyks/reply_to_message_id
Fix: reply_with sets reply_to_message_id instead of reply_to_message
2016-06-01 23:22:32 +03:00
Roman Usherenko
ba1b3c0974 fix reply_to_message_id 2016-06-01 15:18:29 +03:00
Max Melentiev
f61cc1e536 v0.7.4 2016-05-31 17:44:24 +03:00
printercu
2f7ff9d50e Merge pull request #4 from dreyks/rails5
Rails5 compatibility
2016-05-31 17:34:31 +03:00
Roman Usherenko
aca35a1934 Rails5 compatibility 2016-05-31 17:12:36 +03:00
Max Melentiev
5bf98b419b v0.7.3 2016-05-31 11:49:54 +03:00
Max Melentiev
8077ef9bcf Fixed issues with poller in production. Fixes #3 2016-05-31 11:46:58 +03:00
Max Melentiev
5fef6fb43a v0.7.2 2016-05-31 11:02:55 +03:00
Max Melentiev
07be01c07d Bot API 2.1 2016-05-31 11:01:00 +03:00
18 изменённых файлов: 175 добавлений и 71 удалений

Просмотреть файл

@@ -2,5 +2,8 @@ language: ruby
cache: bundler cache: bundler
rvm: rvm:
- 2.2.3 - 2.2.3
env:
- RAILS=4
- RAILS=5
notifications: notifications:
email: false email: false

Просмотреть файл

@@ -1,4 +1,23 @@
# 0.7.1 # 0.8.0
- Fixed `#reply_with`, now it sets `reply_to_message_id` as it's supposed to.
Added `#respond_with` which works the same way, but doesn't set `reply_to_message_id`.
Please, replace all occurrences of `reply_with` to `respond_with` to
keep it working the old way.
- Fixes for Rails 5:
- Controller callbacks
- Middleware
- Setup travis builds
# 0.7.4
- Rails 5 support by @dreyks (#4).
# 0.7.3
- Fixed issues with poller in production (#3)
# 0.7.2
- Bot API 2.1 - Bot API 2.1
- Fixed possible crashes when payload type is not supported. - Fixed possible crashes when payload type is not supported.

Просмотреть файл

@@ -1,6 +1,13 @@
source 'https://rubygems.org' source 'https://rubygems.org'
gemspec gemspec
case ENV['RAILS']
when '5'
gem 'actionpack', '5.0.0.rc1'
when '4'
gem 'actionpack', '~> 4.2'
end
group :development do group :development do
gem 'sdoc', '~> 0.4.1' gem 'sdoc', '~> 0.4.1'
gem 'pry', '~> 0.10.1' gem 'pry', '~> 0.10.1'

Просмотреть файл

@@ -131,9 +131,10 @@ class Telegram::WebhookController < Telegram::Bot::UpdatesController
# There are `chat` & `from` shortcut methods. # There are `chat` & `from` shortcut methods.
response = from ? "Hello #{from['username']}!" : 'Hi there!' response = from ? "Hello #{from['username']}!" : 'Hi there!'
# There is `reply_with` helper to set basic fields # There is `respond_with` helper to set `chat_id` from received message:
# like `reply_to_message` & `chat_id`. respond_with :message, text: response
reply_with :message, text: response # `reply_with` also sets `reply_to_message_id`:
reply_with :photo, photo: File.open('party.jpg')
end end
private private
@@ -188,7 +189,7 @@ class Telegram::WebhookController < Telegram::Bot::UpdatesController
end end
def read def read
reply_with :message, text: session[:text] respond_with :message, text: session[:text]
end end
private private
@@ -214,23 +215,23 @@ class Telegram::WebhookController < Telegram::Bot::UpdatesController
def rename(*) def rename(*)
# set context for the next message # set context for the next message
save_context :rename save_context :rename
reply_with :message, text: 'What name do you like?' respond_with :message, text: 'What name do you like?'
end end
# register context handlers to handle this context # register context handlers to handle this context
context_handler :rename do |*words| context_handler :rename do |*words|
update_name words[0] update_name words[0]
reply_with :message, text: 'Renamed!' respond_with :message, text: 'Renamed!'
end end
# You can do it in other way: # You can do it in other way:
def rename(name = nil, *) def rename(name = nil, *)
if name if name
update_name name update_name name
reply_with :message, text: 'Renamed!' respond_with :message, text: 'Renamed!'
else else
save_context :rename save_context :rename
reply_with :message, text: 'What name do you like?' respond_with :message, text: 'What name do you like?'
end end
end end
@@ -383,6 +384,16 @@ 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, 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](https://rubygems.org). push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
### Different Rails versions
To setup development for specific major Rails version use:
```
RAILS=5 bundle install
# or
RAILS=5 bundle update
```
## Contributing ## Contributing
Bug reports and pull requests are welcome on GitHub at https://github.com/telegram-bot-rb/telegram-bot. Bug reports and pull requests are welcome on GitHub at https://github.com/telegram-bot-rb/telegram-bot.

Просмотреть файл

@@ -1,9 +1,14 @@
namespace :telegram do namespace :telegram do
namespace :bot do namespace :bot do
desc 'Run poller' desc 'Run poller. It broadcasts Rails.logger to STDOUT in dev like `rails s` do. ' \
task poller: :environment do 'Use LOG_TO_STDOUT to enable/disable broadcasting.'
console = ActiveSupport::Logger.new(STDERR) task :poller do
Rails.logger.extend ActiveSupport::Logger.broadcast console ENV['BOT_POLLER_MODE'] = 'true'
Rake::Task['environment'].invoke
if ENV.fetch('LOG_TO_STDOUT') { Rails.env.development? }.present?
console = ActiveSupport::Logger.new(STDERR)
Rails.logger.extend ActiveSupport::Logger.broadcast console
end
Telegram::Bot::UpdatesPoller.start(ENV['BOT'].try!(:to_sym) || :default) Telegram::Bot::UpdatesPoller.start(ENV['BOT'].try!(:to_sym) || :default)
end end

Просмотреть файл

@@ -71,11 +71,16 @@ module Telegram
answerCallbackQuery answerCallbackQuery
answerInlineQuery answerInlineQuery
forwardMessage forwardMessage
getChat
getChatAdministrators
getChatMember
getChatMembersCount
getFile getFile
getMe getMe
getUpdates getUpdates
getUserProfilePhotos getUserProfilePhotos
kickChatMember kickChatMember
leaveChat
sendAudio sendAudio
sendChatAction sendChatAction
sendContact sendContact

Просмотреть файл

@@ -14,9 +14,14 @@ module Telegram
# It just tells routes helpers whether to add routed bots to # It just tells routes helpers whether to add routed bots to
# Bot::UpdatesPoller, so their config will be available by bot key in # Bot::UpdatesPoller, so their config will be available by bot key in
# Bot::UpdatesPoller.start. # Bot::UpdatesPoller.start.
#
# It's enabled by default in Rails dev environment and `rake telegram:bot:poller`
# task. Use `BOT_POLLER_MODE=true` envvar to set it manually.
def bot_poller_mode? def bot_poller_mode?
return @bot_poller_mode if defined?(@bot_poller_mode) return @bot_poller_mode if defined?(@bot_poller_mode)
Rails.env.development? if defined?(Rails) @bot_poller_mode = ENV.fetch('BOT_POLLER_MODE') do
Rails.env.development? if defined?(Rails)
end
end end
# Hash of bots made with bots_config. # Hash of bots made with bots_config.

Просмотреть файл

@@ -1,6 +1,8 @@
require 'active_support/concern' require 'active_support/concern'
require 'active_support/core_ext/hash/indifferent_access'
require 'active_support/json'
require 'action_dispatch/http/mime_type' require 'action_dispatch/http/mime_type'
require 'action_dispatch/middleware/params_parser' require 'action_dispatch/http/request'
module Telegram module Telegram
module Bot module Bot
@@ -13,7 +15,8 @@ module Telegram
end end
def call(env) def call(env)
update = env['action_dispatch.request.request_parameters'] request = ActionDispatch::Request.new(env)
update = request.request_parameters
controller.dispatch(bot, update) controller.dispatch(bot, update)
[200, {}, ['']] [200, {}, ['']]
end end

Просмотреть файл

@@ -21,7 +21,7 @@ module Telegram
# end # end
# #
# def help(*) # def help(*)
# reply_with :message, text: # respond_with :message, text:
# end # end
# #
# To process plain text messages (without commands) or other updates just # To process plain text messages (without commands) or other updates just
@@ -29,7 +29,7 @@ module Telegram
# as an argument. # as an argument.
# #
# def message(message) # def message(message)
# reply_with :message, text: "Echo: #{message['text']}" # respond_with :message, text: "Echo: #{message['text']}"
# end # end
# #
# def inline_query(query) # def inline_query(query)
@@ -63,7 +63,7 @@ module Telegram
include AbstractController::Callbacks include AbstractController::Callbacks
# Redefine callbacks with default terminator. # Redefine callbacks with default terminator.
if ActiveSupport.gem_version >= Gem::Version.new('5') if ActiveSupport::VERSION::MAJOR >= 5
define_callbacks :process_action, define_callbacks :process_action,
skip_after_callbacks_if_terminated: true skip_after_callbacks_if_terminated: true
else else

Просмотреть файл

@@ -6,7 +6,7 @@ module Telegram
module Instrumentation module Instrumentation
class << self class << self
def prepended(base) def prepended(base)
base.config_accessor :logger base.send :config_accessor, :logger
base.extend ClassMethods base.extend ClassMethods
end end
@@ -35,13 +35,13 @@ module Telegram
end end
end end
def reply_with(type, *) def respond_with(type, *)
Instrumentation.instrument(:reply_with, type: type) { super } Instrumentation.instrument(:respond_with, type: type) { super }
end end
%i(answer_callback_query answer_inline_query).each do |type| %i(answer_callback_query answer_inline_query).each do |type|
define_method(type) do |*args| define_method(type) do |*args|
Instrumentation.instrument(:reply_with, type: type) { super(*args) } Instrumentation.instrument(:respond_with, type: type) { super(*args) }
end end
end end

Просмотреть файл

@@ -22,8 +22,8 @@ module Telegram
end end
end end
def reply_with(event) def respond_with(event)
info { "Replied with #{event.payload[:type]}" } info { "Responded with #{event.payload[:type]}" }
end end
def halted_callback(event) def halted_callback(event)

Просмотреть файл

@@ -2,21 +2,23 @@ module Telegram
module Bot module Bot
class UpdatesController class UpdatesController
module ReplyHelpers module ReplyHelpers
# Helper to call bot's `send_#{type}` method with already set `chat_id` and # Helper to call bot's `send_#{type}` method with already set `chat_id`:
# `reply_to_message_id`:
# #
# reply_with :message, text: 'Hello!' # respond_with :message, text: 'Hello!'
# reply_with :message, text: '__Hello!__', parse_mode: :Markdown # respond_with :message, text: '__Hello!__', parse_mode: :Markdown
# reply_with :photo, photo: File.open(photo_to_send), caption: "It's incredible!" # respond_with :photo, photo: File.open(photo_to_send), caption: "It's incredible!"
def reply_with(type, params) def respond_with(type, params)
method = "send_#{type}"
chat = self.chat chat = self.chat
chat_id = chat && chat['id'] or raise 'Can not respond_with when chat is not present'
bot.public_send("send_#{type}", params.merge(chat_id: chat_id))
end
# Same as respond_with but also sets `reply_to_message_id`.
def reply_with(type, params)
payload = self.payload payload = self.payload
params = params.merge( message_id = payload && payload['message_id']
chat_id: (chat && chat['id'] or raise 'Can not reply_with when chat is not present'), params = params.merge(reply_to_message_id: message_id) if message_id
reply_to_message: payload && payload['message_id'], respond_with(type, params)
)
bot.public_send(method, params)
end end
# Same as reply_with, but for inline queries. # Same as reply_with, but for inline queries.

Просмотреть файл

@@ -77,11 +77,25 @@ module Telegram
def reload! def reload!
return yield unless reload return yield unless reload
ActionDispatch::Reloader.prepare! reloading_code do
if controller.is_a?(Class) && controller.name if controller.is_a?(Class) && controller.name
@controller = Object.const_get(controller.name) @controller = Object.const_get(controller.name)
end
yield
end
end
if defined?(Rails) && Rails.application.respond_to?(:reloader)
def reloading_code
Rails.application.reloader.wrap do
yield
end
end
else
def reloading_code
ActionDispatch::Reloader.prepare!
yield.tap { ActionDispatch::Reloader.cleanup! }
end end
yield.tap { ActionDispatch::Reloader.cleanup! }
end end
end end
end end

Просмотреть файл

@@ -1,6 +1,6 @@
module Telegram module Telegram
module Bot module Bot
VERSION = '0.7.1'.freeze VERSION = '0.8.0'.freeze
def self.gem_version def self.gem_version
Gem::Version.new VERSION Gem::Version.new VERSION

Просмотреть файл

@@ -1,3 +1,5 @@
require 'rack/mock'
RSpec.describe Telegram::Bot::Middleware do RSpec.describe Telegram::Bot::Middleware do
let(:instance) { described_class.new bot, controller } let(:instance) { described_class.new bot, controller }
let(:bot) { double(:bot) } let(:bot) { double(:bot) }
@@ -6,10 +8,25 @@ RSpec.describe Telegram::Bot::Middleware do
describe '#call' do describe '#call' do
subject { instance.call(env) } subject { instance.call(env) }
let(:env) { {'action_dispatch.request.request_parameters' => json_body} } let(:env) { {'action_dispatch.request.request_parameters' => json_body} }
let(:json_body) { double(:json_body) } let(:update) { {'message' => {'id' => 1}} }
let(:env) do
Rack::MockRequest.env_for('/',
method: :post,
input: JSON.dump(update),
'CONTENT_TYPE' => 'application/json',
)
end
require 'action_pack/version'
if ActionPack::VERSION::MAJOR < 5
# Before Rails 5, params are parsed in middleware.
# In Rails 5, they are parsed in Request#request_parameters.
require 'action_dispatch/middleware/params_parser'
let(:instance) { ActionDispatch::ParamsParser.new(super()) }
end
it 'calls dispatch on controller' do it 'calls dispatch on controller' do
expect(controller).to receive(:dispatch).with(bot, json_body) expect(controller).to receive(:dispatch).with(bot, update)
subject subject
end end

Просмотреть файл

@@ -1,36 +1,49 @@
RSpec.describe Telegram::Bot::UpdatesController do RSpec.describe Telegram::Bot::UpdatesController do
include_context 'telegram/bot/updates_controller' include_context 'telegram/bot/updates_controller'
let(:params) { {arg: 1, 'other_arg' => 2} }
let(:respond_type) { :photo }
let(:result) { double(:result) }
let(:payload_type) { :message }
let(:payload) { {message_id: double(:message_id)} }
let(:chat) { {'id' => double(:chat_id)} }
describe '#reply_with' do shared_examples 'missing chat' do
subject { controller.reply_with type, params }
let(:params) { {arg: 1, 'other_arg' => 2} }
let(:type) { :photo }
let(:result) { double(:result) }
let(:payload_type) { :message }
let(:payload) { {message_id: double(:message_id)} }
let(:chat) { {'id' => double(:chat_id)} }
it 'sets chat_id & reply_to_message' do
expect(controller).to receive(:chat) { chat }
expect(bot).to receive("send_#{type}").with(params.merge(
chat_id: chat['id'],
reply_to_message: payload[:message_id],
)) { result }
should eq result
end
context 'when chat is missing' do context 'when chat is missing' do
let(:payload_type) { :some_type } let(:payload_type) { :some_type }
it { expect { subject }.to raise_error(/chat/) } it { expect { subject }.to raise_error(/chat/) }
end end
end
describe '#respond_with' do
subject { controller.respond_with respond_type, params }
include_examples 'missing chat'
it 'sets chat_id & reply_to_message_id' do
expect(controller).to receive(:chat) { chat }
expect(bot).to receive("send_#{respond_type}").
with(params.merge(chat_id: chat['id'])) { result }
should eq result
end
end
describe '#reply_with' do
subject { controller.reply_with respond_type, params }
include_examples 'missing chat'
it 'sets chat_id & reply_to_message_id' do
expect(controller).to receive(:chat) { chat }
expect(bot).to receive("send_#{respond_type}").with(params.merge(
chat_id: chat['id'],
reply_to_message_id: payload[:message_id],
)) { result }
should eq result
end
context 'when update is not set' do context 'when update is not set' do
let(:update) { {chat: chat} } let(:update) { {chat: chat} }
it 'sets chat_id & reply_to_message' do it 'sets chat_id' do
expect(bot).to receive("send_#{type}").with(params.merge( expect(bot).to receive("send_#{respond_type}").
chat_id: chat['id'], with(params.merge(chat_id: chat['id'])) { result }
reply_to_message: nil,
)) { result }
should eq result should eq result
end end
end end

Просмотреть файл

@@ -225,12 +225,12 @@ RSpec.describe Telegram::Bot::UpdatesController do
it { should change(controller, :acted).to true } it { should change(controller, :acted).to true }
its(:call) { should eq [nil, nil, args] } its(:call) { should eq [nil, nil, args] }
context 'when callback returns false' do context 'when callback halts chain' do
before do before do
controller_class.prepend(Module.new do controller_class.prepend(Module.new do
def hook def hook
super super
false ActiveSupport::VERSION::MAJOR >= 5 ? throw(:abort) : false
end end
end) end)
end end

Просмотреть файл

@@ -20,8 +20,8 @@ Gem::Specification.new do |spec|
spec.required_ruby_version = '~> 2.0' spec.required_ruby_version = '~> 2.0'
spec.add_dependency 'activesupport', '~> 4.0' spec.add_dependency 'activesupport', '>= 4.0', '< 5.1'
spec.add_dependency 'actionpack', '~> 4.0' spec.add_dependency 'actionpack', '>= 4.0', '< 5.1'
spec.add_dependency 'httpclient', '~> 2.7' spec.add_dependency 'httpclient', '~> 2.7'
spec.add_development_dependency 'bundler', '~> 1.11' spec.add_development_dependency 'bundler', '~> 1.11'
spec.add_development_dependency 'rake', '~> 10.0' spec.add_development_dependency 'rake', '~> 10.0'