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

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

..

11 Коммитов

Автор SHA1 Сообщение Дата
Max Melentiev
b40e4b432d Merge pull request #198 from telegram-bot-rb/nested_files
Add support for editMessageMedia similar to sendMediaGroup
2023-01-14 13:18:38 +00:00
Max Melentiev
ef5ec81386 Add support for editMessageMedia similar to sendMediaGroup 2023-01-13 20:33:30 +00:00
Max Melentiev
7d8a19d3c8 Pass action parameter to RequestBodyFormatter 2022-03-13 21:39:55 +00:00
Max Melentiev
380f6686fc Update to Bot API 5.7 2022-03-12 19:37:53 +00:00
Max Melentiev
ea64230eab Merge pull request #168 from telegram-bot-rb/nested_files
Fix sending File objects in nested objects (ex., in sendMediaGroup)
2022-03-12 19:34:57 +00:00
Max Melentiev
5b9706ed47 Fix sending File objects in nested objects in sendMediaGroup 2022-03-12 19:33:17 +00:00
Max Melentiev
2d73d1c879 Merge pull request #174 from telegram-bot-rb/rails-7
Rails 7.0 support
2022-01-04 22:54:17 +00:00
Max Melentiev
88af1152cf Rails 7.0 support 2022-01-04 22:49:53 +00:00
Max Melentiev
586217585a Merge pull request #164 from KonstantinReido/patch-1
Fix typo in README.md
2021-08-20 12:36:46 +01:00
Konstantin Reido
f83bf92601 Fix typo in README.md 2021-08-20 11:26:00 +03:00
Max Melentiev
3049ced903 Fix tests 2021-06-26 21:25:43 +01:00
18 изменённых файлов: 212 добавлений и 44 удалений

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

@@ -1,3 +1,8 @@
appraise 'rails-70' do
gem 'actionpack', '~> 7.0.0'
gem 'railties', '~> 7.0.0'
end
appraise 'rails-61' do appraise 'rails-61' do
gem 'actionpack', '~> 6.1.0' gem 'actionpack', '~> 6.1.0'
gem 'railties', '~> 6.1.0' gem 'railties', '~> 6.1.0'

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

@@ -1,5 +1,15 @@
# Unreleased # Unreleased
# 0.15.7
- Add support for editMessageMedia similar to sendMediaGroup.
# 0.15.6
- Rails 7.0 support.
- Fix sending File objects in nested objects in sendMediaGroup.
- Update to Bot API 5.7
# 0.15.4 # 0.15.4
- Update to Bot API 5.3 - Update to Bot API 5.3

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

@@ -2,7 +2,7 @@
[![Gem Version](https://badge.fury.io/rb/telegram-bot.svg)](http://badge.fury.io/rb/telegram-bot) [![Gem Version](https://badge.fury.io/rb/telegram-bot.svg)](http://badge.fury.io/rb/telegram-bot)
[![Code Climate](https://codeclimate.com/github/telegram-bot-rb/telegram-bot/badges/gpa.svg)](https://codeclimate.com/github/telegram-bot-rb/telegram-bot) [![Code Climate](https://codeclimate.com/github/telegram-bot-rb/telegram-bot/badges/gpa.svg)](https://codeclimate.com/github/telegram-bot-rb/telegram-bot)
[![Build Status](https://travis-ci.com/telegram-bot-rb/telegram-bot.svg)](https://travis-ci.com/telegram-bot-rb/telegram-bot) [![Build Status](https://app.travis-ci.com/telegram-bot-rb/telegram-bot.svg)](https://app.travis-ci.com/github/telegram-bot-rb/telegram-bot)
Tools for developing Telegram bots. Best used with Rails, but can be used in Tools for developing Telegram bots. Best used with Rails, but can be used in
[standalone app](https://github.com/telegram-bot-rb/telegram-bot/wiki/Not-rails-application). [standalone app](https://github.com/telegram-bot-rb/telegram-bot/wiki/Not-rails-application).
@@ -539,7 +539,7 @@ end
There is a context for testing bot controller in the way similar to Rails controller tests. There is a context for testing bot controller in the way similar to Rails controller tests.
It's supposed to be a low-level alternative for integration tests. Among the differences is It's supposed to be a low-level alternative for integration tests. Among the differences is
that controller tests use a single controller instance for all dispatches in specific exaple, that controller tests use a single controller instance for all dispatches in specific example,
session is stubbed (does not use configured store engine), and update is not serialized session is stubbed (does not use configured store engine), and update is not serialized
so it also supports mocks. This can be useful for unit testing, but should not be used as so it also supports mocks. This can be useful for unit testing, but should not be used as
the default way to test the bot. the default way to test the bot.

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

@@ -10,7 +10,7 @@ group :development do
gem "pry", "~> 0.13.1" gem "pry", "~> 0.13.1"
gem "pry-byebug", "~> 3.9.0" gem "pry-byebug", "~> 3.9.0"
gem "sdoc", "~> 2.0.3" gem "sdoc", "~> 2.0.3"
gem "telegram-bot-types", "~> 0.6.2" gem "telegram-bot-types", "~> 0.6.3"
gem "rspec", "~> 3.10.0" gem "rspec", "~> 3.10.0"
gem "rspec-its", "~> 1.3.0" gem "rspec-its", "~> 1.3.0"
gem "rspec-rails", "~> 4.0.2" gem "rspec-rails", "~> 4.0.2"

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

@@ -10,7 +10,7 @@ group :development do
gem "pry", "~> 0.13.1" gem "pry", "~> 0.13.1"
gem "pry-byebug", "~> 3.9.0" gem "pry-byebug", "~> 3.9.0"
gem "sdoc", "~> 2.0.3" gem "sdoc", "~> 2.0.3"
gem "telegram-bot-types", "~> 0.6.2" gem "telegram-bot-types", "~> 0.6.3"
gem "rspec", "~> 3.10.0" gem "rspec", "~> 3.10.0"
gem "rspec-its", "~> 1.3.0" gem "rspec-its", "~> 1.3.0"
gem "rspec-rails", "~> 4.0.2" gem "rspec-rails", "~> 4.0.2"

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

@@ -10,7 +10,7 @@ group :development do
gem "pry", "~> 0.13.1" gem "pry", "~> 0.13.1"
gem "pry-byebug", "~> 3.9.0" gem "pry-byebug", "~> 3.9.0"
gem "sdoc", "~> 2.0.3" gem "sdoc", "~> 2.0.3"
gem "telegram-bot-types", "~> 0.6.2" gem "telegram-bot-types", "~> 0.6.3"
gem "rspec", "~> 3.10.0" gem "rspec", "~> 3.10.0"
gem "rspec-its", "~> 1.3.0" gem "rspec-its", "~> 1.3.0"
gem "rspec-rails", "~> 4.0.2" gem "rspec-rails", "~> 4.0.2"

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

@@ -10,7 +10,7 @@ group :development do
gem "pry", "~> 0.13.1" gem "pry", "~> 0.13.1"
gem "pry-byebug", "~> 3.9.0" gem "pry-byebug", "~> 3.9.0"
gem "sdoc", "~> 2.0.3" gem "sdoc", "~> 2.0.3"
gem "telegram-bot-types", "~> 0.6.2" gem "telegram-bot-types", "~> 0.6.3"
gem "rspec", "~> 3.10.0" gem "rspec", "~> 3.10.0"
gem "rspec-its", "~> 1.3.0" gem "rspec-its", "~> 1.3.0"
gem "rspec-rails", "~> 4.0.2" gem "rspec-rails", "~> 4.0.2"

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

@@ -10,7 +10,7 @@ group :development do
gem "pry", "~> 0.13.1" gem "pry", "~> 0.13.1"
gem "pry-byebug", "~> 3.9.0" gem "pry-byebug", "~> 3.9.0"
gem "sdoc", "~> 2.0.3" gem "sdoc", "~> 2.0.3"
gem "telegram-bot-types", "~> 0.6.2" gem "telegram-bot-types", "~> 0.6.3"
gem "rspec", "~> 3.10.0" gem "rspec", "~> 3.10.0"
gem "rspec-its", "~> 1.3.0" gem "rspec-its", "~> 1.3.0"
gem "rspec-rails", "~> 4.0.2" gem "rspec-rails", "~> 4.0.2"

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

@@ -10,7 +10,7 @@ group :development do
gem "pry", "~> 0.13.1" gem "pry", "~> 0.13.1"
gem "pry-byebug", "~> 3.9.0" gem "pry-byebug", "~> 3.9.0"
gem "sdoc", "~> 2.0.3" gem "sdoc", "~> 2.0.3"
gem "telegram-bot-types", "~> 0.6.2" gem "telegram-bot-types", "~> 0.6.3"
gem "rspec", "~> 3.10.0" gem "rspec", "~> 3.10.0"
gem "rspec-its", "~> 1.3.0" gem "rspec-its", "~> 1.3.0"
gem "rspec-rails", "~> 4.0.2" gem "rspec-rails", "~> 4.0.2"

21
gemfiles/rails_70.gemfile Обычный файл
Просмотреть файл

@@ -0,0 +1,21 @@
# This file was generated by Appraisal
source "https://rubygems.org"
gem "actionpack", "~> 7.0.0"
gem "railties", "~> 7.0.0"
group :development do
gem "appraisal", "~> 2.2"
gem "pry", "~> 0.13.1"
gem "pry-byebug", "~> 3.9.0"
gem "sdoc", "~> 2.0.3"
gem "telegram-bot-types", "~> 0.6.3"
gem "rspec", "~> 3.10.0"
gem "rspec-its", "~> 1.3.0"
gem "rspec-rails", "~> 4.0.2"
gem "rubocop", "~> 0.52.1"
gem "coveralls", "~> 0.8.23", require: false
end
gemspec path: "../"

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

@@ -1,5 +1,4 @@
require 'active_support/core_ext/hash/keys' require 'active_support/core_ext/hash/keys'
require 'json'
require 'httpclient' require 'httpclient'
module Telegram module Telegram
@@ -8,7 +7,9 @@ module Telegram
SERVER = 'https://api.telegram.org'.freeze SERVER = 'https://api.telegram.org'.freeze
URL_TEMPLATE = '%<server>s/bot%<token>s/'.freeze URL_TEMPLATE = '%<server>s/bot%<token>s/'.freeze
autoload :RequestBodyFormatter, 'telegram/bot/client/request_body_formatter'
autoload :TypedResponse, 'telegram/bot/client/typed_response' autoload :TypedResponse, 'telegram/bot/client/typed_response'
prepend Async prepend Async
include DebugClient include DebugClient
@@ -35,16 +36,8 @@ module Telegram
prepend TypedResponse prepend TypedResponse
end end
# Encodes nested hashes as json.
def prepare_body(body)
body = body.dup
body.each do |k, val|
body[k] = val.to_json if val.is_a?(Hash) || val.is_a?(Array)
end
end
def prepare_async_args(action, body = {}) def prepare_async_args(action, body = {})
[action.to_s, Async.prepare_hash(prepare_body(body))] [action.to_s, Async.prepare_hash(RequestBodyFormatter.format(body, action))]
end end
def error_for_response(response) def error_for_response(response)
@@ -70,7 +63,7 @@ module Telegram
end end
def request(action, body = {}) def request(action, body = {})
response = http_request("#{base_uri}#{action}", self.class.prepare_body(body)) response = http_request("#{base_uri}#{action}", RequestBodyFormatter.format(body, action))
raise self.class.error_for_response(response) if response.status >= 300 raise self.class.error_for_response(response) if response.status >= 300
JSON.parse(response.body) JSON.parse(response.body)
end end

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

@@ -1,5 +1,5 @@
# Generated with bin/fetch-telegram-methods # Generated with bin/fetch-telegram-methods
# Bot API 5.3 # Bot API 5.7
getUpdates getUpdates
setWebhook setWebhook
@@ -35,11 +35,15 @@ unbanChatMember
restrictChatMember restrictChatMember
promoteChatMember promoteChatMember
setChatAdministratorCustomTitle setChatAdministratorCustomTitle
banChatSenderChat
unbanChatSenderChat
setChatPermissions setChatPermissions
exportChatInviteLink exportChatInviteLink
createChatInviteLink createChatInviteLink
editChatInviteLink editChatInviteLink
revokeChatInviteLink revokeChatInviteLink
approveChatJoinRequest
declineChatJoinRequest
setChatPhoto setChatPhoto
deleteChatPhoto deleteChatPhoto
setChatTitle setChatTitle

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

@@ -0,0 +1,61 @@
require 'json'
module Telegram
module Bot
class Client
# Encodes nested hashes and arrays as json and extract File objects from them
# to the top level. Top-level File objects are handled by httpclient.
# More details: https://core.telegram.org/bots/api#sending-files
module RequestBodyFormatter
extend self
def format(body, action)
body = body.dup
case action.to_s
when 'sendMediaGroup'
extract_files_from_array!(body, :media)
when 'editMessageMedia'
replace_field(body, :media) do |value|
files = {}
extract_files_from_hash(value, files).tap { body.merge!(files) }
end
end
body.each do |key, val|
body[key] = val.to_json if val.is_a?(Hash) || val.is_a?(Array)
end
end
private
# Detects field by symbol or string name and replaces it with mapped value.
def replace_field(hash, field_name)
field_name = [field_name.to_sym, field_name.to_s].find { |x| hash.key?(x) }
hash[field_name] = yield hash[field_name] if field_name
end
def extract_files_from_array!(hash, field_name)
replace_field(hash, field_name) do |value|
break value unless value.is_a?(Array)
files = {}
value.map { |x| extract_files_from_hash(x, files) }.
tap { hash.merge!(files) }
end
end
# Replace File objects with `attach` URIs. File objects are added into `files` hash.
def extract_files_from_hash(hash, files)
return hash unless hash.is_a?(Hash)
hash.transform_values do |value|
if value.is_a?(File)
arg_name = "_file#{files.size}"
files[arg_name] = value
"attach://#{arg_name}"
else
value
end
end
end
end
end
end
end

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

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

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

@@ -0,0 +1,92 @@
RSpec.describe Telegram::Bot::Client::RequestBodyFormatter do
describe '.format' do
subject { described_class.format(input, action) }
let(:action) { :sendMessage }
context 'when plain hash is given' do
let(:input) { {a: 1, b: '2', c: nil} }
it { should eq input }
end
context 'when nested hash is given' do
let(:input) { {a: 1, b: '2', c: [1, 2], d: {a: 1}, e: {b: []}} }
it 'encodes nested hashes to json' do
expected = input.dup
%i[c d e].each { |x| expected[x] = expected[x].to_json }
should eq expected
end
end
context 'with sendMediaGroup action' do
let(:action) { :sendMediaGroup }
let(:input) { {media: [{a: file_1}, {'b' => file_2, c: 123}, {d: 456}], x: 789} }
let(:file_1) { File.new(__FILE__) }
let(:file_2) { File.new(__FILE__) }
it 'extracts files to the top-level' do
should eq(
media: [
{a: 'attach://_file0'},
{b: 'attach://_file1', c: 123},
{d: 456},
].to_json,
x: 789,
'_file0' => file_1,
'_file1' => file_2,
)
end
context 'and input has string keys' do
let(:input) { super().stringify_keys }
it 'extracts files to the top-level' do
should eq(
'media' => [
{a: 'attach://_file0'},
{b: 'attach://_file1', c: 123},
{d: 456},
].to_json,
'x' => 789,
'_file0' => file_1,
'_file1' => file_2,
)
end
end
context 'without media' do
let(:input) { {a: 1, b: '2', c: nil} }
it { should eq input }
end
end
context 'with editMessageMedia action' do
let(:action) { :editMessageMedia }
let(:input) { {media: {a: file, b: 123}, x: 789} }
let(:file) { File.new(__FILE__) }
it 'extracts files to the top-level' do
should eq(
media: {a: 'attach://_file0', b: 123}.to_json,
x: 789,
'_file0' => file,
)
end
context 'and input has string keys' do
let(:input) { super().stringify_keys }
it 'extracts files to the top-level' do
should eq(
'media' => {a: 'attach://_file0', b: 123}.to_json,
'x' => 789,
'_file0' => file,
)
end
end
context 'without media' do
let(:input) { {a: 1, b: '2', c: nil} }
it { should eq input }
end
end
end
end

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

@@ -71,25 +71,6 @@ RSpec.describe Telegram::Bot::Client do
end end
end end
describe '.prepare_body' do
subject { described_class.prepare_body(input) }
context 'when plain hash is given' do
let(:input) { {a: 1, b: '2', c: nil} }
it { should eq input }
end
context 'when nested hash is given' do
let(:input) { {a: 1, b: '2', c: [1, 2], d: {a: 1}, e: {b: []}} }
it 'encodes nested hashes to json' do
expected = input.dup
%i[c d e].each { |x| expected[x] = expected[x].to_json }
should eq expected
end
end
end
describe '.prepare_async_args' do describe '.prepare_async_args' do
subject { described_class.prepare_async_args(*input) } subject { described_class.prepare_async_args(*input) }
let(:input) { [:action, a: 1, b: :sym, c: [:other], 'd' => 'str'] } let(:input) { [:action, a: 1, b: :sym, c: [:other], 'd' => 'str'] }
@@ -148,7 +129,8 @@ RSpec.describe Telegram::Bot::Client do
let(:body) { body_json.to_json } let(:body) { body_json.to_json }
let(:body_json) { {'param' => 'val', 'description' => 'some description'} } let(:body_json) { {'param' => 'val', 'description' => 'some description'} }
before do before do
expect(described_class).to receive(:prepare_body).with(request_body) { prepared_body } expect(Telegram::Bot::Client::RequestBodyFormatter).
to receive(:format).with(request_body, action) { prepared_body }
expect(instance).to receive(:http_request).with(url, prepared_body) { response } expect(instance).to receive(:http_request).with(url, prepared_body) { response }
end end
around { |ex| Telegram::Bot::ClientStub.stub_all!(false) { ex.run } } around { |ex| Telegram::Bot::ClientStub.stub_all!(false) { ex.run } }

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

@@ -16,7 +16,7 @@ RSpec.describe Telegram::Bot::UpdatesController::TypedUpdate do
my_chat_member my_chat_member
chat_member chat_member
]). ]).
map { |x| [x, Telegram::Bot::Types.const_get(type.camelize)] }.to_h. map { |x| [x, Telegram::Bot::Types.const_get(x.camelize)] }.to_h.
merge( merge(
'chat_member' => Telegram::Bot::Types::ChatMemberUpdated 'chat_member' => Telegram::Bot::Types::ChatMemberUpdated
) )

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

@@ -19,8 +19,8 @@ Gem::Specification.new do |spec|
spec.required_ruby_version = '>= 2.4' spec.required_ruby_version = '>= 2.4'
spec.add_dependency 'actionpack', '>= 4.0', '< 6.2' spec.add_dependency 'actionpack', '>= 4.0', '< 7.1'
spec.add_dependency 'activesupport', '>= 4.0', '< 6.2' spec.add_dependency 'activesupport', '>= 4.0', '< 7.1'
spec.add_dependency 'httpclient', '~> 2.7' spec.add_dependency 'httpclient', '~> 2.7'
spec.add_development_dependency 'bundler', '> 1.16' spec.add_development_dependency 'bundler', '> 1.16'