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
6 changes: 5 additions & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ get\_group\_member\_profile(self, group\_id, user\_id, timeout=None)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Gets the user profile of a member of a group that the bot is in. This can be
the user ID of a user who has not added the bot as a friend or has blocked
the user ID of a user who has not added the bot as a friend or has blocked
the bot.

https://devdocs.line.me/en/#get-group-room-member-profile
Expand Down Expand Up @@ -577,6 +577,10 @@ Event
- reply\_token
- postback: Postback
- data
- params: Params
- date
- time
- datetime
- BeaconEvent
- type
- timestamp
Expand Down
2 changes: 2 additions & 0 deletions linebot/models/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
PostbackEvent,
BeaconEvent,
Postback,
Params,
Beacon,
)
from .imagemap import ( # noqa
Expand Down Expand Up @@ -79,6 +80,7 @@
PostbackTemplateAction,
MessageTemplateAction,
URITemplateAction,
DatetimePickerTemplateAction,
ImageCarouselTemplate,
ImageCarouselColumn,
)
43 changes: 41 additions & 2 deletions linebot/models/events.py
Original file line number Diff line number Diff line change
Expand Up @@ -265,15 +265,54 @@ class Postback(Base):
https://devdocs.line.me/en/#postback-event
"""

def __init__(self, data=None, **kwargs):
def __init__(self, data=None, params=None, **kwargs):
"""__init__ method.

:param str data:
:param str data: Postback data
:param params: JSON object with the date and time
selected by a user through a datetime picker action.
Only returned for postback actions via the datetime picker.
:type params: T <= :py:class:`linebot.models.events.Params`
:param kwargs:
"""
super(Postback, self).__init__(**kwargs)

self.data = data
self.params = self.get_or_new_from_json_dict(
params, Params
)


class Params(Base):
"""Params.

Object with the date and time selected by a user
through a datetime picker action.
The format for the full-date, time-hour, and time-minute
as shown below follow the RFC3339 protocol.

https://devdocs.line.me/en/#postback-params-object
"""

def __init__(self, date=None, time=None, datetime=None, **kwargs):
"""__init__ method.

:param str date: Date selected by user.
Only included in the date mode.
Format: full-date
:param str time: Time selected by the user.
Only included in the time mode.
Format: time-hour":"time-minute
:param str datetime: Date and time selected by the user.
Only included in the datetime mode.
Format: full-date"T"time-hour":"time-minute
:param kwargs:
"""
super(Params, self).__init__(**kwargs)

self.date = date
self.time = time
self.datetime = datetime


class Beacon(Base):
Expand Down
43 changes: 42 additions & 1 deletion linebot/models/template.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ def _get_action(action):
action, {
'postback': PostbackTemplateAction,
'message': MessageTemplateAction,
'uri': URITemplateAction
'uri': URITemplateAction,
'datetimepicker': DatetimePickerTemplateAction,
}
)
return action_obj
Expand Down Expand Up @@ -361,3 +362,43 @@ def __init__(self, label=None, uri=None, **kwargs):
self.type = 'uri'
self.label = label
self.uri = uri


class DatetimePickerTemplateAction(TemplateAction):
"""DatetimePickerTemplateAction.

https://devdocs.line.me/en/#template-messages

When this action is tapped, a postback event is returned via webhook
with the date and time selected by the user from the date and time selection dialog.
"""

def __init__(self, label=None, data=None, mode=None,
initial=None, max=None, min=None, **kwargs):
"""__init__ method.

:param str label: Label for the action
Max: 20 characters
:param str data: String returned via webhook
in the postback.data property of the postback event
Max: 300 characters
:param str mode: Action mode
date: Pick date
time: Pick time
datetime: Pick date and time
:param str initial: Initial value of date or time
:param str max: Largest date or time value that can be selected.
Must be greater than the min value.
:param str min: Smallest date or time value that can be selected.
Must be less than the max value.
:param kwargs:
"""
super(DatetimePickerTemplateAction, self).__init__(**kwargs)

self.type = 'datetimepicker'
self.label = label
self.data = data
self.mode = mode
self.initial = initial
self.max = max
self.min = min
72 changes: 71 additions & 1 deletion tests/api/test_send_template_message.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,17 @@
)
from linebot.models import (
TemplateSendMessage, ButtonsTemplate,
PostbackTemplateAction, MessageTemplateAction, URITemplateAction,
PostbackTemplateAction, MessageTemplateAction,
URITemplateAction, DatetimePickerTemplateAction,
ConfirmTemplate, CarouselTemplate, CarouselColumn,
ImageCarouselTemplate, ImageCarouselColumn
)


class TestLineBotApi(unittest.TestCase):

maxDiff = None

def setUp(self):
self.tested = LineBotApi('channel_secret')

Expand Down Expand Up @@ -161,6 +165,37 @@ def setUp(self):
uri='http://example.com/2'
)
]
),
CarouselColumn(
thumbnail_image_url='https://example.com'
'/item3.jpg',
title='this is menu3', text='description3',
actions=[
DatetimePickerTemplateAction(
label="datetime picker date",
data="action=sell&itemid=2&mode=date",
mode="date",
initial="2013-04-01",
min="2011-06-23",
max="2017-09-08"
),
DatetimePickerTemplateAction(
label="datetime picker time",
data="action=sell&itemid=2&mode=time",
mode="time",
initial="10:00",
min="00:00",
max="23:59"
),
DatetimePickerTemplateAction(
label="datetime picker datetime",
data="action=sell&itemid=2&mode=datetime",
mode="datetime",
initial="2013-04-01T10:00",
min="2011-06-23T00:00",
max="2017-09-08T23:59"
)
]
)
]
)
Expand Down Expand Up @@ -219,6 +254,41 @@ def setUp(self):
"uri": "http://example.com/2"
}
]
},
{
"thumbnailImageUrl":
"https://example.com/item3.jpg",
"title": "this is menu3",
"text": "description3",
"actions": [
{
"type": "datetimepicker",
"label": "datetime picker date",
"data": "action=sell&itemid=2&mode=date",
"mode": "date",
"initial": "2013-04-01",
"min": "2011-06-23",
"max": "2017-09-08"
},
{
"type": "datetimepicker",
"label": "datetime picker time",
"data": "action=sell&itemid=2&mode=time",
"mode": "time",
"initial": "10:00",
"min": "00:00",
"max": "23:59"
},
{
"type": "datetimepicker",
"label": "datetime picker datetime",
"data": "action=sell&itemid=2&mode=datetime",
"mode": "datetime",
"initial": "2013-04-01T10:00",
"min": "2011-06-23T00:00",
"max": "2017-09-08T23:59"
}
]
}
]
}
Expand Down
46 changes: 46 additions & 0 deletions tests/test_webhook.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
TextMessage, ImageMessage, VideoMessage, AudioMessage,
LocationMessage, StickerMessage,
SourceUser, SourceRoom, SourceGroup,
Params,
)


Expand Down Expand Up @@ -195,6 +196,7 @@ def test_parse(self):
self.assertEqual(events[10].source.user_id, 'U206d25c2ea6bd87c17655609a1c37cb8')
self.assertEqual(events[10].source.sender_id, 'U206d25c2ea6bd87c17655609a1c37cb8')
self.assertEqual(events[10].postback.data, 'action=buyItem&itemId=123123&color=red')
self.assertEqual(events[10].postback.params, None)

# BeaconEvent, SourceUser
self.assertIsInstance(events[11], BeaconEvent)
Expand Down Expand Up @@ -254,6 +256,45 @@ def test_parse(self):
self.assertEqual(events[14].message.type, 'text')
self.assertEqual(events[14].message.text, 'Hello, world')

# PostbackEvent, SourceUser, with date params
self.assertIsInstance(events[15], PostbackEvent)
self.assertEqual(events[15].reply_token, 'nHuyWiB7yP5Zw52FIkcQobQuGDXCTA')
self.assertEqual(events[15].type, 'postback')
self.assertEqual(events[15].timestamp, 1462629479859)
self.assertIsInstance(events[15].source, SourceUser)
self.assertEqual(events[15].source.type, 'user')
self.assertEqual(events[15].source.user_id, 'U206d25c2ea6bd87c17655609a1c37cb8')
self.assertEqual(events[15].source.sender_id, 'U206d25c2ea6bd87c17655609a1c37cb8')
self.assertEqual(events[15].postback.data, 'action=buyItem&itemId=123123&color=red')
self.assertIsInstance(events[15].postback.params, Params)
self.assertEqual(events[15].postback.params.date, '2013-04-01')

# PostbackEvent, SourceUser, with date params
self.assertIsInstance(events[16], PostbackEvent)
self.assertEqual(events[16].reply_token, 'nHuyWiB7yP5Zw52FIkcQobQuGDXCTA')
self.assertEqual(events[16].type, 'postback')
self.assertEqual(events[16].timestamp, 1462629479859)
self.assertIsInstance(events[16].source, SourceUser)
self.assertEqual(events[16].source.type, 'user')
self.assertEqual(events[16].source.user_id, 'U206d25c2ea6bd87c17655609a1c37cb8')
self.assertEqual(events[16].source.sender_id, 'U206d25c2ea6bd87c17655609a1c37cb8')
self.assertEqual(events[16].postback.data, 'action=buyItem&itemId=123123&color=red')
self.assertIsInstance(events[15].postback.params, Params)
self.assertEqual(events[16].postback.params.time, '10:00')

# PostbackEvent, SourceUser, with date params
self.assertIsInstance(events[17], PostbackEvent)
self.assertEqual(events[17].reply_token, 'nHuyWiB7yP5Zw52FIkcQobQuGDXCTA')
self.assertEqual(events[17].type, 'postback')
self.assertEqual(events[17].timestamp, 1462629479859)
self.assertIsInstance(events[17].source, SourceUser)
self.assertEqual(events[17].source.type, 'user')
self.assertEqual(events[17].source.user_id, 'U206d25c2ea6bd87c17655609a1c37cb8')
self.assertEqual(events[17].source.sender_id, 'U206d25c2ea6bd87c17655609a1c37cb8')
self.assertEqual(events[17].postback.data, 'action=buyItem&itemId=123123&color=red')
self.assertIsInstance(events[15].postback.params, Params)
self.assertEqual(events[17].postback.params.datetime, '2013-04-01T10:00')


class TestWebhookHandler(unittest.TestCase):
def setUp(self):
Expand Down Expand Up @@ -321,6 +362,11 @@ def test_handler(self):
self.assertEqual(self.calls[10], '6 postback')
self.assertEqual(self.calls[11], '7 beacon')
self.assertEqual(self.calls[12], '7 beacon')
self.assertEqual(self.calls[13], '1 message_text')
self.assertEqual(self.calls[14], '1 message_text')
self.assertEqual(self.calls[15], '6 postback')
self.assertEqual(self.calls[16], '6 postback')
self.assertEqual(self.calls[17], '6 postback')


if __name__ == '__main__':
Expand Down
45 changes: 45 additions & 0 deletions tests/text/webhook.json
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,51 @@
"type": "text",
"text": "Hello, world"
}
},
{
"replyToken": "nHuyWiB7yP5Zw52FIkcQobQuGDXCTA",
"type": "postback",
"timestamp": 1462629479859,
"source": {
"type": "user",
"userId": "U206d25c2ea6bd87c17655609a1c37cb8"
},
"postback": {
"data": "action=buyItem&itemId=123123&color=red",
"params": {
"date": "2013-04-01"
}
}
},
{
"replyToken": "nHuyWiB7yP5Zw52FIkcQobQuGDXCTA",
"type": "postback",
"timestamp": 1462629479859,
"source": {
"type": "user",
"userId": "U206d25c2ea6bd87c17655609a1c37cb8"
},
"postback": {
"data": "action=buyItem&itemId=123123&color=red",
"params": {
"time": "10:00"
}
}
},
{
"replyToken": "nHuyWiB7yP5Zw52FIkcQobQuGDXCTA",
"type": "postback",
"timestamp": 1462629479859,
"source": {
"type": "user",
"userId": "U206d25c2ea6bd87c17655609a1c37cb8"
},
"postback": {
"data": "action=buyItem&itemId=123123&color=red",
"params": {
"datetime": "2013-04-01T10:00"
}
}
}
]
}