Class: TelegramBotMiddleware
- Inherits:
-
Object
- Object
- TelegramBotMiddleware
- Includes:
- HTTMultiParty
- Defined in:
- lib/telegram_bot_middleware.rb,
lib/telegram_bot_middleware/version.rb
Constant Summary collapse
- VERSION =
"0.1.0"
Instance Method Summary collapse
- #_call(env) ⇒ Object
-
#call(env) ⇒ Object
necessary for thread safe.
-
#initialize(app) {|@config| ... } ⇒ TelegramBotMiddleware
constructor
A new instance of TelegramBotMiddleware.
- #send_to_bot(path, query) ⇒ Object
- #start_get_updates_thread ⇒ Object
Constructor Details
#initialize(app) {|@config| ... } ⇒ TelegramBotMiddleware
Returns a new instance of TelegramBotMiddleware.
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
# File 'lib/telegram_bot_middleware.rb', line 16 def initialize(app, &block) # save the app var @app = app puts 'Initializing...' # create the config and populate passing do the block function @config = OpenStruct.new yield(@config) if block_given? # setup webhook if @config.webhook.nil? @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_bot('setWebhook', {url: ''}) # setup a thread with get_updates function start_get_updates_thread # setup webhook when :webhook send_to_bot('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 or :polling.') end end |
Instance Method Details
#_call(env) ⇒ Object
82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 |
# File 'lib/telegram_bot_middleware.rb', line 82 def _call(env) # retrieve the request object req = Rack::Request.new(env) # if the request is a post to bot webhhok if req.post? and req.path == "/#{@config.token}" # in case someone already read it req.body.rewind # build an openstruct based on post params params = OpenStruct.from_json(req.body.read) # build path based on message # - get only message part of post params # - remove empty chars from beginning or end (strip) # - replace first sequence of spaces with / # - encode as uri path = URI.escape(params..text.strip.sub(/\s+/, '/')) # - add first / if not present path = "/#{path}" unless path.start_with?('/') # build the querystring using message but nested query_string = Rack::Utils.build_nested_query(params..to_h_nested) # transform the POST in GET env['PATH_INFO'] = path env['QUERY_STRING'] = query_string env['REQUEST_METHOD'] = 'GET' env['REQUEST_URI'] = "https://#{req.host}#{path}" # TODO use update(hash) { |name, old_value, new_value| } # call the rack stack status, headers, body = @app.call(env) if status == 200 or status == '200' case headers['Content-Type'].split(';').first when 'text/html', 'application/json' if body.is_a? Hash query = body.clone query[:chat_id] = params..chat.id unless query.include?(:chat_id) query[:reply_markup] = query[:reply_markup].to_json if query.include?(:reply_markup) body = Array.new(1) { '' } if query.include?(:text) send_to_bot('sendMessage', query) elsif query.include?(:latitude) and query.include?(:longitude) send_to_bot('sendLocation', query) elsif query.include?(:photo) send_to_bot('sendPhoto', query) elsif query.include?(:audio) send_to_bot('sendAudio', query) elsif query.include?(:video) send_to_bot('sendVideo', query) else # TODO: invalid query end else body.each do |data| send_to_bot('sendMessage', {chat_id: params..chat.id, text: data}) end end when /(^image\/)/ send_to_bot('sendPhoto', {chat_id: params..chat.id, photo: File.new(body)}) when /(^audio\/)/ send_to_bot('sendAudio', {chat_id: params..chat.id, audio: File.new(body)}) when /(^video\/)/ send_to_bot('sendVideo', {chat_id: params..chat.id, video: File.new(body)}) end end # return result [status, headers, body] else # normal rack flow - not a bot call @app.call(env) end end |
#call(env) ⇒ Object
necessary for thread safe
78 79 80 |
# File 'lib/telegram_bot_middleware.rb', line 78 def call(env) dup._call(env) end |
#send_to_bot(path, query) ⇒ Object
168 169 170 171 |
# File 'lib/telegram_bot_middleware.rb', line 168 def send_to_bot(path, query) response = self.class.post("/bot#{@config.token}/#{path}", query: query) # TODO check respobse error end |
#start_get_updates_thread ⇒ Object
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 |
# File 'lib/telegram_bot_middleware.rb', line 53 def start_get_updates_thread # start a new thread Thread.new do # the initial offset is always 0 @offset = 0 # wait 5 seconds to don't risk to post message too early when the app is not still up sleep 5 # loop forever loop do # call the getUpdates telegram function response = send_to_bot('getUpdates', {offset: @offset}) # enumerate the results response.to_hash['result'].each do |data| # create an update message from the post data update = OpenStruct.new(data) # store the last offset +1 but ensure that is not lower than the already stored @offset = (update.update_id + 1) if update.update_id + 1 > @offset # simulate a post to itself HTTP.post @config.webhook, json: update.to_h_nested end end end end |