Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 8 additions & 3 deletions linebot/models/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,11 +86,15 @@ def as_json_dict(self):
return data

@classmethod
def new_from_json_dict(cls, data):
def new_from_json_dict(cls, data, use_raw_message=False):
"""Create a new instance from a dict.

:param data: JSON dict
:param bool use_raw_message: Using original Message key as attribute
"""
if use_raw_message:
return cls(use_raw_message=use_raw_message, **data)

new_data = {utils.to_snake_case(key): value
for key, value in data.items()}

Expand All @@ -117,7 +121,7 @@ def get_or_new_from_json_dict(data, cls):

@staticmethod
def get_or_new_from_json_dict_with_types(
data, cls_map, type_key='type'
data, cls_map, type_key='type', use_raw_message=False
):
"""Get `cls` object w/ deserialization from json by using type key hint if needed.

Expand All @@ -129,12 +133,13 @@ def get_or_new_from_json_dict_with_types(
:param cls_map:
:param type_key:
:rtype: object
:param bool use_raw_message: Using original Message key as attribute
"""
if isinstance(data, tuple(cls_map.values())):
return data
elif isinstance(data, dict):
type_val = data[type_key]
if type_val in cls_map:
return cls_map[type_val].new_from_json_dict(data)
return cls_map[type_val].new_from_json_dict(data, use_raw_message=use_raw_message)

return None
5 changes: 3 additions & 2 deletions linebot/models/events.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ class MessageEvent(Event):
"""

def __init__(self, mode=None, timestamp=None, source=None, reply_token=None, message=None,
**kwargs):
use_raw_message=False, **kwargs):
"""__init__ method.

:param str mode: Channel state
Expand All @@ -113,6 +113,7 @@ def __init__(self, mode=None, timestamp=None, source=None, reply_token=None, mes
:param str reply_token: Reply token
:param message: Message object
:type message: T <= :py:class:`linebot.models.messages.Message`
:param bool use_raw_message: Using original Message key as attribute
:param kwargs:
"""
super(MessageEvent, self).__init__(
Expand All @@ -130,7 +131,7 @@ def __init__(self, mode=None, timestamp=None, source=None, reply_token=None, mes
'location': LocationMessage,
'sticker': StickerMessage,
'file': FileMessage
}
}, use_raw_message=use_raw_message
)


Expand Down
13 changes: 12 additions & 1 deletion linebot/models/messages.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,17 +35,28 @@
class Message(with_metaclass(ABCMeta, Base)):
"""Abstract Base Class of Message."""

def __init__(self, id=None, **kwargs):
def __init__(self, id=None, use_raw_message=False, **kwargs):
"""__init__ method.

:param str id: Message ID
:param bool use_raw_message: Using original Message key as attribute
:param kwargs:
"""
super(Message, self).__init__(**kwargs)

if use_raw_message:
self.__dict__.update(kwargs)

self.type = None
self.id = id

def __getitem__(self, key):
"""__getitem__ method.

:param str key: Message key
"""
return self.__dict__.get(key, None)


@deprecated(reason="Use 'from linebot.v3.webhooks import TextMessageContent' instead. See https://github.com/line/line-bot-sdk-python/blob/master/README.rst for more details.", version='3.0.0', category=LineBotSdkDeprecatedIn30) # noqa: E501
class TextMessage(Message):
Expand Down
12 changes: 8 additions & 4 deletions linebot/webhook.py
Original file line number Diff line number Diff line change
Expand Up @@ -138,14 +138,15 @@ def __init__(self, channel_secret):
"""
self.signature_validator = SignatureValidator(channel_secret)

def parse(self, body, signature, as_payload=False):
def parse(self, body, signature, as_payload=False, use_raw_message=False):
"""Parse webhook request body as text.

:param str body: Webhook request body (as text)
:param str signature: X-Line-Signature value (as text)
:param bool as_payload: (optional) True to return WebhookPayload object.
:rtype: list[T <= :py:class:`linebot.models.events.Event`]
| :py:class:`linebot.webhook.WebhookPayload`
:param bool use_raw_message: Using original Message key as attribute
:return: Events list, or WebhookPayload instance
"""
if not self.signature_validator.validate(body, signature):
Expand All @@ -157,7 +158,8 @@ def parse(self, body, signature, as_payload=False):
for event in body_json['events']:
event_type = event['type']
if event_type == 'message':
events.append(MessageEvent.new_from_json_dict(event))
events.append(MessageEvent.new_from_json_dict(event,
use_raw_message=use_raw_message))
elif event_type == 'follow':
events.append(FollowEvent.new_from_json_dict(event))
elif event_type == 'unfollow':
Expand Down Expand Up @@ -244,13 +246,15 @@ def decorator(func):

return decorator

def handle(self, body, signature):
def handle(self, body, signature, use_raw_message=False):
"""Handle webhook.

:param str body: Webhook request body (as text)
:param str signature: X-Line-Signature value (as text)
:param bool use_raw_message: Using original Message key as attribute
"""
payload = self.parser.parse(body, signature, as_payload=True)
payload = self.parser.parse(body, signature, as_payload=True,
use_raw_message=use_raw_message)

for event in payload.events:
func = None
Expand Down
14 changes: 12 additions & 2 deletions tests/test_webhook.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
import inspect

from linebot import (
SignatureValidator, WebhookParser, WebhookHandler
SignatureValidator, WebhookParser, WebhookHandler, utils
)
from linebot.models import (
MessageEvent, FollowEvent, UnfollowEvent, JoinEvent,
Expand Down Expand Up @@ -614,6 +614,9 @@ def test_parse_webhook_req_without_destination(self):
class TestWebhookHandler(unittest.TestCase):
def setUp(self):
self.handler = WebhookHandler('channel_secret')
self.use_raw_message = True
self.retrieve_attr_name = lambda x: x if self.use_raw_message \
else utils.to_snake_case(x)

@self.handler.add(MessageEvent, message=TextMessage)
def message_text(event, destination):
Expand All @@ -635,6 +638,13 @@ def message_sticker(event):
self.assertEqual('message', event.type)
self.assertEqual('sticker', event.message.type)

@self.handler.add(MessageEvent, message=FileMessage)
def message_file(event):
self.assertEqual('message', event.type)
self.assertEqual('file', event.message.type)
self.assertNotEqual(event.message[self.retrieve_attr_name("fileName")], None)
self.assertNotEqual(event.message[self.retrieve_attr_name("fileSize")], None)

@self.handler.add(MessageEvent)
def message(event):
self.assertEqual('message', event.type)
Expand Down Expand Up @@ -680,7 +690,7 @@ def test_handler(self):
# mock
self.handler.parser.signature_validator.validate = lambda a, b: True

self.handler.handle(body, 'signature')
self.handler.handle(body, 'signature', self.use_raw_message)


class TestInvokeWebhookHandler(unittest.TestCase):
Expand Down