def callback(request): if request.method == 'POST': signature = request.META['HTTP_X_LINE_SIGNATURE'] body = request.body.decode('utf-8') try: events = parser.parse(body, signature) # 傳入的事件 except InvalidSignatureError: return HttpResponseForbidden() except LineBotApiError: return HttpResponseBadRequest() for event in events: if isinstance(event, MessageEvent()): # 如果有訊息事件 if (event.message.text == '測試'): line_bot_api.reply_message( # 回復傳入的訊息文字 event.reply_token, TextSendMessage(text='測試成功')) else: line_bot_api.reply_message( # 回復傳入的訊息文字 event.reply_token, TextSendMessage(text=event.message.text)) return HttpResponse() else: return HttpResponseBadRequest()
def test_agent_handle_text_message_fail(): agent = create_mock_agent() # Parser error text_message = TextMessage(text="mock message") mock_event = MessageEvent(timestamp=123, source='123', reply_token='123', message=text_message) assert agent.handle_text_message(mock_event) == None # Command error text_message = TextMessage(text="!yatta order") mock_event = MessageEvent(timestamp=123, source='123', reply_token='123', message=text_message) assert agent.handle_text_message(mock_event) == None
def test_momo_phone(self, bot, line_bot_api): profile = Profile(display_name="RandomGuy") line_bot_api.get_profile = MagicMock(return_value=profile) line_bot_api.get_group_member_profile = MagicMock(return_value=profile) source = SourceUser("Uxxxxxxxxx") message = TextMessage() event = MessageEvent(source=source, message=message) # Test '吃MoMo' case insensitive line_bot_api.reply_message = MagicMock() message.text = "吃MoMo" bot.handle_message(event) message.text = "吃momo" bot.handle_message(event) message.text = "來吃mOmO" bot.handle_message(event) message.text = "想吃MOMO阿" bot.handle_message(event) assert line_bot_api.reply_message.call_count == 4 for (reply, _) in line_bot_api.reply_message.call_args_list: assert reply[1].text == '內湖MoMo訂位專線:(02)8792-9938' # Test normal message line_bot_api.reply_message.reset_mock() message.text = "沒有要吃喔" bot.handle_message(event) assert line_bot_api.reply_message.call_count == 0
def handle_sqs_message(event: SQSEvent) -> None: for record in event: message_event: MessageEvent = MessageEvent.new_from_json_dict( json.loads(record.body)) if not isinstance(message_event.message, ImageMessage): continue image: bytes = download_and_resize_image(message_event, PIXEL_RESIZE_TO) response = rekognition_client.detect_labels(Image={'Bytes': image}) labels_to_reply = [ l['Name'] for l in response['Labels'] if l['Confidence'] > CONFIDENCE_THRESHOLD ] reply_message = ', '.join( labels_to_reply ) if labels_to_reply else 'No label is detected, try another one' try: line_bot_api.reply_message(message_event.reply_token, TextSendMessage(text=reply_message)) except LineBotApiError as e: if e.message == 'Invalid reply token': app.log.error(f'Failed to reply message: {message_event}') else: raise
def test_do_handle_event(self, _mock): linebot_api = mock.Mock(spec=LineBotApi) impl = self.task1.do_handle_event( MessageEvent(reply_token=REPLY_TOKEN_FLAG), linebot_api) impl() linebot_api.reply_message.assert_called_once_with( REPLY_TOKEN_FLAG, BOT_MESSAGE_FLAG)
def setup_handler_tests(request): from linebot.models import MessageEvent, SourceUser request.cls.push_message = patch( 'line_event_handlers.abstract_line_event_handler.push_message', MagicMock()).start() request.cls.reply_message = patch( 'line_event_handlers.abstract_line_event_handler.reply_message', MagicMock()).start() message_event = MessageEvent() message_event.reply_token = 'replytoken' message_event.source = SourceUser(user_id='userid') request.cls.message_event = message_event yield patch.stopall()
def test_agent_handle_text_message_user_source(): agent = create_mock_agent() user_source = SourceUser(user_id="U10001") text_message = TextMessage(text="!new myOrder") mock_event = MessageEvent(timestamp=123, source=user_source, reply_token='123', message=text_message) assert agent.handle_text_message(mock_event) != None
def test_freedan(self, bot, line_bot_api): source = SourceUser("Uxxxxxxxxx") event = MessageEvent(source=source, message=TextMessage(text="RandomMessage")) line_bot_api.reply_message = MagicMock() profile = Profile() line_bot_api.get_profile = MagicMock(return_value=profile) # Test 'FreeDan' and his possible name and message profile.display_name = 'FreeDan - 啊哈' event.message.text = '今天晚餐吃甚麼?' bot.handle_message(event) event.message.text = '今天晚餐吃什麼?' bot.handle_message(event) event.message.text = '今天晚餐吃啥?' bot.handle_message(event) profile.display_name = '數學教師弗力丹' event.message.text = '今天午餐吃甚麼?' bot.handle_message(event) event.message.text = '今天午餐吃什麼?' bot.handle_message(event) event.message.text = '今天午餐吃啥?' bot.handle_message(event) profile.display_name = '阿丹不是阿舟' event.message.text = '明天早餐吃甚麼?' bot.handle_message(event) event.message.text = '明天早餐吃什麼?' bot.handle_message(event) event.message.text = '明天早餐吃啥?' bot.handle_message(event) assert line_bot_api.reply_message.call_count == 9 for (reply, _) in line_bot_api.reply_message.call_args_list: assert reply[1].text == '阿丹吃MoMo阿' line_bot_api.reply_message.reset_mock() event.message.text = '晚餐吃麥當勞' # Test 'FreeDan' and his possible name profile.display_name = 'FreeDan - 啊哈' bot.handle_message(event) profile.display_name = '數學教師弗力丹' bot.handle_message(event) profile.display_name = '阿丹不是阿舟' bot.handle_message(event) assert line_bot_api.reply_message.call_count == 0 line_bot_api.reply_message.reset_mock() # Test normal people line_bot_api.reply_message.reset_mock() profile.display_name = '冰凍麵包' bot.handle_message(event) assert line_bot_api.reply_message.call_count == 0
def test_handle_event(): adapter = LineAdapter(channel_secret=channel_secret, channel_access_token=channel_access_token, default_dialog_service=MyDialog, debug=True, prepare_table=True) with pytest.raises(LineBotApiError): adapter.handle_event( MessageEvent.new_from_json_dict({ "replyToken": "nHuyWiB7yP5Zw52FIkcQobQuGDXCTA", "type": "message", "timestamp": 1462629479859, "source": { "type": "user", "userId": "U4af4980629..." }, "message": { "id": "325708", "type": "text", "text": "Hello, world!" } })) adapter.debug = False with pytest.raises(LineBotApiError): adapter.handle_event( MessageEvent.new_from_json_dict({ "replyToken": "nHuyWiB7yP5Zw52FIkcQobQuGDXCTA", "type": "message", "timestamp": 1462629479859, "source": { "type": "user", "userId": "U4af4980629..." }, "message": { "id": "325708", "type": "text", "text": "Hello, world!" } }))
def fx_message_event() -> MessageEvent: return MessageEvent.new_from_json_dict({ 'message': { 'contentProvider': { 'type': 'line', }, 'id': '10780982258255', 'type': 'image', }, 'replyToken': '776377ba91dc4d72bbf0ded24edb0dbd', 'source': { 'type': 'user', 'userId': '', }, 'timestamp': 1571669106624, 'type': 'message', })
def test_extract_token(): adapter = LineAdapter(channel_secret=channel_secret, channel_access_token=channel_access_token, prepare_table=True) event = MessageEvent.new_from_json_dict({ "replyToken": "nHuyWiB7yP5Zw52FIkcQobQuGDXCTA", "type": "message", "timestamp": 1462629479859, "source": { "type": "user", "userId": "U4af4980629..." }, "message": { "id": "325708", "type": "text", "text": "Hello, world!" } }) token = adapter._extract_token(event) assert token == "nHuyWiB7yP5Zw52FIkcQobQuGDXCTA"
def parse(self, body, signature): """Parse webhook request body as text. :param str body: Webhook request body (as text) :param str signature: X-Line-Signature value (as text) :rtype: list[T <= :py:class:`linebot.models.events.Event`] :return: """ if not self.signature_validator.validate(body, signature): raise InvalidSignatureError('Invalid signature. signature=' + signature) body_json = json.loads(body) events = [] for event in body_json['events']: event_type = event['type'] if event_type == 'message': events.append(MessageEvent.new_from_json_dict(event)) elif event_type == 'follow': events.append(FollowEvent.new_from_json_dict(event)) elif event_type == 'unfollow': events.append(UnfollowEvent.new_from_json_dict(event)) elif event_type == 'join': events.append(JoinEvent.new_from_json_dict(event)) elif event_type == 'leave': events.append(LeaveEvent.new_from_json_dict(event)) elif event_type == 'postback': events.append(PostbackEvent.new_from_json_dict(event)) elif event_type == 'beacon': events.append(BeaconEvent.new_from_json_dict(event)) elif event_type == 'memberJoined': events.append(MemberJoinEvent.new_from_json_dict(event)) elif event_type == 'memberLeft': events.append(MemberLeaveEvent.new_from_json_dict(event)) else: LOGGER.warn('Unknown event type. type=' + event_type) return events
def callback(request): if settings.DEBUG: reply = '' request_json = json.loads(request.body.decode('utf-8')) for e in request_json['events']: reply_token = e['replyToken'] message_type = e['message']['type'] source_user = SourceUser(user_id=e['source']['userId']) if message_type == 'text': text = e['message']['text'] timestamp = e['timestamp'] text_message = TextMessage(text=text) message_event = MessageEvent(timestamp=timestamp, source=source_user, message=text_message) router.relay(message_event) return HttpResponse() else: if request.method == 'POST': signature = request.META['HTTP_X_LINE_SIGNATURE'] print('signature: ', signature) body = request.body.decode('utf-8') try: events = parser.parse(body, signature) except InvalidSignatureError: return HttpResponseForbidden() except LineBotApiError: return HttpResponseBadRequest() for event in events: router.relay(event) return HttpResponse() else: return HttpResponseBadRequest()
else: result = 'เยอะขนาดนั้นไปทอยเอาเองนะครับ' else: result = 'ไม่มี' line_bot_api.reply_message(event.reply_token, bot_message(result)) if event.message.text == 'teststickerkrub': # "packageId": "1305699", "stickerId": "12354168" line_bot_api.reply_message(event.reply_token, StickerSendMessage('1305699', '12354168')) cache.set('d20switch', False, None) @handler.default() def default(event): save_message(event) if os.environ.get('TEST_API', ''): handle_message( MessageEvent(message=TextMessage(text='ตอนนี้กี่โมงที่ไทยอ่ะบอท'))) try: line_bot_api.push_message('U4b1094667bd89d0d3f18cb28fa105680', bot_message(text='bot started')) except LineBotApiError as e: print('Unable to send init msg to kenny') print(e)
def test_handle_event_not_text_message(self): agent = TextMessageHook.handle_event( MessageEvent(message=ImageMessage()), None) self.assertEqual(agent, None)
def test_to_minette_message(): # setup adapter adapter = LineAdapter(channel_secret=channel_secret, channel_access_token=channel_access_token, prepare_table=True) # text event = MessageEvent.new_from_json_dict({ "replyToken": "nHuyWiB7yP5Zw52FIkcQobQuGDXCTA", "type": "message", "timestamp": 1462629479859, "source": { "type": "user", "userId": "U4af4980629..." }, "message": { "id": "325708", "type": "text", "text": "Hello, world!" } }) message = adapter._to_minette_message(event) assert message.id == "325708" assert message.type == "text" assert message.text == "Hello, world!" assert message.channel_user_id == "U4af4980629..." # image event = MessageEvent.new_from_json_dict({ "replyToken": "nHuyWiB7yP5Zw52FIkcQobQuGDXCTA", "type": "message", "timestamp": 1462629479859, "source": { "type": "user", "userId": "U4af4980629..." }, "message": { "id": "325708", "type": "image", "contentProvider": { "type": "line" } } }) message = adapter._to_minette_message(event) assert message.type == "image" assert message.payloads[0].url == \ "https://api.line.me/v2/bot/message/325708/content" assert message.payloads[0].thumb == \ "https://api.line.me/v2/bot/message/325708/content" # video event = MessageEvent.new_from_json_dict({ "replyToken": "nHuyWiB7yP5Zw52FIkcQobQuGDXCTA", "type": "message", "timestamp": 1462629479859, "source": { "type": "user", "userId": "U4af4980629..." }, "message": { "id": "325708", "type": "video", "duration": 60000, "contentProvider": { "type": "external", "originalContentUrl": "https://example.com/original.mp4", "previewImageUrl": "https://example.com/preview.jpg" } } }) message = adapter._to_minette_message(event) assert message.type == "video" assert message.payloads[0].url == \ "https://api.line.me/v2/bot/message/325708/content" assert message.payloads[0].thumb == \ "https://api.line.me/v2/bot/message/325708/content" # audio event = MessageEvent.new_from_json_dict({ "replyToken": "nHuyWiB7yP5Zw52FIkcQobQuGDXCTA", "type": "message", "timestamp": 1462629479859, "source": { "type": "user", "userId": "U4af4980629..." }, "message": { "id": "325708", "type": "audio", "duration": 60000, "contentProvider": { "type": "line" } } }) message = adapter._to_minette_message(event) assert message.type == "audio" assert message.payloads[0].url == \ "https://api.line.me/v2/bot/message/325708/content" # location event = MessageEvent.new_from_json_dict({ "replyToken": "nHuyWiB7yP5Zw52FIkcQobQuGDXCTA", "type": "message", "timestamp": 1462629479859, "source": { "type": "user", "userId": "U4af4980629..." }, "message": { "id": "325708", "type": "location", "title": "my location", "address": "〒150-0002 東京都渋谷区渋谷2丁目21−1", "latitude": 35.65910807942215, "longitude": 139.70372892916203 } }) message = adapter._to_minette_message(event) assert message.type == "location" assert message.payloads[0].content["title"] == "my location" assert message.payloads[0].content["address"] == \ "〒150-0002 東京都渋谷区渋谷2丁目21−1" assert message.payloads[0].content["latitude"] == 35.65910807942215 assert message.payloads[0].content["longitude"] == 139.70372892916203 # sticker event = MessageEvent.new_from_json_dict({ "replyToken": "nHuyWiB7yP5Zw52FIkcQobQuGDXCTA", "type": "message", "timestamp": 1462629479859, "source": { "type": "user", "userId": "U4af4980629..." }, "message": { "id": "325708", "type": "sticker", "packageId": "1", "stickerId": "2" } }) message = adapter._to_minette_message(event) assert message.type == "sticker" assert message.payloads[0].content["package_id"] == "1" assert message.payloads[0].content["sticker_id"] == "2" # postback event = PostbackEvent.new_from_json_dict({ "type": "postback", "replyToken": "b60d432864f44d079f6d8efe86cf404b", "source": { "userId": "U91eeaf62d...", "type": "user" }, "timestamp": 1513669370317, "postback": { "data": "storeId=12345", "params": { "datetime": "2017-12-25T01:00" } } }) message = adapter._to_minette_message(event) assert message.type == "postback" assert message.payloads[0].content["data"] == "storeId=12345" assert message.payloads[0].content["params"] == \ {"datetime": "2017-12-25T01:00"} # follow event = FollowEvent.new_from_json_dict({ "replyToken": "nHuyWiB7yP5Zw52FIkcQobQuGDXCTA", "type": "follow", "timestamp": 1462629479859, "source": { "type": "user", "userId": "U4af4980629..." } }) message = adapter._to_minette_message(event) assert message.type == "follow" # unfollow event = UnfollowEvent.new_from_json_dict({ "type": "unfollow", "timestamp": 1462629479859, "source": { "type": "user", "userId": "U4af4980629..." } }) message = adapter._to_minette_message(event) assert message.type == "unfollow" # join event = JoinEvent.new_from_json_dict({ "replyToken": "nHuyWiB7yP5Zw52FIkcQobQuGDXCTA", "type": "join", "timestamp": 1462629479859, "source": { "type": "group", "groupId": "C4af4980629..." } }) message = adapter._to_minette_message(event) assert message.type == "join" # leave event = LeaveEvent.new_from_json_dict({ "type": "leave", "timestamp": 1462629479859, "source": { "type": "group", "groupId": "C4af4980629..." } }) message = adapter._to_minette_message(event) assert message.type == "leave" # member join event = MemberJoinedEvent.new_from_json_dict({ "replyToken": "0f3779fba3b349968c5d07db31eabf65", "type": "memberJoined", "timestamp": 1462629479859, "source": { "type": "room", "roomId": "C4af4980629..." }, "joined": { "members": [{ "type": "user", "userId": "U4af4980629..." }, { "type": "user", "userId": "U91eeaf62d9..." }] } }) message = adapter._to_minette_message(event) assert message.type == "memberJoined" assert message.group.type == "room" # member leave event = MemberLeftEvent.new_from_json_dict({ "type": "memberLeft", "timestamp": 1462629479960, "source": { "type": "room", "roomId": "C4af4980629..." }, "left": { "members": [{ "type": "user", "userId": "U4af4980629..." }, { "type": "user", "userId": "U91eeaf62d9..." }] } }) message = adapter._to_minette_message(event) assert message.type == "memberLeft" assert message.group.type == "room" # beacon event = BeaconEvent.new_from_json_dict({ "replyToken": "nHuyWiB7yP5Zw52FIkcQobQuGDXCTA", "type": "beacon", "timestamp": 1462629479859, "source": { "type": "user", "userId": "U4af4980629..." }, "beacon": { "hwid": "d41d8cd98f", "type": "enter" } }) message = adapter._to_minette_message(event) assert message.type == "beacon" # other(account link) event = AccountLinkEvent.new_from_json_dict({ "type": "accountLink", "replyToken": "b60d432864f44d079f6d8efe86cf404b", "source": { "userId": "U91eeaf62d...", "type": "user" }, "timestamp": 1513669370317, "link": { "result": "ok", "nonce": "xxxxxxxxxxxxxxx" } }) message = adapter._to_minette_message(event) assert message.type == "accountLink"
def test_handle_event_not_matching(self): agent = TextMessageHook.handle_event( MessageEvent(message=TextMessage(text="Test")), None) self.assertEqual(agent, None)
def test_handle_event(self): agent = TextMessageHook.handle_event( MessageEvent(message=TextMessage(text="test")), None) self.assertEqual(agent, self.hook1.pk)
def test_handle_event_no_case_matches(self): agent = TextMessageHook.handle_event( MessageEvent(message=TextMessage(text="TEST")), None) self.assertEqual(agent, self.hook1.pk)
def test_handle_event_case_sensitive_matches(self): agent = TextMessageHook.handle_event( MessageEvent(message=TextMessage(text="Test")), None) self.assertEqual(agent, self.hook2.pk)
def handle_message(event: MessageEvent): # handle previous room if db.check_source(event.source): pass else: print('new room') db.collect_source(event.source, SourceInfo.old(ENV).to_dict()) text = event.message.text.lower().strip() # data to text try: profile = line_bot_api.get_profile(event.source.user_id) db.collect_usr(profile=profile, source=event.source) print(profile.display_name) user_not_follow = False except Exception as e: if event.source.type == 'room': profile = line_bot_api.get_group_member_profile( event.source.room_id, event.source.user_id) else: profile = line_bot_api.get_room_member_profile( event.source.group_id, event.source.user_id) print(profile.display_name) print(e, 'user not follow') user_not_follow = True pass event_dict = {} event_dict['event'] = event.as_json_dict() msg_dict = {} msg_dict['msg'] = event.message.as_json_dict() auto_mode = db.get_source_auto_config(event.source) latest_msg = db.get_latest_msg(source=event.source) # handle testing functions if ENV == 'test': try: text, env_test = process_test(text) event.message.text = text handle_funct = handle_dict[env_test] except: handle_funct = handle_dict['puan'] else: handle_funct = handle_dict[ENV] msg = '' event_dict['bot_reply'] = False # bot flow if user_not_follow: msg = reply_howto() event_dict['bot_reply'] = False elif text == '#' + str(bot_info.display_name): # show manual msg = bot_command.reply_how_to event_dict['bot_reply'] = True elif text == bot_command.com_hi: msg = bot_command.reply_greeting event_dict['bot_reply'] = True elif text == bot_command.com_kick: if event.source.type == 'user': msg = bot_command.reply_kick_user_room event_dict['bot_reply'] = True else: msg = bot_command.reply_kick event_dict['bot_action'] = 'leave' event_dict['bot_reply'] = True elif text == bot_command.com_echo: msg = db.get_latest_msg(source=event.source, msg_if_none='no history') event_dict['bot_reply'] = True # toggle auto mode elif text == bot_command.com_auto: db.update_source_info(event.source, {'source_info': { 'auto_mode': not (auto_mode) }}) msg = bot_command.reply_auto_mode(auto_mode=auto_mode) event_dict['bot_reply'] = True # elif text.startswith('#'): # pass else: # main puan logic # check if auto mode text_to_puan = False if ENV in ['test', 'lu', 'puan']: check_case = (text == CONST['exec']) or (text == CONST['exec_anti']) else: check_case = text == CONST['exec'] if check_case: text_to_puan = latest_msg if ENV in ['test', 'lu', 'puan']: if text == CONST['exec_anti']: text_to_puan = '@' + text_to_puan # puan process usage if text_to_puan: event_dict['text_to_puan'] = text_to_puan event_dict['bot_reply'] = True try: puan_result = handle_funct(text_to_puan) msg = puan_result['msg'] event_dict['puan_result'] = puan_result except Exception as e: if text_to_puan.startswith("#"): msg = bot_command.reply_error_text_for_action( text_to_puan) else: msg = bot_command.reply_error_text(text_to_puan) error_msg = f'{str(repr(e))}' print(error_msg) event_dict['error'] = error_msg finally: pass else: msg = bot_command.reply_no_history print('no history') event_dict['bot_reply'] = True # check if execution phrase elif auto_mode: print('auto mode') text_to_puan = text # puan process event_dict['text_to_puan'] = text_to_puan event_dict['bot_reply'] = True try: puan_result = handle_funct(text_to_puan) msg = puan_result['msg'] event_dict['puan_result'] = puan_result except Exception as e: if text_to_puan.startswith("#"): msg = bot_command.reply_error_text_for_action(text_to_puan) else: msg = bot_command.reply_error_text(text_to_puan) error_msg = f'{str(repr(e))}' print(error_msg) event_dict['error'] = error_msg finally: pass # write event_dict['msg'] = msg print(event_dict) db.collect_event(event_dict=event_dict, source=event.source) db.collect_msg(msg_dict=msg_dict, source=event.source, msg_id=event.message.id) # if error keep another record too if 'error' in event_dict: db.write(event_dict, DB_ERR) # reply bot print(f'write to {DB}') if 'bot_reply' in event_dict: if event_dict['bot_reply']: # collect bot reply as msg too db.collect_msg(msg_dict={ 'msg': { 'text': msg }, 'type': 'bot' }, source=event.source, msg_id=event.message.id + "_bot") line_bot_api.reply_message(event.reply_token, TextSendMessage(text=msg)) # manage bot leave if 'bot_action' in event_dict: if event_dict['bot_action'] == 'leave': if event.source.type == 'room': line_bot_api.leave_room(event.source.room_id) elif event.source.type == 'group': line_bot_api.leave_group(event.source.group_id)