From de1e1474658ce75f5007e0da24493cfbed39235a Mon Sep 17 00:00:00 2001 From: jerrychuang Date: Thu, 21 Dec 2023 19:51:30 +0800 Subject: [PATCH 1/2] feat: Support sticker message and check status api in cli --- lotify/cli.py | 13 ++++++- lotify/client.py | 8 ++-- tests/test_cli.py | 98 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 113 insertions(+), 6 deletions(-) create mode 100644 tests/test_cli.py diff --git a/lotify/cli.py b/lotify/cli.py index d3e6a57..0732414 100644 --- a/lotify/cli.py +++ b/lotify/cli.py @@ -12,15 +12,24 @@ def cli(): @cli.command() @click.option('-t', '--access_token', type=str, help='LINE Notify access token', required=True) -@click.option('-m', '--message', type=str, help='send text message', required=True) +@click.option('-m', '--message', type=str, help='send text message') @click.option('-u', '--image-url', type=str, help='Send image with image url', default=None) @click.option('-f', '--image-file', type=str, help='Send image file with local file', default=None) -def send_message(message, access_token, image_url, image_file): +@click.option('--sticker-package-id', type=str, help='Sticker package id', default=None) +@click.option('--sticker-id', type=str, help='Sticker id', default=None) +@click.option('-c', '--check-status', is_flag=True, help='Check status', default=False) +def send_message(message, access_token, image_url, image_file, + sticker_package_id, sticker_id, check_status): client = Client() + if check_status: + status = client.status(access_token) + click.echo("Status: {status}".format(status=status)) if image_url is not None: client.send_message_with_image_url(access_token, message, image_url, image_url) elif image_file is not None: client.send_message_with_image_file(access_token, message, open(image_file, 'rb')) + elif sticker_package_id is not None and sticker_id is not None: + client.send_message_with_sticker(access_token, message, sticker_id, sticker_package_id) else: client.send_message(access_token, message) click.echo("Send notification success.") diff --git a/lotify/client.py b/lotify/client.py index 3311a2f..d643f51 100644 --- a/lotify/client.py +++ b/lotify/client.py @@ -17,7 +17,6 @@ def __init__(self, bot_origin=None, api_origin=None, *args, **kwargs): - super(Client, self).__init__(*args, **kwargs) self.client_id = client_id or self.CLIENT_ID self.client_secret = client_secret or self.CLIENT_SECRET self.redirect_uri = redirect_uri or self.REDIRECT_URI @@ -86,8 +85,8 @@ def send_message_with_sticker( notification_disabled=False): params = { 'message': message, - 'stickerId': sticker_id, - 'stickerPackageId': sticker_package_id + 'stickerPackageId': sticker_package_id, + 'stickerId': sticker_id } if notification_disabled: params.update({'notificationDisabled': notification_disabled}) @@ -96,7 +95,8 @@ def send_message_with_sticker( url='{url}/api/notify'.format(url=self.api_origin), data=params, headers={ - 'Authorization': 'Bearer {token}'.format(token=access_token) + 'Authorization': 'Bearer {token}'.format(token=access_token), + 'Content-Type': 'application/x-www-form-urlencoded' }) return response.json() diff --git a/tests/test_cli.py b/tests/test_cli.py new file mode 100644 index 0000000..a816cb2 --- /dev/null +++ b/tests/test_cli.py @@ -0,0 +1,98 @@ +import unittest +import responses +from unittest.mock import patch +from click.testing import CliRunner +from lotify.cli import send_message + + +class TestCli(unittest.TestCase): + def setUp(self): + self.runner = CliRunner() + self.token = 'YgVGZjHTprZdsooj5xOGXBl9vVwLGBEbjyjaBWY1Mbe' + self.bot_origin = "https://notify-bot.line.me" + self.api_origin = "https://notify-api.line.me" + + @responses.activate + @patch('lotify.client.Client') + def test_check_status(self, mock_client): + responses.add( + responses.GET, + '{url}/api/status'.format(url=self.api_origin), + json={ + 'status': 200, + 'message': 'ok' + }, + status=200 + ) + mock_client.status.return_value = {'status': 200, 'message': 'ok'} + result = self.runner.invoke(send_message, ['--check-status', '--access_token', self.token]) + self.assertEqual(result.output, "Status: {'status': 200, 'message': 'ok'}\n") + + @responses.activate + @patch('lotify.client.Client') + def test_send_message(self, mock_client): + responses.add( + responses.POST, + '{url}/api/notify'.format(url=self.api_origin), + json={ + 'status': 200, + 'message': 'ok' + }, + status=200 + ) + mock_client.send_message.return_value = {'status': 200, 'message': 'ok'} + result = self.runner.invoke(send_message, ['--access_token', self.token, '--message', 'Hello']) + self.assertEqual(result.output, "Send notification success.\n") + + @responses.activate + @patch('lotify.client.Client') + def test_send_image_with_image_url(self, mock_client): + responses.add( + responses.POST, + '{url}/api/notify'.format(url=self.api_origin), + json={ + 'status': 200, + 'message': 'ok' + }, + status=200 + ) + mock_client.send_message_with_image_url.return_value = {'status': 200, 'message': 'ok'} + result = self.runner.invoke(send_message, ['--access_token', self.token, '--message', 'Hello', '--image-url', 'https://example.com/image.png']) + self.assertEqual(result.output, "Send notification success.\n") + + @responses.activate + @patch('lotify.client.Client') + def test_send_image_with_image_file(self, mock_client): + responses.add( + responses.POST, + '{url}/api/notify'.format(url=self.api_origin), + json={ + 'status': 200, + 'message': 'ok' + }, + status=200 + ) + + with self.runner.isolated_filesystem(): + with open('image.png', 'w') as f: + f.write('This is file object') + mock_client.send_message_with_image_file.return_value = {'status': 200, 'message': 'ok'} + result = self.runner.invoke(send_message, ['--access_token', self.token, '--message', 'Hello', '--image-file', 'image.png']) + + self.assertEqual(result.output, "Send notification success.\n") + + @responses.activate + @patch('lotify.client.Client') + def test_send_sticker_message(self, mock_client): + responses.add( + responses.POST, + '{url}/api/notify'.format(url=self.api_origin), + json={ + 'status': 200, + 'message': 'ok' + }, + status=200 + ) + mock_client.send_sticker_message.return_value = {'status': 200, 'message': 'ok'} + result = self.runner.invoke(send_message, ['--access_token', self.token, '--message', 'Hello', '--sticker-package-id', '1', '--sticker-id', '1']) + self.assertEqual(result.output, "Send notification success.\n") From ca71f8fc478a775721f4a3a88aeb142743803755 Mon Sep 17 00:00:00 2001 From: jerrychuang Date: Sat, 23 Dec 2023 22:43:59 +0800 Subject: [PATCH 2/2] Fix the CI error --- tests/test_cli.py | 123 ++++++++++++++++++++++++++++------------------ 1 file changed, 75 insertions(+), 48 deletions(-) diff --git a/tests/test_cli.py b/tests/test_cli.py index a816cb2..5f08fd9 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -8,91 +8,118 @@ class TestCli(unittest.TestCase): def setUp(self): self.runner = CliRunner() - self.token = 'YgVGZjHTprZdsooj5xOGXBl9vVwLGBEbjyjaBWY1Mbe' + self.token = "YgVGZjHTprZdsooj5xOGXBl9vVwLGBEbjyjaBWY1Mbe" self.bot_origin = "https://notify-bot.line.me" self.api_origin = "https://notify-api.line.me" @responses.activate - @patch('lotify.client.Client') + @patch("lotify.client.Client") def test_check_status(self, mock_client): responses.add( responses.GET, - '{url}/api/status'.format(url=self.api_origin), - json={ - 'status': 200, - 'message': 'ok' - }, - status=200 + "{url}/api/status".format(url=self.api_origin), + json={"status": 200, "message": "ok"}, + status=200, + ) + mock_client.status.return_value = {"status": 200, "message": "ok"} + result = self.runner.invoke( + send_message, ["--check-status", "--access_token", self.token] ) - mock_client.status.return_value = {'status': 200, 'message': 'ok'} - result = self.runner.invoke(send_message, ['--check-status', '--access_token', self.token]) self.assertEqual(result.output, "Status: {'status': 200, 'message': 'ok'}\n") @responses.activate - @patch('lotify.client.Client') + @patch("lotify.client.Client") def test_send_message(self, mock_client): responses.add( responses.POST, - '{url}/api/notify'.format(url=self.api_origin), - json={ - 'status': 200, - 'message': 'ok' - }, - status=200 + "{url}/api/notify".format(url=self.api_origin), + json={"status": 200, "message": "ok"}, + status=200, + ) + mock_client.send_message.return_value = {"status": 200, "message": "ok"} + result = self.runner.invoke( + send_message, ["--access_token", self.token, "--message", "Hello"] ) - mock_client.send_message.return_value = {'status': 200, 'message': 'ok'} - result = self.runner.invoke(send_message, ['--access_token', self.token, '--message', 'Hello']) self.assertEqual(result.output, "Send notification success.\n") @responses.activate - @patch('lotify.client.Client') + @patch("lotify.client.Client") def test_send_image_with_image_url(self, mock_client): responses.add( responses.POST, - '{url}/api/notify'.format(url=self.api_origin), - json={ - 'status': 200, - 'message': 'ok' - }, - status=200 + "{url}/api/notify".format(url=self.api_origin), + json={"status": 200, "message": "ok"}, + status=200, + ) + mock_client.send_message_with_image_url.return_value = { + "status": 200, + "message": "ok", + } + result = self.runner.invoke( + send_message, + [ + "--access_token", + self.token, + "--message", + "Hello", + "--image-url", + "https://example.com/image.png", + ], ) - mock_client.send_message_with_image_url.return_value = {'status': 200, 'message': 'ok'} - result = self.runner.invoke(send_message, ['--access_token', self.token, '--message', 'Hello', '--image-url', 'https://example.com/image.png']) self.assertEqual(result.output, "Send notification success.\n") @responses.activate - @patch('lotify.client.Client') + @patch("lotify.client.Client") def test_send_image_with_image_file(self, mock_client): responses.add( responses.POST, - '{url}/api/notify'.format(url=self.api_origin), - json={ - 'status': 200, - 'message': 'ok' - }, - status=200 + "{url}/api/notify".format(url=self.api_origin), + json={"status": 200, "message": "ok"}, + status=200, ) with self.runner.isolated_filesystem(): - with open('image.png', 'w') as f: - f.write('This is file object') - mock_client.send_message_with_image_file.return_value = {'status': 200, 'message': 'ok'} - result = self.runner.invoke(send_message, ['--access_token', self.token, '--message', 'Hello', '--image-file', 'image.png']) + with open("image.png", "w") as f: + f.write("This is file object") + mock_client.send_message_with_image_file.return_value = { + "status": 200, + "message": "ok", + } + result = self.runner.invoke( + send_message, + [ + "--access_token", + self.token, + "--message", + "Hello", + "--image-file", + "image.png", + ], + ) self.assertEqual(result.output, "Send notification success.\n") @responses.activate - @patch('lotify.client.Client') + @patch("lotify.client.Client") def test_send_sticker_message(self, mock_client): responses.add( responses.POST, - '{url}/api/notify'.format(url=self.api_origin), - json={ - 'status': 200, - 'message': 'ok' - }, - status=200 + "{url}/api/notify".format(url=self.api_origin), + json={"status": 200, "message": "ok"}, + status=200, + ) + mock_client.send_sticker_message.return_value = {"status": 200, "message": "ok"} + result = self.runner.invoke( + send_message, + [ + "--access_token", + self.token, + "--message", + "Hello", + "--sticker-package-id", + "1", + "--sticker-id", + "1", + ], ) - mock_client.send_sticker_message.return_value = {'status': 200, 'message': 'ok'} - result = self.runner.invoke(send_message, ['--access_token', self.token, '--message', 'Hello', '--sticker-package-id', '1', '--sticker-id', '1']) self.assertEqual(result.output, "Send notification success.\n")