Browse Source

Merge pull request #2962 from andrey-yantsen/telegram_send_media_group

Allow to send media groups via telegram
Akinori MUSHA 3 years ago
parent
commit
f3c91515f2
2 changed files with 29 additions and 11 deletions
  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
     description <<-MD
       The Telegram Agent receives and collects events and sends them via [Telegram](https://telegram.org/).
       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 `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 `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**
       **Setup**
 
 
@@ -31,7 +32,7 @@ module Agents
 
 
       **Options**
       **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_notification`: send a message silently in a channel
       * `disable_web_page_preview`: disable link previews for links in a text message
       * `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.
       * `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,
       photo:    :sendPhoto,
       audio:    :sendAudio,
       audio:    :sendAudio,
       document: :sendDocument,
       document: :sendDocument,
-      video:    :sendVideo
+      video:    :sendVideo,
+      group:    :sendMediaGroup,
     }.freeze
     }.freeze
 
 
     def configure_params(params)
     def configure_params(params)
@@ -101,7 +103,7 @@ module Agents
       if params.has_key?(:text)
       if params.has_key?(:text)
         params[:disable_web_page_preview] = interpolated['disable_web_page_preview'] if interpolated['disable_web_page_preview'].present?
         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?
         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?
         params[:caption] = interpolated['caption'] if interpolated['caption'].present?
       end
       end
 
 
@@ -113,7 +115,11 @@ module Agents
         messages_send = TELEGRAM_ACTIONS.count do |field, _method|
         messages_send = TELEGRAM_ACTIONS.count do |field, _method|
           payload = event.payload[field]
           payload = event.payload[field]
           next unless payload.present?
           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
           true
         end
         end
         error("No valid key found in event #{event.payload.inspect}") if messages_send.zero?
         error("No valid key found in event #{event.payload.inspect}") if messages_send.zero?
@@ -121,7 +127,9 @@ module Agents
     end
     end
 
 
     def send_message(field, params)
     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']
       unless response['ok']
         error(response)
         error(response)
       end
       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' } }])
       expect(@sent_messages).to eq([{ video: { chat_id: 'xxxxxxxx', video: 'https://example.com/video.avi' } }])
     end
     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
     it 'creates a log entry when no key of the received event was useable' do
       event = event_with_payload test: '1234'
       event = event_with_payload test: '1234'
       expect {
       expect {
@@ -140,10 +150,10 @@ describe Agents::TelegramAgent do
     end
     end
   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'
     event = event_with_payload text: 'hello'
     stub_request(:post, "https://api.telegram.org/botxxxxxxxxx:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/sendMessage").
     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'})
       to_return(status: 200, body: '{"ok": false}', headers: {'Content-Type' => 'application/json'})
 
 
     expect {
     expect {
@@ -165,7 +175,7 @@ describe Agents::TelegramAgent do
   describe '#complete_chat_id' do
   describe '#complete_chat_id' do
     it 'returns a list of all recents chats, groups and channels' do
     it 'returns a list of all recents chats, groups and channels' do
       stub_request(:post, "https://api.telegram.org/botxxxxxxxxx:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/getUpdates").
       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'})
         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"},
       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
   describe '#validate_auth_token' do
     it 'returns true if the token is valid' do
     it 'returns true if the token is valid' do
       stub_request(:post, "https://api.telegram.org/botxxxxxxxxx:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/getMe").
       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'})
         to_return(status: 200, body: '{"ok": true}', headers: {'Content-Type' => 'application/json'})
 
 
       expect(@checker.validate_auth_token).to be_truthy
       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
     it 'returns false if the token is invalid' do
       stub_request(:post, "https://api.telegram.org/botxxxxxxxxx:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/getMe").
       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: "{}")
         to_return(status: 200, body: "{}")
 
 
       expect(@checker.validate_auth_token).to be_falsy
       expect(@checker.validate_auth_token).to be_falsy