1
0
зеркало из https://github.com/glebtv/telegram-bot.git synced 2026-08-28 15:26:18 +03:00
Этот коммит содержится в:
Max Melentiev
2016-05-12 14:20:51 +03:00
родитель 1f139a2b36
Коммит 9b9e55a449
9 изменённых файлов: 220 добавлений и 27 удалений

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

@@ -309,6 +309,42 @@ Check out `telegram/bot/updates_controller/rspec_helpers` and
Use `rake telegram:bot:set_webhook` to update webhook url for all configured bots.
Certificate can be specified with `CERT=path/to/cert`.
### Botan.io metrics
Initialize with `bot = Bot.new(token, botan: 'botan token')`
or just add `botan` key in `secrets.yml`:
```yml
telegram:
bot:
token: bot_token
botan: botan_token
```
Access to Botan client with `bot.botan`.
Use `bot.botan.track(event, uid, payload)` to track events.
There are some helpers for controllers in `Telegram::Bot::UpdatesController::Botan`:
```ruby
class Telegram::WebhookController < Telegram::Bot::UpdatesController
include Telegram::Bot::UpdatesController::Botan
# This will track with event: action_name & data: payload
before_action :botan_track_action
def smth(*)
# This will track event for current user only when botan is configured.
botan_track :my_event, custom_data
# or get access directly to botan client:
botan.track(...)
end
end
```
There is no stubbing for botan clients, so don't set botan token in tests.
## Development
After checking out the repo, run `bin/setup` to install dependencies.

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

@@ -26,6 +26,7 @@ module Telegram
end
end
autoload :Botan, 'telegram/bot/botan'
autoload :Client, 'telegram/bot/client'
autoload :ClientStub, 'telegram/bot/client_stub'
autoload :Middleware, 'telegram/bot/middleware'

36
lib/telegram/bot/botan.rb Обычный файл
Просмотреть файл

@@ -0,0 +1,36 @@
module Telegram
module Bot
class Botan
TRACK_URI = 'https://api.botan.io/track'.freeze
class Error < Bot::Error; end
include DebugClient
attr_reader :client, :token
def initialize(token)
@client = HTTPClient.new
@token = token
end
def track(event, uid, payload = {})
res = http_request(
:post,
TRACK_URI,
{token: token, name: event, uid: uid},
payload.to_json,
)
status = res.status
return JSON.parse(res.body) if 300 > status
result = JSON.parse(res.body) rescue nil # rubocop:disable RescueModifier
err_msg = "#{res.reason}: #{result && result['info'] || '-'}"
raise Error, err_msg
end
def http_request(method, uri, query, body)
client.request(method, uri, query, body)
end
end
end
end

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

@@ -2,14 +2,16 @@ require 'json'
require 'httpclient'
require 'active_support/core_ext/string/inflections'
require 'active_support/core_ext/hash/keys'
require 'telegram/bot/debug_client'
module Telegram
module Bot
class Client
autoload :TypedResponse, 'telegram/bot/client/typed_response'
URL_TEMPLATE = 'https://api.telegram.org/bot%s/'.freeze
autoload :TypedResponse, 'telegram/bot/client/typed_response'
include DebugClient
class << self
# Accepts different options to initialize bot.
def wrap(input)
@@ -18,7 +20,7 @@ module Telegram
when Array then input.map(&method(__callee__))
when Hash then
input = input.stringify_keys
new input['token'], input['username']
new input['token'], input['username'], botan: input['botan']
when Symbol
Telegram.bots[input] or
raise "Bot #{input} not configured, check Telegram.bots_config."
@@ -41,31 +43,14 @@ module Telegram
end
end
attr_reader :client, :token, :username, :base_uri
attr_reader :client, :token, :username, :base_uri, :botan
def initialize(token, username = nil)
def initialize(token, username = nil, botan: nil)
@client = HTTPClient.new
@token = token
@username = username
@base_uri = format URL_TEMPLATE, token
end
def debug!(dev = STDOUT)
if block_given?
begin
old_dev = client.debug_dev
client.debug_dev = dev
yield
ensure
client.debug_dev = old_dev
end
else
client.debug_dev = dev
end
end
def debug_off!
client.debug_dev = nil
@botan = Botan.new(botan) if botan
end
def request(action, body = {}) # rubocop:disable PerceivedComplexity

23
lib/telegram/bot/debug_client.rb Обычный файл
Просмотреть файл

@@ -0,0 +1,23 @@
module Telegram
module Bot
module DebugClient
def debug!(dev = STDOUT)
if block_given?
begin
old_dev = client.debug_dev
client.debug_dev = dev
yield
ensure
client.debug_dev = old_dev
end
else
client.debug_dev = dev
end
end
def debug_off!
client.debug_dev = nil
end
end
end
end

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

@@ -57,6 +57,7 @@ module Telegram
require 'telegram/bot/updates_controller/log_subscriber'
require 'telegram/bot/updates_controller/instrumentation'
autoload :MessageContext, 'telegram/bot/updates_controller/message_context'
autoload :Botan, 'telegram/bot/updates_controller/botan'
include AbstractController::Callbacks
# Redefine callbacks with default terminator.

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

@@ -0,0 +1,33 @@
module Telegram
module Bot
class UpdatesController
# Helpers for botan.io metrics.
module Botan
class MissingFrom < Error; end
protected
def botan
@botan ||= bot.try!(:botan)
end
# Track custom event for user taken from `from` field:
#
# botan_track :my_event, {data: :val}
#
def botan_track(event, data = {})
raise MissingFrom, 'Can not track without user' unless from
botan.try! { |x| x.track(event, from['id'], data) }
end
# Track current action and payload for current user. Best used with `before_action`:
#
# before_action :botan_track_action
#
def botan_track_action
botan_track(action_name, payload)
end
end
end
end
end

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

@@ -1,10 +1,12 @@
RSpec.describe Telegram::Bot::Client do
let(:instance) { described_class.new 'token' }
let(:token) { 'token' }
let(:botan_token) { double(:botan_token) }
describe '.wrap' do
subject { described_class.wrap(input) }
let(:result) { double(:result) }
let(:token) { 'token' }
let(:username) { 'username' }
let(:instance) { described_class.new 'token' }
context 'when input is a string' do
let(:input) { token }
@@ -19,9 +21,20 @@ RSpec.describe Telegram::Bot::Client do
let(:input) { {token: token, username: username, ignore: :ignore} }
it 'extracts token & username' do
expect(described_class).to receive(:new).with(token, username) { result }
expect(described_class).to receive(:new).
with(token, username, botan: nil) { result }
should eq result
end
context 'when `botan` is given' do
let(:input) { super().merge(botan: botan_token) }
it 'passes it to initializer' do
expect(described_class).to receive(:new).
with(token, username, botan: botan_token) { result }
should eq result
end
end
end
context 'when input is an instance of described_class' do
@@ -50,7 +63,7 @@ RSpec.describe Telegram::Bot::Client do
it 'calls wrap for every element' do
expect(described_class).to receive(:new).with('other_token') { result }
expect(described_class).to receive(:new).with(token, username) { result_2 }
expect(described_class).to receive(:new).with(token, username, botan: nil) { result_2 }
should eq [result, instance, result_2]
end
end
@@ -74,4 +87,15 @@ RSpec.describe Telegram::Bot::Client do
end
end
end
describe '#botan' do
subject { instance.botan }
it { should eq nil }
context 'when botan token is set' do
let(:instance) { described_class.new token, botan: botan_token }
it { should be_instance_of Telegram::Bot::Botan }
its(:token) { should eq botan_token }
end
end
end

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

@@ -0,0 +1,54 @@
RSpec.describe Telegram::Bot::UpdatesController::Botan do
include_context 'telegram/bot/updates_controller'
let(:controller_class) do
described_class = self.described_class
Class.new(Telegram::Bot::UpdatesController) do
include described_class
end
end
let(:botan) { double(:botan) }
let(:result) { double(:result) }
let(:payload) { {from: {id: user_id}} }
let(:payload_type) { :message }
let(:user_id) { double(:user_id) }
before { allow(bot).to receive(:botan) { botan } }
shared_examples 'basic tracking' do
context 'when botan is not configured' do
let(:botan) {}
it { should eq nil }
end
context 'when `from` is empty' do
let(:payload) { {text: 'test'} }
it { expect { subject }.to raise_error described_class::MissingFrom }
end
end
describe '#botan_track' do
subject { controller.send(:botan_track, event, data) }
let(:event) { double(:event) }
let(:data) { double(:data) }
it 'calls botan#track' do
expect(botan).to receive(:track).with(event, user_id, data) { result }
should eq result
end
include_examples 'basic tracking'
end
describe '#botan_track_action' do
subject { controller.send(:botan_track_action) }
let(:action_name) { double(:action_name) }
it 'calls botan#track with current action and payload' do
expect(controller).to receive(:action_name) { action_name }
expect(botan).to receive(:track).
with(action_name, user_id, deep_stringify(payload)) { result }
should eq result
end
include_examples 'basic tracking'
end
end