Repository: line/line-bot-sdk-python
Pull request #28 (2017-01-13 04:02:40)

Support multicast API
ref: https://github.com/line/line-bot-sdk-python/issues/27



Patch:
diff --git a/README.rst b/README.rst
index af4ed81..44ad957 100644
--- a/README.rst
+++ b/README.rst
@@ -114,6 +114,18 @@ https://devdocs.line.me/en/#push-message
 
     line_bot_api.push_message(to, TextSendMessage(text='Hello World!'))
 
+multicast(self, to, messages, timeout=None)
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Send messages to multiple users at any time.
+
+https://devdocs.line.me/en/#multicast
+
+.. code:: python
+
+    line_bot_api.multicast(['to1', 'to2'], TextSendMessage(text='Hello World!'))
+
+
 get\_profile(self, user\_id, timeout=None)
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
diff --git a/linebot/__about__.py b/linebot/__about__.py
index 3176786..30ad3cd 100644
--- a/linebot/__about__.py
+++ b/linebot/__about__.py
@@ -16,7 +16,7 @@
 
 from __future__ import unicode_literals
 
-__version__ = '1.0.2'
+__version__ = '1.1.0'
 __author__ = 'LINE Corporation'
 __copyright__ = 'Copyright 2016, LINE Corporation'
 __license__ = 'Apache 2.0'
diff --git a/linebot/api.py b/linebot/api.py
index ab6f590..702313c 100644
--- a/linebot/api.py
+++ b/linebot/api.py
@@ -124,6 +124,38 @@ class LineBotApi(object):
             '/v2/bot/message/push', data=json.dumps(data), timeout=timeout
         )
 
+    def multicast(self, to, messages, timeout=None):
+        """Call multicast API.
+
+        https://devdocs.line.me/en/#multicast
+
+        Send messages to multiple users at any time.
+
+        :param to: IDs of the receivers
+            Max: 150 users
+        :type to: list[str]
+        :param messages: Messages.
+            Max: 5
+        :type messages: T <= :py:class:`linebot.models.send_messages.SendMessage` |
+            list[T <= :py:class:`linebot.models.send_messages.SendMessage`]
+        :param timeout: (optional) How long to wait for the server
+            to send data before giving up, as a float,
+            or a (connect timeout, readtimeout) float tuple.
+            Default is self.http_client.timeout
+        :type timeout: float | tuple(float, float)
+        """
+        if not isinstance(messages, (list, tuple)):
+            messages = [messages]
+
+        data = {
+            'to': to,
+            'messages': [message.as_json_dict() for message in messages]
+        }
+
+        self._post(
+            '/v2/bot/message/multicast', data=json.dumps(data), timeout=timeout
+        )
+
     def get_profile(self, user_id, timeout=None):
         """Call get profile API.
 


Test patch:
diff --git a/tests/api/test_send_audio_message.py b/tests/api/test_send_audio_message.py
index 64b75b0..9db1e52 100644
--- a/tests/api/test_send_audio_message.py
+++ b/tests/api/test_send_audio_message.py
@@ -18,6 +18,7 @@ import json
 import unittest
 
 import responses
+
 from linebot import (
     LineBotApi
 )
@@ -88,6 +89,29 @@ class TestLineBotApi(unittest.TestCase):
             }
         )
 
+    @responses.activate
+    def test_multicast_audio_message(self):
+        responses.add(
+            responses.POST,
+            LineBotApi.DEFAULT_API_ENDPOINT + '/v2/bot/message/multicast',
+            json={}, status=200
+        )
+
+        self.tested.multicast(['to1', 'to2'], self.audio_message)
+
+        request = responses.calls[0].request
+        self.assertEqual(request.method, 'POST')
+        self.assertEqual(
+            request.url,
+            LineBotApi.DEFAULT_API_ENDPOINT + '/v2/bot/message/multicast')
+        self.assertEqual(
+            json.loads(request.body),
+            {
+                "to": ['to1', 'to2'],
+                "messages": self.message
+            }
+        )
+
 
 if __name__ == '__main__':
     unittest.main()
diff --git a/tests/api/test_send_image_message.py b/tests/api/test_send_image_message.py
index 77fc67d..0ef0115 100644
--- a/tests/api/test_send_image_message.py
+++ b/tests/api/test_send_image_message.py
@@ -88,6 +88,29 @@ class TestLineBotApi(unittest.TestCase):
             }
         )
 
+    @responses.activate
+    def test_multicast_image_message(self):
+        responses.add(
+            responses.POST,
+            LineBotApi.DEFAULT_API_ENDPOINT + '/v2/bot/message/multicast',
+            json={}, status=200
+        )
+
+        self.tested.multicast(['to1', 'to2'], self.image_message)
+
+        request = responses.calls[0].request
+        self.assertEqual(request.method, 'POST')
+        self.assertEqual(
+            request.url,
+            LineBotApi.DEFAULT_API_ENDPOINT + '/v2/bot/message/multicast')
+        self.assertEqual(
+            json.loads(request.body),
+            {
+                "to": ['to1', 'to2'],
+                "messages": self.message
+            }
+        )
+
 
 if __name__ == '__main__':
     unittest.main()
diff --git a/tests/api/test_send_imagemap_message.py b/tests/api/test_send_imagemap_message.py
index 63734bf..b94f315 100644
--- a/tests/api/test_send_imagemap_message.py
+++ b/tests/api/test_send_imagemap_message.py
@@ -18,6 +18,7 @@ import json
 import unittest
 
 import responses
+
 from linebot import (
     LineBotApi
 )
@@ -129,6 +130,29 @@ class TestLineBotApi(unittest.TestCase):
             }
         )
 
+    @responses.activate
+    def test_multicast_imagemap_message(self):
+        responses.add(
+            responses.POST,
+            LineBotApi.DEFAULT_API_ENDPOINT + '/v2/bot/message/multicast',
+            json={}, status=200
+        )
+
+        self.tested.multicast(['to1', 'to2'], self.imagemap_message)
+
+        request = responses.calls[0].request
+        self.assertEqual(request.method, 'POST')
+        self.assertEqual(
+            request.url,
+            LineBotApi.DEFAULT_API_ENDPOINT + '/v2/bot/message/multicast')
+        self.assertEqual(
+            json.loads(request.body),
+            {
+                "to": ['to1', 'to2'],
+                "messages": self.message
+            }
+        )
+
 
 if __name__ == '__main__':
     unittest.main()
diff --git a/tests/api/test_send_location_message.py b/tests/api/test_send_location_message.py
index 3ecd23a..03fa5c9 100644
--- a/tests/api/test_send_location_message.py
+++ b/tests/api/test_send_location_message.py
@@ -18,6 +18,7 @@ import json
 import unittest
 
 import responses
+
 from linebot import (
     LineBotApi
 )
@@ -91,6 +92,29 @@ class TestLineBotApi(unittest.TestCase):
             }
         )
 
+    @responses.activate
+    def test_multicast_location_message(self):
+        responses.add(
+            responses.POST,
+            LineBotApi.DEFAULT_API_ENDPOINT + '/v2/bot/message/multicast',
+            json={}, status=200
+        )
+
+        self.tested.multicast(['to1', 'to2'], self.location_message)
+
+        request = responses.calls[0].request
+        self.assertEqual(request.method, 'POST')
+        self.assertEqual(
+            request.url,
+            LineBotApi.DEFAULT_API_ENDPOINT + '/v2/bot/message/multicast')
+        self.assertEqual(
+            json.loads(request.body),
+            {
+                "to": ['to1', 'to2'],
+                "messages": self.message
+            }
+        )
+
 
 if __name__ == '__main__':
     unittest.main()
diff --git a/tests/api/test_send_sticker_message.py b/tests/api/test_send_sticker_message.py
index a83aa94..940c59e 100644
--- a/tests/api/test_send_sticker_message.py
+++ b/tests/api/test_send_sticker_message.py
@@ -18,6 +18,7 @@ import json
 import unittest
 
 import responses
+
 from linebot import (
     LineBotApi
 )
@@ -86,6 +87,29 @@ class TestLineBotApi(unittest.TestCase):
             }
         )
 
+    @responses.activate
+    def test_multicast_sticker_message(self):
+        responses.add(
+            responses.POST,
+            LineBotApi.DEFAULT_API_ENDPOINT + '/v2/bot/message/multicast',
+            json={}, status=200
+        )
+
+        self.tested.multicast(['to1', 'to2'], self.sticker_message)
+
+        request = responses.calls[0].request
+        self.assertEqual(request.method, 'POST')
+        self.assertEqual(
+            request.url,
+            LineBotApi.DEFAULT_API_ENDPOINT + '/v2/bot/message/multicast')
+        self.assertEqual(
+            json.loads(request.body),
+            {
+                "to": ['to1', 'to2'],
+                "messages": self.message
+            }
+        )
+
 
 if __name__ == '__main__':
     unittest.main()
diff --git a/tests/api/test_send_template_message.py b/tests/api/test_send_template_message.py
index 100d465..a6a2d01 100644
--- a/tests/api/test_send_template_message.py
+++ b/tests/api/test_send_template_message.py
@@ -18,6 +18,7 @@ import json
 import unittest
 
 import responses
+
 from linebot import (
     LineBotApi
 )
@@ -361,6 +362,29 @@ class TestLineBotApi(unittest.TestCase):
             }
         )
 
+    @responses.activate
+    def test_multicast_carousel_template_message(self):
+        responses.add(
+            responses.POST,
+            LineBotApi.DEFAULT_API_ENDPOINT + '/v2/bot/message/multicast',
+            json={}, status=200
+        )
+
+        self.tested.multicast(['to1', 'to2'], self.carousel_template_message)
+
+        request = responses.calls[0].request
+        self.assertEqual(request.method, 'POST')
+        self.assertEqual(
+            request.url,
+            LineBotApi.DEFAULT_API_ENDPOINT + '/v2/bot/message/multicast')
+        self.assertEqual(
+            json.loads(request.body),
+            {
+                "to": ['to1', 'to2'],
+                "messages": self.carousel_message
+            }
+        )
+
 
 if __name__ == '__main__':
     unittest.main()
diff --git a/tests/api/test_send_text_message.py b/tests/api/test_send_text_message.py
index 212344a..f64921d 100644
--- a/tests/api/test_send_text_message.py
+++ b/tests/api/test_send_text_message.py
@@ -18,6 +18,7 @@ import json
 import unittest
 
 import responses
+
 from linebot import (
     LineBotApi
 )
@@ -80,6 +81,29 @@ class TestSendTestMessage(unittest.TestCase):
             }
         )
 
+    @responses.activate
+    def test_multicast_text_message(self):
+        responses.add(
+            responses.POST,
+            LineBotApi.DEFAULT_API_ENDPOINT + '/v2/bot/message/multicast',
+            json={}, status=200
+        )
+
+        self.tested.multicast(['to1', 'to2'], self.text_message)
+
+        request = responses.calls[0].request
+        self.assertEqual(
+            request.url,
+            LineBotApi.DEFAULT_API_ENDPOINT + '/v2/bot/message/multicast')
+        self.assertEqual(request.method, 'POST')
+        self.assertEqual(
+            json.loads(request.body),
+            {
+                "to": ['to1', 'to2'],
+                "messages": self.message
+            }
+        )
+
 
 if __name__ == '__main__':
     unittest.main()
diff --git a/tests/api/test_send_video_message.py b/tests/api/test_send_video_message.py
index 3f2b121..217b583 100644
--- a/tests/api/test_send_video_message.py
+++ b/tests/api/test_send_video_message.py
@@ -18,6 +18,7 @@ import json
 import unittest
 
 import responses
+
 from linebot import (
     LineBotApi
 )
@@ -87,6 +88,29 @@ class TestLineBotApi(unittest.TestCase):
             }
         )
 
+    @responses.activate
+    def test_multicast_video_message(self):
+        responses.add(
+            responses.POST,
+            LineBotApi.DEFAULT_API_ENDPOINT + '/v2/bot/message/multicast',
+            json={}, status=200
+        )
+
+        self.tested.multicast(['to1', 'to2'], self.video_message)
+
+        request = responses.calls[0].request
+        self.assertEqual(request.method, 'POST')
+        self.assertEqual(
+            request.url,
+            LineBotApi.DEFAULT_API_ENDPOINT + '/v2/bot/message/multicast')
+        self.assertEqual(
+            json.loads(request.body),
+            {
+                "to": ['to1', 'to2'],
+                "messages": self.message
+            }
+        )
+
 
 if __name__ == '__main__':
     unittest.main()