Explorar o código

Merge pull request #2962 from andrey-yantsen/telegram_send_media_group

Allow to send media groups via telegram
Akinori MUSHA %!s(int64=3) %!d(string=hai) anos
pai
achega
f3c91515f2
Modificáronse 2 ficheiros con 29 adicións e 11 borrados
  1. 14 6
      app/models/agents/telegram_agent.rb
  2. 15 5
      spec/models/agents/telegram_agent_spec.rb

+ 14 - 6
app/models/agents/telegram_agent.rb

@@ -12,10 +12,11 @@ module Agents
     description <<-MD
       The Telegram Agent receives and collects events and sends them via [Telegram](https://telegram.org/).
 
-      It is assumed that events have either a `text`, `photo`, `audio`, `document` or `video` key. You can use the EventFormattingAgent if your event does not provide these keys.
+      It is assumed that events have either a `text`, `photo`, `audio`, `document`, `video` or `group` key. You can use the EventFormattingAgent if your event does not provide these keys.
 
       The value of `text` key is sent as a plain text message. You can also tell Telegram how to parse the message with `parse_mode`, set to either `html`, `markdown` or `markdownv2`.
       The value of `photo`, `audio`, `document` and `video` keys should be a url whose contents will be sent to you.
+      The value of `group` key should be a list and must consist of 2-10 objects representing an [InputMedia](https://core.telegram.org/bots/api#inputmedia) from the [Telegram Bot API](https://core.telegram.org/bots/api#inputmedia). Be careful: the `caption` field is not covered by the "long message" setting. 
 
       **Setup**
 
@@ -31,7 +32,7 @@ module Agents
 
       **Options**
 
-      * `caption`: caption for a media content (0-1024 characters)
+      * `caption`: caption for a media content (0-1024 characters), applied only for `photo`, `audio`, `document`, or `video`
       * `disable_notification`: send a message silently in a channel
       * `disable_web_page_preview`: disable link previews for links in a text message
       * `long_message`: truncate (default) or split text messages and captions that exceed Telegram API limits. Markdown and HTML tags can't span across messages and, if not opened or closed properly, will render as plain text.
@@ -92,7 +93,8 @@ module Agents
       photo:    :sendPhoto,
       audio:    :sendAudio,
       document: :sendDocument,
-      video:    :sendVideo
+      video:    :sendVideo,
+      group:    :sendMediaGroup,
     }.freeze
 
     def configure_params(params)
@@ -101,7 +103,7 @@ module Agents
       if params.has_key?(:text)
         params[:disable_web_page_preview] = interpolated['disable_web_page_preview'] if interpolated['disable_web_page_preview'].present?
         params[:parse_mode] = interpolated['parse_mode'] if interpolated['parse_mode'].present?
-      else
+      elsif not params.has_key?(:media)
         params[:caption] = interpolated['caption'] if interpolated['caption'].present?
       end
 
@@ -113,7 +115,11 @@ module Agents
         messages_send = TELEGRAM_ACTIONS.count do |field, _method|
           payload = event.payload[field]
           next unless payload.present?
-          send_telegram_messages field, configure_params(field => payload)
+          if field == :group
+            send_telegram_messages field, configure_params(:media => payload)
+          else
+            send_telegram_messages field, configure_params(field => payload)
+          end
           true
         end
         error("No valid key found in event #{event.payload.inspect}") if messages_send.zero?
@@ -121,7 +127,9 @@ module Agents
     end
 
     def send_message(field, params)
-      response = HTTMultiParty.post telegram_bot_uri(TELEGRAM_ACTIONS[field]), query: params
+      response = HTTMultiParty.post telegram_bot_uri(TELEGRAM_ACTIONS[field]),
+                                    body: params.to_json,
+                                    headers: { 'Content-Type' => 'application/json' }
       unless response['ok']
         error(response)
       end

+ 15 - 5
spec/models/agents/telegram_agent_spec.rb

@@ -132,6 +132,16 @@ describe Agents::TelegramAgent do
       expect(@sent_messages).to eq([{ video: { chat_id: 'xxxxxxxx', video: 'https://example.com/video.avi' } }])
     end
 
+    it 'accepts group key and uses :send_media_group to send the file' do
+      event = event_with_payload group: [{ type: 'photo', media: 'https://example.com/photo1.jpg' }, { type: 'photo', media: 'https://example.com/photo2.jpg' }]
+      @checker.receive [event]
+
+      expect(@sent_messages).to eq([{ group: { chat_id: 'xxxxxxxx',
+                                               media: [{ 'type' => 'photo', 'media' => 'https://example.com/photo1.jpg' },
+                                                       { 'type' => 'photo', 'media' => 'https://example.com/photo2.jpg' }]
+      } }])
+    end
+
     it 'creates a log entry when no key of the received event was useable' do
       event = event_with_payload test: '1234'
       expect {
@@ -140,10 +150,10 @@ describe Agents::TelegramAgent do
     end
   end
 
-  it 'creates and error log if the request fails' do
+  it 'creates an error log if the request fails' do
     event = event_with_payload text: 'hello'
     stub_request(:post, "https://api.telegram.org/botxxxxxxxxx:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/sendMessage").
-      with(headers: {'Accept'=>'*/*', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'User-Agent'=>'Ruby'}).
+      with(headers: {'Content-type'=>'application/json'}).
       to_return(status: 200, body: '{"ok": false}', headers: {'Content-Type' => 'application/json'})
 
     expect {
@@ -165,7 +175,7 @@ describe Agents::TelegramAgent do
   describe '#complete_chat_id' do
     it 'returns a list of all recents chats, groups and channels' do
       stub_request(:post, "https://api.telegram.org/botxxxxxxxxx:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/getUpdates").
-        with(headers: {'Accept'=>'*/*', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'User-Agent'=>'Ruby'}).
+        with(headers: {}).
         to_return(status: 200, body: '{"ok":true,"result":[{"update_id":252965475,"message":{"message_id":15,"from":{"id":97201077,"is_bot":false,"first_name":"Dominik","last_name":"Sander","language_code":"en-US"},"chat":{"id":97201077,"first_name":"Dominik","last_name":"Sander","type":"private"},"date":1506774710,"text":"test"}},{"update_id":252965476,"channel_post":{"message_id":4,"chat":{"id":-1001144599139,"title":"Much channel","type":"channel"},"date":1506782283,"text":"channel"}},{"update_id":252965477,"message":{"message_id":18,"from":{"id":97201077,"is_bot":false,"first_name":"Dominik","last_name":"Sander","language_code":"en-US"},"chat":{"id":-217850512,"title":"Just a test","type":"group","all_members_are_administrators":true},"date":1506782504,"left_chat_participant":{"id":136508315,"is_bot":true,"first_name":"Huginn","username":"HuginnNotificationBot"},"left_chat_member":{"id":136508315,"is_bot":true,"first_name":"Huginn","username":"HuginnNotificationBot"}}}]}', headers: {'Content-Type' => 'application/json'})
 
       expect(@checker.complete_chat_id).to eq([{:id=>97201077, :text=>"Dominik Sander"},
@@ -177,7 +187,7 @@ describe Agents::TelegramAgent do
   describe '#validate_auth_token' do
     it 'returns true if the token is valid' do
       stub_request(:post, "https://api.telegram.org/botxxxxxxxxx:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/getMe").
-        with(headers: {'Accept'=>'*/*', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'User-Agent'=>'Ruby'}).
+        with(headers: {}).
         to_return(status: 200, body: '{"ok": true}', headers: {'Content-Type' => 'application/json'})
 
       expect(@checker.validate_auth_token).to be_truthy
@@ -185,7 +195,7 @@ describe Agents::TelegramAgent do
 
     it 'returns false if the token is invalid' do
       stub_request(:post, "https://api.telegram.org/botxxxxxxxxx:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/getMe").
-        with(headers: {'Accept'=>'*/*', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'User-Agent'=>'Ruby'}).
+        with(headers: {}).
         to_return(status: 200, body: "{}")
 
       expect(@checker.validate_auth_token).to be_falsy