def run(content_config, env, variables): """ content_config schema: Platform independent message: { 'text': 'text to send' } Platform dependent message: { 'text': { 'Facebook': 'text to send', 'Line': 'text to send', ... } } """ text = content_config['text'] if not isinstance(text, list): text = [text] # Platform independent message if not isinstance(text[0], dict): msgs = [Message(t, variables=variables) for t in text] else: platform_type = env['platform_type'].value msgs = [Message(t[platform_type], variables=variables) for t in text] for qr in content_config.get('quick_replies', []): msgs[-1].add_quick_reply( Message.QuickReply.FromDict(qr, variables=variables)) return msgs
def run(content_config, env, variables): """ content_config schema: Platform dependent message: { 'text': 'blablabla', 'choices': [ { 'title': 'option 1', 'payload': '1', 'acceptable_inputs': ['opt 1'] }, ... ] } """ platform_type = env['platform_type'].value m = Message(buttons_text=content_config['text'], variables=variables) for i, choice in enumerate(content_config['choices']): # Facebook only support 3 buttons if i == 3 and platform_type == SupportedPlatform.Facebook: break b = Message.Button(Message.ButtonType.POSTBACK, choice['title'], payload=TextPayload(choice['payload']), acceptable_inputs=choice['acceptable_inputs'], variables=variables) m.add_button(b) return [m]
def render_cards(news_info, news): """Render cards given a list of new entries.""" if not len(news): return [Message(u'找不到你要的新聞喔!')] m = Message() for n in news: image_url = (n.image_url if n.image_url != '' else get_default_image(n.source)) b = Message.Bubble(n.title, image_url=image_url, subtitle=n.description) b.add_button(Message.Button( Message.ButtonType.POSTBACK, u'在這讀', payload=EventPayload('GET_CONTENT', { 'entry_link': n.link, 'char_offset': 0, 'pic_index': 1, }, False))) b.add_button(Message.Button( Message.ButtonType.WEB_URL, u'去網站讀', url=n.link)) b.add_button(Message.Button(Message.ButtonType.ELEMENT_SHARE)) m.add_bubble(b) add_quick_reply_keywords(news_info, m, True) return [m]
def run(content_config, env, variables): news_info = NewsInfo() n_items = content_config.get('n_items', DEFAULT_N_ITEMS) user_id = GetUserId() limit = 200 if env['platform_type'] == SupportedPlatform.Line: limit = 160 if content_config['mode'] == 'get_content': return run_get_content(news_info, variables, limit) if content_config['mode'] == 'list_by_source': source_name = Resolve(content_config['query_term'], variables) return render_cards( news_info, news_info.trending(user_id, source_name, n_items)) elif content_config['mode'] == 'prompt': m = Message(u'想要知道什麼呢?今天這些字最夯!') add_quick_reply_keywords(news_info, m) return [m] elif content_config['mode'] == 'search': query_term = Resolve(content_config['query_term'], variables) return render_cards( news_info, (news_info.search(query_term, n_items) if query_term else news_info.trending(user_id))) return render_cards(news_info, news_info.trending(user_id))
def run(content_config, env, variables): """ content_config schema: Platform independent message: { 'messages': [Message, ...] } Platform dependent message: { 'message': { 'Facebook': [Message, ... ] 'Line': [Message, ... ] ... } } """ messages = content_config.get('messages') msgs = [] if not isinstance(messages, list): platform_type = env['platform_type'].value messages = messages[platform_type] for message in messages: msgs.append(Message.FromDict(message, variables)) for quick_reply in content_config.get('quick_replies', []): msgs[-1].add_quick_reply(Message.QuickReply.FromDict(quick_reply)) return msgs
def run(content_config, unused_env, variables): """ content_config schema: { "response": "{{variable}", } """ m = Message(Resolve(content_config['response'], variables)) return [m]
def run(content_config, unused_env, variables): msgs = [] # The output messages. url = Render(content_config['url'], variables) method = content_config.get('method', 'post') params = content_config.get('params', []) params = [ (Render(x[0], variables), Render(x[1], variables)) for x in params] try: js = FetchData(url=url, params=params, method=method) for m in js: msg = Message.FromDict(m) msgs.append(msg) except Exception as e: _LOG.exception(e) msgs.append(Message(u'我好像壞掉了,快通知管理員。')) return msgs
def schema(): return { 'type': 'object', 'required': ['messages'], 'additionalProperties': False, 'properties': { 'messages': { 'oneOf': [{ 'type': 'array', 'items': Message.schema() }, { 'type': 'object', 'required': ['Facebook', 'Line'], 'additionalProperties': False, 'properties': { 'Facebook': { 'type': 'array', 'items': Message.schema() }, 'Line': { 'type': 'array', 'items': Message.schema() } } }] }, 'quick_replies': { 'type': 'array', 'items': {'$ref': '#/definitions/quick_reply'} } }, 'definitions': { 'button': Message.Button.schema(), 'bubble': Message.Bubble.schema(), 'list_item': Message.ListItem.schema(), 'quick_reply': Message.QuickReply.schema() } }
def add_quick_reply_keywords(news_info, message, show_related=False): """Install QuickReply keywords into message.""" keywords = news_info.get_keywords(MAX_KEYWORDS) reply_kws = [] if show_related: query_term = CollectedData.GetLast('query_term', '') related_kws = news_info.get_related_keywords(query_term, 3) reply_kws = [kw.name for kw in related_kws] for kw in keywords: if len(reply_kws) < MAX_KEYWORDS and kw.name not in reply_kws: reply_kws.append(kw.name) else: reply_kws += [kw.name for kw in keywords] for kw in reply_kws: message.add_quick_reply(Message.QuickReply( Message.QuickReplyType.TEXT, kw)) message.add_quick_reply(Message.QuickReply( Message.QuickReplyType.TEXT, u'熱門新聞')) message.add_quick_reply(Message.QuickReply( Message.QuickReplyType.TEXT, u'搜尋'))
def run(content_config, unused_env, unused_variables): if content_config['target'] == 'memory': target = Memory else: target = Settings if content_config['mode'] == 'set': target.Set('data', content_config['data']) elif content_config['mode'] == 'get': return [Message(target.Get('data'))] elif content_config['mode'] == 'clear': target.Clear() return []
def render_dramas(dramas): """Render cards given a list of dramas""" if not len(dramas): return Message(u'找不到你要的劇喔!') m = Message() for d in dramas: b = Message.Bubble(d.name, image_url=CacheImage(d.image_url), subtitle=d.description) if d.subscribed: b.add_button( Message.Button(Message.ButtonType.POSTBACK, u'取消追蹤', payload=EventPayload('UNSUBSCRIBE', { 'drama_id': d.id, }, False))) else: b.add_button( Message.Button(Message.ButtonType.POSTBACK, u'追蹤我', payload=EventPayload('SUBSCRIBE', { 'drama_id': d.id, }, False))) b.add_button( Message.Button(Message.ButtonType.POSTBACK, u'我想看前幾集', payload=EventPayload( 'GET_HISTORY', { 'drama_id': d.id, 'from_episode': 0, 'backward': True, }))) b.add_button(Message.Button(Message.ButtonType.ELEMENT_SHARE)) m.add_bubble(b) return m
def run(unused_content_config, unused_env, unused_variables): m = Message() b = Message.Bubble('Tap postback') b.add_button( Message.Button(Message.ButtonType.POSTBACK, 'Postback', payload=TextPayload('PAYLOAD_TEXT'))) m.add_bubble(b) return [m]
def run(content_config, unused_env, variables): """ content_config schema: { "type": "random or query", "term": "query term if type is query", "max_count": 5, // max number of images to return "auth": { "client_id": "imgur client_id", "client_secret": "imgur client_secret" } } """ client = imgurpython.ImgurClient(content_config['auth']['client_id'], content_config['auth']['client_secret']) if content_config['type'] == 'random': images = [ x for x in client.gallery_random() if isinstance(x, GalleryImage) ] else: term = Resolve(content_config['term'], variables) images = [ x for x in client.gallery_search(term) if isinstance(x, GalleryImage) ] images = random.sample(images, int(content_config['max_count'])) m = Message() for i in images: c = Message.Bubble(i.title, i.link[:-4], i.link, i.description) c.add_button( Message.Button(Message.ButtonType.WEB_URL, 'Source', url=i.link[:-4])) c.add_button( Message.Button(Message.ButtonType.POSTBACK, 'Like', payload=TextPayload('like %s' % i.link))) m.add_bubble(c) return [Message('Here are the images you requested'), m]
def append_categories_to_quick_reply(m): m.add_quick_reply( Message.QuickReply(Message.QuickReplyType.TEXT, u'荼蘼')) m.add_quick_reply( Message.QuickReply(Message.QuickReplyType.TEXT, u'The K2 第十集')) m.add_quick_reply( Message.QuickReply(Message.QuickReplyType.TEXT, u'熱門韓劇')) m.add_quick_reply( Message.QuickReply(Message.QuickReplyType.TEXT, u'熱門日劇')) m.add_quick_reply( Message.QuickReply(Message.QuickReplyType.TEXT, u'熱門台劇')) m.add_quick_reply( Message.QuickReply(Message.QuickReplyType.TEXT, u'熱門陸劇')) m.add_quick_reply( Message.QuickReply(Message.QuickReplyType.TEXT, u'通知設定')) return [m]
def run(content_config, unused_env, variables): """ content_config schema: { "settings": { "key1": "value1", "key2": "value2", }, "message": "message" } """ for key, value in content_config['settings'].iteritems(): if isinstance(value, str): value = Render(value, variables) Settings.Set(key, value) return [Message(content_config['message'], variables=variables)]
def run(content_config, unused_env, variables): """ content_config schema: { "query_url": "http://ecshweb.pchome.com.tw/search/v3.3/all/results?" "q=%s&page=1&sort=rnk/dc", "term": "{{matches#1}}", "max_count": 7, "list": "prods", "attributes": { "title": "${{price}}: {{name}}", "image": "http://a.ecimg.tw/{{picB}}", "item_url": "http://24h.pchome.com.tw/{{Id}}", "subtitle": "{{describe}}", "buttons": [ { "type": "web_url", "title": "商品頁面", "url": "http://24h.pchome.com.tw/{{Id}}" } ] } } """ url = content_config['query_url'] timeout = content_config.get('timeout_secs', DEFAULT_TIMEOUT_SECS) if 'term' in content_config: term = Resolve(content_config['term'], variables) url = url % urllib.quote(term.encode('utf-8')) try: content = json.loads(urllib2.urlopen(url, timeout=timeout).read()) except Exception: return [] max_count = content_config['max_count'] attributes = content_config['attributes'] elements = content.get(content_config['list'], []) if len(elements) > max_count: elements = elements[:max_count] m = Message() for element in elements: var = dict(variables, **element) bub = Message.Bubble(title=attributes['title'], item_url=attributes.get('item_url', None), image_url=attributes['image'], subtitle=attributes.get('subtitle', None), variables=var) for b in attributes.get('buttons', []): payload = b.get('payload', None) bub.add_button( Message.Button( b_type=Message.ButtonType(b['type']), title=b['title'], url=b.get('url', None), payload=TextPayload(payload) if payload else None, variables=var)) m.add_bubble(bub) return [m]
def run(unused_content_config, env, unused_variables): user_input = UserInput() msgs = [] # The output messages. # output limit and map size size = (500, 260) if env['platform_type'] == SupportedPlatform.Line: max_count = 3 else: max_count = 5 address = u'' # str. The address user entered. filters_str = u'' # str. The filter used this time. geocoder = GoogleMapsPlaceAPI(api_key=GOOGLE_STATIC_MAP_API_KEY) more_data = user_input.Get('more_data') latlng = Memory.Get('latlng', None) # tuple. User's current location. cached_transaction = Memory.Get('cached_transaction', None) next_data_index = Memory.Get('next_data_index', max_count) if more_data: # Yes, user clicks 'more data', dump data from cache. if not cached_transaction: return [Message(u'請重新輸入地址或條件。')] trans = cached_transaction[next_data_index:next_data_index + max_count] Memory.Set('next_data_index', next_data_index + max_count) if not trans: return [Message(u'沒有更多物件了,請重新輸入地址或條件。')] else: # Nope. User is not entering 'more data'. reset = user_input.Get('reset') location = user_input.Get('location') if reset: latlng = Memory.Get('latlng', None) rules = None # User uploaded current location. elif location and 'coordinates' in location: latlng = (location['coordinates']['lat'], location['coordinates']['long']) rules = Deser(Memory.Get('rules', None)) if rules: rules.AddPureSortingRules(latlng) else: # User entered either an address or criteria; or both. query = user_input.Get('query') rules = twrealprice_rule.Rules.Create() query = rules.ParseQuery(query) address = query.strip() _LOG.info('User query: address=[%s] filters:[%s]', address, rules.filters) if address: if latlng: center = {'lat': latlng[0], 'long': latlng[1]} else: center = None geo_results = geocoder.query_top_n(n=3, address=address, language='zh_TW', region='TW', bounds=[[[20.0, 118.0], [26.0, 123.0]]], center=center) if not geo_results: if rules.filters: msgs.append( Message((u'我不認識這個地址:[%s], 但是我認' u'識條件:[%s]. 請修改一下地址。') % (address, ' '.join(rules.filters)))) address = u'' else: return [Message(u'我不認識這個地址:[%s]' % address)] if len(geo_results) == 1: latlng = (geo_results[0]['location'][0], geo_results[0]['location'][1]) if len(geo_results) > 1: m = Message(buttons_text=u'你指的是以下哪一個地址呢?') for r in geo_results: m.add_button( Message.Button(Message.ButtonType.POSTBACK, r['address'], payload=LocationPayload( r['location'], False))) # If user also entered criteria, save it for later query. if rules.filters: Memory.Set('rules', cPickle.dumps(rules)) # Postpone the AddPureSortingRules until we get latlng. return [m] if not rules.filters: # If user didn't enter filter, use the previous one. rules = Deser(Memory.Get('rules', None)) if rules: _LOG.info('User prev rules: %s', rules.filters) if rules: rules.AddPureSortingRules(latlng) next_data_index = max_count if not latlng: return [Message(u'我還不知道你想查的地方是哪裡。請輸入地址或是送出你的位置。')] Memory.Set('rules', cPickle.dumps(rules)) Memory.Set('latlng', latlng) Memory.Set('next_data_index', next_data_index) twrealprice = TwRealPrice() try: trans = twrealprice.nearby_transaction(max_count, latlng, rules) except IOError: return [Message(u'資料庫找不到,趕快回報給粉絲頁管理員,謝謝。')] if rules and rules.filters: filters_str = u'篩選條件: 「%s」。' % u'」「'.join(rules.filters) if not trans: msg = Message(u'對不起,找不到成交行情喔!試試別的地址或條件。') msgs.append(msg) return msgs # Construct main result cards. main_map = GoogleStaticMapAPIRequestBuilder(GOOGLE_STATIC_MAP_API_KEY, size) style = MarkerStyle() main_map.add_marker(latlng, **style.next()) for s in trans: lat = float(s['latlng'][0]) lng = float(s['latlng'][1]) main_map.add_marker((lat, lng), **style.next()) subtitle = (filters_str + u'搜尋結果僅供參考,詳細完整實價登錄資料,以內政部公佈為準。') msg = Message() b = Message.Bubble(u'%s附近的成交行情' % address, image_url=main_map.build_url(), subtitle=subtitle) msg.add_bubble(b) msgs.append(msg) # At this point, 'trans' must have data to show. i = -1 for s in trans: # In this loop, the strings are concatenated in utf-8 first because the # transaction data come with utf-8 encoded. try: def UnitPrice(s): try: return '%.2f萬' % (float(s['單價每平方公尺']) * twrealprice_rule.M2_PER_PING / 10000) except ValueError: return '--.--' lines = [ ' '.join([ '%d萬' % (int(s['總價元']) / 10000), '(%s * %.2f坪 + %d萬)' % (UnitPrice(s), float(s['建物移轉總面積平方公尺']) / twrealprice_rule.M2_PER_PING, int(s['車位總價元']) / 10000), '%s(%s)' % ( s['建物型態'].split('(')[0], Age(s['建築完成年月']), ), ]).decode('utf-8'), ' '.join([ '%s/共%s' % (s['移轉層次'].replace('層', '樓'), s['總樓層數'].replace('層', '樓')), StreetOnly(s), ]).decode('utf-8'), ' '.join([ RocSlash(s['交易年月日']) + '成交', '%s房%s廳%s衛' % (s['建物現況格局-房'], s['建物現況格局-廳'], s['建物現況格局-衛']), '地坪%.2f' % (float(s['土地移轉總面積平方公尺']) / twrealprice_rule.M2_PER_PING), '車位%.2f坪' % (float(s['車位移轉總面積平方公尺']) / twrealprice_rule.M2_PER_PING), s['車位類別'], s['主要用途'], '備註: ' + s['備註'] if s['備註'] else '', ]).decode('utf-8'), ] if env['platform_type'] == SupportedPlatform.Line: title = lines[0] subtitle = lines[1] + lines[2] else: title = lines[0] + lines[1] subtitle = lines[2] i += 1 msg = Message() msg.add_bubble( Message.Bubble((u'%c: ' % (i + ord('A'))) + title, subtitle=subtitle)) msgs.append(msg) except ValueError: traceback.print_exc() continue return msgs
def run(content_config, unused_env, variables): """ content_config schema: Platform dependent message: { 'send_payload_to_current_node': False, 'api_key': 'google geocoding api key', 'query_term': 'query term', 'language': 'zh_TW', 'region': 'tw', 'bounds': [ {'lat': 23.816576, 'long': 119.781068}, {'lat': 25.314444, 'long': 122.053702} ], 'center': {'lat': 23.816576, 'long': 122.053702} } """ query_term = Resolve(content_config['query_term'], variables) # Remove stop words query_term = re.sub(STOP_WORDS, '', query_term) cfg = content_config api = GoogleMapsPlaceAPI(content_config['api_key']) py_bounds = [] for b in cfg.get('bounds', []): py_bounds.append([(b[0]['lat'], b[0]['long']), (b[1]['lat'], b[1]['long'])]) results = api.query_top_n(3, query_term, cfg['language'], cfg['region'], py_bounds, cfg.get('center', None)) in_currrent = content_config['send_payload_to_current_node'] if not results: m = Message(u'對不起,我找不到這個地址, 請重新輸入 >_<') elif len(results) == 1: m = Message(u'你指的是「%s」嗎?' % results[0]['address']) m.add_quick_reply( Message.QuickReply(Message.QuickReplyType.TEXT, u'是', payload=LocationPayload(results[0]['location'], in_currrent), acceptable_inputs=[u'^對', '(?i)y', '(?i)ok'])) m.add_quick_reply( Message.QuickReply(Message.QuickReplyType.TEXT, u'否', payload=EventPayload('WRONG_ADDRESS', None, in_currrent), acceptable_inputs=[u'不', '(?i)n'])) else: m = Message(buttons_text=u'你指的是以下哪一個地址呢?') for r in results: m.add_button( Message.Button(Message.ButtonType.POSTBACK, r['address'], payload=LocationPayload(r['location'], in_currrent))) return [m]
def run(parser_config, user_input, unused_as_root): """ { "links": [ { "action_ident": "continue", "end_node_id": null, "ack_message": "" }, { "action_ident": "done", "end_node_id": "[[root]]", "ack_message": "" } ] } """ if user_input.text: if u'重設' in user_input.text or 'reset' in user_input.text.lower(): Memory.Clear() return ParseResult(ack_message=u'讓我們重新開始吧!') if user_input.event: event = user_input.event if event.key == 'CONTROL_FLOW': if event.value == 'reset': Memory.Clear() return ParseResult(parser_config['done'], ack_message=u'放棄操作') elif event.key == 'SELECT_BOT': Memory.Set('bot', event.value) elif event.key == 'SELECT_OP': Memory.Set('operation', event.value) elif event.key == 'MESSAGE_INPUT': if event.value == 'done': Memory.Set('status', 'preview_message') elif event.value == 'restart': Memory.Set('broadcast_message', None) Memory.Set('status', None) elif event.key == 'CONFIRM_MESSAGE': if event.value: bot = Bot.get_by(id=Memory.Get('bot'), single=True) if not bot: return ParseResult(ack_message=u'發生錯誤,找不到對應的' u'機器人') msgs = [ Message.FromDict(raw_msg) for raw_msg in Memory.Get('broadcast_message') ] BroadcastMessage(bot, msgs) Memory.Clear() return ParseResult(parser_config['done'], ack_message=u'您的訊息已送出!') else: Memory.Set('broadcast_message', None) status = Memory.Get('status') if status == 'input_broadcast_message': broadcast_message = Memory.Get('broadcast_message') or [] broadcast_message.append(user_input.raw_message) Memory.Set('broadcast_message', broadcast_message) return ParseResult(skip_content_module=False)
def run(content_config, unused_env, variables): """ content_config schema: { "bot_admins": { "platform_user_ident_1": ["bot_id_1", "bot_id_2" ..], ... } } """ user = g.user bots = content_config['bot_admins'].get(user.platform_user_ident) if not bots: return [] bot = Memory.Get('bot') if not bot: msgs = [ Message(u'嗨 {{user.first_name}},你想要操作哪隻機器人呢?', variables=variables) ] page = 1 m = Message() msgs.append(m) bubble = Message.Bubble('第 %d 頁' % page) for bot_id in bots: bot = Bot.get_by(id=bot_id, single=True) if not bot: continue bubble.add_button( Message.Button(Message.ButtonType.POSTBACK, title=bot.name, payload=EventPayload('SELECT_BOT', bot_id))) if len(bubble.buttons) == 3: m.add_bubble(bubble) page += 1 bubble = Message.Bubble(u'第 %d 頁' % page) if len(bubble.buttons): m.add_bubble(bubble) msgs[-1].add_quick_reply( Message.QuickReply(Message.QuickReplyType.TEXT, u'放棄', payload=EventPayload('CONTROL_FLOW', 'reset'), acceptable_inputs=['(?i)giveup', '(?i)reset'])) return msgs operation = Memory.Get('operation') if not operation: m = Message(buttons_text=u'你想要執行什麼動作呢?') m.add_button( Message.Button(Message.ButtonType.POSTBACK, title=u'廣播訊息', payload=EventPayload('SELECT_OP', 'broadcast'))) m.add_button( Message.Button(Message.ButtonType.POSTBACK, title=u'放棄', payload=EventPayload('CONTROL_FLOW', 'reset'))) return [m] if operation == 'broadcast': broadcast_message = Memory.Get('broadcast_message') status = Memory.Get('status') if status == 'input_broadcast_message': m = Message(u'你可以繼續輸入下一則訊息:') m.add_quick_reply( Message.QuickReply( Message.QuickReplyType.TEXT, u'完成', payload=EventPayload('MESSAGE_INPUT', 'done'), acceptable_inputs=[u'好了', u'(?i)done', '(?i)y'])) m.add_quick_reply( Message.QuickReply( Message.QuickReplyType.TEXT, u'重來', payload=EventPayload('MESSAGE_INPUT', 'restart'), acceptable_inputs=[u'好了', u'(?i)restart', '(?i)cancel'])) m.add_quick_reply( Message.QuickReply( Message.QuickReplyType.TEXT, u'放棄', payload=EventPayload('CONTROL_FLOW', 'reset'), acceptable_inputs=['(?i)giveup', '(?i)reset'])) return [m] elif not broadcast_message: Memory.Set('status', 'input_broadcast_message') return [Message(u'請輸入你要廣播的訊息:')] elif status == 'preview_message': msgs = [Message(u'請確認你要廣播的訊息:')] for raw_msg in broadcast_message: msgs.append(Message.FromDict(raw_msg)) m = msgs[-1] m.add_quick_reply( Message.QuickReply(Message.QuickReplyType.TEXT, u'確認', payload=EventPayload( 'CONFIRM_MESSAGE', True), acceptable_inputs=[u'是', '(?i)y', '(?i)ok'])) m.add_quick_reply( Message.QuickReply( Message.QuickReplyType.TEXT, u'取消', payload=EventPayload('CONFIRM_MESSAGE', False), acceptable_inputs=[u'是', '(?i)no', '(?i)cancel'])) return msgs return [Message(u'錯誤的操作')]
def run_get_content(news_info, variables, limit): try: event = variables['event'] content, char_offset, total_length = news_info.get_content( event.value['entry_link'], event.value['char_offset'], limit) src, alt, pic_index = news_info.get_picture( event.value['entry_link'], event.value['pic_index']) except KeyError: return [Message(u'抱歉,有些東西出錯了,請再試一次!')] content_ended = char_offset == -1 picture_ended = pic_index == -1 all_ended = content_ended and picture_ended has_picture = src and alt has_content = content != '' progress = float(char_offset) / total_length * 100 \ if char_offset >= 0 else 100.0 msgs = [] if has_content and not all_ended: m = Message(buttons_text=content) m.add_button(Message.Button( Message.ButtonType.POSTBACK, u'繼續讀 ({:.0f}%)'.format(progress), payload=EventPayload('GET_CONTENT', { 'entry_link': event.value['entry_link'], 'char_offset': char_offset, 'pic_index': pic_index, }, False))) m.add_button(Message.Button( Message.ButtonType.WEB_URL, u'去網站讀', url=event.value['entry_link'])) msgs.append(m) elif has_content: msgs.append(Message(content)) if has_picture: src_msg = Message(image_url=src) if alt.strip(): alt_msg = Message() b = Message.Bubble(alt, subtitle=' ') # Only append button to the last message, so only append if # content is empty if not has_content and not all_ended: b.add_button(Message.Button( Message.ButtonType.POSTBACK, u'繼續看圖 (文字已結束)', payload=EventPayload('GET_CONTENT', { 'entry_link': event.value['entry_link'], 'char_offset': char_offset, 'pic_index': pic_index, }, False))) b.add_button(Message.Button( Message.ButtonType.WEB_URL, u'去網站讀', url=event.value['entry_link'])) alt_msg.add_bubble(b) msgs = [src_msg, alt_msg] + msgs else: msgs = [src_msg] + msgs if all_ended: m = Message(u'這則新聞讀完囉!') add_quick_reply_keywords(news_info, m, True) msgs.append(m) return msgs
def run(content_config, unused_env, variables): """ content_config schema: { "api_key": "api_key", "send_payload_to_current_node": true, "location": "location variables", "max_count": 3 "distance_threshold": 0.050, "display_weather": true } """ location = Resolve(content_config['location'], variables) if 'coordinates' not in location: return [Message('不正確的輸入,請重新輸入')] c = (location['coordinates']['lat'], location['coordinates']['long']) youbike = YoubikeInfo() k = content_config.get('max_count', 5) size = (500, 260) stations = youbike.find_knn(k, c, content_config['distance_threshold']) if not stations: return [Message('對不起,這裡附近沒有 Ubike 站喔!')] m = GoogleStaticMapAPIRequestBuilder(content_config['api_key'], size) m.add_marker(c, 'purple') for s in stations: m.add_marker((float(s['lat']), float(s['lng']))) msgs = [] # Construct main result cards. msg = Message() b = Message.Bubble(u'附近的 Ubike 站點', image_url=m.build_url(), subtitle=u'以下是最近的 %d 個站點' % k) best = stations[0] for s in stations: if s['sbi'] > 0: best = s break best_gps_coord = (float(best['lat']), float(best['lng'])) b.add_button(Message.Button(Message.ButtonType.WEB_URL, u'帶我去', url=m.build_navigation_url(best_gps_coord))) to_current = content_config['send_payload_to_current_node'] b.add_button(Message.Button(Message.ButtonType.POSTBACK, u'再次查詢', payload=LocationPayload(c, to_current))) msg.add_bubble(b) for s in stations: m.clear_markers() m.add_marker(c, 'purple') gps_coord = (float(s['lat']), float(s['lng'])) m.add_marker(gps_coord, color='red') sbi, bemp = int(s['sbi']), int(s['bemp']) subtitle = u'剩餘數量: %d\n空位數量: %d\n' % (sbi, bemp) if sbi < 5: subtitle += (u'預計進車時間: %d 分鐘\n' % youbike.average_waiting_time( str(s['sno']), youbike.Direction.In)) if bemp < 5: subtitle += (u'預計出位時間:%d 分鐘\n' % youbike.average_waiting_time( str(s['sno']), youbike.Direction.Out)) b = Message.Bubble(s['ar'], image_url=m.build_url(), subtitle=subtitle) b.add_button(Message.Button(Message.ButtonType.WEB_URL, u'地圖導航', url=m.build_navigation_url(gps_coord))) msg.add_bubble(b) msgs.append(msg) if content_config['display_weather'] and 'weather' in best: # See http://openweathermap.org/weather-conditions # for weather codes. weather = best['weather'] code = best['weather']['weather_code'] temp = weather['temp'] time = GetUserTime() if code / 100 == 3 or code in [500, 501, 520]: msgs.append(Message(u'提醒你,現在外面天雨路滑,騎車小心!' u'記得帶傘或穿件雨衣唷')) elif (code / 100 == 2 or code in [502, 503, 504, 511, 521, 522, 531, 901, 902]): msgs.append(Message(u'現在外面大雨滂沱,不如叫個 Uber 吧!')) elif temp >= 30 and time.hour >= 10 and time.hour <= 16: msgs.append(Message(u'提醒你,現在外面天氣炎熱 (攝氏 %.1f 度) ,' u'記得做好防曬唷' % temp)) return msgs
def run(content_config, unused_env, variables): drama_info = DramaInfo() n_items = content_config.get('n_items', DEFAULT_N_ITEMS) user_id = GetUserId() def append_categories_to_quick_reply(m): m.add_quick_reply( Message.QuickReply(Message.QuickReplyType.TEXT, u'荼蘼')) m.add_quick_reply( Message.QuickReply(Message.QuickReplyType.TEXT, u'The K2 第十集')) m.add_quick_reply( Message.QuickReply(Message.QuickReplyType.TEXT, u'熱門韓劇')) m.add_quick_reply( Message.QuickReply(Message.QuickReplyType.TEXT, u'熱門日劇')) m.add_quick_reply( Message.QuickReply(Message.QuickReplyType.TEXT, u'熱門台劇')) m.add_quick_reply( Message.QuickReply(Message.QuickReplyType.TEXT, u'熱門陸劇')) m.add_quick_reply( Message.QuickReply(Message.QuickReplyType.TEXT, u'通知設定')) return [m] if content_config['mode'] == 'subscribe': event = variables['event'] drama_id = event.value['drama_id'] Memory.Set('last_query_drama_id', drama_id) drama_info.subscribe(user_id, drama_id) episodes = drama_info.get_history(drama_id=drama_id, from_episode=0, backward=True) return ([ Message(u'謝謝您的追蹤,' u'我們會在有更新的時候通知您!'), Message(u'在等待的同時,' u'您可以先看看之前的集數喲!') ] + render_episodes(episodes, variables)) if content_config['mode'] == 'unsubscribe': event = variables['event'] drama_id = event.value['drama_id'] drama_info.unsubscribe(user_id, drama_id) return [Message(u'已成功取消訂閱')] if content_config['mode'] == 'get_history': event = variables['event'] drama_id = event.value['drama_id'] Memory.Set('last_query_drama_id', drama_id) from_episode = event.value['from_episode'] backward = event.value['backward'] episodes = drama_info.get_history(drama_id=drama_id, from_episode=from_episode, backward=backward) return render_episodes(episodes, variables) if content_config['mode'] == 'prompt': m = Message(u'你比較喜歡以下的什麼劇呢?') append_categories_to_quick_reply(m) return [m] country = content_config['mode'].replace('trending_', '') if content_config['mode'] == 'search': query_term = Resolve(content_config['query_term'], variables) dramas = drama_info.search(user_id, query_term, n_items) if dramas: if len(dramas) == 1: Memory.Set('last_query_drama_id', dramas[0].id) m = render_dramas(dramas) append_categories_to_quick_reply(m) return [m] m = Message(u'找不到耶!你可以換個關鍵字或試試熱門的類別:') append_categories_to_quick_reply(m) return [m] if content_config['mode'] == 'search_episode': if len(variables['matches']) == 3: dramas = drama_info.search(user_id, variables['matches'][1], 1) if dramas: Memory.Set('last_query_drama_id', dramas[0].id) drama_id = Memory.Get('last_query_drama_id') if drama_id: try: try: serial_number = int( Resolve(content_config['episode'], variables)) except ValueError: serial_number = convert_to_arabic_numbers( Resolve(content_config['episode'], variables)) episode = drama_info.get_episode(drama_id, serial_number) except Exception: return [Message('沒有這一集喔')] return render_episodes([episode], variables) else: return [Message('請先告訴我你要查的劇名')] m = render_dramas(drama_info.get_trending(user_id, country=country)) append_categories_to_quick_reply(m) return [m]
def render_episodes(episodes, variables): """Render cards given a list of episodes""" if not len(episodes): return [Message(u'沒有更多的集數可以看囉 :(')] m = Message() for ep in episodes: b = Message.Bubble(ep.drama_name + u'第 %d 集' % ep.serial_number, image_url=CacheImage(ep.image_url), subtitle=ep.description) b.add_button( Message.Button(Message.ButtonType.WEB_URL, u'帶我去看', url=TrackedURL(ep.link, 'WatchButton'), variables=variables)) b.add_button( Message.Button(Message.ButtonType.POSTBACK, u'我想看前幾集', payload=EventPayload( 'GET_HISTORY', { 'drama_id': ep.drama_id, 'from_episode': ep.serial_number, 'backward': True, }))) m.add_bubble(b) m.add_quick_reply(Message.QuickReply(Message.QuickReplyType.TEXT, u'第1集')) m.add_quick_reply(Message.QuickReply(Message.QuickReplyType.TEXT, u'熱門韓劇')) m.add_quick_reply(Message.QuickReply(Message.QuickReplyType.TEXT, u'熱門日劇')) m.add_quick_reply(Message.QuickReply(Message.QuickReplyType.TEXT, u'熱門台劇')) m.add_quick_reply(Message.QuickReply(Message.QuickReplyType.TEXT, u'熱門陸劇')) m.add_quick_reply(Message.QuickReply(Message.QuickReplyType.TEXT, u'通知設定')) return [m]