Skip to content

Commit

Permalink
Merge pull request #4 from zhum/master
Browse files Browse the repository at this point in the history
Some new features
  • Loading branch information
MirkoMignini authored May 19, 2017
2 parents 033b347 + 6e53202 commit 8acd4da
Show file tree
Hide file tree
Showing 5 changed files with 80 additions and 43 deletions.
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ end
* connection_pool_size (optional, default is 2):
* connection_keep_alive (optional, default is 30):
* connection_force_retry (optional, default is true):
* prefix (optional, default ''): prefix path for telegram messages.

## Usage

Expand Down Expand Up @@ -154,6 +155,15 @@ In this case the bot will send an image, a message and a location.
### Session and cookies
The middleware supports the standard sessions variables, that are stored as a cookie and the values are valid for the given chat, see the [calculator sample](https://github.com/MirkoMignini/telegram_bot_middleware/blob/master/examples/sinatra/calc.rb).

### Messages not in reply
If you want to send notification, you can yse special class TeleBot.

```ruby
::TeleBot.send {chat_id: to, text: msg}
```

Warning! TeleBot can be user only for last initialized bot, multiple bots are not supported.

## Examples

To run an example call:
Expand Down
6 changes: 5 additions & 1 deletion examples/sinatra/calc.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,13 @@
session[:result] += cmd
end

get '/=' do
get '/telegram/=' do
{
text: eval(session[:result]).to_s,
reply_markup: {hide_keyboard: true}
}
end

get '*' do |x|
{ text: "Bad request: #{x}" }
end
24 changes: 12 additions & 12 deletions examples/sinatra/example.rb
Original file line number Diff line number Diff line change
@@ -1,47 +1,47 @@
require_relative 'example_init'

get %r{/hello$}i do
get %r{/telegram/hello$}i do
{
text: "Hello #{params['from']['first_name']} #{params['from']['last_name']}!",
reply_markup: {keyboard: [%w(A B), ['C', 'D']], resize_keyboard: true, one_time_keyboard: true, selective: false}
}
end

get %r{/greets/(.*)}i do |name|
get %r{/telegram/greets/(.*)}i do |name|
"Hello #{name}!"
end

get %r{/image/?$}i do
get %r{/telegram/image/?$}i do
#send_file 'tmp/test.png'
{
photo: '../../tmp/test.png',
caption: 'caption'
}
}
end

get %r{/audio/?$}i do
get %r{/telegram/audio/?$}i do
send_file 'tmp/test.mp3'
end

get %r{/video/?$}i do
get %r{/telegram/video/?$}i do
send_file 'tmp/test.mp4'
end

get '/location' do
get '/telegram/location' do
{
latitude: params['location']['latitude'],
longitude: params['location']['longitude'],
}
end

get %r{/location/?$}i do
get %r{/telegram/location/?$}i do
{
latitude: 38.115036,
longitude: 13.366640
}
end

get %r{/test/?$}i do
get %r{/telegram/test/?$}i do
{
multiple:
[
Expand All @@ -60,8 +60,8 @@
}
end

get '/inline_query' do
{
get '/telegram/inline_query' do
{
results:
[
{
Expand All @@ -70,7 +70,7 @@
title: 'Test',
message_text: 'Description'
}
]
]
}
end

Expand Down
1 change: 1 addition & 0 deletions examples/sinatra/example_init.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@
#config.host = 'https://telegram-bot-middleware.herokuapp.com'
config.host = 'http://127.0.0.1:9292'
config.get_updates = :polling
config.prefix='telegram'
end
82 changes: 52 additions & 30 deletions lib/telegram_bot_middleware.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,30 +6,46 @@
require_relative 'ostruct_nested'
require_relative 'telegram_bot_middleware/version'

class TeleBot
class<< self
def init(bot)
@@bot=bot
end

def send msg
@@bot.send_to_telegram('sendMessage',msg)
end
end
end


class TelegramBotMiddleware
include HTTMultiParty
base_uri 'https://api.telegram.org'

def initialize(app, &_block)
TeleBot.init(self)

# save the app var
@app = app

# local cookies hash
@cookies = Hash.new

# create the config and populate passing do the block function
@config = OpenStruct.new
yield(@config) if block_given?


@prefix=@config.prefix
# validate required input params
raise ArgumentError.new("Config error: host can't be null || empty.") if @config.host.nil? || @config.host.empty?
raise ArgumentError.new("Config error: token can't be null || empty.") if @config.token.nil? || @config.token.empty?

# initialize persistent connection to telegram
self.class.persistent_connection_adapter pool_size: (@config.connection_pool_size || 2),
keep_alive: (@config.connection_keep_alive || 30),
force_retry: (@config.connection_force_retry || true)

# if get_updates is empty set to :polling by default
@config.get_updates ||= :polling

Expand All @@ -38,28 +54,28 @@ def initialize(app, &_block)
@config.host = "#{@config.host}/" unless @config.host.end_with?('/')
@config.webhook = "#{@config.host}#{@config.token}"
end

# setup telegram messages input
case @config.get_updates

# setup polling
when :polling
# clear the webhook in case was set in the past
send_to_telegram('setWebhook', {url: ''})

# setup a thread with get_updates function
start_get_updates_thread

# setup webhook
when :webhook
send_to_telegram('setWebhook', {url: @config.webhook})

# in this case get_updates is a non valid value
else
raise ArgumentError.new('Config error: get_updates must be :webhook || :polling.')
end
end

def start_get_updates_thread
# start a new thread
Thread.new do
Expand Down Expand Up @@ -92,54 +108,60 @@ def call(env)
def _call(env)
# retrieve the request object
request = Rack::Request.new(env)

# if the request is a post to bot webhhok
if request.post? and request.path == "/#{@config.token}"

# in case someone already read it
request.body.rewind
# build an openstruct based on post params
params = OpenStruct.from_json(request.body.read)

log_debug("Message from chat: #{params}")

if params['message']
type = 'message'
chat_id = params.message.chat.id
env['QUERY_STRING'] = Rack::Utils.build_nested_query(params.message.to_h_nested)
env['QUERY_STRING'] = Rack::Utils.build_nested_query(params.message.to_h_nested,@prefix)
elsif params['inline_query']
type = 'inline_query'
chat_id = params.inline_query.id
env['QUERY_STRING'] = Rack::Utils.build_nested_query(params.inline_query.to_h_nested)
env['QUERY_STRING'] = Rack::Utils.build_nested_query(params.inline_query.to_h_nested,@prefix)
end

# build command based on message
command = get_command(params)

pr=if @prefix
"/#{@prefix}"
else
''
end

# transform the POST in GET
env['PATH_INFO'] = command
# env['PATH_INFO'] = @prefix ? "/#{@prefix}#{command}" : command
env['PATH_INFO'] = "#{pr}#{command}"
env['REQUEST_METHOD'] = 'GET'
env['REQUEST_URI'] = "https://#{request.host}#{command}"
env['REQUEST_URI'] = "https://#{request.host}#{pr}#{command}"

# if in cache a cookie for this chat was present add to the header
env['HTTP_COOKIE'] = @cookies[chat_id] if @cookies.include?(chat_id)

# call the rack stack
status, headers, body = @app.call(env)

#body = body.body[0] if body.class == Rack::BodyProxy
#puts body.class
#puts body

# try to send to telegram only if no errors
if status == 200 || status == '200'

# if the call setted a cookie save to local cache
@cookies[chat_id] = headers['Set-Cookie'] if headers.include?('Set-Cookie')

if type == 'message'
case headers['Content-Type'].split(';').first
when 'text/html', 'application/json'
when 'text/html', 'application/json'
if body.is_a? Hash
process_hash_message(body.clone, params)
body = Array.new(1) { '' }
Expand Down Expand Up @@ -170,7 +192,7 @@ def _call(env)
headers['Content-Length'] = '0'
end
end

# return result
[status, headers, body]
else
Expand Down

0 comments on commit 8acd4da

Please sign in to comment.