Skip to content

Commit ccb97de

Browse files
be-haseokdtsk
authored andcommitted
Implement flex message feature (#107)
* Support flex message. Close #102 (#106) * Support flex message. Close #102 Ref. line/line-bot-sdk-java#198 * fixed test case * Fixed typo. s/filter/filler/ * follow flake8 rules * Add docstring of flex_message
1 parent d6d5215 commit ccb97de

File tree

7 files changed

+608
-24
lines changed

7 files changed

+608
-24
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ nosetests.xml
4848
coverage.xml
4949
*,cover
5050
.hypothesis/
51+
.pytest_cache/
5152

5253
# Translations
5354
*.mo

examples/flask-kitchensink/app.py

Lines changed: 115 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,13 @@
1919
import sys
2020
import tempfile
2121
from argparse import ArgumentParser
22-
2322
from flask import Flask, request, abort
2423

2524
from linebot import (
2625
LineBotApi, WebhookHandler
2726
)
2827
from linebot.exceptions import (
29-
InvalidSignatureError
28+
LineBotApiError, InvalidSignatureError
3029
)
3130
from linebot.models import (
3231
MessageEvent, TextMessage, TextSendMessage,
@@ -37,7 +36,10 @@
3736
CarouselTemplate, CarouselColumn, PostbackEvent,
3837
StickerMessage, StickerSendMessage, LocationMessage, LocationSendMessage,
3938
ImageMessage, VideoMessage, AudioMessage, FileMessage,
40-
UnfollowEvent, FollowEvent, JoinEvent, LeaveEvent, BeaconEvent
39+
UnfollowEvent, FollowEvent, JoinEvent, LeaveEvent, BeaconEvent,
40+
FlexSendMessage, BubbleContainer, ImageComponent, BoxComponent,
41+
TextComponent, SpacerComponent, IconComponent, ButtonComponent,
42+
SeparatorComponent,
4143
)
4244

4345
app = Flask(__name__)
@@ -81,6 +83,11 @@ def callback():
8183
# handle webhook body
8284
try:
8385
handler.handle(body, signature)
86+
except LineBotApiError as e:
87+
print("Got exception from LINE Messaging API: %s\n" % e.message)
88+
for m in e.error.details:
89+
print(" %s: %s" % (m.property, m.message))
90+
print("\n")
8491
except InvalidSignatureError:
8592
abort(400)
8693

@@ -166,6 +173,111 @@ def handle_text_message(event):
166173
line_bot_api.reply_message(event.reply_token, template_message)
167174
elif text == 'imagemap':
168175
pass
176+
elif text == 'flex':
177+
bubble = BubbleContainer(
178+
direction='ltr',
179+
hero=ImageComponent(
180+
url='https://example.com/cafe.jpg',
181+
size='full',
182+
aspect_ratio='20:13',
183+
aspect_mode='cover',
184+
action=URIAction(uri='http://example.com', label='label')
185+
),
186+
body=BoxComponent(
187+
layout='vertical',
188+
contents=[
189+
# title
190+
TextComponent(text='Brown Cafe', weight='bold', size='xl'),
191+
# review
192+
BoxComponent(
193+
layout='baseline',
194+
margin='md',
195+
contents=[
196+
IconComponent(size='sm', url='https://example.com/gold_star.png'),
197+
IconComponent(size='sm', url='https://example.com/grey_star.png'),
198+
IconComponent(size='sm', url='https://example.com/gold_star.png'),
199+
IconComponent(size='sm', url='https://example.com/gold_star.png'),
200+
IconComponent(size='sm', url='https://example.com/grey_star.png'),
201+
TextComponent(text='4.0', size='sm', color='#999999', margin='md',
202+
flex=0)
203+
]
204+
),
205+
# info
206+
BoxComponent(
207+
layout='vertical',
208+
margin='lg',
209+
spacing='sm',
210+
contents=[
211+
BoxComponent(
212+
layout='baseline',
213+
spacing='sm',
214+
contents=[
215+
TextComponent(
216+
text='Place',
217+
color='#aaaaaa',
218+
size='sm',
219+
flex=1
220+
),
221+
TextComponent(
222+
text='Shinjuku, Tokyo',
223+
wrap=True,
224+
color='#666666',
225+
size='sm',
226+
flex=5
227+
)
228+
],
229+
),
230+
BoxComponent(
231+
layout='baseline',
232+
spacing='sm',
233+
contents=[
234+
TextComponent(
235+
text='Time',
236+
color='#aaaaaa',
237+
size='sm',
238+
flex=1
239+
),
240+
TextComponent(
241+
text="10:00 - 23:00",
242+
wrap=True,
243+
color='#666666',
244+
size='sm',
245+
flex=5,
246+
),
247+
],
248+
),
249+
],
250+
)
251+
],
252+
),
253+
footer=BoxComponent(
254+
layout='vertical',
255+
spacing='sm',
256+
contents=[
257+
# callAction, separator, websiteAction
258+
SpacerComponent(size='sm'),
259+
# callAction
260+
ButtonComponent(
261+
style='link',
262+
height='sm',
263+
action=URIAction(label='CALL', uri='tel:000000'),
264+
),
265+
# separator
266+
SeparatorComponent(),
267+
# websiteAction
268+
ButtonComponent(
269+
style='link',
270+
height='sm',
271+
action=URIAction(label='WEBSITE', uri="https://example.com")
272+
)
273+
]
274+
),
275+
)
276+
message = FlexSendMessage(alt_text="hello", contents=bubble)
277+
line_bot_api.reply_message(
278+
event.reply_token,
279+
message
280+
)
169281
else:
170282
line_bot_api.reply_message(
171283
event.reply_token, TextSendMessage(text=event.message.text))

linebot/models/__init__.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,3 +103,20 @@
103103
ImageCarouselTemplate,
104104
ImageCarouselColumn,
105105
)
106+
from .flex_message import ( # noqa
107+
FlexSendMessage,
108+
FlexContainer,
109+
BubbleContainer,
110+
BubbleStyle,
111+
BlockStyle,
112+
CarouselContainer,
113+
FlexComponent,
114+
BoxComponent,
115+
ButtonComponent,
116+
FillerComponent,
117+
IconComponent,
118+
ImageComponent,
119+
SeparatorComponent,
120+
SpacerComponent,
121+
TextComponent
122+
)

linebot/models/base.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,8 +90,7 @@ def as_json_dict(self):
9090

9191
elif hasattr(value, 'as_json_dict'):
9292
data[camel_key] = value.as_json_dict()
93-
94-
else:
93+
elif value is not None:
9594
data[camel_key] = value
9695

9796
return data

0 commit comments

Comments
 (0)