From 000ab155fe827370c042daf962db52e05eff9003 Mon Sep 17 00:00:00 2001 From: CA-Lee Date: Tue, 13 Oct 2020 09:30:37 +0800 Subject: [PATCH 01/15] Add function prototypes --- linebot/api.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/linebot/api.py b/linebot/api.py index 85bee50a..b93e7e8b 100644 --- a/linebot/api.py +++ b/linebot/api.py @@ -1129,6 +1129,15 @@ def get_insight_message_event(self, request_id, timeout=None): return InsightMessageEventResponse.new_from_json_dict(response.json) + def set_webhook_endpoint(self, webhook_endpoint, timeout=None): + pass + + def get_webhook_endpoint(self, timeout=None): + pass + + def test_webhook_endpoint(self, webhook_endpoint=None, timeout=None): + pass + def _get(self, path, endpoint=None, params=None, headers=None, stream=False, timeout=None): url = (endpoint or self.endpoint) + path From 67e905fc2e6229b9470c4e57678ab80ff62b8c03 Mon Sep 17 00:00:00 2001 From: CA-Lee Date: Tue, 13 Oct 2020 11:44:15 +0800 Subject: [PATCH 02/15] update feature: get_webhook_endpoint --- linebot/api.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/linebot/api.py b/linebot/api.py index b93e7e8b..2107fa00 100644 --- a/linebot/api.py +++ b/linebot/api.py @@ -1133,7 +1133,13 @@ def set_webhook_endpoint(self, webhook_endpoint, timeout=None): pass def get_webhook_endpoint(self, timeout=None): - pass + + response = self._get( + '/v2/bot/channel/webhook/endpoint', + timeout=timeout, + ) + + return response.json def test_webhook_endpoint(self, webhook_endpoint=None, timeout=None): pass From 17b263b06a53b018e14c9be2b41a4370b1e99c63 Mon Sep 17 00:00:00 2001 From: CA-Lee Date: Tue, 13 Oct 2020 13:17:22 +0800 Subject: [PATCH 03/15] Implent put method request --- linebot/api.py | 14 ++++++++++++++ linebot/http_client.py | 13 +++++++++++++ 2 files changed, 27 insertions(+) diff --git a/linebot/api.py b/linebot/api.py index 2107fa00..56801a38 100644 --- a/linebot/api.py +++ b/linebot/api.py @@ -1186,6 +1186,20 @@ def _delete(self, path, endpoint=None, data=None, headers=None, timeout=None): self.__check_error(response) return response + def _put(self, path, endpoint=None, data=None, headers=None, timeout=None): + url = (endpoint or self.endpoint) + path + + if headers is None: + headers = {'Content-Type': 'application/json'} + headers.update(self.headers) + + response = self.http_client.put( + url, headers=headers, data=data, timeout=timeout + ) + + self.__check_error(response) + return response + @staticmethod def __check_error(response): if 200 <= response.status_code < 300: diff --git a/linebot/http_client.py b/linebot/http_client.py index b3e05689..036ce1a3 100644 --- a/linebot/http_client.py +++ b/linebot/http_client.py @@ -92,6 +92,9 @@ def delete(self, url, headers=None, data=None, timeout=None): """ raise NotImplementedError + @abstractmethod + def put(self, url, headers=None, data=None, timeout=None): + raise NotImplementedError class RequestsHttpClient(HttpClient): """HttpClient implemented by requests.""" @@ -177,6 +180,16 @@ def delete(self, url, headers=None, data=None, timeout=None): return RequestsHttpResponse(response) + def put(self, url, headers=None, data=None, timeout=None): + + if timeout is None: + timeout = self.timeout + + response = requests.put( + url, headers=headers, data=data, timeout=timeout + ) + + return RequestsHttpResponse(response) class HttpResponse(with_metaclass(ABCMeta)): """HttpResponse.""" From 443979dd4a40eff9617f50e075e62c2808120c6c Mon Sep 17 00:00:00 2001 From: CA-Lee Date: Tue, 13 Oct 2020 13:18:23 +0800 Subject: [PATCH 04/15] Implent feature: set_webhook_endpoint --- linebot/api.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/linebot/api.py b/linebot/api.py index 56801a38..a72f6fc0 100644 --- a/linebot/api.py +++ b/linebot/api.py @@ -1130,7 +1130,16 @@ def get_insight_message_event(self, request_id, timeout=None): return InsightMessageEventResponse.new_from_json_dict(response.json) def set_webhook_endpoint(self, webhook_endpoint, timeout=None): - pass + + data={ + 'endpoint': webhook_endpoint + } + + self._put( + '/v2/bot/channel/webhook/endpoint', + data=json.dumps(data), + timeout=timeout, + ) def get_webhook_endpoint(self, timeout=None): From e263e772e274c6333f3b43e4b30dcf24aba47d02 Mon Sep 17 00:00:00 2001 From: CA-Lee Date: Tue, 13 Oct 2020 16:03:12 +0800 Subject: [PATCH 05/15] Implent feature: test_webhook_endpoint --- linebot/api.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/linebot/api.py b/linebot/api.py index a72f6fc0..ebc8021e 100644 --- a/linebot/api.py +++ b/linebot/api.py @@ -1151,7 +1151,19 @@ def get_webhook_endpoint(self, timeout=None): return response.json def test_webhook_endpoint(self, webhook_endpoint=None, timeout=None): - pass + + data = {} + + if webhook_endpoint is not None: + data['endpoint'] = webhook_endpoint + + response = self._post( + '/v2/bot/channel/webhook/test', + data=json.dumps(data), + timeout=timeout, + ) + + return response.json def _get(self, path, endpoint=None, params=None, headers=None, stream=False, timeout=None): url = (endpoint or self.endpoint) + path From 26215f8042bb5e2b63ccff8a40dde79d80b4912b Mon Sep 17 00:00:00 2001 From: CA-Lee Date: Tue, 13 Oct 2020 22:22:08 +0800 Subject: [PATCH 06/15] Add documentations --- linebot/api.py | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/linebot/api.py b/linebot/api.py index ebc8021e..6458450f 100644 --- a/linebot/api.py +++ b/linebot/api.py @@ -1130,7 +1130,17 @@ def get_insight_message_event(self, request_id, timeout=None): return InsightMessageEventResponse.new_from_json_dict(response.json) def set_webhook_endpoint(self, webhook_endpoint, timeout=None): + """Sets the webhook endpoint URL. + https://developers.line.biz/en/reference/messaging-api/#set-webhook-endpoint-url + + :param str webhook_endpoint: A valid webhook URL to be set. + :param timeout: (optional) How long to wait for the server + to send data before giving up, as a float, + or a (connect timeout, read timeout) float tuple. + Default is self.http_client.timeout + :type timeout: float | tuple(float, float) + """ data={ 'endpoint': webhook_endpoint } @@ -1142,7 +1152,19 @@ def set_webhook_endpoint(self, webhook_endpoint, timeout=None): ) def get_webhook_endpoint(self, timeout=None): + """Gets information on a webhook endpoint. + https://developers.line.biz/en/reference/messaging-api/#get-webhook-endpoint-information + + :param timeout: (optional) How long to wait for the server + to send data before giving up, as a float, + or a (connect timeout, read timeout) float tuple. + Default is self.http_client.timeout + :type timeout: float | tuple(float, float) + :rtype: dict + :return: Webhook information, including `endpoint` for webhook + URL and `active` for webhook usage status. + """ response = self._get( '/v2/bot/channel/webhook/endpoint', timeout=timeout, @@ -1151,7 +1173,20 @@ def get_webhook_endpoint(self, timeout=None): return response.json def test_webhook_endpoint(self, webhook_endpoint=None, timeout=None): + """Checks if the configured webhook endpoint can receive a test webhook event. + https://developers.line.biz/en/reference/messaging-api/#test-webhook-endpoint + + :param webhook_endpoint: (optional) Set this parameter to + specific the webhook endpoint of the webhook. Default is the webhook + endpoint that is already set to the channel. + :param timeout: (optional) How long to wait for the server + to send data before giving up, as a float, + or a (connect timeout, read timeout) float tuple. + Default is self.http_client.timeout + :type timeout: float | tuple(float, float) + :rtype: dict + """ data = {} if webhook_endpoint is not None: From b0c4d4f75b14997449f9603d7184d77b890ca2dc Mon Sep 17 00:00:00 2001 From: CA-Lee Date: Wed, 14 Oct 2020 00:24:37 +0800 Subject: [PATCH 07/15] Add test --- tests/api/test_get_webhook_endpoint.py | 54 ++++++++++++++++++++++ tests/api/test_set_webhook_endpoint.py | 49 ++++++++++++++++++++ tests/api/test_test_webhook_endpoint.py | 60 +++++++++++++++++++++++++ 3 files changed, 163 insertions(+) create mode 100644 tests/api/test_get_webhook_endpoint.py create mode 100644 tests/api/test_set_webhook_endpoint.py create mode 100644 tests/api/test_test_webhook_endpoint.py diff --git a/tests/api/test_get_webhook_endpoint.py b/tests/api/test_get_webhook_endpoint.py new file mode 100644 index 00000000..39c56bbc --- /dev/null +++ b/tests/api/test_get_webhook_endpoint.py @@ -0,0 +1,54 @@ +# -*- coding: utf-8 -*- + +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +from __future__ import unicode_literals, absolute_import + +import unittest + +import responses + +from linebot import ( + LineBotApi +) + + +class TestLineBotApi(unittest.TestCase): + def setUp(self): + self.tested = LineBotApi('channel_secret') + + @responses.activate + def test_get_webhook_endpoint(self): + responses.add( + responses.GET, + LineBotApi.DEFAULT_API_ENDPOINT + '/v2/bot/channel/webhook/endpoint', + json={ + "endpoint": "https://example.herokuapp.com/test", + "active": "true", + }, + status=200 + ) + + webhook = self.tested.get_webhook_endpoint() + + request = responses.calls[0].request + self.assertEqual(request.method, 'GET') + self.assertEqual( + request.url, + LineBotApi.DEFAULT_API_ENDPOINT + '/v2/bot/channel/webhook/endpoint') + self.assertEqual(webhook['endpoint'], 'https://example.herokuapp.com/test') + self.assertEqual(webhook['active'], 'true') + + +if __name__ == '__main__': + unittest.main() diff --git a/tests/api/test_set_webhook_endpoint.py b/tests/api/test_set_webhook_endpoint.py new file mode 100644 index 00000000..96ad3d0d --- /dev/null +++ b/tests/api/test_set_webhook_endpoint.py @@ -0,0 +1,49 @@ +# -*- coding: utf-8 -*- + +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +from __future__ import unicode_literals, absolute_import + +import unittest + +import responses + +from linebot import ( + LineBotApi +) + + +class TestLineBotApi(unittest.TestCase): + def setUp(self): + self.tested = LineBotApi('channel_secret') + + @responses.activate + def test_set_webhook_endpoint(self): + responses.add( + responses.PUT, + LineBotApi.DEFAULT_API_ENDPOINT + '/v2/bot/channel/webhook/endpoint', + json={}, + status=200 + ) + + result = self.tested.set_webhook_endpoint('endpoint') + + request = responses.calls[0].request + self.assertEqual(request.method, 'PUT') + self.assertEqual( + request.url, + LineBotApi.DEFAULT_API_ENDPOINT + '/v2/bot/channel/webhook/endpoint') + + +if __name__ == '__main__': + unittest.main() diff --git a/tests/api/test_test_webhook_endpoint.py b/tests/api/test_test_webhook_endpoint.py new file mode 100644 index 00000000..717d3d2f --- /dev/null +++ b/tests/api/test_test_webhook_endpoint.py @@ -0,0 +1,60 @@ +# -*- coding: utf-8 -*- + +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +from __future__ import unicode_literals, absolute_import + +import unittest + +import responses + +from linebot import ( + LineBotApi +) + + +class TestLineBotApi(unittest.TestCase): + def setUp(self): + self.tested = LineBotApi('channel_secret') + + @responses.activate + def test_test_webhook_endpoint_with_endpoint(self): + responses.add( + responses.POST, + LineBotApi.DEFAULT_API_ENDPOINT + '/v2/bot/channel/webhook/test', + json={ + "success": "true", + "timestamp": "2020-09-30T05:38:20.031Z", + "statusCode": 200, + "reason": "OK", + "detail": "200" + }, + status=200 + ) + + result = self.tested.test_webhook_endpoint('endpoint') + + request = responses.calls[0].request + self.assertEqual(request.method, 'POST') + self.assertEqual( + request.url, + LineBotApi.DEFAULT_API_ENDPOINT + '/v2/bot/channel/webhook/test') + self.assertEqual(result['success'], 'true') + self.assertEqual(result['timestamp'], '2020-09-30T05:38:20.031Z') + self.assertEqual(result['statusCode'], 200) + self.assertEqual(result['reason'], 'OK') + self.assertEqual(result['detail'], '200') + + +if __name__ == '__main__': + unittest.main() From a978004922aa1c7ae90d9952d56d73bbbb2e91c3 Mon Sep 17 00:00:00 2001 From: CA-Lee Date: Wed, 14 Oct 2020 11:39:16 +0800 Subject: [PATCH 08/15] fix CI errors --- linebot/api.py | 14 +++++++------- linebot/http_client.py | 29 ++++++++++++++++++++++++++++- 2 files changed, 35 insertions(+), 8 deletions(-) diff --git a/linebot/api.py b/linebot/api.py index 6458450f..2623d47c 100644 --- a/linebot/api.py +++ b/linebot/api.py @@ -1130,8 +1130,8 @@ def get_insight_message_event(self, request_id, timeout=None): return InsightMessageEventResponse.new_from_json_dict(response.json) def set_webhook_endpoint(self, webhook_endpoint, timeout=None): - """Sets the webhook endpoint URL. - + """Set the webhook endpoint URL. + https://developers.line.biz/en/reference/messaging-api/#set-webhook-endpoint-url :param str webhook_endpoint: A valid webhook URL to be set. @@ -1141,7 +1141,7 @@ def set_webhook_endpoint(self, webhook_endpoint, timeout=None): Default is self.http_client.timeout :type timeout: float | tuple(float, float) """ - data={ + data = { 'endpoint': webhook_endpoint } @@ -1152,8 +1152,8 @@ def set_webhook_endpoint(self, webhook_endpoint, timeout=None): ) def get_webhook_endpoint(self, timeout=None): - """Gets information on a webhook endpoint. - + """Get information on a webhook endpoint. + https://developers.line.biz/en/reference/messaging-api/#get-webhook-endpoint-information :param timeout: (optional) How long to wait for the server @@ -1174,9 +1174,9 @@ def get_webhook_endpoint(self, timeout=None): def test_webhook_endpoint(self, webhook_endpoint=None, timeout=None): """Checks if the configured webhook endpoint can receive a test webhook event. - + https://developers.line.biz/en/reference/messaging-api/#test-webhook-endpoint - + :param webhook_endpoint: (optional) Set this parameter to specific the webhook endpoint of the webhook. Default is the webhook endpoint that is already set to the channel. diff --git a/linebot/http_client.py b/linebot/http_client.py index 036ce1a3..2bfe5c94 100644 --- a/linebot/http_client.py +++ b/linebot/http_client.py @@ -94,8 +94,22 @@ def delete(self, url, headers=None, data=None, timeout=None): @abstractmethod def put(self, url, headers=None, data=None, timeout=None): + """PUT request. + + :param str url: Request url + :param dict headers: (optional) Request headers + :param data: (optional) Dictionary, bytes, or file-like object to send in the body + :param timeout: (optional), How long to wait for the server + to send data before giving up, as a float, + or a (connect timeout, read timeout) float tuple. + Default is :py:attr:`self.timeout` + :type timeout: float | tuple(float, float) + :rtype: :py:class:`RequestsHttpResponse` + :return: RequestsHttpResponse instance + """ raise NotImplementedError + class RequestsHttpClient(HttpClient): """HttpClient implemented by requests.""" @@ -181,7 +195,19 @@ def delete(self, url, headers=None, data=None, timeout=None): return RequestsHttpResponse(response) def put(self, url, headers=None, data=None, timeout=None): - + """PUT request. + + :param str url: Request url + :param dict headers: (optional) Request headers + :param data: (optional) Dictionary, bytes, or file-like object to send in the body + :param timeout: (optional), How long to wait for the server + to send data before giving up, as a float, + or a (connect timeout, read timeout) float tuple. + Default is :py:attr:`self.timeout` + :type timeout: float | tuple(float, float) + :rtype: :py:class:`RequestsHttpResponse` + :return: RequestsHttpResponse instance + """ if timeout is None: timeout = self.timeout @@ -191,6 +217,7 @@ def put(self, url, headers=None, data=None, timeout=None): return RequestsHttpResponse(response) + class HttpResponse(with_metaclass(ABCMeta)): """HttpResponse.""" From f9b57f02a543b14fa61ee947a529af158fdafb15 Mon Sep 17 00:00:00 2001 From: CA-Lee Date: Wed, 14 Oct 2020 11:39:36 +0800 Subject: [PATCH 09/15] remove unused variable --- tests/api/test_set_webhook_endpoint.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/api/test_set_webhook_endpoint.py b/tests/api/test_set_webhook_endpoint.py index 96ad3d0d..329a8cd5 100644 --- a/tests/api/test_set_webhook_endpoint.py +++ b/tests/api/test_set_webhook_endpoint.py @@ -36,7 +36,7 @@ def test_set_webhook_endpoint(self): status=200 ) - result = self.tested.set_webhook_endpoint('endpoint') + self.tested.set_webhook_endpoint('endpoint') request = responses.calls[0].request self.assertEqual(request.method, 'PUT') From 5527f743451854ce3c02c009bbd8c08614267033 Mon Sep 17 00:00:00 2001 From: CA-Lee Date: Mon, 19 Oct 2020 14:55:46 +0800 Subject: [PATCH 10/15] Update feature: Use GetWebhookResponse model --- linebot/api.py | 4 ++-- linebot/models/__init__.py | 1 + linebot/models/responses.py | 22 ++++++++++++++++++++++ tests/api/test_get_webhook_endpoint.py | 4 ++-- 4 files changed, 27 insertions(+), 4 deletions(-) diff --git a/linebot/api.py b/linebot/api.py index 2623d47c..886456fb 100644 --- a/linebot/api.py +++ b/linebot/api.py @@ -28,7 +28,7 @@ MessageDeliveryPushResponse, MessageDeliveryReplyResponse, InsightMessageDeliveryResponse, InsightFollowersResponse, InsightDemographicResponse, InsightMessageEventResponse, BroadcastResponse, NarrowcastResponse, - MessageProgressNarrowcastResponse, + MessageProgressNarrowcastResponse, GetWebhookResponse ) from .models.responses import Group @@ -1170,7 +1170,7 @@ def get_webhook_endpoint(self, timeout=None): timeout=timeout, ) - return response.json + return GetWebhookResponse.new_from_json_dict(response.json) def test_webhook_endpoint(self, webhook_endpoint=None, timeout=None): """Checks if the configured webhook endpoint can receive a test webhook event. diff --git a/linebot/models/__init__.py b/linebot/models/__init__.py index f321a37d..b921d5df 100644 --- a/linebot/models/__init__.py +++ b/linebot/models/__init__.py @@ -150,6 +150,7 @@ BroadcastResponse, NarrowcastResponse, MessageProgressNarrowcastResponse, + GetWebhookResponse, ) from .rich_menu import ( # noqa RichMenu, diff --git a/linebot/models/responses.py b/linebot/models/responses.py index 936c60af..d2d23103 100644 --- a/linebot/models/responses.py +++ b/linebot/models/responses.py @@ -496,3 +496,25 @@ def __init__(self, request_id=None, **kwargs): super(NarrowcastResponse, self).__init__(**kwargs) self.request_id = request_id + + +class GetWebhookResponse(Base): + """Response of `get_webhook_endpoint()` . + + https://developers.line.biz/en/reference/messaging-api/#get-webhook-endpoint-information + """ + + def __init__(self, endpoint=None, active=None, **kwargs): + """__init__ method. + + :param str endpoint: The webhook endpoint URL. + :param bool active: Whether the webhook is in use. + :param kwargs: + """ + super(GetWebhookResponse, self).__init__(**kwargs) + + self.endpoint = endpoint + if active == 'true': + self.active = True + elif active == 'false': + self.active = False diff --git a/tests/api/test_get_webhook_endpoint.py b/tests/api/test_get_webhook_endpoint.py index 39c56bbc..d2013630 100644 --- a/tests/api/test_get_webhook_endpoint.py +++ b/tests/api/test_get_webhook_endpoint.py @@ -46,8 +46,8 @@ def test_get_webhook_endpoint(self): self.assertEqual( request.url, LineBotApi.DEFAULT_API_ENDPOINT + '/v2/bot/channel/webhook/endpoint') - self.assertEqual(webhook['endpoint'], 'https://example.herokuapp.com/test') - self.assertEqual(webhook['active'], 'true') + self.assertEqual(webhook.endpoint, 'https://example.herokuapp.com/test') + self.assertEqual(webhook.active, True) if __name__ == '__main__': From df150daf09422bcaf831e16089ecb467b2c705dc Mon Sep 17 00:00:00 2001 From: CA-Lee Date: Mon, 19 Oct 2020 15:23:22 +0800 Subject: [PATCH 11/15] fix bug --- linebot/models/responses.py | 6 ++---- tests/api/test_get_webhook_endpoint.py | 2 +- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/linebot/models/responses.py b/linebot/models/responses.py index d2d23103..fa2828c7 100644 --- a/linebot/models/responses.py +++ b/linebot/models/responses.py @@ -514,7 +514,5 @@ def __init__(self, endpoint=None, active=None, **kwargs): super(GetWebhookResponse, self).__init__(**kwargs) self.endpoint = endpoint - if active == 'true': - self.active = True - elif active == 'false': - self.active = False + self.active = active + diff --git a/tests/api/test_get_webhook_endpoint.py b/tests/api/test_get_webhook_endpoint.py index d2013630..ae69be65 100644 --- a/tests/api/test_get_webhook_endpoint.py +++ b/tests/api/test_get_webhook_endpoint.py @@ -34,7 +34,7 @@ def test_get_webhook_endpoint(self): LineBotApi.DEFAULT_API_ENDPOINT + '/v2/bot/channel/webhook/endpoint', json={ "endpoint": "https://example.herokuapp.com/test", - "active": "true", + "active": True, }, status=200 ) From 7d15a1f800a996f009dfad99f0a350e3be694a86 Mon Sep 17 00:00:00 2001 From: CA-Lee Date: Mon, 19 Oct 2020 15:24:19 +0800 Subject: [PATCH 12/15] Update feature: use TestWebhookResponse --- linebot/api.py | 4 ++-- linebot/models/__init__.py | 1 + linebot/models/responses.py | 26 +++++++++++++++++++++++++ tests/api/test_test_webhook_endpoint.py | 12 ++++++------ 4 files changed, 35 insertions(+), 8 deletions(-) diff --git a/linebot/api.py b/linebot/api.py index 886456fb..7c209c07 100644 --- a/linebot/api.py +++ b/linebot/api.py @@ -28,7 +28,7 @@ MessageDeliveryPushResponse, MessageDeliveryReplyResponse, InsightMessageDeliveryResponse, InsightFollowersResponse, InsightDemographicResponse, InsightMessageEventResponse, BroadcastResponse, NarrowcastResponse, - MessageProgressNarrowcastResponse, GetWebhookResponse + MessageProgressNarrowcastResponse, GetWebhookResponse, TestWebhookResponse ) from .models.responses import Group @@ -1198,7 +1198,7 @@ def test_webhook_endpoint(self, webhook_endpoint=None, timeout=None): timeout=timeout, ) - return response.json + return TestWebhookResponse.new_from_json_dict(response.json) def _get(self, path, endpoint=None, params=None, headers=None, stream=False, timeout=None): url = (endpoint or self.endpoint) + path diff --git a/linebot/models/__init__.py b/linebot/models/__init__.py index b921d5df..50017a4b 100644 --- a/linebot/models/__init__.py +++ b/linebot/models/__init__.py @@ -151,6 +151,7 @@ NarrowcastResponse, MessageProgressNarrowcastResponse, GetWebhookResponse, + TestWebhookResponse, ) from .rich_menu import ( # noqa RichMenu, diff --git a/linebot/models/responses.py b/linebot/models/responses.py index fa2828c7..ac1377bc 100644 --- a/linebot/models/responses.py +++ b/linebot/models/responses.py @@ -516,3 +516,29 @@ def __init__(self, endpoint=None, active=None, **kwargs): self.endpoint = endpoint self.active = active + +class TestWebhookResponse(Base): + """Response of `test_webhook_endpoint()` . + + https://developers.line.biz/en/reference/messaging-api/#test-webhook-endpoint + """ + + def __init__(self, success=None, timestamp=None, status_code=None, + reason=None, detail=None, **kwargs): + """__init__ method. + + :param bool success: Result of the communication from the LINE platform + to the webhook URL. + :param str timestamp: Timestamp + :param int status_code: The HTTP status code. + :param str reason: Reason for the response. + :param str detail: Details of the response. + :param kwargs: + """ + super(TestWebhookResponse, self).__init__(**kwargs) + + self.success = success + self.timestamp = timestamp + self.status_code = status_code + self.reason = reason + self.detail = detail diff --git a/tests/api/test_test_webhook_endpoint.py b/tests/api/test_test_webhook_endpoint.py index 717d3d2f..6bced6c7 100644 --- a/tests/api/test_test_webhook_endpoint.py +++ b/tests/api/test_test_webhook_endpoint.py @@ -33,7 +33,7 @@ def test_test_webhook_endpoint_with_endpoint(self): responses.POST, LineBotApi.DEFAULT_API_ENDPOINT + '/v2/bot/channel/webhook/test', json={ - "success": "true", + "success": True, "timestamp": "2020-09-30T05:38:20.031Z", "statusCode": 200, "reason": "OK", @@ -49,11 +49,11 @@ def test_test_webhook_endpoint_with_endpoint(self): self.assertEqual( request.url, LineBotApi.DEFAULT_API_ENDPOINT + '/v2/bot/channel/webhook/test') - self.assertEqual(result['success'], 'true') - self.assertEqual(result['timestamp'], '2020-09-30T05:38:20.031Z') - self.assertEqual(result['statusCode'], 200) - self.assertEqual(result['reason'], 'OK') - self.assertEqual(result['detail'], '200') + self.assertEqual(result.success, True) + self.assertEqual(result.timestamp, '2020-09-30T05:38:20.031Z') + self.assertEqual(result.status_code, 200) + self.assertEqual(result.reason, 'OK') + self.assertEqual(result.detail, '200') if __name__ == '__main__': From 4950d8b7dd1b206b4884e15a824e5355bf108eea Mon Sep 17 00:00:00 2001 From: CA-Lee Date: Mon, 19 Oct 2020 16:24:23 +0800 Subject: [PATCH 13/15] fix: set webhook response body --- linebot/api.py | 6 +++++- tests/api/test_set_webhook_endpoint.py | 3 ++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/linebot/api.py b/linebot/api.py index 7c209c07..0bb79d8c 100644 --- a/linebot/api.py +++ b/linebot/api.py @@ -1140,17 +1140,21 @@ def set_webhook_endpoint(self, webhook_endpoint, timeout=None): or a (connect timeout, read timeout) float tuple. Default is self.http_client.timeout :type timeout: float | tuple(float, float) + :rtype: dict + :return: Empty dict. """ data = { 'endpoint': webhook_endpoint } - self._put( + response = self._put( '/v2/bot/channel/webhook/endpoint', data=json.dumps(data), timeout=timeout, ) + return response.json + def get_webhook_endpoint(self, timeout=None): """Get information on a webhook endpoint. diff --git a/tests/api/test_set_webhook_endpoint.py b/tests/api/test_set_webhook_endpoint.py index 329a8cd5..59574c6c 100644 --- a/tests/api/test_set_webhook_endpoint.py +++ b/tests/api/test_set_webhook_endpoint.py @@ -36,13 +36,14 @@ def test_set_webhook_endpoint(self): status=200 ) - self.tested.set_webhook_endpoint('endpoint') + result = self.tested.set_webhook_endpoint('endpoint') request = responses.calls[0].request self.assertEqual(request.method, 'PUT') self.assertEqual( request.url, LineBotApi.DEFAULT_API_ENDPOINT + '/v2/bot/channel/webhook/endpoint') + self.assertEqual(result, {}) if __name__ == '__main__': From 21170f57841cb11c1c62ec658523a10927f29759 Mon Sep 17 00:00:00 2001 From: CA-Lee Date: Mon, 19 Oct 2020 16:27:28 +0800 Subject: [PATCH 14/15] Update documentation --- linebot/api.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/linebot/api.py b/linebot/api.py index 0bb79d8c..9f1a9c85 100644 --- a/linebot/api.py +++ b/linebot/api.py @@ -1165,7 +1165,7 @@ def get_webhook_endpoint(self, timeout=None): or a (connect timeout, read timeout) float tuple. Default is self.http_client.timeout :type timeout: float | tuple(float, float) - :rtype: dict + :rtype: :py:class:`linebot.models.responses.GetWebhookResponse` :return: Webhook information, including `endpoint` for webhook URL and `active` for webhook usage status. """ @@ -1189,7 +1189,7 @@ def test_webhook_endpoint(self, webhook_endpoint=None, timeout=None): or a (connect timeout, read timeout) float tuple. Default is self.http_client.timeout :type timeout: float | tuple(float, float) - :rtype: dict + :rtype: :py:class:`linebot.models.responses.TestWebhookResponse` """ data = {} From 315596d16f2888f16c9d2811c3e73d74566ad818 Mon Sep 17 00:00:00 2001 From: CA-Lee Date: Mon, 19 Oct 2020 13:59:00 +0800 Subject: [PATCH 15/15] Update README.rst: get/set/test_webhook_endpoint() --- README.rst | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/README.rst b/README.rst index 368f99a8..b129bdf8 100644 --- a/README.rst +++ b/README.rst @@ -591,6 +591,46 @@ https://developers.line.biz/en/reference/messaging-api/#get-message-event insight = line_bot_api.get_insight_message_event(broadcast_response.request_id) print(insight.overview) +set\_webhook\_endpoint(self, webhook_endpoint, timeout=None) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Set the webhook endpoint URL. + +https://developers.line.biz/en/reference/messaging-api/#set-webhook-endpoint-url + +.. code:: python + + line_bot_api.set_webhook_endpoint() + +get\_webhook\_endpoint(self, timeout=None) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Get information on a webhook endpoint. + +https://developers.line.biz/en/reference/messaging-api/#get-webhook-endpoint-information + +.. code:: python + + webhook = line_bot_api.get_webhook_endpoint() + print(webhook.endpoint) + print(webhook.active) + +test\_webhook\_endpoint(self, webhook_endpoint=None, timeout=None) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Check if the configured webhook endpoint can receive a test webhook event. + +https://developers.line.biz/en/reference/messaging-api/#test-webhook-endpoint + +.. code:: python + + test_result = line_bot_api.test_webhook_endpoint() + print(test_result.success) + print(test_result.timestamp) + print(test_result.status_code) + print(test_result.reason) + print(test_result.detail) + ※ Error handling ^^^^^^^^^^^^^^^^^