def generate_carousel_for_top10(books): contents = [] for book in books: content = BubbleContainer( action=URIAction(uri=book['url']), size='micro', header=BoxComponent(layout='vertical', contents=[ TextComponent(text='TOP ' + book['no'], weight='bold', size='lg', align='center'), SeparatorComponent(margin='md', color='#a0a0a0') ]), hero=ImageComponent(url=book['photo_url'], size='full', aspect_mode='cover'), body=BoxComponent(layout='vertical', spacing='sm', padding_all='13px', contents=[ TextComponent(text=book['name'], weight='bold', size='sm', align='center', wrap=True), TextComponent(text=book['authors'], size='sm', color='#8c8c8c', margin='md', align='center') ]), footer=BoxComponent(layout='vertical', contents=[ SeparatorComponent(margin='md', color='#a0a0a0'), TextComponent(text=book['price'], wrap=True, size='sm', flex=5, align='center') ])) contents.append(content) return CarouselContainer(contents=contents)
def send_msg(user_id, reply_token, msg): try: line_bot_api.reply_message( reply_token, FlexSendMessage(alt_text="trainings", contents=CarouselContainer.new_from_json_dict( json.loads(msg)))) return except json.decoder.JSONDecodeError: pass except Exception as e: app.logger.error(e) return try: line_bot_api.reply_message(reply_token, TextSendMessage(text=msg)) except Exception as e: app.logger.error(e) return
def flex_oil(): oil_obj = crawler.oil() oil_data = oil_obj.getData() oil_flex_container_json = json.load(open("container/oil.json", 'r', encoding="utf-8")) for i in range(2): oil_flex_container_json["contents"][i]["header"]["contents"][0]["text"] = oil_data[i][0] oil_flex_container_json["contents"][i]["body"]["contents"][0]["contents"][1]["text"] = str(oil_data[i][1]) oil_flex_container_json["contents"][i]["body"]["contents"][2]["contents"][1]["text"] = str(oil_data[i][2]) oil_flex_container_json["contents"][i]["body"]["contents"][4]["contents"][1]["text"] = str(oil_data[i][3]) oil_flex_container_json["contents"][i]["body"]["contents"][6]["contents"][1]["text"] = str(oil_data[i][4]) oil_flex_container_json["contents"][i]["footer"]["contents"][0]["text"] = oil_data[i][6] + ' ' + oil_data[i][ 5] oil_carousel_content = CarouselContainer.new_from_json_dict(oil_flex_container_json) flex_bubble_send_message = FlexSendMessage(alt_text="oil", contents=oil_carousel_content) return flex_bubble_send_message
def notify(self, channels, reviews, platform): if self.__check_usage() > 490: print("Line-bot Push Message Usage 已達上限!") return False for idx in range(0, len(reviews), 10): contents = self.__flex_message_builder(reviews=reviews[idx:idx+10], platform=platform) message = FlexSendMessage(alt_text="➤ 新的 App 評論來囉!", contents=CarouselContainer(contents=contents)) for channel in channels: try: self.__line_bot_api.push_message(to=channel, messages=message) except Exception as e: print(f"Line-bot Notify ERROR: {e}") return True
def get_custom_response(message: Dict[Text, Any]) -> FlexSendMessage: responses = None if "locations" in message: locations = message.get("locations") bubbles = [] for loc in locations: bubbles.append(construct_location_message(loc)) carousel = CarouselContainer(contents=bubbles) responses = FlexSendMessage( alt_text="Daftar Lokasi Psikolog Terdekat", contents=carousel) elif "payload" in message: payload = message.get("payload") bubble = construct_multiple_choice(payload) responses = FlexSendMessage(alt_text=payload.get("text"), contents=bubble) return responses
def handle_message(event): # ユーザからの検索ワードを取得 word = event.message.text # 記事取得関数を呼び出し if word !="人気記事": result = sc.getNews(word) else: result = ranklis #この後おすすめでpv数から記事取得 # 応答メッセージ(記事検索結果)を送信 if word == "hello": line_bot_api.reply_message( event.reply_token, TextSendMessage(text=str(categ)) ) elif word=="人気記事": les="les" # template = template_env.get_template('j1.json') template = template_env.get_template('temp.json') # template = "temp.json" data = template.render(dict(items=les)) line_bot_api.reply_message( event.reply_token, # =================================================== FlexSendMessage( alt_text="items", # dataを入力してカルーセルで応答 contents=CarouselContainer.new_from_json_dict(json.loads(data)) ) # ---------------------------------------------------------------- ) else: line_bot_api.reply_message( event.reply_token, TextSendMessage(text=result) )
def get_all_news(reply_token): print('handle_postback: news=all') carousel_template = CarouselContainer() # bbc-sport bbc_data = rss_feed.get_bbc_feed(5) carousel_template.contents.append( football_news.get_news_bubble("#FEE63E", bbc_data, header_text_color="#000000")) print('news=all, bbc-sport completed') # sky-sport sky_data = rss_feed.get_skysports_feed(5) carousel_template.contents.append( football_news.get_news_bubble("#BB0211", sky_data)) print('news=all, sky-sports completed') # guardian guardian_data = rss_feed.get_guardian_feed(5) carousel_template.contents.append( football_news.get_news_bubble("#09508D", guardian_data)) print('news=all, guardian completed') # mirror mirror_data = rss_feed.get_mirror_feed(5) carousel_template.contents.append( football_news.get_news_bubble("#E80E0D", mirror_data)) print('news=all, mirror completed') # goal-com goal_data = rss_feed.get_goal_feed(5) carousel_template.contents.append( football_news.get_news_bubble("#091F2C", goal_data)) print('news=all, goal-com completed') # shotongoal shotongoal_data = rss_feed.get_shot_on_goal_feed(5) carousel_template.contents.append( football_news.get_news_bubble("#1A1A1A", shotongoal_data)) print('news=all, shotongoal completed') # soccersuck soccersuck_data = rss_feed.get_soccersuck_feed(5) carousel_template.contents.append( football_news.get_news_bubble("#197F4D", soccersuck_data)) print('news=all, soccersuck completed') line_bot_api.reply_message( reply_token, FlexSendMessage(alt_text='AllNews', contents=carousel_template))
def show_menu_handler(group_id): print("[DEBUG] use show_menu_handler") template = template_env.get_template(PROJECTS_FLEX_JSON_FP) carousel_list = [] for proj in env["projects"]: if proj["group_id"] == group_id: rendered_template = template.render(project_name=proj["name"]) dict_template = eval(rendered_template) carousel_list.append( BubbleContainer.new_from_json_dict(dict_template)) template_opera = template_env.get_template(PROJECT_OPERA_FLEX_JSON_FP) dict_template_opera = eval(template_opera.render()) carousel_list.append( BubbleContainer.new_from_json_dict(dict_template_opera)) flex_message = FlexSendMessage(alt_text="請選擇專案加入", contents=CarouselContainer(carousel_list)) line_bot_api.push_message(group_id, flex_message)
def flex_invoice(): inv = crawler.invoice() old = inv.show(3) invoice_flex_container_json = json.load(open("container/invoice.json", 'r', encoding="utf-8")) for i in range(3): invoice_flex_container_json["contents"][i]["header"]["contents"][0]["text"] = old[i][0] invoice_flex_container_json["contents"][i]["body"]["contents"][0]["contents"][1]["text"] = old[i][1][0] invoice_flex_container_json["contents"][i]["body"]["contents"][2]["contents"][1]["text"] = old[i][1][1] invoice_flex_container_json["contents"][i]["body"]["contents"][4]["contents"][1]["text"] = old[i][1][2] invoice_flex_container_json["contents"][i]["body"]["contents"][5]["contents"][1]["text"] = old[i][1][3] invoice_flex_container_json["contents"][i]["body"]["contents"][6]["contents"][1]["text"] = old[i][1][4] invoice_flex_container_json["contents"][i]["body"]["contents"][8]["contents"][1]["text"] = ' '.join( old[i][1][5:]) invoice_carousel_content = CarouselContainer.new_from_json_dict(invoice_flex_container_json) flex_bubble_send_message = FlexSendMessage(alt_text="invoice", contents=invoice_carousel_content) return flex_bubble_send_message
def test_carousel_container(self): arg = { 'contents': [ BubbleContainer( body=BoxComponent( layout='vertical', contents=[TextComponent(text='Hey')] ) ), BubbleContainer( body=BoxComponent( layout='vertical', contents=[TextComponent(text='Foo')] ) ), ] } self.assertEqual( self.serialize_as_dict(arg, type=self.CAROUSEL), CarouselContainer(**arg).as_json_dict() )
def tenMod(dset): contents = [] if len(dset): for x in dset: contents.append( BubbleContainer( hero=ImageComponent(url=x, size='full', align='center', aspect_ratio='13:13', aspect_mode='cover'), body=BoxComponent( layout='vertical', contents=[ TextComponent(margin='md', text=dset[x], weight='bold', size='md', align='center'), SeparatorComponent(margin='xl', color='#0000FF'), BoxComponent(margin='md', layout='horizontal', spacing='xs', contents=[ ButtonComponent( style='link', color='#84C1FF', flex=1, height='sm', action=MessageAction( label="加入最愛", text='MyLove:' + dset[x])) ]) ]))) Carousel = CarouselContainer(contents=contents) message = FlexSendMessage(alt_text="hello", contents=Carousel) else: message = TextSendMessage(text='無符合您輸入的葡萄酒'+chr(0x100010)+"\n"\ +"請重新選擇"+chr(0x10008D)) return message
def process_postback_event(event): query_string_dict = parse_qs(event.postback.data) user_profile = vars(line_bot_api.get_profile(event.source.user_id)) user_id = user_profile["user_id"] if "menu" in query_string_dict.keys(): pg.update_data(user_id, query_string_dict["menu"][0]) linkRichMenuId = open( "data/" + query_string_dict.get('menu')[0] + '/rich_menu_id', 'r').read() # link_rich_menu_to_user : 更換選單指令 line_bot_api.link_rich_menu_to_user(event.source.user_id, linkRichMenuId) # 新聞頭條 flexCarouselContainerJsonDict = create_news_message( query_string_dict.get('menu')[0], "首頁") if flexCarouselContainerJsonDict != "": carouselContent = CarouselContainer.new_from_json_dict( json.loads(flexCarouselContainerJsonDict)) flexCarouselSendMeesage = FlexSendMessage(alt_text="新聞頭條", contents=carouselContent) # 發送 line_bot_api.reply_message(event.reply_token, flexCarouselSendMeesage)
def handle_message(event): text = event.message.text if text == "学部再登録": userid = event.source.user_id user_db.del_userinfo(userid) # user情報を削除 line_bot_api.reply_message(event.reply_token, [ TextSendMessage(text="現在登録されていた学部は削除されました。"), TextSendMessage( text="もう一度下のボタンから学部を選択してください。", quick_reply=QuickReply(items=[ QuickReplyButton( action=PostbackAction(label=major, data=major)) for major in major_list ])) ]) elif text == "送信フォーム": line_bot_api.reply_message( event.reply_token, TemplateSendMessage( alt_text="送信フォーム", template=ButtonsTemplate( text="送信フォーム", image_size="cover", actions=[ URIAction(uri="https://forms.gle/cAMusm8ZN8i4SmbL8", label="ご感想、ご要望はこちら") ]))) elif text == "ゼミ協": line_bot_api.reply_message( event.reply_token, TextSendMessage(text="https://lin.ee/bOegrZ3\n上記のリンクより友だち追加できます!")) #教官または講義名いずれかが送信されたとき.もしくはもう一度探すとき elif "_" not in text or "でもう一度探す" in text: if "でもう一度探す" in text: text = text.split("_")[0] teacherList = onihotoke_db.searchTeacher(text, False) #教員列からワードを検索 lectureList = onihotoke_db.searchLecture(text, False) #講義列からワードを検索 kibutsuList = [] #2つのリストを結合 1つは空であるはず. kibutsuList.extend(teacherList) kibutsuList.extend(lectureList) #検索結果が空でないとき,その検索結果をlabelにもつボタンを送信. if kibutsuList: #kibutsuListの要素数が20を超えないようにする. if len(kibutsuList) > 19: kibutsuList = random.sample( kibutsuList, 19) #一応シャッフルする.何回か表示すればすべての講義を見れるように. kibutsuList.extend(["でもう一度探す"]) #20個目 buttons_templates = [] roop = (len(kibutsuList) + 3) // 4 #最大4つまで表示できるテンプレートを何回表示すればいいか. for i in range(roop): #その回数だけ回す. if i == roop - 1: #最後は4つ以下になるからスライス部分を変える必要あり. buttons_templates.append( ButtonsTemplate(title='講義名を選択してください', text='choose the lecture name', actions=[ MessageAction( label=text + " " + name[:10], text=text + "_" + name) for name in kibutsuList[4 * i:] ])) break buttons_templates.append( ButtonsTemplate( title='講義名を選択してください', text='choose the lecture name', actions=[ MessageAction(label=text + " " + name[:10], text=text + "_" + name) for name in kibutsuList[4 * i:4 * (i + 1)] ])) try: line_bot_api.reply_message(event.reply_token, [ TemplateSendMessage(alt_text='講義を選択してください', template=buttons_template) for buttons_template in buttons_templates ]) # slackに報告 requests.post(SLACKBOT_SEARCH_KEYWORD, data=json.dumps({'text': "検索ワード : " + text})) except: line_bot_api.reply_message( event.reply_token, TextSendMessage(text="エラーのため講義情報を表示できません。エラーは報告済みです。")) # slackに報告 requests.post(SLACKBOT_ERROR_KEYWORD, data=json.dumps({'text': "エラー検索ワード : " + text})) # 該当する講義がなかったとき else: line_bot_api.reply_message( event.reply_token, TextSendMessage(text='該当する講義情報が見つかりませんでした。')) # slackに報告 requests.post(SLACKBOT_ERROR_KEYWORD, data=json.dumps({'text': "見つからなかった検索ワード : " + text})) #教官名と講義名のどちらも送信されたとき、その講義の鬼仏情報をユーザーに送信 elif "_" in text: texts = text.split("_") #『教官名_講義名』 という入力を期待している kibutsuList = onihotoke_db.searchAll(texts[0], texts[1].split(",")[0]) print(texts[1].split(",")[0]) #講義情報の辞書のリスト # print(kibutsuList) if kibutsuList: if len(kibutsuList) > 10: kibutsuList = random.sample( kibutsuList, 10) #一応シャッフルする.何回か表示すればすべての講義を見れるように. try: line_bot_api.reply_message( event.reply_token, FlexSendMessage(alt_text='鬼仏情報', contents=CarouselContainer([ gen_card_onihotoke(dic) for dic in kibutsuList ]))) # slackに報告 requests.post(SLACKBOT_SEARCH_KEYWORD, data=json.dumps({'text': "検索ワード : " + text})) except: line_bot_api.reply_message( event.reply_token, TextSendMessage(text="エラーのため講義情報を表示できません。エラーは報告済みです。")) # slackに報告 SLACKBOT_WEBHOOK_URL = os.environ["SLACKBOT_ERROR_KEYWORD"] requests.post(SLACKBOT_ERROR_KEYWORD, data=json.dumps({'text': "エラー検索ワード : " + text})) # 該当する講義がなかったとき else: line_bot_api.reply_message( event.reply_token, TextSendMessage(text='該当する講義情報が見つかりませんでした。')) # slackに報告 SLACKBOT_WEBHOOK_URL = os.environ["SLACKBOT_ERROR_KEYWORD"] requests.post(SLACKBOT_ERROR_KEYWORD, data=json.dumps({'text': "見つからなかった検索ワード : " + text})) #検索結果が空だったとき、その旨をユーザーに送信 else: line_bot_api.reply_message(event.reply_token, TextSendMessage(text='教官名または講義名を入力してください.')) # slackに報告 SLACKBOT_WEBHOOK_URL = os.environ["SLACKBOT_ERROR_KEYWORD"] requests.post(SLACKBOT_ERROR_KEYWORD, data=json.dumps({'text': "たぶん適当な検索ワード : " + text}))
def get_weather_aqi_daily_message(self, daily_data): flex_carousel = {"type": "carousel", "contents": []} for af in daily_data['aqi_forecast']: af['av'] = (af['max'] + af['min']) / 2 current_date = datetime.now().date().strftime('%Y-%m-%d') if af['date'] < current_date: continue if af['av'] > 0 and af['av'] <= 50: bg_color = '#009966' aqi_level_text = 'Good' text_color = '#ffffff' elif af['av'] > 50 and af['av'] <= 100: bg_color = '#ffde33' aqi_level_text = 'Moderate' text_color = '#000000' elif af['av'] > 100 and af['av'] <= 150: bg_color = '#ff9933' aqi_level_text = 'Unhealthy for Sensitive Groups' text_color = '#000000' elif af['av'] > 150 and af['av'] <= 200: bg_color = '#cc0033' aqi_level_text = 'Unhealthy' text_color = '#ffffff' elif af['av'] > 200 and af['av'] <= 300: bg_color = '#660099' aqi_level_text = 'Very Unhealthy' text_color = '#ffffff' elif af['av'] > 300: bg_color = '#7e0023' aqi_level_text = 'Hazardous' text_color = '#ffffff' bubble = { "type": "bubble", "body": { "type": "box", "layout": "vertical", "spacing": "md", "contents": [{ "type": "text", "text": self._format_date(af['date'], to_format='%a, %-d %b %Y'), "size": "md", "color": text_color, "weight": "bold" }, { "type": "text", "text": daily_data['station_name'], "size": "xs", "color": text_color, "wrap": True }, { "type": "text", "text": "{0} ~ {1}".format(af['min'], af['max']), "size": "3xl", "wrap": True, "color": text_color, "weight": "bold" }, { "type": "text", "text": aqi_level_text, "wrap": True, "color": text_color, "size": "sm" }] }, "styles": { "body": { "backgroundColor": bg_color } } } flex_carousel['contents'].append(bubble) carousel_msg = CarouselContainer.new_from_json_dict(flex_carousel) return FlexSendMessage(alt_text='AQI Daily Forecast', contents=carousel_msg)
def on_postback(event): user_id = event.source.user_id reply_token = event.reply_token post_data = event.postback.data if post_data == "工学部": line_bot_api.reply_message(event.reply_token, [ TextSendMessage( text="下のボタンから学科を選択してください。", quick_reply=QuickReply(items=[ QuickReplyButton( action=PostbackAction(label=major, data=major)) for major in major_list["工学部"] ])) ]) elif post_data == "ヘルプ": line_bot_api.reply_message(event.reply_token, [ TextSendMessage(text="""再登録をしたいとき・・・ 下の「学部再登録」のボタンを押してください。もう一度下にボタンが出現します。\n ご感想、エラー報告・・・ 「送信フォーム」のボタンを押してください。Googleフォームが現れ、匿名で送信できます。\n 鬼仏情報の投稿・・・ 「トンペー鬼仏表」のボタンを押してください。サイトに移動します。\n 経済学部の方・・・ 「ゼミ協」とテキストを送信してください。ゼミ協(東北大学経済学部)が運営するLINEbotの紹介リンクを送信します。"""), TemplateSendMessage( alt_text="選択ボタン", template=ButtonsTemplate( text="以下から選択してください", image_size="cover", actions=[ MessageAction(text="学部再登録", label="学部再登録"), URIAction(uri="https://forms.gle/XmjrKMPacj9H7nDH9", label="送信フォーム"), URIAction(uri="https://www.tonpe.site/toppages/index", label="トンペー鬼仏表") ])) ]) # 絞り込み検索 elif post_data[-1] == "論" or post_data[-1] == "学" or post_data[-1] == "語": lecture_group = post_data user_major = get_usermajor(user_id) if user_major: lecture_info = syllabus_db.search_lecture_info( lecture_group, user_major) # 講義情報の辞書のリストが返ってくる if (user_major == "機知" or user_major == "情物" or user_major == "化バイ" or user_major == "材料" or user_major == "建築" or user_major == "理") and post_data == "自然科学": line_bot_api.reply_message( event.reply_token, TextSendMessage(text="工,理は件数が多いため表示できません")) if len(lecture_info) < 10: line_bot_api.reply_message(event.reply_token, [ FlexSendMessage(alt_text='シラバス情報', contents=CarouselContainer([ gen_card_syllabus(dic, post_data) for dic in lecture_info[:10] ])), TextSendMessage(text=f"上記{len(lecture_info)}件の講義が見つかりました") ]) elif 10 < len(lecture_info) and len(lecture_info) <= 20: line_bot_api.reply_message(event.reply_token, [ FlexSendMessage(alt_text='シラバス情報', contents=CarouselContainer([ gen_card_syllabus(dic, post_data) for dic in lecture_info[:10] ])), FlexSendMessage(alt_text='シラバス情報', contents=CarouselContainer([ gen_card_syllabus(dic, post_data) for dic in lecture_info[10:20] ])), TextSendMessage(text=f"上記{len(lecture_info)}件の講義が見つかりました") ]) elif 20 < len(lecture_info) and len(lecture_info) <= 30: line_bot_api.reply_message(event.reply_token, [ FlexSendMessage(alt_text='シラバス情報', contents=CarouselContainer([ gen_card_syllabus(dic, post_data) for dic in lecture_info[:10] ])), FlexSendMessage(alt_text='シラバス情報', contents=CarouselContainer([ gen_card_syllabus(dic, post_data) for dic in lecture_info[10:20] ])), FlexSendMessage(alt_text='シラバス情報', contents=CarouselContainer([ gen_card_syllabus(dic, post_data) for dic in lecture_info[20:30] ])), TextSendMessage(text=f"上記{len(lecture_info)}件の講義が見つかりました") ]) # 所属登録が済んでいない場合 else: line_bot_api.reply_message(event.reply_token, TextSendMessage(text="所属を登録してください")) else: # ユーザ情報をDBに格納 if post_data[-1] == "部": user_major = post_data[0] else: user_major = post_data user_db.add_userinfo(user_major, user_id) line_bot_api.reply_message( event.reply_token, TextSendMessage(text=post_data + "で登録しました!"))
def get_packages_flex_message(self): content_list = [] for package in self.packages: content_list.append( BubbleContainer( direction='ltr', hero=ImageComponent( url=package['icon_url'], size='xl', aspectMode='cover', ), body=BoxComponent( layout='vertical', contents=[ TextComponent( text=package['name'], weight='bold', size='xl', margin='lg', ), TextComponent( text=package['content'], size='md', margin='xxl' ), BoxComponent( layout='baseline', margin='xl', contents=[ TextComponent( text='Price', flex=2, color='#aaaaaa', size='md' ), TextComponent( text=package['price'], size='md', flex=5 ) ] ), SeparatorComponent(margin='xl') ] ), footer=BoxComponent( layout='vertical', margin='xl', contents=[ ButtonComponent( style='secondary', action=PostbackAction( label='CHOOSE', data=package['data'] ) ) ] ) ) ) carousel = CarouselContainer( contents=content_list ) return FlexSendMessage(alt_text='packages', contents=carousel)
async def getWakeUpWrapper(text): num = 10 if isTenth.match(text) else 1 text = isTenth.match(text).group(1) if isTenth.match( text) is not None else text rule = reduce( lambda accu, curr: accu or (curr if curr['rule'](text) else False), rules, False) or rules[0] if rule['rule'] == isTriggeredWineSwordGodWakeUp: bubbles = [] for i in range(num): if random.random() > 0.5: beer = getBeer() bubble = getStandradRateBeerBubble(beer) bubbles.append(bubble) else: thumb, url, originimage, meta = await rule['func']()[0] bubble = getStandradPixivBubble(url, thumb, originimage, meta, "劍龍醒醒!!") bubbles.append(bubble) return FlexSendMessage( alt_text=rule['altText'], contents=(bubbles[0] if ((len(bubbles) == 1)) else CarouselContainer( contents=bubbles))) elif rule['rule'] == isTriggeredRibWakeUp: slice_point = random.randint(0, num) bubbles = [] cats = [] if (slice_point > 0): # cataas # loop = asyncio.get_event_loop() # asyncio.set_event_loop(loop) cats = await asyncio.gather( *[getRandomCatAsync() for i in range(slice_point)]) cats = list(filter(lambda x: x is not None, cats)) for cat in cats: bubble = BubbleContainer(direction='ltr', spacing='none', hero=ImageComponent( url=cat, size='full', aspect_ratio="1:1", aspect_mode='cover', action=URIAction(label='FULL', uri=cat), )) bubbles.append(bubble) if (num - len(cats)) > 0: for img in await rule['func'](num - len(cats)): thumb, url, originimage, meta = img bubbles.append( getStandradPixivBubble(url, thumb, originimage, meta, rule['altText'])) random.shuffle(bubbles) return FlexSendMessage( alt_text=rule['altText'], contents=(bubbles[0] if ((len(bubbles) == 1)) else CarouselContainer( contents=bubbles))) elif rule['rule'] == isTriggeredFishWakeUp: bubbles = [] police_count = random.randint(0, num) if police_count > 0: bubbles.extend(await getPoliceWrappers(police_count)) if police_count < num: for img in await rule['func'](num - police_count): thumb, url, originimage, meta = img bubbles.append( getStandradPixivBubble(url, thumb, originimage, meta, rule['altText'])) random.shuffle(bubbles) return FlexSendMessage( alt_text=rule['altText'], contents=(bubbles[0] if ((len(bubbles) == 1)) else CarouselContainer( contents=bubbles))) else: bubbles = [] for img in await rule['func'](num): thumb, url, originimage, meta = img bubbles.append( getStandradPixivBubble(url, thumb, originimage, meta, rule['altText'])) return FlexSendMessage( alt_text=rule['altText'], contents=(bubbles[0] if ((len(bubbles) == 1)) else CarouselContainer( contents=bubbles)))
"height": "md", "style": "primary", "gravity": "center" } ] } } ] } """ from linebot.models import (FlexSendMessage, CarouselContainer) import json carouselContent = CarouselContainer.new_from_json_dict( json.loads(flexCarouselContainerJsonDict)) flexCarouselSendMeesage = FlexSendMessage(alt_text="壓力", contents=carouselContent) template_message_dict = {"Book": flexCarouselSendMeesage} from collections import OrderedDict x = OrderedDict() # 每個人的狀態記下來用{ID:Q(n)} # 不管輸入什麼都回應text的內容 @handler.add(MessageEvent, message=TextMessage) def handle_message(event): user_profile = line_bot_api.get_profile(event.source.user_id)
def mylove(n, ulist): a = ulist s = [] alen = len(ulist) if alen == 0: a.append('None') s.append('x') else: s.append(a[0]) contents = [ BoxComponent(margin='md', layout='vertical', spacing='xs', contents=[ BoxComponent( margin='xs', layout='horizontal', spacing='xs', contents=[ ButtonComponent(style='secondary', color='#84C1FF', flex=8, height='sm', action=MessageAction( label=a[0], text='See:' + a[0])), ButtonComponent(style='secondary', color='#ECFFFF', flex=4, height='sm', action=MessageAction( label="刪除", text='re:' + s[0])) ]) ]) ] for x in range(1, alen): contents.append( BoxComponent(margin='md', layout='vertical', spacing='xs', contents=[ BoxComponent( margin='xs', layout='horizontal', spacing='xs', contents=[ ButtonComponent(style='secondary', color='#84C1FF', flex=8, height='sm', action=MessageAction( label=a[x], text='See:' + a[x])), ButtonComponent(style='secondary', color='#ECFFFF', flex=4, height='sm', action=MessageAction( label='刪除', text='re:' + a[x])) ]) ])) Carousel = CarouselContainer(contents=[ BubbleContainer(header=BoxComponent( layout='baseline', contents=[ TextComponent( text=n + "的最愛", weight='bold', size='xl', align='center') ]), body=BoxComponent(layout='vertical', contents=contents)) ]) message = FlexSendMessage(alt_text="hello", contents=Carousel) return message
def handle_teams(event): print('handle_teams') postback_data = event.postback.data team_id = postback_data.split('=')[1] team_data = football_api.get_team(team_id) carousel = CarouselContainer() pages = [ team_data['players'][i:i + 10] for i in range(0, len(team_data['players']), 10) ] for page in pages: bubble = { "type": "bubble", "styles": { "header": { "backgroundColor": "#4a4b4c" } }, "header": { "type": "box", "layout": "vertical", "contents": [{ "type": "text", "text": team_data["team_name"], "weight": "bold", "size": "md", "color": "#ffffff", "action": { "type": "uri", "uri": team_data["team_website"] } }, { "type": "text", "text": "Coach: {}".format(team_data["head_coach"]), "size": "xs", "color": "#ffffff" }] }, "body": { "type": "box", "layout": "vertical", "spacing": "md", "contents": [{ "type": "box", "layout": "horizontal", "contents": [{ "type": "text", "text": "Full Name", "weight": "bold", "size": "xxs", "flex": 5 }, { "type": "text", "text": "Position", "weight": "bold", "size": "xxs", "flex": 2 }, { "type": "text", "text": "Age", "weight": "bold", "size": "xxs", "flex": 1 }] }, { "type": "separator" }] } } body_contents = bubble['body']['contents'] for player in page: body_contents.append({ "type": "box", "layout": "horizontal", "contents": [{ "type": "text", "text": player['name'], "size": "xxs", "wrap": True, "flex": 5 }, { "type": "text", "text": player['position'], "size": "xxs", "flex": 2 }, { "type": "text", "text": str(player['age']), "size": "xxs", "flex": 1 }] }) bubble_container = BubbleContainer.new_from_json_dict(bubble) carousel.contents.append(bubble_container) line_bot_api.reply_message( event.reply_token, FlexSendMessage(alt_text='Team', contents=carousel))
def handle_standings(event): print('handle_standings') data = event.postback.data league_name = str(data).split('=')[1] standings_data = football_api.get_standings(league_name) if len(standings_data['teams']) == 0: line_bot_api.reply_message( event.reply_token, messages=TextSendMessage(text='No Standings Data')) return carousel = CarouselContainer() pages = [ standings_data['teams'][i:i + 10] for i in range(0, len(standings_data['teams']), 10) ] for page in pages: bubble = { "type": "bubble", "styles": { "header": { "backgroundColor": fixtures_header_color[league_name] }, "body": { "separator": True } }, "header": { "type": "box", "layout": "vertical", "contents": [{ "type": "text", "text": "{0} - Standings".format( standings_data['competition_name']), "color": "#ffffff" }] }, "body": { "type": "box", "layout": "vertical", "spacing": "sm", "contents": [{ "type": "box", "layout": "horizontal", "contents": [{ "type": "text", "text": "#", "size": "xs", "weight": "bold", "flex": 2 }, { "type": "text", "text": "Team", "size": "xs", "weight": "bold", "flex": 11 }, { "type": "text", "text": "P", "size": "xs", "weight": "bold", "flex": 2 }, { "type": "text", "text": "Pts", "size": "xs", "weight": "bold", "flex": 3 }] }, { "type": "separator" }] } } bubble_body_contents = bubble['body']['contents'] for team in page: bubble_body_contents.append({ "type": "box", "layout": "horizontal", "contents": [{ "type": "text", "text": team['position'], "size": "xxs", "flex": 2 }, { "type": "text", "text": team['team_name'], "size": "xxs", "wrap": True, "flex": 11, "action": { "type": "postback", "data": "team={}".format(team['team_id']) } }, { "type": "text", "text": team['played'], "size": "xxs", "flex": 2 }, { "type": "text", "text": team['pts'], "size": "xxs", "flex": 3 }] }) bubble_container = BubbleContainer.new_from_json_dict(bubble) carousel.contents.append(bubble_container) line_bot_api.reply_message( event.reply_token, FlexSendMessage(alt_text='Standings', contents=carousel))
def handle_text_message(event): text = event.message.text print_source(event) result = '' if text.lower() == 'liff': line_bot_api.reply_message(event.reply_token, messages=TextSendMessage(text=get_liff_app('/liff'))) return if 'live' in text.lower(): data = rss_feed.get_live_feed() if len(data) > 0: carousel_data = rss_feed.create_live_flxed(data['data']) if carousel_data is not None: carousel_message = CarouselContainer.new_from_json_dict(carousel_data) line_bot_api.reply_message(event.reply_token, messages=FlexSendMessage(alt_text="โปรแกรมถ่ายทอดสดฟุตบอล", contents=carousel_message)) if text.lower() == '@bot help': print_help(event) return if '@bot results=' in text.lower(): league_name = text.lower().split('=')[1] if league_name in fixtures_header_color: results_pb = PostbackEvent(timestamp=time(), source=event.source, reply_token=event.reply_token, postback={ 'data': 'results={0}'.format(league_name) }) handle_results(results_pb) else: print_help(event) if '@bot fixtures=' in text.lower(): league_name = text.lower().split('=')[1] if league_name in fixtures_header_color: fixtures_pb = PostbackEvent(timestamp=time(), source=event.source, reply_token=event.reply_token, postback={ 'data': 'fixtures={0}'.format(league_name) }) handle_fixtures(fixtures_pb) else: print_help(event) if '@bot teamnews=' in text.lower(): team_name = text.lower().split('=')[1] if team_name in team_name_dict: teamnews_pb = PostbackEvent(timestamp=time(), source=event.source, reply_token=event.reply_token, postback={ 'data': 'team_news={0}'.format(team_name) }) handle_team_news(teamnews_pb) else: print_help(event) if '@bot team=' in text.lower(): team_name = text.lower().split('=')[1] if team_name in team_name_dict: team_pb = PostbackEvent(timestamp=time(), source=event.source, reply_token=event.reply_token, postback={ 'data': 'team={0}'.format(team_name_dict[team_name]) }) handle_teams(team_pb) else: print_help(event) if '@bot standings=' in text.lower(): league_name = text.lower().split('=')[1] if league_name in fixtures_header_color: standings_pb = PostbackEvent(timestamp=time(), source=event.source, reply_token=event.reply_token, postback={ 'data': 'standings={0}'.format(league_name) }) handle_standings(standings_pb) else: print_help(event) if text.lower() == 'news=bbc-sport': data = rss_feed.get_bbc_feed(5) result = football_news.get_news_bubble("#FEE63E", data) if text.lower() == 'news=sky-sport': data = rss_feed.get_skysports_feed(5) result = football_news.get_news_bubble("#BB0211", data, header_text_color="#ffffff") if text.lower() == 'news=goal.com': data = rss_feed.get_goal_feed(5) result = football_news.get_news_bubble("#091F2C", data, header_text_color="#ffffff") if text.lower() == 'news=guardian': data = rss_feed.get_guardian_feed(5) result = football_news.get_news_bubble("#09508D", data, header_text_color="#ffffff") if text.lower() == 'news=mirror': data = rss_feed.get_mirror_feed(5) result = football_news.get_news_bubble("#E80E0D", data, header_text_color="#ffffff") if text.lower() == 'news=shotongoal': data = rss_feed.get_shot_on_goal_feed(5) result = football_news.get_news_bubble("#1A1A1A", data, header_text_color="#ffffff") if text.lower() == 'news=soccersuck': data = rss_feed.get_soccersuck_feed(5) result = football_news.get_news_bubble("#197F4D", data) if text.lower() == 'news=dailymail': data = rss_feed.get_daily_mail_feed(5) result = football_news.get_news_bubble("#ffffff", data) if text.lower() == '@bot allnews': get_all_news(event.reply_token) if isinstance(result, BubbleContainer): line_bot_api.reply_message(event.reply_token, FlexSendMessage(alt_text='news', contents=result))
def handle_results(event): print('handle_results') data = event.postback.data league_name = str(data).split('=')[1] fixtures_data = football_api.get_results(league_name, 7) if len(fixtures_data) == 1: line_bot_api.reply_message(event.reply_token, messages=TextSendMessage(text='No Result')) return # carousel template carousel_container = CarouselContainer() for date, data in fixtures_data.items(): bubble = { "type": "bubble", "styles": { "header": { "backgroundColor": fixtures_header_color[league_name] }, "body": { "separator": True } }, "header": { "type": "box", "layout": "vertical", "contents": [{ "type": "text", "weight": "bold", "text": "{0} Results".format(fixtures_data['competition_name']), "color": "#ffffff" }] }, "body": { "type": "box", "layout": "vertical", "spacing": "sm", "contents": [{ "type": "text", "text": date, "size": "sm", "weight": "bold", "align": "center" }, { "type": "separator" }] } } bubble_contents = bubble['body']['contents'] if isinstance(data, list): for match in data: bubble_contents.append({ "type": "box", "layout": "horizontal", "spacing": "sm", "contents": [{ "type": "text", "size": "xxs", "text": match['homeTeam']['name'], "flex": 3, "wrap": True, "action": { "type": "postback", "data": "team={0}".format(match['homeTeam']['id']) } }, { "type": "text", "size": "xxs", "text": match['score'], "flex": 1, "action": { "type": "postback", "data": "match={0}".format(match['match_id']) } }, { "type": "text", "size": "xxs", "text": match['awayTeam']['name'], "flex": 3, "wrap": True, "action": { "type": "postback", "data": "team={0}".format(match['awayTeam']['id']) } }] }) carousel_container.contents.append(bubble) line_bot_api.reply_message(event.reply_token, messages=FlexSendMessage( alt_text='Results', contents=carousel_container))
def handle_message(event): if event.message.text == "呼叫助理": flex_message = FlexSendMessage( alt_text="呼叫助理 Flex", contents=BubbleContainer( body=BoxComponent( layout="vertical", contents=[ TextComponent(text="排程", align="center", weight="bold", size="xl"), BoxComponent(layout="baseline", contents=[ TextComponent(text="沒事幹"), TextComponent(text="20/04/31 00:00", align="end") ]) ]), footer=BoxComponent( layout="horizontal", spacing="md", contents=[ ButtonComponent(action=URIAction( label="我要排程", uri= "https://liff.line.me/1654548127-50gGKZyE/Manager" ), style="primary"), ButtonComponent(action=URIAction( label="修改行程", uri= "https://liff.line.me/1654548127-50gGKZyE/Manager" ), style="primary") ]))) line_bot_api.reply_message(event.reply_token, flex_message) elif event.message.text == "推薦行程": carousel_template = TemplateSendMessage( alt_text="Carousel Template 推薦行程", template=CarouselTemplate(columns=[ CarouselColumn(thumbnail_image_url=locations[0][4], title=locations[0][0], text="天氣:" + locations[0][2] + " 溫度:" + str(locations[0][3]) + "°C" + "\n" + locations[0][1], actions=[ MessageTemplateAction(label="開始導航", text="開始導航" + locations[0][0]), MessageTemplateAction(label="這個我不喜歡", text="不喜歡" + locations[0][0]) ]), CarouselColumn(thumbnail_image_url=locations[1][4], title=locations[1][0], text="天氣:" + locations[1][2] + " 溫度:" + str(locations[1][3]) + "°C" + "\n" + locations[1][1], actions=[ MessageTemplateAction(label="開始導航", text="開始導航" + locations[1][0]), MessageTemplateAction(label="這個我不喜歡", text="不喜歡" + locations[1][0]) ]) ])) line_bot_api.reply_message(event.reply_token, carousel_template) elif "開始導航" in event.message.text: if locations[0][0] in event.message.text: flex_message = FlexSendMessage( alt_text="導航 Flex", contents=BubbleContainer( body=BoxComponent( layout="vertical", contents=[TextComponent(text=locations[0][0] + "導航")]), footer=BoxComponent( layout="horizontal", contents=[ ButtonComponent(action=URIAction( label="開啟 Google 地圖", uri= ("https://www.google.com/maps/search/?api=1&query=" + locations[0][0]))) ]))) elif locations[1][0] in event.message.text: flex_message = FlexSendMessage( alt_text="導航 Flex", contents=BubbleContainer( body=BoxComponent( layout="vertical", contents=[TextComponent(text=locations[1][0] + "導航")]), footer=BoxComponent( layout="horizontal", contents=[ ButtonComponent(action=URIAction( label="開啟 Google 地圖", uri= ("https://www.google.com/maps/search/?api=1&query=" + locations[1][0]))) ]))) line_bot_api.reply_message(event.reply_token, flex_message) elif event.message.text == "記帳小本本": money = 69 budget = 420 flex_message = FlexSendMessage( alt_text="記帳小本本 Flex", contents=BubbleContainer( body=BoxComponent( layout="vertical", contents=[ TextComponent(text="記帳小本本", align="center", weight="bold", size="xl"), BoxComponent(layout="horizontal", contents=[ TextComponent(text="當前餘額"), TextComponent(text=str(money) + " 元", align="end") ]), BoxComponent(layout="horizontal", contents=[ TextComponent(text="每日可用餘額"), TextComponent(text=str(budget) + " 元", align="end") ]) ]), footer=BoxComponent( layout="horizontal", spacing="md", contents=[ ButtonComponent(action=URIAction( label="開始記帳", uri= "https://liff.line.me/1654548127-50gGKZyE/Account" ), style="primary"), ButtonComponent(action=URIAction( label="餘額設定", uri= "https://liff.line.me/1654548127-50gGKZyE/Account" ), style="primary") ]))) line_bot_api.reply_message(event.reply_token, flex_message) elif event.message.text == "天氣及空氣品質": flex_message = FlexSendMessage( alt_text="天氣及空氣品質 Flex", contents=CarouselContainer(contents=[ BubbleContainer( size="kilo", body=BoxComponent( layout="vertical", spacing="sm", contents=[ BoxComponent( layout="horizontal", spacing="sm", contents=[ ButtonComponent(action=PostbackAction( label="臺北", data="臺北-天氣及空氣品質"), style="secondary", color="#94d3e2"), ButtonComponent(action=PostbackAction( label="新北", data="新北-天氣及空氣品質"), style="secondary", color="#94d3e2"), ButtonComponent(action=PostbackAction( label="基隆", data="基隆-天氣及空氣品質"), style="secondary", color="#94d3e2") ]), BoxComponent( layout="horizontal", spacing="sm", contents=[ ButtonComponent(action=PostbackAction( label="桃園", data="桃園-天氣及空氣品質"), style="secondary", color="#94d3e2"), ButtonComponent(action=PostbackAction( label="新竹", data="新竹-天氣及空氣品質"), style="secondary", color="#94d3e2"), ButtonComponent(action=PostbackAction( label="苗栗", data="苗栗-天氣及空氣品質"), style="secondary", color="#94d3e2") ]), BoxComponent( layout="horizontal", spacing="sm", contents=[ ButtonComponent(action=PostbackAction( label="臺中", data="臺中-天氣及空氣品質"), style="secondary", color="#94d3e2"), ButtonComponent(action=PostbackAction( label="彰化", data="彰化-天氣及空氣品質"), style="secondary", color="#94d3e2"), ButtonComponent(action=PostbackAction( label="南投", data="南投-天氣及空氣品質"), style="secondary", color="#94d3e2") ]), ])), BubbleContainer( size="kilo", body=BoxComponent( layout="vertical", spacing="sm", contents=[ BoxComponent( layout="horizontal", spacing="sm", contents=[ ButtonComponent(action=PostbackAction( label="雲林", data="雲林-天氣及空氣品質"), style="secondary", color="#94d3e2"), ButtonComponent(action=PostbackAction( label="嘉義", data="嘉義-天氣及空氣品質"), style="secondary", color="#94d3e2"), ButtonComponent(action=PostbackAction( label="臺南", data="臺南-天氣及空氣品質"), style="secondary", color="#94d3e2") ]), BoxComponent( layout="horizontal", spacing="sm", contents=[ ButtonComponent(action=PostbackAction( label="高雄", data="高雄-天氣及空氣品質"), style="secondary", color="#94d3e2"), ButtonComponent(action=PostbackAction( label="屏東", data="屏東-天氣及空氣品質"), style="secondary", color="#94d3e2"), ButtonComponent(action=PostbackAction( label="宜蘭", data="宜蘭-天氣及空氣品質"), style="secondary", color="#94d3e2"), ]), BoxComponent( layout="horizontal", spacing="sm", contents=[ ButtonComponent(action=PostbackAction( label="花蓮", data="花蓮-天氣及空氣品質"), style="secondary", color="#94d3e2"), ButtonComponent(action=PostbackAction( label="臺東", data="臺東-天氣及空氣品質"), style="secondary", color="#94d3e2"), TextComponent(text=" ") ]), ])) ])) line_bot_api.reply_message(event.reply_token, flex_message) elif event.message.text == "油價": try: ssl._create_default_https_context = ssl._create_unverified_context data = pd.read_html( 'https://www2.moeaboe.gov.tw/oil102/oil2017/A01/A0108/tablesprices.asp', header=0)[0] # 取得網頁上的表格資訊 except: ssl._create_default_https_context = ssl._create_unverified_context data = pd.read_html( 'https://www2.moeaboe.gov.tw/oil102/oil2017/A01/A0108/tablesprices.asp', header=0)[0] print("Second Try") response = requests.get("https://m.gas.goodlife.tw/") soup = BeautifulSoup(response.text, "html.parser") def printt(response, soup): timer = soup.find("ul", {"id": "gas-price"}).find("li").find("p") if "明日" in timer.get_text(): return timer.get_text().replace(" ", "")[8:-5] elif "今日" in timer.get_text(): return timer.get_text().replace(" ", "")[8:-5] else: return timer.get_text().replace(" ", "")[:-10] def printgas(response, soup): if soup.find("h2", {"class": "down"}) != None: pregas = "汽油每公升降" elif soup.find("h2", {"class": "up"}) != None: pregas = "汽油每公升漲" if soup.find("h2").find("em") == None: return "汽油每公升不調整" gas = soup.find("h2").find("em").get_text() return pregas + gas + "元" def printdiesel(response, soup): diesel = soup.find("ul", {"id": "gas-price"}).find_all("li")[1] unwanted = diesel.find('h3') unwanted.extract() diesel = diesel.get_text().replace(" ", "").strip("元").strip("\n") if "0.0" in diesel: return "柴油每公升不調整" elif "-" in diesel: prediesel = "柴油每公升降" diesel = diesel.strip("-") return prediesel + diesel + "元" elif "+" in diesel: prediesel = "柴油每公升漲" diesel = diesel.strip("+") return prediesel + diesel + "元" flex_message = FlexSendMessage( alt_text="油價 Flex", contents=BubbleContainer( size="giga", body=BoxComponent( layout="vertical", contents=[ TextComponent(text="今日油價", size="lg", align="center"), TextComponent(text=" ", size="xxs"), BoxComponent(layout="horizontal", contents=[ TextComponent(text="供應商", size="xs"), TextComponent(text="98無鉛", size="xs"), TextComponent(text="95無鉛", size="xs"), TextComponent(text="92無鉛", size="xs"), TextComponent(text="柴油", size="xs"), TextComponent(text=" ", size="xs") ]), BoxComponent(layout="horizontal", contents=[ TextComponent(text="中油"), TextComponent(text=str(data.iloc[1, 1]), weight="bold"), TextComponent(text=str(data.iloc[1, 2]), weight="bold"), TextComponent(text=str(data.iloc[1, 3]), weight="bold"), TextComponent(text=str(data.iloc[1, 4]), weight="bold"), TextComponent(text="元/公升", size="xs", gravity="bottom") ]), BoxComponent(layout="horizontal", contents=[ TextComponent(text="台塑"), TextComponent(text=str(data.iloc[0, 1]), weight="bold"), TextComponent(text=str(data.iloc[0, 2]), weight="bold"), TextComponent(text=str(data.iloc[0, 3]), weight="bold"), TextComponent(text=str(data.iloc[0, 4]), weight="bold"), TextComponent(text="元/公升", size="xs", gravity="bottom") ]), TextComponent(text=" ", size="xxs"), TextComponent(text=printt(response, soup), align="center", size="sm"), TextComponent(text=str( printgas(response, soup) + " " + printdiesel(response, soup)), align="center"), TextComponent(text="*實際漲幅受亞洲鄰國油價限制", size="xs", align="center") ]))) line_bot_api.reply_message(event.reply_token, flex_message) elif event.message.text == "幫助": flex_message = FlexSendMessage( alt_text="幫助 Flex", contents=CarouselContainer(contents=[ BubbleContainer(size="kilo", body=BoxComponent( layout="vertical", spacing="sm", contents=[ ButtonComponent(action=PostbackAction( label="呼叫助理", data="呼叫助理-幫助"), style="secondary"), ButtonComponent(action=PostbackAction( label="推薦行程", data="推薦行程-幫助"), style="secondary"), ButtonComponent(action=PostbackAction( label="記帳小本本", data="記帳小本本-幫助"), style="secondary") ])), BubbleContainer( size="kilo", body=BoxComponent( layout="vertical", spacing="sm", contents=[ ButtonComponent(action=PostbackAction( label="天氣及空氣品質", data="天氣及空氣品質-幫助"), style="secondary"), ButtonComponent(action=PostbackAction( label="油價", data="油價-幫助"), style="secondary"), TextComponent(text=" ") ])) ])) line_bot_api.reply_message(event.reply_token, [ TextSendMessage(text="歡迎加入行動助理\n讓你輕鬆管理生活大小事\n以下是此助理的功能說明"), flex_message ]) elif event.message.text == "小遊戲": flex_message = FlexSendMessage( alt_text="小遊戲 Flex", contents=CarouselContainer(contents=[ BubbleContainer( size="micro", action=URIAction( label="Snake", uri="https://www.google.com/fbx?fbx=snake_arcade"), hero=ImageComponent(url="https://i.imgur.com/tUXJI3R.png", size="full", aspectMode="cover"), body=BoxComponent( layout="vertical", contents=[ ButtonComponent(action=URIAction( label="Snake", uri= "https://www.google.com/fbx?fbx=snake_arcade")) ])), BubbleContainer( size="micro", action=URIAction( label="Tetris", uri="https://binaryify.github.io/vue-tetris/?lan=en"), hero=ImageComponent(url="https://i.imgur.com/nuxsFbb.png", size="full", aspectMode="cover"), body=BoxComponent( layout="vertical", contents=[ ButtonComponent(action=URIAction( label="Tetris", uri= "https://binaryify.github.io/vue-tetris/?lan=en" )) ])), BubbleContainer( size="micro", action=URIAction(label="Tower Game", uri="https://www.towergame.app/"), hero=ImageComponent(url="https://i.imgur.com/uzzivML.png", size="full", aspectMode="cover"), body=BoxComponent( layout="vertical", contents=[ ButtonComponent(action=URIAction( label="Tower Game", uri="https://www.towergame.app/")) ])) ])) line_bot_api.reply_message(event.reply_token, flex_message) elif event.message.text == "RNG": RNGmsg = "" ran = random.randrange(3) if ran == 0: RNGmsg = "https://youtu.be/keXfiffBzFw" elif ran == 1: RNGmsg = "https://youtu.be/EWKX3wass9s" elif ran == 2: RNGmsg = "https://youtu.be/1snEYPg8TXs" elif ran == 3: RNGmsg = "https://youtu.be/joZaJqyl2S0" elif ran == 4: RNGmsg = "https://youtu.be/96HtY9XJSMA" line_bot_api.reply_message(event.reply_token, TextSendMessage(text=RNGmsg)) elif "=" in event.message.text: x = event.message.text.split("=", 1) try: line_bot_api.reply_message( event.reply_token, TextSendMessage(text=eval(x[0], {"__builtins__": None}, {}))) except: line_bot_api.reply_message(event.reply_token, "計算有誤") elif event.message.text == "send nudes": message = ImageSendMessage( original_content_url= "https://danbooru.donmai.us/data/__atlanta_kantai_collection_drawn_by_rui_shi_rayze_ray__c62475e083da5351641192f3569a3412.jpg", preview_image_url= "https://pbs.twimg.com/media/EdNl79IUYAAh_68?format=jpg&name=small" ) line_bot_api.reply_message(event.reply_token, message) else: line_bot_api.reply_message( event.reply_token, TextSendMessage(text="未知Message:\n" + event.message.text))
def create_place_flex_message(self, places): carousel = CarouselContainer() for place in places: bubble = { "type": "bubble", "hero": { "type": "image", "url": place['photo_url'], "size": "full", "aspectRatio": "20:13", "aspectMode": "cover" }, "body": { "type": "box", "layout": "vertical", "contents": [{ "type": "box", "layout": "baseline", "spacing": "md", "contents": [{ "type": "icon", "url": place['icon'] }, { "type": "text", "text": place['name'], "weight": "bold", "size": "lg", "wrap": True }] }] } } bubble_body_contents = bubble['body']['contents'] if place['rating'] is not None: bubble_body_contents.append({ "type": "box", "layout": "baseline", "margin": "md", "contents": [] }) bubble_body_rating_contents = bubble['body']['contents'][1][ "contents"] for star_rating in range(0, place['rating']): bubble_body_rating_contents.append({ "type": "icon", "size": "sm", "url": "https://scdn.line-apps.com/n/channel_devcenter/img/fx/review_gold_star_28.png" }) bubble_body_rating_contents.append({ "type": "text", "text": str(place["rating"]), "size": "sm", "color": "#999999", "margin": "md", "flex": 0 }) bubble_body_contents.append({ "type": "box", "layout": "baseline", "spacing": "sm", "contents": [{ "type": "text", "text": "Place", "color": "#aaaaaa", "size": "sm", "flex": 1 }, { "type": "text", "text": place["address"], "wrap": True, "color": "#666666", "size": "sm", "flex": 5, "action": { "type": "uri", "uri": place["address_url"] } }] }) bubble_body_contents.append({ "type": "box", "layout": "baseline", "spacing": "sm", "contents": [{ "type": "text", "text": "Time", "color": "#aaaaaa", "size": "sm", "flex": 1 }, { "type": "text", "text": place["operating_hours"], "wrap": True, "color": "#666666", "size": "sm", "flex": 5 }] }) if place["website"] is not None: bubble["footer"] = { "type": "box", "layout": "vertical", "contents": [{ "type": "button", "style": "link", "height": "sm", "action": { "type": "uri", "label": "Website", "uri": place["website"] } }] } bubble_container = BubbleContainer.new_from_json_dict(bubble) carousel.contents.append(bubble_container) return carousel
def generate_latest_result(self, data): carousel = CarouselContainer() for suite in data['suites']: bubble = { "type": "bubble", "styles": { "header": { "backgroundColor": data["header_color"] } }, "header": { "type": "box", "layout": "vertical", "contents": [{ "type": "text", "text": data["job_name"], "color": "#ffffff", "size": "lg", "weight": "bold" }, { "type": "text", "text": "Build#{0}, {1}".format(data["build_no"], data['run_at']), "color": "#ffffff", "size": "xs" }] }, "body": { "type": "box", "layout": "vertical", "spacing": "md", "contents": [{ "type": "box", "layout": "horizontal", "contents": [{ "type": "text", "text": suite['suite_name'], "size": "xs" }] }, { "type": "separator" }, { "type": "box", "layout": "vertical", "contents": [] }] } } bubble_test_contents = bubble['body']['contents'][2]['contents'] for test in suite['tests']: bubble_test_contents.append({ "type": "box", "layout": "horizontal", "contents": [{ "type": "text", "text": test["test_name"], "size": "sm", "wrap": True, "flex": 4, "action": { "type": "postback", "data": "detail_job={0}&build_no={1}&test_name={2}".format( data['job_name'], data["build_no"], test["test_name"]) } }, { "type": "text", "text": test["status"], "color": test['status_color'], "size": "xs", "align": "end" }] }) bubble_container = BubbleContainer.new_from_json_dict(bubble) carousel.contents.append(bubble_container) return carousel
def create_flight_route_message(self, data, paging=10): carousel_container = CarouselContainer() pages = [ data['flights'][i:i + paging] for i in range(0, len(data['flights']), paging) ] for page in pages: bubble = { "type": "bubble", "direction": "ltr", "body": { "type": "box", "layout": "vertical", "spacing": "sm", "contents": [{ "type": "box", "layout": "vertical", "contents": [{ "type": "text", "text": data['title'], "size": "sm", "align": "start", "weight": "bold", "color": "#000000" }, { "type": "text", "text": data['description'], "size": "xs", "color": "#929292", "wrap": True }] }, { "type": "separator" }] } } for flight in page: bubble_contents = bubble['body']['contents'].extend(({ "type": "box", "layout": "horizontal", "contents": [{ "type": "box", "layout": "vertical", "flex": 2, "contents": [{ "type": "text", "text": flight['time'], "size": "xs", "gravity": "top", "color": "#000000", "action": { "type": "postback", "label": "flight_info={0}".format(flight['flight_no']), "data": "flight_info={0}".format(flight['flight_no']) } }, { "type": "text", "text": flight['carrier_name'], "size": "xs", "color": "#878787", "wrap": True, "action": { "type": "postback", "label": "flight_info={0}".format(flight['flight_no']), "data": "flight_info={0}".format(flight['flight_no']) } }] }, { "type": "text", "text": flight['flight_no'], "size": "lg", "align": "center", "color": "#269CB0", "align": "center", "gravity": "center", "action": { "type": "postback", "label": "flight_info={0}".format(flight['flight_no']), "data": "flight_info={0}".format(flight['flight_no']) } }] }, { "type": "separator" })) bubble_container = BubbleContainer.new_from_json_dict(bubble) carousel_container.contents.append(bubble) if len(carousel_container.contents) == 7: break return carousel_container
def callback(): signature = request.headers['X-Line-Signature'] # get request body as text body = request.get_data(as_text=True) app.logger.info("Request body: " + body) # parse webhook body try: events = parser.parse(body, signature) except InvalidSignatureError: abort(400) # start getting user event and respond for event in events: #if event type is FollowEvent if isinstance(event, FollowEvent): line_bot_api.reply_message( event.reply_token, TextSendMessage(text='這裡提供各種遊戲攻略,請輸入"攻略"以接受最新遊戲訊息,不然就會一直發大財')) #if message type is message if isinstance(event, MessageEvent): #get user text text = event.message.text #create bubble container project if user text is 攻略 if text == '攻略': #bubble container for Fate/GrandOrder攻略 fgo = BubbleContainer( direction= 'ltr', #set bubble layout direction to left to right(ltr) header=BoxComponent( #set header type = box layout='horizontal', #set layout contents=[ #set contents #content 1 type = text TextComponent( text='FGO 最新攻略 (appmedia日文)', #set type size='md', #set size weight='bold', #set weight color='#1CA0DC' #set color ), ]), hero=ImageComponent( #set hero type = image url='https://pbs.twimg.com/media/D1huyvBU4AEiDtf.jpg', size='full', margin='sm', aspect_ratio='1.51:1', aspect_mode='cover', gravity='bottom', align='center', ), body=BoxComponent( #set body type = box layout='horizontal', spacing='md', contents=[ #set contents #box 1 BoxComponent( layout='vertical', flex=1, #set contents for box 1(3 images) contents=[ ImageComponent( #set url, size, flex, margin, align, aspect ration, aspect mode, background_color and action url= 'https://appmedia.jp/wp-content/uploads/2019/08/top_banner.png', size='full', flex=0, margin='lg', align='end', aspect_ratio='1.91:1', aspect_mode='cover', background_color='#060000', action=URIAction( label='website', uri= 'https://appmedia.jp/fategrandorder/3706486' )), ImageComponent( url= 'https://appmedia.jp/wp-content/uploads/2017/09/d91d441543dc34269289e49c36343e25.png', size='full', margin='md', aspect_ratio='1.91:1', aspect_mode='cover', background_color='#000000'), ImageComponent( url= 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRh1KnzPNfkRTC5fSB-X6CvWqxUEgj7Nwx4OBY9pUI-blkt43_r', ) ]), #box 2 BoxComponent( layout='vertical', flex=2, #set contents for box 2 (3 buttons 2 seperators) contents=[ ButtonComponent( #set action of the button(uri) action=URIAction( label='水着剣豪七色勝負 活動攻略', uri= 'https://appmedia.jp/fategrandorder/3706486' ), style='link', margin='md', gravity='top', height='sm'), SeparatorComponent(margin='md', color='#FFFFFF'), ButtonComponent(action=URIAction( label='素材一覧', uri= 'https://appmedia.jp/fategrandorder/98413' ), style='link', margin='md', gravity='top', height='sm'), SeparatorComponent(margin='md', color='#FFFFFF'), ButtonComponent(action=URIAction( label='五星從者攻略一覽', uri= 'https://appmedia.jp/fategrandorder/96261' ), style='link', margin='md', gravity='top', height='sm'), ]) ]), #set footer type = box footer=BoxComponent( layout='horizontal', contents=[ ButtonComponent(action=URIAction( label='更多攻略', uri='https://appmedia.jp/fategrandorder'), flex=7, gravity='top') ], )) #message = FlexSendMessage(alt_text="Fate/GrandOrder攻略", contents=bubble) #line_bot_api.reply_message(event.reply_token, message) #elif text.lower()=='gbf'.lower() or text.lower()=='granblue fantasy'.lower() or text=='碧藍幻想': #create bubble container for gbf攻略 gbf = BubbleContainer( direction='ltr', header=BoxComponent(layout='horizontal', contents=[ TextComponent(text='碧蘭幻想攻略', size='md', weight='bold', color='#18BCF4') ]), hero=ImageComponent( url= 'https://www.thesubnation.com/dev3/sites/default/files/styles/wide_background/public/2019-06/granblue_fantasy_versus_cover.jpg?h=8f74817f&itok=dnPJIhT8', size='full', aspect_ratio='20:13', aspect_mode='cover'), body=BoxComponent( layout='horizontal', spacing='md', contents=[ BoxComponent( layout='vertical', flex=1, contents=[ ImageComponent( url= 'https://images-na.ssl-images-amazon.com/images/I/A1GKAs+6ykL.jpg', size='full', aspect_ratio='16:9', aspect_mode='cover'), ImageComponent( url= 'https://truth.bahamut.com.tw/s01/201805/e35c8592c8941c560e6d692a20a6440d.JPG', size='full', margin='md', aspect_ratio='16:9', aspect_mode='cover'), ImageComponent( url= 'https://img.ruten.com.tw/s2/6/3c/e8/21742224438504_873.jpg', margin='md', size='full', aspect_ratio='16:9', aspect_mode='cover') ]), BoxComponent( layout='vertical', contents=[ ButtonComponent( action=URIAction( label='SSR角色', uri= 'https://gbf.huijiwiki.com/wiki/SSR人物' ), style='primary', ), SeparatorComponent(margin='xxl', color='#FFFFFF'), SeparatorComponent(margin='sm', color='#FFFFFF'), TextComponent(text=' 新手向武器編成', size='sm', weight='bold', margin='xs'), ButtonComponent( action=URIAction( label='攻略連結', uri= 'https://forum.gamer.com.tw/C.php?bsn=25204&snA=7062' ), style='primary', margin='sm', height='sm', ), SeparatorComponent(margin='sm', color='#FFFFFF'), SeparatorComponent(margin='lg', color='#FFFFFF'), ButtonComponent( action=URIAction( label='最新情報', uri= 'https://グランブルーファンタジー.gamewith.jp/article/show/21113' ), style='primary', ), ]) ]), footer=BoxComponent( layout='horizontal', contents=[ ButtonComponent(action=URIAction( label='更多攻略', uri='https://gbf.huijiwiki.com/wiki/SSR人物'), ) ])) """ #not completed yet sv = BubbleContainer( direction='ltr', header=BoxComponent( layout='horizontal', contents=[ TextComponent ] ) ) """ #wrap fgo and gbf into a carousel container carousel = CarouselContainer(contents=[fgo, gbf]) #put carousel into the flex message type message = FlexSendMessage(alt_text="更多攻略", contents=carousel) #send message line_bot_api.reply_message(event.reply_token, message) else: line_bot_api.reply_message(event.reply_token, TextSendMessage(text='發大財')) if not isinstance(event, MessageEvent): continue if not isinstance(event.message, TextMessage): continue line_bot_api.reply_message(event.reply_token, TextSendMessage(text='fdt')) return 'OK'
def create_airport_message(self, airport_data): carousel_container = CarouselContainer() departures_bubble = { "type": "bubble", "styles": { "header": { "backgroundColor": "#FFF800" }, "body": { "backgroundColor": "#000000" } }, "direction": "ltr", "header": { "type": "box", "layout": "vertical", "contents": [{ "type": "text", "text": 'DEPARTURES', "align": "start", "size": "xl", "weight": "bold" }, { "type": "text", "text": airport_data['departure_title'], "size": "xs", "align": "start", "wrap": True }] }, "body": { "type": "box", "layout": "vertical", "spacing": "sm", "contents": [{ "type": "box", "layout": "horizontal", "contents": [{ "type": "text", "text": "Time", "flex": 1, "size": "xs", "align": "start", "color": "#FFFFFF" }, { "type": "text", "text": "Destination", "flex": 2, "size": "xs", "align": "start", "color": "#FFFFFF" }, { "type": "text", "text": "Flight", "size": "xs", "align": "end", "color": "#FFFFFF" }] }, { "type": "separator" }] } } for departure in airport_data['departures']: departures_bubble['body']['contents'].append({ "type": "box", "layout": "horizontal", "contents": [{ "type": "text", "text": departure['time'], "flex": 1, "size": "xs", "align": "start", "color": "#FFFFFF" }, { "type": "text", "text": departure['destination'], "flex": 2, "size": "xs", "align": "start", "color": "#FFFFFF", "wrap": True, "action": { "type": "postback", "data": "airport={0}".format(departure['destination_code']) } }, { "type": "text", "text": departure['flight_no'], "size": "xs", "align": "end", "color": "#FFFFFF", "action": { "type": "postback", "data": "flight_info={0}".format(departure['flight_no']) } }] }) arrivals_bubble = { "type": "bubble", "styles": { "header": { "backgroundColor": "#9FE9FF" }, "body": { "backgroundColor": "#000000" } }, "direction": "ltr", "header": { "type": "box", "layout": "vertical", "contents": [{ "type": "text", "text": "ARRIVALS", "align": "start", "size": "xl", "weight": "bold" }, { "type": "text", "text": airport_data['arrival_title'], "align": "start", "size": "xs", "wrap": True }] }, "body": { "type": "box", "layout": "vertical", "spacing": "sm", "contents": [{ "type": "box", "layout": "horizontal", "contents": [{ "type": "text", "text": "Time", "flex": 1, "size": "xs", "align": "start", "color": "#FFFFFF" }, { "type": "text", "text": "Origin", "flex": 2, "size": "xs", "align": "start", "color": "#FFFFFF" }, { "type": "text", "text": "Flight", "size": "xs", "align": "end", "color": "#FFFFFF" }] }, { "type": "separator" }] } } for arrival in airport_data['arrivals']: arrivals_bubble['body']['contents'].append({ "type": "box", "layout": "horizontal", "contents": [{ "type": "text", "text": arrival['time'], "flex": 1, "size": "xs", "align": "start", "color": "#FFFFFF" }, { "type": "text", "text": arrival['origin'], "flex": 2, "size": "xs", "align": "start", "color": "#FFFFFF", "wrap": True, "action": { "type": "postback", "data": "airport={0}".format(arrival['origin_code']) } }, { "type": "text", "text": arrival['flight_no'], "size": "xs", "align": "end", "color": "#FFFFFF", "action": { "type": "postback", "data": "flight_info={0}".format(arrival['flight_no']) } }] }) departure_container = BubbleContainer.new_from_json_dict( departures_bubble) arrival_container = BubbleContainer.new_from_json_dict(arrivals_bubble) carousel_container.contents.append(departure_container) carousel_container.contents.append(arrival_container) return carousel_container
def handle_message(event): hands = ["グー", "チョキ", "パー"] battle_flg = False commands = { "bye": "グループを退会します。", "dir": "ディレクトリの表示をします。", "Test": "FlexMessageのテストを表示します。", "UserId": "UserIdを表示します。" } if event.message.text == 'じゃんけん': hands_img = { "グー": "https://image.middle-edge.jp/medium/d334db3f-010d-45f0-8999-d57c84e76677.jpg?1485589415", "チョキ": "https://www.sozai-library.com/wp-content/uploads/2015/07/5092-300x225.jpg", "パー": "https://image.jimcdn.com/app/cms/image/transf/none/path/se516d3bb2a89d52e/image" "/i65b87465dfb3a4ab/version/1551120498/image.jpg" } items = [ QuickReplyButton(image_url=hands_img[hand], action=MessageAction(label=f"{hand}", text=f"{hand}")) for hand in hands ] messages = TextSendMessage(text="じゃーんけーん", quick_reply=QuickReply(items=items)) client.reply_message(event.reply_token, messages=messages) battle_flg = True if event.message.text in hands and battle_flg: res_text = Janken.Rock_Paper_Scissors(event.message.text) client.reply_message(event.reply_token, TextSendMessage(res_text)) battle_flg = False print(battle_flg) if event.message.text == 'help': cmd_mes = '' for cmd in commands: cmd_mes += cmd + ":" cmd_mes += commands[cmd] + "\n" client.reply_message(event.reply_token, TextSendMessage(cmd_mes)) if event.message.text == "bye": client.reply_message(event.reply_token, TextSendMessage("See you!")) # グループトークからの退出処理 if hasattr(event.source, "group_id"): client.leave_group(event.source.group_id) # ルームからの退出処理 if hasattr(event.source, "room_id"): client.leave_room(event.source.room_id) return if event.message.text == 'UserId': client.reply_message(event.reply_token, TextSendMessage(event.source.user_id)) if event.message.text == 'Profile': profile = client.get_profile(event.source.user_id) name = profile.display_name # -> 表示名 userid = profile.user_id # -> ユーザーID image = profile.picture_url # -> 画像のURL client.reply_message(event.reply_token, TextSendMessage(f"Name:{name}\nUserId:{userid}")) client.reply_message( event.reply_token, ImageSendMessage(original_content_url=image, preview_image_url=image)) if event.message.text == "dir": current_dir = os.getcwd() ls = os.listdir(current_dir) full_path = os.path.realpath(__file__) client.reply_message( event.reply_token, TextSendMessage(str(f"{current_dir}\n{str(ls)}\n{full_path}"))) if event.message.text == "Test": try: item = "ぶりぶり" template = template_env.get_template('Test.json') data = template.render(dict(items=item)) client.reply_message( event.reply_token, messages=FlexSendMessage( alt_text='hello', contents=CarouselContainer.new_from_json_dict( json.loads(data)))) except Exception as e: tb = sys.exc_info()[2] client.reply_message( event.reply_token, TextSendMessage(f"[Error]\nType:{str(type(e))}\n" f"Args:{str(e.args)}\n" f"Except:{str(e)}\n" f"Mes:\n{e.with_traceback(tb)}")) '''client.reply_message(