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.2.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.
- #process_hash_message(message, params) ⇒ Object
- #process_json_message(message, params) ⇒ Object
- #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 |
# File 'lib/telegram_bot_middleware.rb', line 16 def initialize(app, &block) # save the app var @app = app # 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
80 81 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 |
# File 'lib/telegram_bot_middleware.rb', line 80 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) path = nil unless params.['text'].nil? # 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?('/') else %w(audio document photo sticker video voice contact location new_chat_participant left_chat_participant new_chat_title new_chat_photo delete_chat_photo group_chat_created).each do |type| unless params.[type].nil? path = "/#{type}" break end end end # 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 (body.clone, params) body = Array.new(1) { '' } else body.each do |data| begin #TODO: add better json parsing to support symbols too (JSON.parse(data.gsub('=>', ':')), params) rescue send_to_bot('sendMessage', {chat_id: params..chat.id, text: data}) end 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
76 77 78 |
# File 'lib/telegram_bot_middleware.rb', line 76 def call(env) dup._call(env) end |
#process_hash_message(message, params) ⇒ Object
161 162 163 164 165 166 167 168 169 |
# File 'lib/telegram_bot_middleware.rb', line 161 def (, params) if (.include?(:multiple) && [:multiple].is_a?(Array)) [:multiple].each { |item| (item, params) } elsif (.include?('multiple') && ['multiple'].is_a?(Array)) ['multiple'].each { |item| (item, params) } else (, params) end end |
#process_json_message(message, params) ⇒ Object
171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 |
# File 'lib/telegram_bot_middleware.rb', line 171 def (, params) [:chat_id] = params..chat.id unless .include?(:chat_id) or .include?('chat_id') [:reply_markup] = [:reply_markup].to_json if .include?(:reply_markup) ['reply_markup'] = ['reply_markup'].to_json if .include?('reply_markup') ['photo', :photo, 'audio', :audio, 'video', :video].each do |item| [item] = File.new([item]) if .include?(item) end if .include?(:text) or .include?('text') send_to_bot('sendMessage', ) elsif (.include?(:latitude) and .include?(:longitude)) or (.include?('latitude') and .include?('longitude')) send_to_bot('sendLocation', ) elsif .include?(:photo) or .include?('photo') send_to_bot('sendPhoto', ) elsif .include?(:audio) or .include?('audio') send_to_bot('sendAudio', ) elsif .include?(:video) or .include?('video') send_to_bot('sendVideo', ) else # TODO: invalid query end end |
#send_to_bot(path, query) ⇒ Object
196 197 198 199 |
# File 'lib/telegram_bot_middleware.rb', line 196 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
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
# File 'lib/telegram_bot_middleware.rb', line 51 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 |