예제 #1
0
def line(event, context):

    # イベントデータの表示
    logger.info('headers:' + str(event['headers']['X-Line-Signature']))
    logger.info('body:' + str(event['body']))

    # リクエスト本体と、X-LINE-Signatureヘッダを取出す
    body = event['body']
    signature = event['headers']['X-Line-Signature']

    # Channel Secretを使って入力が正しいかを確認する
    secret = 'ここにシークレットを入力'
    parser = WebhookParser(secret)

    try:
        events = parser.parse(body,signature)
    except InvalidSignatureError:
        logger.error('InvalidSignatureError')
        return {"stautsCode" : 400,"body" : ""};

    # LineBotAPIオブジェクトを作成する
    token = 'ここにトークンを入力'
    line_bot_api = LineBotApi(token)

    try:
        events = parser.parse(body,signature)
    except InvalidSignatureError:
        return {"stautsCode" : 400,"body" : ""};

    # for event in events:
    logger.info('events:' + str(events))

    # DBにメッセージを保存
    user_id = events[0].source.user_id
    line_message = events[0].message.text

    put_response = table.put_item(
        Item={
            'timestamp': int(datetime.datetime.now().timestamp()),
            'id': user_id,
            'message': line_message
        }
    )

    reply_token = events[0].reply_token
    success_message = TextSendMessage(
        text='メッセージを登録しました!\n\n'
             'メッセージを修正する場合はもう一度メッセージを送ってください\n\n'
             'メッセージにはあなたのお名前がわかるようにしてください'
    )

    try:
        line_bot_api.reply_message(reply_token,success_message)
    except LineBotApiError as e:
        print(e.status_code)
        print(e.error.message)
        print(e.error.details)

    return {"stautsCode" : 200,"body" : "OK"};
def register_temperature(request):
    execution_id = request.headers.get('Function-Execution-Id')
    channel_secret = os.environ.get('LINE_CHANNEL_SECRET')
    channel_access_token = os.environ.get('LINE_CHANNEL_ACCESS_TOKEN')

    bot_api = LineBotApi(channel_access_token)
    parser = WebhookParser(channel_secret)

    body = request.get_data(as_text=True)
    hash = hmac.new(channel_secret.encode('utf-8'),
                    body.encode('utf-8'), hashlib.sha256).digest()
    signature = base64.b64encode(hash).decode()

    if signature != request.headers['X_LINE_SIGNATURE']:
        return abort(405)

    try:
        events = parser.parse(body, signature)
    except InvalidSignatureError:
        return abort(405)

    for event in events:
        if not isinstance(event, MessageEvent):
            continue
        if not isinstance(event.message, TextMessage):
            continue

        handle_event(event, channel_access_token, bot_api, execution_id)
    return jsonify({'message': 'ok'})
예제 #3
0
def callback():
    if channel_secret is None:
        print('Specify LINE_CHANNEL_SECRET as environment variable.')
        sys.exit(1)
    if channel_access_token is None:
        print('Specify LINE_CHANNEL_ACCESS_TOKEN as environment variable.')
        sys.exit(1)

    line_bot_api = LineBotApi(channel_access_token)
    parser = WebhookParser(channel_secret)
    signature = request.headers['X-Line-Signature']

    # get request body as text
    body = request.get_data(as_text=True)
    # app.logger.info("Request body: " + body)
    print("Request body: %s" % body)

    # parse webhook body
    try:
        events = parser.parse(body, signature)
        for event in events:
            if isinstance(event, MessageEvent):
                handle_message(event)
    except InvalidSignatureError:
        abort(400)

    return 'OK~~'
예제 #4
0
def main(request):
    body = request.get_data(as_text=True)
    line_receiver_id = request.headers.get('LINE_RECEIVER_ID')

    if line_receiver_id and request.headers.get('GOOD_MORNING_AUTH') == GOOD_MORNING_AUTH:
      push_good_morning_image(line_receiver_id)
    else:
      hash = hmac.new(LINE_CHANNEL_SECRET.encode('utf-8'),
          body.encode('utf-8'), hashlib.sha256).digest()
      signature = base64.b64encode(hash).decode()
      parser = WebhookParser(LINE_CHANNEL_SECRET)

      if signature != request.headers['X_LINE_SIGNATURE']:
          return abort(405)
      try:
          events = parser.parse(body, signature)
      except InvalidSignatureError:
          return abort(405)

      for event in events:
          if not isinstance(event, MessageEvent):
              continue
          if isinstance(event.message, ImageMessage) and (event.source.type == 'room' and event.source.user_id == LINE_TARGET_ID):
              image_message_id = event.message.id
              image_content = line_bot_api.get_message_content(image_message_id).content
              upload_image(image_content, GOOD_MORNING_ALBUM_ID)
    return jsonify({ 'message': 'ok'})
예제 #5
0
def callback():
    channel_secret = os.getenv('LINE_CHANNEL_SECRET', None)
    channel_access_token = os.getenv('LINE_CHANNEL_ACCESS_TOKEN', None)
    if not channel_secret:
        print('Specify LINE_CHANNEL_SECRET as environment variable.')
        abort(500)
    if not channel_access_token:
        print('Specify LINE_CHANNEL_ACCESS_TOKEN as environment variable.')
        abort(500)

    line_bot_api = LineBotApi(channel_access_token)
    parser = WebhookParser(channel_secret)
    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)
        # if event is MessageEvent and message is TextMessage, then echo text
        for event in events:
            if not isinstance(event, MessageEvent):
                continue
            if not isinstance(event.message, TextMessage):
                continue

            line_bot_api.reply_message(event.reply_token,
                                       get_message(event.message.text))

    except InvalidSignatureError:
        abort(400)

    return 'OK'
예제 #6
0
def linebot(request):
    signature = request.headers['X-Line-Signature']

    # get channel_secret and channel_access_token from your environment variable
    channel_secret = os.getenv('LINE_CHANNEL_SECRET', None)
    channel_access_token = os.getenv('LINE_CHANNEL_ACCESS_TOKEN', None)
    if channel_secret is None:
        print('Specify LINE_CHANNEL_SECRET as environment variable.')
        sys.exit(1)
    if channel_access_token is None:
        print('Specify LINE_CHANNEL_ACCESS_TOKEN as environment variable.')
        sys.exit(1)

    line_bot_api = LineBotApi(channel_access_token)
    parser = WebhookParser(channel_secret)

    # get request body as text
    body = request.get_data(as_text=True)

    events = parser.parse(body, signature)

    # if event is MessageEvent and message is TextMessage, then echo text
    for event in events:
        if not isinstance(event, MessageEvent):
            continue
        if not isinstance(event.message, TextMessage):
            continue

        line_bot_api.reply_message(event.reply_token,
                                   set_reply_message(event.message.text))
    def callback(self, signature, body):
        parser = WebhookParser(self.CHANNEL_SECRET)

        try:
            events = parser.parse(body, signature)
            self.__handle_message(events[0])
        except InvalidSignatureError as e:
            print(e)
class PollService:
    def __init__(self, secret: str):
        self.op_interrupts = {}
        self.parser = WebhookParser(secret)

    def handle_operation(self, body: str, signature: str):
        """Operation Handler
        LINEから飛んできたWebhookをParseし、Wrapper向けに書き直す
        :param body: string 飛んできたWebHookの内容
        :param signature: string シグネチャー
        :return: None
        """
        ops = self.parser.parse(body, signature)
        for op in ops:
            if op.type not in self.op_interrupts:
                continue
            self.set_reply_token(op)
            self.execute_func(op)

    def set_reply_token(self, op: Event):
        """
        set reply token for talk Service
        :param op: Event
        :return: None
        """
        self.reply_token = getattr(op, "reply_token")

    def execute_func(self, op: Event):
        """func executer
        :param op_type: parsed Event from Webhook
        :return: None
        """
        try:
            self.op_interrupts[op.type](self, op)
        except Exception:
            print_exc()

    def add_op_interrupt(self, op_type: OpType, func: Callable):
        """ Add Event to handler
        :param op_type: Event which you want to handle
        :param func: Function which you want to call
        :return: None
        """
        if op_type in self.op_interrupts:
            warnings.warn(f"{op_type} is already added to interrupts", stacklevel=2)

        self.op_interrupts[op_type] = func

    def add_op_interrupts(self, dicts: Dict[OpType, Callable]):
        """Add Events to handler
        :param dicts: Dict[Event, func]
        :return: None
        """
        for event, fnc in dicts.items():
            self.add_op_interrupt(event, fnc)
예제 #9
0
def main(request):
    """This is a LINE Bot function

    Args:
        request (flask.Request): [description]

    Returns:
        Response|HTTPException: [description]
    """

    # LINEアプリ設定(環境変数)
    channel_secret = os.environ.get('LINE_CHANNEL_SECRET')
    channel_access_token = os.environ.get('LINE_CHANNEL_ACCESS_TOKEN')

    # LINE Bot(Messaging) API
    line_bot_api = LineBotApi(channel_access_token)
    parser = WebhookParser(channel_secret)

    # WebhookリクエストからBODYを取得
    body = request.get_data(as_text=True)

    # チャネルの秘密鍵からシグネチャを取得
    hashcode = hmac.new(channel_secret.encode('utf-8'), body.encode('utf-8'),
                        hashlib.sha256).digest()
    signature = base64.b64encode(hashcode).decode()

    # シグネチャの合致判定
    if signature != request.headers['X_LINE_SIGNATURE']:
        return abort(405)

    # リクエストボディからWebhookイベントオブジェクト(Payload)を取得
    try:
        events = parser.parse(body, signature)
    except InvalidSignatureError:
        return abort(405)

    # Webhookイベントオブジェクトを処理
    for event in events:
        if not isinstance(event, MessageEvent):  # メッセージイベント以外は未処理
            continue
        if not isinstance(event.message, TextMessage):  # テキスト以外は未処理
            continue

        if event.message.text == u'おわり':  # エコーバックしないワードの処理
            # 「おわり」というメッセで「ほんとに?」を返す
            line_bot_api.reply_message(event.reply_token,
                                       TextSendMessage(text=u"ほんとに?"))
        else:
            # 上記以外のメッセはそのままオウム返し
            line_bot_api.reply_message(
                event.reply_token, TextSendMessage(text=event.message.text))

    return ("", 200)
예제 #10
0
class Linebot:

    bot = None
    webhookParser = None

    def __init__(self, channel_access_token, channel_secret):
        self.bot = LineBotApi(channel_access_token)
        self.webhookParser = WebhookParser(channel_secret)

    def parse(self, body, signature): #把Line訊息轉換成要的東西
        resultLIST = []

        try:
            events = self.webhookParser.parse(body, signature)
            for event in events:
                if event.source.user_id == "Udeadbeefdeadbeefdeadbeefdeadbeef":
                    continue

                if event.type == "message":
                    try:
                        resultDICT = {
                            "status": True,
                            "type": event.type,
                            "userID": event.source.user_id,
                            "replyToken": event.reply_token,
                            "message": event.message.text,
                            "timestamp": event.timestamp
                        }
                    except Exception as e:
                        print("Linebot parseError => {}".format(str(e)))
                        resultDICT = {"status": False}

                resultLIST.append(resultDICT)

        except InvalidSignatureError as e:
            print("Linebot InvalidSignatureError => {}".format(str(e)))
        except LineBotApiError as e:
            print("Linebot LineBotApiError => {}".format(str(e)))

        return resultLIST

    def respTexts(self, replyToken, textLIST):
        messageLIST = [TextSendMessage(text=text) for text in textLIST]
        self.bot.reply_message(replyToken, messageLIST, notification_disabled=True)

    def respText(self, replyToken, text):
        self.bot.reply_message(replyToken, TextSendMessage(text=text), notification_disabled=True)
예제 #11
0
async def main(req: func.HttpRequest) -> func.HttpResponse:
    # create api client
    line_api = AioLineBotApi(
        channel_access_token="<YOUR CHANNEL ACCESS TOKEN>")

    # get events from request
    parser = WebhookParser(channel_secret="<YOUR CHANNEL SECRET>")
    events = parser.parse(req.get_body().decode("utf-8"),
                          req.headers.get("X-Line-Signature", ""))

    for ev in events:
        # reply echo
        await line_api.reply_message(
            ev.reply_token, TextMessage(text=f"You said: {ev.message.text}"))

    # 200 response
    return func.HttpResponse("ok")
예제 #12
0
def main(request):
    line_bot_api = LineBotApi(LINE_CHANNEL_ACCESS_TOKEN)
    parser = WebhookParser(LINE_CHANNEL_SECRET)

    body = request.get_data(as_text=True)
    hash = hmac.new(LINE_CHANNEL_SECRET.encode('utf-8'), body.encode('utf-8'),
                    hashlib.sha256).digest()
    signature = base64.b64encode(hash).decode()

    if signature != request.headers['X_LINE_SIGNATURE']:
        return abort(405)

    try:
        events = parser.parse(body, signature)
    except InvalidSignatureError:
        return abort(405)

    for event in events:
        if not isinstance(event, MessageEvent):
            continue
        if not isinstance(event.message, TextMessage):
            continue
        text = event.message.text
        if '新增圖片\n' in text:
            tmp, desc, image_url = text.split('\n')
            response = upload_image_by_url(image_url, desc, MAIN_ALBUM_ID)
            message = ('格式錯誤 新增失敗', '新增成功')[response.status_code == 200]
            reply_instance = TextSendMessage(text=message)
        elif text == '關鍵字查詢':
            images = get_images(MAIN_ALBUM_ID)
            desc_list = [image['description'] for image in images]
            #uniqueness
            uniq_desc_list = list(set(desc_list))
            reply_instance = TextSendMessage(text=','.join(uniq_desc_list))
        else:
            #從一般相簿中過濾 or 從美女相簿中隨機
            images = ([
                image for image in get_images(MAIN_ALBUM_ID)
                if image['description'] == text
            ], get_images(SUB_ALBUM_ID))[text == '抽']
            image_url = random.choice(images)['link']
            reply_instance = ImageSendMessage(original_content_url=image_url,
                                              preview_image_url=image_url)

        line_bot_api.reply_message(event.reply_token, reply_instance)
    return jsonify({'message': 'ok'})
예제 #13
0
def home(request):
    line_bot_api = LineBotApi(LINE_CAT)
    webhook_parser = WebhookParser(LINE_CS)
    signature = ""
    if request.META["HTTP_X_LINE_SIGNATURE"]:
        signature = request.META["HTTP_X_LINE_SIGNATURE"]
    body = request.body

    try:
        events = webhook_parser.parse(body, signature)
        for event in events:
            print event.reply_token
            line_bot_api.reply_message(
                event.reply_token, TextSendMessage(text=event.message.text))
    except InvalidSignatureError:
        return HttpResponse("Signature invalid")

    return HttpResponse("")
예제 #14
0
async def main(req: func.HttpRequest) -> func.HttpResponse:
    # APIインターフェイスの初期化
    # api = LineBotApi(channel_access_token="<YOUR CHANNEL ACCESS TOKEN>")      # <-- 同期APIを利用した場合
    api = AioLineBotApi(channel_access_token="<YOUR CHANNEL ACCESS TOKEN>")

    # リクエストからイベントを取得
    parser = WebhookParser(channel_secret="<YOUR CHANNEL SECRET>")
    events = parser.parse(req.get_body().decode("utf-8"),
                          req.headers.get("X-Line-Signature", ""))

    for ev in events:
        # おうむ返し
        # api.reply_message(ev.reply_token, TextMessage(text=f"You said: {ev.message.text}"))      # <-- 同期APIを利用した場合
        await api.reply_message(
            ev.reply_token, TextMessage(text=f"You said: {ev.message.text}"))

    # HTTPのレスポンス
    return func.HttpResponse("ok")
예제 #15
0
class LineGateway(Gateway):
    def __init__(self, channel_access_token:str, channel_secret:str,
                 host="localhost", port="5000", webhook_suffix="line",
                 dispatcher=RequestDispatcher.load(), message_parser=LineParser):
        super().__init__(dispatcher=dispatcher, message_parser=message_parser)
        self.channel_access_token = channel_access_token
        self.channel_secret = channel_secret
        self.port = port
        self.webhook_suffix = webhook_suffix
        self.host = host
        self.line_bot_api = LineBotApi(self.channel_access_token)
        self.webhook_handler = WebhookHandler(self.channel_secret)
        self.parser = WebhookParser(self.channel_secret)
        bottle.default_app().route(path='/', callback=self.landing)
        bottle.default_app().route('/{}'.format(webhook_suffix), callback=self.webhook_callback, method="POST")

    def landing(self):
        return "Running"

    def webhook_callback(self):
        signature = bottle.request.headers['X-Line-Signature']
        body = bottle.request.body.getvalue().decode('utf-8')
        print('%s' % signature)
        try:
            events = self.parser.parse(body, signature)
            for event in events:
                message = self.message_parser.parse(event)
                print(message)
                if message is not None:
                    self.dispatcher.dispatch(message)
        except InvalidSignatureError as e:
            print(e)
            bottle.abort(400)

        return 'OK'

    def run(self):
        print("Started line webhook on http://{}:{}/{}".format(
              self.host, self.port, self.webhook_suffix))

        bottle.run(host=self.host, port=self.port, debug=True)
예제 #16
0
    def test_parse(self):
        file_dir = os.path.dirname(__file__)
        webhook_sample_json_path = os.path.join(file_dir, 'text',
                                                'webhook.json')
        with open(webhook_sample_json_path) as fp:
            body = fp.read()

        parser = WebhookParser('channel_secret')
        # mock
        parser.signature_validator.validate = lambda a, b: True

        events = parser.parse(body, 'channel_secret')

        # MessageEvent, SourceUser, TextMessage
        self.assertIsInstance(events[0], MessageEvent)
        self.assertEqual(events[0].reply_token,
                         'nHuyWiB7yP5Zw52FIkcQobQuGDXCTA')
        self.assertEqual(events[0].type, 'message')
        self.assertEqual(events[0].timestamp, 1462629479859)
        self.assertIsInstance(events[0].source, SourceUser)
        self.assertEqual(events[0].source.type, 'user')
        self.assertEqual(events[0].source.user_id,
                         'U206d25c2ea6bd87c17655609a1c37cb8')
        self.assertEqual(events[0].source.sender_id,
                         'U206d25c2ea6bd87c17655609a1c37cb8')
        self.assertIsInstance(events[0].message, TextMessage)
        self.assertEqual(events[0].message.id, '325708')
        self.assertEqual(events[0].message.type, 'text')
        self.assertEqual(events[0].message.text, 'Hello, world')

        # MessageEvent, SourceRoom, TextMessage
        self.assertIsInstance(events[1], MessageEvent)
        self.assertEqual(events[1].reply_token,
                         'nHuyWiB7yP5Zw52FIkcQobQuGDXCTA')
        self.assertEqual(events[1].type, 'message')
        self.assertEqual(events[1].timestamp, 1462629479859)
        self.assertIsInstance(events[1].source, SourceRoom)
        self.assertEqual(events[1].source.type, 'room')
        self.assertEqual(events[1].source.room_id,
                         'Ra8dbf4673c4c812cd491258042226c99')
        self.assertEqual(events[1].source.user_id, None)
        self.assertEqual(events[1].source.sender_id,
                         'Ra8dbf4673c4c812cd491258042226c99')
        self.assertIsInstance(events[1].message, ImageMessage)
        self.assertEqual(events[1].message.id, '325708')
        self.assertEqual(events[1].message.type, 'image')

        # MessageEvent, SourceUser, VideoMessage
        self.assertIsInstance(events[2], MessageEvent)
        self.assertEqual(events[2].reply_token,
                         'nHuyWiB7yP5Zw52FIkcQobQuGDXCTA')
        self.assertEqual(events[2].type, 'message')
        self.assertEqual(events[2].timestamp, 1462629479859)
        self.assertIsInstance(events[2].source, SourceUser)
        self.assertEqual(events[2].source.type, 'user')
        self.assertEqual(events[2].source.user_id,
                         'U206d25c2ea6bd87c17655609a1c37cb8')
        self.assertEqual(events[2].source.sender_id,
                         'U206d25c2ea6bd87c17655609a1c37cb8')
        self.assertIsInstance(events[2].message, VideoMessage)
        self.assertEqual(events[2].message.id, '325708')
        self.assertEqual(events[2].message.type, 'video')

        # MessageEvent, SourceUser, AudioMessage
        self.assertIsInstance(events[3], MessageEvent)
        self.assertEqual(events[3].reply_token,
                         'nHuyWiB7yP5Zw52FIkcQobQuGDXCTA')
        self.assertEqual(events[3].type, 'message')
        self.assertEqual(events[3].timestamp, 1462629479859)
        self.assertIsInstance(events[3].source, SourceUser)
        self.assertEqual(events[3].source.type, 'user')
        self.assertEqual(events[3].source.user_id,
                         'U206d25c2ea6bd87c17655609a1c37cb8')
        self.assertEqual(events[3].source.sender_id,
                         'U206d25c2ea6bd87c17655609a1c37cb8')
        self.assertIsInstance(events[3].message, AudioMessage)
        self.assertEqual(events[3].message.id, '325708')
        self.assertEqual(events[3].message.type, 'audio')

        # MessageEvent, SourceUser, LocationMessage
        self.assertIsInstance(events[4], MessageEvent)
        self.assertEqual(events[4].reply_token,
                         'nHuyWiB7yP5Zw52FIkcQobQuGDXCTA')
        self.assertEqual(events[4].type, 'message')
        self.assertEqual(events[4].timestamp, 1462629479859)
        self.assertIsInstance(events[4].source, SourceUser)
        self.assertEqual(events[4].source.type, 'user')
        self.assertEqual(events[4].source.user_id,
                         'U206d25c2ea6bd87c17655609a1c37cb8')
        self.assertEqual(events[4].source.sender_id,
                         'U206d25c2ea6bd87c17655609a1c37cb8')
        self.assertIsInstance(events[4].message, LocationMessage)
        self.assertEqual(events[4].message.id, '325708')
        self.assertEqual(events[4].message.type, 'location')
        self.assertEqual(events[4].message.title, 'my location')
        self.assertEqual(events[4].message.address, 'Tokyo')
        self.assertEqual(events[4].message.latitude, 35.65910807942215)
        self.assertEqual(events[4].message.longitude, 139.70372892916203)

        # MessageEvent, SourceUser, StickerMessage
        self.assertIsInstance(events[5], MessageEvent)
        self.assertEqual(events[5].reply_token,
                         'nHuyWiB7yP5Zw52FIkcQobQuGDXCTA')
        self.assertEqual(events[5].type, 'message')
        self.assertEqual(events[5].timestamp, 1462629479859)
        self.assertIsInstance(events[5].source, SourceUser)
        self.assertEqual(events[5].source.type, 'user')
        self.assertEqual(events[5].source.user_id,
                         'U206d25c2ea6bd87c17655609a1c37cb8')
        self.assertEqual(events[5].source.sender_id,
                         'U206d25c2ea6bd87c17655609a1c37cb8')
        self.assertIsInstance(events[5].message, StickerMessage)
        self.assertEqual(events[5].message.id, '325708')
        self.assertEqual(events[5].message.type, 'sticker')
        self.assertEqual(events[5].message.package_id, '1')
        self.assertEqual(events[5].message.sticker_id, '1')

        # FollowEvent, SourceUser
        self.assertIsInstance(events[6], FollowEvent)
        self.assertEqual(events[6].reply_token,
                         'nHuyWiB7yP5Zw52FIkcQobQuGDXCTA')
        self.assertEqual(events[6].type, 'follow')
        self.assertEqual(events[6].timestamp, 1462629479859)
        self.assertIsInstance(events[6].source, SourceUser)
        self.assertEqual(events[6].source.type, 'user')
        self.assertEqual(events[6].source.user_id,
                         'U206d25c2ea6bd87c17655609a1c37cb8')
        self.assertEqual(events[6].source.sender_id,
                         'U206d25c2ea6bd87c17655609a1c37cb8')

        # UnfollowEvent, SourceUser
        self.assertIsInstance(events[7], UnfollowEvent)
        self.assertEqual(events[7].type, 'unfollow')
        self.assertEqual(events[7].timestamp, 1462629479859)
        self.assertIsInstance(events[7].source, SourceUser)
        self.assertEqual(events[7].source.type, 'user')
        self.assertEqual(events[7].source.user_id,
                         'U206d25c2ea6bd87c17655609a1c37cb8')
        self.assertEqual(events[7].source.sender_id,
                         'U206d25c2ea6bd87c17655609a1c37cb8')

        # JoinEvent, SourceGroup
        self.assertIsInstance(events[8], JoinEvent)
        self.assertEqual(events[8].reply_token,
                         'nHuyWiB7yP5Zw52FIkcQobQuGDXCTA')
        self.assertEqual(events[8].type, 'join')
        self.assertEqual(events[8].timestamp, 1462629479859)
        self.assertIsInstance(events[8].source, SourceGroup)
        self.assertEqual(events[8].source.type, 'group')
        self.assertEqual(events[8].source.group_id,
                         'Ca56f94637cc4347f90a25382909b24b9')
        self.assertEqual(events[8].source.user_id, None)
        self.assertEqual(events[8].source.sender_id,
                         'Ca56f94637cc4347f90a25382909b24b9')

        # LeaveEvent, SourceGroup
        self.assertIsInstance(events[9], LeaveEvent)
        self.assertEqual(events[9].type, 'leave')
        self.assertEqual(events[9].timestamp, 1462629479859)
        self.assertIsInstance(events[9].source, SourceGroup)
        self.assertEqual(events[9].source.type, 'group')
        self.assertEqual(events[9].source.group_id,
                         'Ca56f94637cc4347f90a25382909b24b9')
        self.assertEqual(events[9].source.user_id, None)
        self.assertEqual(events[9].source.sender_id,
                         'Ca56f94637cc4347f90a25382909b24b9')

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

        # BeaconEvent, SourceUser
        self.assertIsInstance(events[11], BeaconEvent)
        self.assertEqual(events[11].reply_token,
                         'nHuyWiB7yP5Zw52FIkcQobQuGDXCTA')
        self.assertEqual(events[11].type, 'beacon')
        self.assertEqual(events[11].timestamp, 1462629479859)
        self.assertIsInstance(events[11].source, SourceUser)
        self.assertEqual(events[11].source.type, 'user')
        self.assertEqual(events[11].source.user_id,
                         'U206d25c2ea6bd87c17655609a1c37cb8')
        self.assertEqual(events[11].source.sender_id,
                         'U206d25c2ea6bd87c17655609a1c37cb8')
        self.assertEqual(events[11].beacon.hwid, 'd41d8cd98f')
        self.assertEqual(events[11].beacon.type, 'enter')
        self.assertEqual(events[11].beacon.dm, None)
        self.assertEqual(events[11].beacon.device_message, None)

        # BeaconEvent, SourceUser (with device message)
        self.assertIsInstance(events[12], BeaconEvent)
        self.assertEqual(events[12].reply_token,
                         'nHuyWiB7yP5Zw52FIkcQobQuGDXCTA')
        self.assertEqual(events[12].type, 'beacon')
        self.assertEqual(events[12].timestamp, 1462629479859)
        self.assertIsInstance(events[12].source, SourceUser)
        self.assertEqual(events[12].source.type, 'user')
        self.assertEqual(events[12].source.user_id,
                         'U206d25c2ea6bd87c17655609a1c37cb8')
        self.assertEqual(events[12].source.sender_id,
                         'U206d25c2ea6bd87c17655609a1c37cb8')
        self.assertEqual(events[12].beacon.hwid, 'd41d8cd98f')
        self.assertEqual(events[12].beacon.type, 'enter')
        self.assertEqual(events[12].beacon.dm, '1234567890abcdef')
        self.assertEqual(events[12].beacon.device_message,
                         bytearray(b'\x124Vx\x90\xab\xcd\xef'))

        # MessageEvent, SourceGroup with userId, TextMessage
        self.assertIsInstance(events[13], MessageEvent)
        self.assertEqual(events[13].reply_token,
                         'nHuyWiB7yP5Zw52FIkcQobQuGDXCTA')
        self.assertEqual(events[13].type, 'message')
        self.assertEqual(events[13].timestamp, 1462629479859)
        self.assertIsInstance(events[13].source, SourceGroup)
        self.assertEqual(events[13].source.type, 'group')
        self.assertEqual(events[13].source.group_id,
                         'Ca56f94637cc4347f90a25382909b24b9')
        self.assertEqual(events[13].source.user_id,
                         'U206d25c2ea6bd87c17655609a1c37cb8')
        self.assertEqual(events[13].source.sender_id,
                         'Ca56f94637cc4347f90a25382909b24b9')
        self.assertIsInstance(events[13].message, TextMessage)
        self.assertEqual(events[13].message.id, '325708')
        self.assertEqual(events[13].message.type, 'text')
        self.assertEqual(events[13].message.text, 'Hello, world')

        # MessageEvent, SourceRoom with userId, TextMessage
        self.assertIsInstance(events[14], MessageEvent)
        self.assertEqual(events[14].reply_token,
                         'nHuyWiB7yP5Zw52FIkcQobQuGDXCTA')
        self.assertEqual(events[14].type, 'message')
        self.assertEqual(events[14].timestamp, 1462629479859)
        self.assertIsInstance(events[14].source, SourceRoom)
        self.assertEqual(events[14].source.type, 'room')
        self.assertEqual(events[14].source.room_id,
                         'Ra8dbf4673c4c812cd491258042226c99')
        self.assertEqual(events[14].source.user_id,
                         'U206d25c2ea6bd87c17655609a1c37cb8')
        self.assertEqual(events[14].source.sender_id,
                         'Ra8dbf4673c4c812cd491258042226c99')
        self.assertIsInstance(events[14].message, TextMessage)
        self.assertEqual(events[14].message.id, '325708')
        self.assertEqual(events[14].message.type, 'text')
        self.assertEqual(events[14].message.text, 'Hello, world')

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

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

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

    def __init__(self):
        secret, access_token = self.check_required_environmental_variables()
        self.commands = [PingCommand(), JinguReservationStateThisWeek()]
        self.line_bot_api = LineBotApi(access_token)
        self.parser = WebhookParser(secret)

    def check_required_environmental_variables(self):
        channel_secret = os.getenv('LINEBOT_TENNIS_LINE_CHANNEL_SECRET', None)
        channel_access_token = os.getenv(
            'LINEBOT_TENNIS_LINE_CHANNEL_ACCESS_TOKEN', None)
        if channel_secret is None:
            raise Exception(
                'Specify LINEBOT_TENNIS_LINE_CHANNEL_SECRET as environment variable.'
            )
        if channel_access_token is None:
            raise Exception(
                'Specify LINEBOT_TENNIS_LINE_CHANNEL_ACCESS_TOKEN as environment variable.'
            )
        return (channel_secret, channel_access_token)

    def handle_request(self, request):
        if request.method != 'POST':
            return Response('404', status=404)
        signature = request.headers.get('X_LINE_SIGNATURE')
        wsgi_input = request.headers.get('wsgi.input')
        content_length = int(request.headers.get('CONTENT_LENGTH'))
        #body = wsgi_input.read(content_length).decode('utf-8')
        body = request.stream.read().decode('utf-8')

        try:
            events = self.parser.parse(body, signature)
        except InvalidSignatureError:
            return Response('Bad request', status=400)

        for event in events:
            if self.is_event_for_connection_test(event):
                print('Ignore the message because it is connection test')
            elif event.type == 'message' and event.message.type == 'text':
                self.handle_message(event.message.text, event.reply_token)

        return Response('OK', status=200)

    def send_help_string(self, reply_token):
        help_string = 'Available commands:\n' + '\n'.join(
            [c.help() for c in self.commands])
        self.line_bot_api.reply_message(reply_token,
                                        TextSendMessage(text=help_string))

    def is_event_for_connection_test(self, event):
        return (event.type == 'message' and
                (event.message.id == '100001' or event.message.id == '100002'))

    def handle_message(self, message_text, reply_token):
        if message_text.startswith(self.COMMAND_PREFIX):
            message_body = message_text[len(self.COMMAND_PREFIX):].strip()
            for command in self.commands:
                if command.is_match(message_body):
                    command.reply(message_body, reply_token, self.line_bot_api)
                    return
            self.send_help_string(reply_token)
예제 #18
0
    def test_parse(self):
        file_dir = os.path.dirname(__file__)
        webhook_sample_json_path = os.path.join(file_dir, 'text', 'webhook.json')
        with open(webhook_sample_json_path) as fp:
            body = fp.read()

        parser = WebhookParser('channel_secret')
        # mock
        parser.signature_validator.validate = lambda a, b: True

        events = parser.parse(body, 'channel_secret')

        # MessageEvent, SourceUser, TextMessage
        self.assertIsInstance(events[0], MessageEvent)
        self.assertEqual(events[0].reply_token, 'nHuyWiB7yP5Zw52FIkcQobQuGDXCTA')
        self.assertEqual(events[0].type, 'message')
        self.assertEqual(events[0].timestamp, 1462629479859)
        self.assertIsInstance(events[0].source, SourceUser)
        self.assertEqual(events[0].source.type, 'user')
        self.assertEqual(events[0].source.user_id, 'U206d25c2ea6bd87c17655609a1c37cb8')
        self.assertIsInstance(events[0].message, TextMessage)
        self.assertEqual(events[0].message.id, '325708')
        self.assertEqual(events[0].message.type, 'text')
        self.assertEqual(events[0].message.text, 'Hello, world')

        # MessageEvent, SourceRoom, TextMessage
        self.assertIsInstance(events[1], MessageEvent)
        self.assertEqual(events[1].reply_token, 'nHuyWiB7yP5Zw52FIkcQobQuGDXCTA')
        self.assertEqual(events[1].type, 'message')
        self.assertEqual(events[1].timestamp, 1462629479859)
        self.assertIsInstance(events[1].source, SourceRoom)
        self.assertEqual(events[1].source.type, 'room')
        self.assertEqual(events[1].source.room_id, 'Ra8dbf4673c4c812cd491258042226c99')
        self.assertEqual(events[1].source.user_id, None)
        self.assertIsInstance(events[1].message, ImageMessage)
        self.assertEqual(events[1].message.id, '325708')
        self.assertEqual(events[1].message.type, 'image')
        self.assertEqual(events[1].message.content_provider.type, 'external')
        self.assertEqual(events[1].message.content_provider.original_content_url,
                         "https://example.com")
        self.assertEqual(events[1].message.content_provider.preview_image_url,
                         "https://example.com")

        # MessageEvent, SourceUser, VideoMessage
        self.assertIsInstance(events[2], MessageEvent)
        self.assertEqual(events[2].reply_token, 'nHuyWiB7yP5Zw52FIkcQobQuGDXCTA')
        self.assertEqual(events[2].type, 'message')
        self.assertEqual(events[2].timestamp, 1462629479859)
        self.assertIsInstance(events[2].source, SourceUser)
        self.assertEqual(events[2].source.type, 'user')
        self.assertEqual(events[2].source.user_id, 'U206d25c2ea6bd87c17655609a1c37cb8')
        self.assertIsInstance(events[2].message, VideoMessage)
        self.assertEqual(events[2].message.id, '325708')
        self.assertEqual(events[2].message.type, 'video')
        self.assertEqual(events[2].message.duration, 60000)
        self.assertEqual(events[2].message.content_provider.type, 'external')
        self.assertEqual(events[2].message.content_provider.original_content_url,
                         "https://example.com")
        self.assertEqual(events[2].message.content_provider.preview_image_url,
                         "https://example.com")

        # MessageEvent, SourceUser, AudioMessage
        self.assertIsInstance(events[3], MessageEvent)
        self.assertEqual(events[3].reply_token, 'nHuyWiB7yP5Zw52FIkcQobQuGDXCTA')
        self.assertEqual(events[3].type, 'message')
        self.assertEqual(events[3].timestamp, 1462629479859)
        self.assertIsInstance(events[3].source, SourceUser)
        self.assertEqual(events[3].source.type, 'user')
        self.assertEqual(events[3].source.user_id, 'U206d25c2ea6bd87c17655609a1c37cb8')
        self.assertIsInstance(events[3].message, AudioMessage)
        self.assertEqual(events[3].message.id, '325708')
        self.assertEqual(events[3].message.type, 'audio')
        self.assertEqual(events[3].message.duration, 60000)
        self.assertEqual(events[3].message.content_provider.type, 'external')
        self.assertEqual(events[3].message.content_provider.original_content_url,
                         "https://example.com")

        # MessageEvent, SourceUser, LocationMessage
        self.assertIsInstance(events[4], MessageEvent)
        self.assertEqual(events[4].reply_token, 'nHuyWiB7yP5Zw52FIkcQobQuGDXCTA')
        self.assertEqual(events[4].type, 'message')
        self.assertEqual(events[4].timestamp, 1462629479859)
        self.assertIsInstance(events[4].source, SourceUser)
        self.assertEqual(events[4].source.type, 'user')
        self.assertEqual(events[4].source.user_id, 'U206d25c2ea6bd87c17655609a1c37cb8')
        self.assertIsInstance(events[4].message, LocationMessage)
        self.assertEqual(events[4].message.id, '325708')
        self.assertEqual(events[4].message.type, 'location')
        self.assertEqual(events[4].message.title, 'my location')
        self.assertEqual(events[4].message.address, 'Tokyo')
        self.assertEqual(events[4].message.latitude, 35.65910807942215)
        self.assertEqual(events[4].message.longitude, 139.70372892916203)

        # MessageEvent, SourceUser, StickerMessage
        self.assertIsInstance(events[5], MessageEvent)
        self.assertEqual(events[5].reply_token, 'nHuyWiB7yP5Zw52FIkcQobQuGDXCTA')
        self.assertEqual(events[5].type, 'message')
        self.assertEqual(events[5].timestamp, 1462629479859)
        self.assertIsInstance(events[5].source, SourceUser)
        self.assertEqual(events[5].source.type, 'user')
        self.assertEqual(events[5].source.user_id, 'U206d25c2ea6bd87c17655609a1c37cb8')
        self.assertIsInstance(events[5].message, StickerMessage)
        self.assertEqual(events[5].message.id, '325708')
        self.assertEqual(events[5].message.type, 'sticker')
        self.assertEqual(events[5].message.package_id, '1')
        self.assertEqual(events[5].message.sticker_id, '1')

        # FollowEvent, SourceUser
        self.assertIsInstance(events[6], FollowEvent)
        self.assertEqual(events[6].reply_token, 'nHuyWiB7yP5Zw52FIkcQobQuGDXCTA')
        self.assertEqual(events[6].type, 'follow')
        self.assertEqual(events[6].timestamp, 1462629479859)
        self.assertIsInstance(events[6].source, SourceUser)
        self.assertEqual(events[6].source.type, 'user')
        self.assertEqual(events[6].source.user_id, 'U206d25c2ea6bd87c17655609a1c37cb8')

        # UnfollowEvent, SourceUser
        self.assertIsInstance(events[7], UnfollowEvent)
        self.assertEqual(events[7].type, 'unfollow')
        self.assertEqual(events[7].timestamp, 1462629479859)
        self.assertIsInstance(events[7].source, SourceUser)
        self.assertEqual(events[7].source.type, 'user')
        self.assertEqual(events[7].source.user_id, 'U206d25c2ea6bd87c17655609a1c37cb8')

        # JoinEvent, SourceGroup
        self.assertIsInstance(events[8], JoinEvent)
        self.assertEqual(events[8].reply_token, 'nHuyWiB7yP5Zw52FIkcQobQuGDXCTA')
        self.assertEqual(events[8].type, 'join')
        self.assertEqual(events[8].timestamp, 1462629479859)
        self.assertIsInstance(events[8].source, SourceGroup)
        self.assertEqual(events[8].source.type, 'group')
        self.assertEqual(events[8].source.group_id, 'Ca56f94637cc4347f90a25382909b24b9')
        self.assertEqual(events[8].source.user_id, None)

        # LeaveEvent, SourceGroup
        self.assertIsInstance(events[9], LeaveEvent)
        self.assertEqual(events[9].type, 'leave')
        self.assertEqual(events[9].timestamp, 1462629479859)
        self.assertIsInstance(events[9].source, SourceGroup)
        self.assertEqual(events[9].source.type, 'group')
        self.assertEqual(events[9].source.group_id, 'Ca56f94637cc4347f90a25382909b24b9')
        self.assertEqual(events[9].source.user_id, None)

        # PostbackEvent, SourceUser
        self.assertIsInstance(events[10], PostbackEvent)
        self.assertEqual(events[10].reply_token, 'nHuyWiB7yP5Zw52FIkcQobQuGDXCTA')
        self.assertEqual(events[10].type, 'postback')
        self.assertEqual(events[10].timestamp, 1462629479859)
        self.assertIsInstance(events[10].source, SourceUser)
        self.assertEqual(events[10].source.type, 'user')
        self.assertEqual(events[10].source.user_id, 'U206d25c2ea6bd87c17655609a1c37cb8')
        self.assertEqual(events[10].postback.data, 'action=buyItem&itemId=123123&color=red')
        self.assertEqual(events[10].postback.params, None)

        # BeaconEvent, SourceUser
        self.assertIsInstance(events[11], BeaconEvent)
        self.assertEqual(events[11].reply_token, 'nHuyWiB7yP5Zw52FIkcQobQuGDXCTA')
        self.assertEqual(events[11].type, 'beacon')
        self.assertEqual(events[11].timestamp, 1462629479859)
        self.assertIsInstance(events[11].source, SourceUser)
        self.assertEqual(events[11].source.type, 'user')
        self.assertEqual(events[11].source.user_id, 'U206d25c2ea6bd87c17655609a1c37cb8')
        self.assertEqual(events[11].beacon.hwid, 'd41d8cd98f')
        self.assertEqual(events[11].beacon.type, 'enter')
        self.assertEqual(events[11].beacon.dm, None)
        self.assertEqual(events[11].beacon.device_message, None)

        # BeaconEvent, SourceUser (with device message)
        self.assertIsInstance(events[12], BeaconEvent)
        self.assertEqual(events[12].reply_token, 'nHuyWiB7yP5Zw52FIkcQobQuGDXCTA')
        self.assertEqual(events[12].type, 'beacon')
        self.assertEqual(events[12].timestamp, 1462629479859)
        self.assertIsInstance(events[12].source, SourceUser)
        self.assertEqual(events[12].source.type, 'user')
        self.assertEqual(events[12].source.user_id, 'U206d25c2ea6bd87c17655609a1c37cb8')
        self.assertEqual(events[12].beacon.hwid, 'd41d8cd98f')
        self.assertEqual(events[12].beacon.type, 'enter')
        self.assertEqual(events[12].beacon.dm, '1234567890abcdef')
        self.assertEqual(events[12].beacon.device_message, bytearray(b'\x124Vx\x90\xab\xcd\xef'))

        # AccountEvent, SourceUser
        self.assertIsInstance(events[13], AccountLinkEvent)
        self.assertEqual(events[13].reply_token, 'nHuyWiB7yP5Zw52FIkcQobQuGDXCTA')
        self.assertEqual(events[13].type, 'accountLink')
        self.assertEqual(events[13].timestamp, 1462629479859)
        self.assertIsInstance(events[13].source, SourceUser)
        self.assertEqual(events[13].source.type, 'user')
        self.assertEqual(events[13].source.user_id, 'U206d25c2ea6bd87c17655609a1c37cb8')
        self.assertEqual(events[13].link.result, 'ok')
        self.assertEqual(events[13].link.nonce, 'Vb771wDYtXuammLszK6h9A')

        # MessageEvent, SourceGroup with userId, TextMessage
        self.assertIsInstance(events[14], MessageEvent)
        self.assertEqual(events[14].reply_token, 'nHuyWiB7yP5Zw52FIkcQobQuGDXCTA')
        self.assertEqual(events[14].type, 'message')
        self.assertEqual(events[14].timestamp, 1462629479859)
        self.assertIsInstance(events[14].source, SourceGroup)
        self.assertEqual(events[14].source.type, 'group')
        self.assertEqual(events[14].source.group_id, 'Ca56f94637cc4347f90a25382909b24b9')
        self.assertEqual(events[14].source.user_id, 'U206d25c2ea6bd87c17655609a1c37cb8')
        self.assertIsInstance(events[14].message, TextMessage)
        self.assertEqual(events[14].message.id, '325708')
        self.assertEqual(events[14].message.type, 'text')
        self.assertEqual(events[14].message.text, 'Hello, world')

        # MessageEvent, SourceRoom with userId, TextMessage
        self.assertIsInstance(events[15], MessageEvent)
        self.assertEqual(events[15].reply_token, 'nHuyWiB7yP5Zw52FIkcQobQuGDXCTA')
        self.assertEqual(events[15].type, 'message')
        self.assertEqual(events[15].timestamp, 1462629479859)
        self.assertIsInstance(events[15].source, SourceRoom)
        self.assertEqual(events[15].source.type, 'room')
        self.assertEqual(events[15].source.room_id, 'Ra8dbf4673c4c812cd491258042226c99')
        self.assertEqual(events[15].source.user_id, 'U206d25c2ea6bd87c17655609a1c37cb8')
        self.assertIsInstance(events[15].message, TextMessage)
        self.assertEqual(events[15].message.id, '325708')
        self.assertEqual(events[15].message.type, 'text')
        self.assertEqual(events[15].message.text, 'Hello, world')

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

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

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

        # ThingsEvent, SourceUser, link
        self.assertIsInstance(events[19], ThingsEvent)
        self.assertEqual(events[19].reply_token, 'nHuyWiB7yP5Zw52FIkcQobQuGDXCTA')
        self.assertEqual(events[19].type, 'things')
        self.assertEqual(events[19].timestamp, 1462629479859)
        self.assertIsInstance(events[19].source, SourceUser)
        self.assertEqual(events[19].source.type, 'user')
        self.assertEqual(events[19].source.user_id, 'U206d25c2ea6bd87c17655609a1c37cb8')
        self.assertIsInstance(events[19].things, DeviceLink)
        self.assertEqual(events[19].things.type, 'link')
        self.assertEqual(events[19].things.device_id, 't2c449c9d1')

        # MemberJoinedEvent
        self.assertIsInstance(events[20], MemberJoinedEvent)
        self.assertEqual(events[20].reply_token, '0f3779fba3b349968c5d07db31eabf65')
        self.assertEqual(events[20].type, 'memberJoined')
        self.assertEqual(events[20].timestamp, 1462629479859)
        self.assertIsInstance(events[20].source, SourceGroup)
        self.assertEqual(events[20].source.type, 'group')
        self.assertEqual(events[20].source.group_id, 'C4af4980629...')
        self.assertEqual(len(events[20].joined.members), 2)
        self.assertIsInstance(events[20].joined.members[0], SourceUser)
        self.assertEqual(events[20].joined.members[0].user_id, 'U4af4980629...')
        self.assertEqual(events[20].joined.members[1].user_id, 'U91eeaf62d9...')

        # MemberLeftEvent
        self.assertIsInstance(events[21], MemberLeftEvent)
        self.assertEqual(events[21].type, 'memberLeft')
        self.assertEqual(events[21].timestamp, 1462629479960)
        self.assertIsInstance(events[21].source, SourceGroup)
        self.assertEqual(events[21].source.type, 'group')
        self.assertEqual(events[21].source.group_id, 'C4af4980629...')
        self.assertEqual(len(events[21].left.members), 2)
        self.assertIsInstance(events[21].left.members[0], SourceUser)
        self.assertEqual(events[21].left.members[0].user_id, 'U4af4980629...')
        self.assertEqual(events[21].left.members[1].user_id, 'U91eeaf62d9...')

        # ThingsEvent, SourceUser, unlink
        self.assertIsInstance(events[22], ThingsEvent)
        self.assertEqual(events[22].reply_token, 'nHuyWiB7yP5Zw52FIkcQobQuGDXCTA')
        self.assertEqual(events[22].type, 'things')
        self.assertEqual(events[22].timestamp, 1462629479859)
        self.assertIsInstance(events[22].source, SourceUser)
        self.assertEqual(events[22].source.type, 'user')
        self.assertEqual(events[22].source.user_id, 'U206d25c2ea6bd87c17655609a1c37cb8')
        self.assertIsInstance(events[22].things, DeviceUnlink)
        self.assertEqual(events[22].things.type, 'unlink')
        self.assertEqual(events[22].things.device_id, 't2c449c9d1')

        # MessageEvent, SourceUser, FileMessage
        self.assertIsInstance(events[23], MessageEvent)
        self.assertEqual(events[23].reply_token, 'nHuyWiB7yP5Zw52FIkcQobQuGDXCTA')
        self.assertEqual(events[23].type, 'message')
        self.assertEqual(events[23].timestamp, 1462629479859)
        self.assertIsInstance(events[23].source, SourceUser)
        self.assertEqual(events[23].source.type, 'user')
        self.assertEqual(events[23].source.user_id, 'U206d25c2ea6bd87c17655609a1c37cb8')
        self.assertEqual(events[23].source.sender_id, 'U206d25c2ea6bd87c17655609a1c37cb8')
        self.assertIsInstance(events[23].message, FileMessage)
        self.assertEqual(events[23].message.id, '325708')
        self.assertEqual(events[23].message.type, 'file')
        self.assertEqual(events[23].message.file_name, "file.txt")
        self.assertEqual(events[23].message.file_size, 2138)

        # ThingsEvent, SourceUser, scenarioResult
        self.assertIsInstance(events[24], ThingsEvent)
        self.assertEqual(events[24].reply_token, 'nHuyWiB7yP5Zw52FIkcQobQuGDXCTA')
        self.assertEqual(events[24].type, 'things')
        self.assertEqual(events[24].timestamp, 1547817848122)
        self.assertIsInstance(events[24].source, SourceUser)
        self.assertEqual(events[24].source.type, 'user')
        self.assertEqual(events[24].source.user_id, 'U206d25c2ea6bd87c17655609a1c37cb8')
        self.assertIsInstance(events[24].things, ScenarioResult)
        self.assertEqual(events[24].things.type, 'scenarioResult')
        self.assertEqual(events[24].things.device_id, 't2c449c9d1')
        self.assertEqual(events[24].things.result.scenario_id, 'XXX')
        self.assertEqual(events[24].things.result.revision, 2)
        self.assertEqual(events[24].things.result.start_time, 1547817845950)
        self.assertEqual(events[24].things.result.end_time, 1547817845952)
        self.assertEqual(events[24].things.result.result_code, 'success')
        self.assertEqual(events[24].things.result.ble_notification_payload, 'AQ==')
        self.assertIsInstance(events[24].things.result.action_results[0], ActionResult)
        self.assertEqual(events[24].things.result.action_results[0].type, 'binary')
        self.assertEqual(events[24].things.result.action_results[0].data, '/w==')
        self.assertIsInstance(events[24].things.result.action_results[1], ActionResult)
        self.assertEqual(events[24].things.result.action_results[1].type, 'void')
예제 #19
0
파일: client.py 프로젝트: Freiza/program-y
class LineBotClient(FlaskRestBotClient):

    def __init__(self, argument_parser=None):
        FlaskRestBotClient.__init__(self, "line", argument_parser)

        self.create_line_bot()

        YLogger.debug(self, "Line Client is running....")

    def get_description(self):
        return 'ProgramY AIML2.0 Line Client'

    def get_client_configuration(self):
        return LineConfiguration()

    def get_license_keys(self):
        self._channel_secret = self.license_keys.get_key("LINE_CHANNEL_SECRET")
        self._channel_access_token = self.license_keys.get_key("LINE_ACCESS_TOKEN")

    def create_line_bot(self):
        self._line_bot_api = LineBotApi(self._channel_access_token)
        self._parser = WebhookParser(self._channel_secret)

    def handle_text_message(self, event):
        question = event.message.text
        userid = event.source.user_id

        answer = self.ask_question(userid, question)

        self._line_bot_api.reply_message(event.reply_token, TextSendMessage(text=answer))

    def get_unknown_response(self, userid):
        if self.configuration.client_configuration.unknown_command_srai is None:
            unknown_response = self.configuration.client_configuration.unknown_command
        else:
            unknown_response = self.ask_question(userid, self.configuration.client_configuration.unknown_command_srai)
            if unknown_response is None or unknown_response == "":
                unknown_response = self.configuration.client_configuration.unknown_command
        return unknown_response

    def handle_unknown_event(self, event):
        userid = ""
        unknown_response = self.get_unknown_response(userid)
        self._line_bot_api.reply_message(event.reply_token, TextSendMessage(text=unknown_response))

    def handle_unknown_message(self, event):
        userid = ""
        unknown_response = self.get_unknown_response(userid)
        self._line_bot_api.reply_message(event.reply_token, TextSendMessage(text=unknown_response))

    def handle_message_request(self, body, signature):

        events = self._parser.parse(body, signature)

        for event in events:
            if isinstance(event, MessageEvent):
                if isinstance(event.message, TextMessage):
                    self.handle_text_message(event)
                else:
                    self.handle_unknown_message(event)
            else:
                self.handle_unknown_event(event)

    def receive_message(self, request):

        if self.configuration.client_configuration.debug is True:
            self.dump_request(request)

        # get X-Line-Signature header value
        signature = request.headers['X-Line-Signature']

        # get request body as text
        body = request.get_data(as_text=True)

        # handle webhook body
        try:
            self.handle_message_request(body, signature)
        except InvalidSignatureError as excep:
            YLogger.exception(self, "Line error", excep)
            abort(500)

        return Response(status=200)
예제 #20
0
    def test_parse(self):
        file_dir = os.path.dirname(__file__)
        webhook_sample_json_path = os.path.join(file_dir, 'text',
                                                'webhook.json')
        with open(webhook_sample_json_path) as fp:
            body = fp.read()

        parser = WebhookParser('channel_secret')
        # mock
        parser.signature_validator.validate = lambda a, b: True

        events = parser.parse(body, 'channel_secret')

        # MessageEvent, SourceUser, TextMessage
        self.assertIsInstance(events[0], MessageEvent)
        self.assertEqual(events[0].reply_token,
                         'nHuyWiB7yP5Zw52FIkcQobQuGDXCTA')
        self.assertEqual(events[0].type, 'message')
        self.assertEqual(events[0].timestamp, 1462629479859)
        self.assertIsInstance(events[0].source, SourceUser)
        self.assertEqual(events[0].source.type, 'user')
        self.assertEqual(events[0].source.user_id,
                         'U206d25c2ea6bd87c17655609a1c37cb8')
        self.assertEqual(events[0].source.sender_id,
                         'U206d25c2ea6bd87c17655609a1c37cb8')
        self.assertIsInstance(events[0].message, TextMessage)
        self.assertEqual(events[0].message.id, '325708')
        self.assertEqual(events[0].message.type, 'text')
        self.assertEqual(events[0].message.text, 'Hello, world')

        # MessageEvent, SourceRoom, TextMessage
        self.assertIsInstance(events[1], MessageEvent)
        self.assertEqual(events[1].reply_token,
                         'nHuyWiB7yP5Zw52FIkcQobQuGDXCTA')
        self.assertEqual(events[1].type, 'message')
        self.assertEqual(events[1].timestamp, 1462629479859)
        self.assertIsInstance(events[1].source, SourceRoom)
        self.assertEqual(events[1].source.type, 'room')
        self.assertEqual(events[1].source.room_id,
                         'U206d25c2ea6bd87c17655609a1c37cb8')
        self.assertEqual(events[1].source.sender_id,
                         'U206d25c2ea6bd87c17655609a1c37cb8')
        self.assertIsInstance(events[1].message, ImageMessage)
        self.assertEqual(events[1].message.id, '325708')
        self.assertEqual(events[1].message.type, 'image')

        # MessageEvent, SourceUser, VideoMessage
        self.assertIsInstance(events[2], MessageEvent)
        self.assertEqual(events[2].reply_token,
                         'nHuyWiB7yP5Zw52FIkcQobQuGDXCTA')
        self.assertEqual(events[2].type, 'message')
        self.assertEqual(events[2].timestamp, 1462629479859)
        self.assertIsInstance(events[2].source, SourceUser)
        self.assertEqual(events[2].source.type, 'user')
        self.assertEqual(events[2].source.user_id,
                         'U206d25c2ea6bd87c17655609a1c37cb8')
        self.assertEqual(events[2].source.sender_id,
                         'U206d25c2ea6bd87c17655609a1c37cb8')
        self.assertIsInstance(events[2].message, VideoMessage)
        self.assertEqual(events[2].message.id, '325708')
        self.assertEqual(events[2].message.type, 'video')

        # MessageEvent, SourceUser, AudioMessage
        self.assertIsInstance(events[3], MessageEvent)
        self.assertEqual(events[3].reply_token,
                         'nHuyWiB7yP5Zw52FIkcQobQuGDXCTA')
        self.assertEqual(events[3].type, 'message')
        self.assertEqual(events[3].timestamp, 1462629479859)
        self.assertIsInstance(events[3].source, SourceUser)
        self.assertEqual(events[3].source.type, 'user')
        self.assertEqual(events[3].source.user_id,
                         'U206d25c2ea6bd87c17655609a1c37cb8')
        self.assertEqual(events[3].source.sender_id,
                         'U206d25c2ea6bd87c17655609a1c37cb8')
        self.assertIsInstance(events[3].message, AudioMessage)
        self.assertEqual(events[3].message.id, '325708')
        self.assertEqual(events[3].message.type, 'audio')

        # MessageEvent, SourceUser, LocationMessage
        self.assertIsInstance(events[4], MessageEvent)
        self.assertEqual(events[4].reply_token,
                         'nHuyWiB7yP5Zw52FIkcQobQuGDXCTA')
        self.assertEqual(events[4].type, 'message')
        self.assertEqual(events[4].timestamp, 1462629479859)
        self.assertIsInstance(events[4].source, SourceUser)
        self.assertEqual(events[4].source.type, 'user')
        self.assertEqual(events[4].source.user_id,
                         'U206d25c2ea6bd87c17655609a1c37cb8')
        self.assertEqual(events[4].source.sender_id,
                         'U206d25c2ea6bd87c17655609a1c37cb8')
        self.assertIsInstance(events[4].message, LocationMessage)
        self.assertEqual(events[4].message.id, '325708')
        self.assertEqual(events[4].message.type, 'location')
        self.assertEqual(events[4].message.title, 'my location')
        self.assertEqual(events[4].message.address, 'Tokyo')
        self.assertEqual(events[4].message.latitude, 35.65910807942215)
        self.assertEqual(events[4].message.longitude, 139.70372892916203)

        # MessageEvent, SourceUser, StickerMessage
        self.assertIsInstance(events[5], MessageEvent)
        self.assertEqual(events[5].reply_token,
                         'nHuyWiB7yP5Zw52FIkcQobQuGDXCTA')
        self.assertEqual(events[5].type, 'message')
        self.assertEqual(events[5].timestamp, 1462629479859)
        self.assertIsInstance(events[5].source, SourceUser)
        self.assertEqual(events[5].source.type, 'user')
        self.assertEqual(events[5].source.user_id,
                         'U206d25c2ea6bd87c17655609a1c37cb8')
        self.assertEqual(events[5].source.sender_id,
                         'U206d25c2ea6bd87c17655609a1c37cb8')
        self.assertIsInstance(events[5].message, StickerMessage)
        self.assertEqual(events[5].message.id, '325708')
        self.assertEqual(events[5].message.type, 'sticker')
        self.assertEqual(events[5].message.package_id, '1')
        self.assertEqual(events[5].message.sticker_id, '1')

        # FollowEvent, SourceUser
        self.assertIsInstance(events[6], FollowEvent)
        self.assertEqual(events[6].reply_token,
                         'nHuyWiB7yP5Zw52FIkcQobQuGDXCTA')
        self.assertEqual(events[6].type, 'follow')
        self.assertEqual(events[6].timestamp, 1462629479859)
        self.assertIsInstance(events[6].source, SourceUser)
        self.assertEqual(events[6].source.type, 'user')
        self.assertEqual(events[6].source.user_id,
                         'U206d25c2ea6bd87c17655609a1c37cb8')
        self.assertEqual(events[6].source.sender_id,
                         'U206d25c2ea6bd87c17655609a1c37cb8')

        # UnfollowEvent, SourceUser
        self.assertIsInstance(events[7], UnfollowEvent)
        self.assertEqual(events[7].type, 'unfollow')
        self.assertEqual(events[7].timestamp, 1462629479859)
        self.assertIsInstance(events[7].source, SourceUser)
        self.assertEqual(events[7].source.type, 'user')
        self.assertEqual(events[7].source.user_id,
                         'U206d25c2ea6bd87c17655609a1c37cb8')
        self.assertEqual(events[7].source.sender_id,
                         'U206d25c2ea6bd87c17655609a1c37cb8')

        # JoinEvent, SourceGroup
        self.assertIsInstance(events[8], JoinEvent)
        self.assertEqual(events[8].reply_token,
                         'nHuyWiB7yP5Zw52FIkcQobQuGDXCTA')
        self.assertEqual(events[8].type, 'join')
        self.assertEqual(events[8].timestamp, 1462629479859)
        self.assertIsInstance(events[8].source, SourceGroup)
        self.assertEqual(events[8].source.type, 'group')
        self.assertEqual(events[8].source.group_id,
                         'cxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx')
        self.assertEqual(events[8].source.sender_id,
                         'cxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx')

        # LeaveEvent, SourceGroup
        self.assertIsInstance(events[9], LeaveEvent)
        self.assertEqual(events[9].type, 'leave')
        self.assertEqual(events[9].timestamp, 1462629479859)
        self.assertIsInstance(events[9].source, SourceGroup)
        self.assertEqual(events[9].source.type, 'group')
        self.assertEqual(events[9].source.group_id,
                         'cxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx')
        self.assertEqual(events[9].source.sender_id,
                         'cxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx')

        # PostbackEvent, SourceUser
        self.assertIsInstance(events[10], PostbackEvent)
        self.assertEqual(events[10].reply_token,
                         'nHuyWiB7yP5Zw52FIkcQobQuGDXCTA')
        self.assertEqual(events[10].type, 'postback')
        self.assertEqual(events[10].timestamp, 1462629479859)
        self.assertIsInstance(events[10].source, SourceUser)
        self.assertEqual(events[10].source.type, 'user')
        self.assertEqual(events[10].source.user_id,
                         'U206d25c2ea6bd87c17655609a1c37cb8')
        self.assertEqual(events[10].source.sender_id,
                         'U206d25c2ea6bd87c17655609a1c37cb8')
        self.assertEqual(events[10].postback.data,
                         'action=buyItem&itemId=123123&color=red')

        # BeaconEvent, SourceUser
        self.assertIsInstance(events[11], BeaconEvent)
        self.assertEqual(events[11].reply_token,
                         'nHuyWiB7yP5Zw52FIkcQobQuGDXCTA')
        self.assertEqual(events[11].type, 'beacon')
        self.assertEqual(events[11].timestamp, 1462629479859)
        self.assertIsInstance(events[11].source, SourceUser)
        self.assertEqual(events[11].source.type, 'user')
        self.assertEqual(events[11].source.user_id,
                         'U206d25c2ea6bd87c17655609a1c37cb8')
        self.assertEqual(events[11].source.sender_id,
                         'U206d25c2ea6bd87c17655609a1c37cb8')
        self.assertEqual(events[11].beacon.hwid, 'd41d8cd98f')
        self.assertEqual(events[11].beacon.type, 'enter')
예제 #21
0
class OAClient(object):
    
    def __init__(self, client):
        self.lock = Lock()
        with Acquire(client.lock, self.lock):
            self.client = client
        with Acquire(self.lock):
            self.thread = None
                
            self._1client = LineBotApi(self.channelAccessToken)
            if self.channelSecret is None:
                self.parser = None
            else:
                self.parser = WebhookParser(self.channelSecret)
            self.idLocks = {}
            self.adminObjs = []
            self.running = False
            
    @property
    def name(self):
        return self.client.oAName
                    
    @property
    def obj(self):
        return self.client.oAObj
    
    @obj.setter
    def obj(self, value):
        self.client.oAObj = value
                    
    @property
    def mid(self):
        return self.client.oAMid
    
    @mid.setter
    def mid(self, value):
        self.client.oAMid = value
                    
    @property
    def db(self):
        return self.client.db
    
    def GetCursor(self):
        return self.client.db.GetCursor()
                    
    @property
    def adminIds(self):
        return self.client.adminIds
    
    @adminIds.setter
    def adminIds(self, value):
        self.client.adminIds = value
                    
    @property
    def tries(self):
        return self.client.tries
    
    @tries.setter
    def tries(self, value):
        self.client.tries = value
                    
    @property
    def channelSecret(self):
        return self.client.channelSecret
    
    @channelSecret.setter
    def channelSecret(self, value):
        self.client.channelSecret = value
                    
    @property
    def channelAccessToken(self):
        return self.client.channelAccessToken
    
    @channelAccessToken.setter
    def channelAccessToken(self, value):
        self.client.channelAccessToken = value
            
    def _1TextMessage(self, id, text, chatroom, sender = None):
        chatroom.hasOA = True
        return self.client._1TextMessage(id, text, chatroom, Receiver.oA, sender=sender)
    
    def _1StickerMessage(self, id, packageId, stickerId, chatroom, sender = None):
        chatroom.hasOA = True
        return self.client._1StickerMessage(id, packageId, stickerId, chatroom, Receiver.oA, sender=sender)
    
    def _1LocationMessage(self, id, title, address, latitude, longitude, chatroom, sender = None):
        chatroom.hasOA = True
        return self.client._1LocationMessage(id, title, address, latitude, longitude, chatroom, Receiver.oA, sender=sender)
    
    def _1ImageMessage(self, id, chatroom, sender = None, url=None, bytes=None):
        chatroom.hasOA = True
        return self.client._1ImageMessage(id, chatroom, Receiver.oA, sender=sender, url=url, bytes=bytes)
    
    def _1AudioMessage(self, id, chatroom, sender = None, url=None, bytes=None):
        chatroom.hasOA = True
        return self.client._1AudioMessage(id, chatroom, Receiver.oA, sender=sender, url=url, bytes=bytes)
    
    def _1VideoMessage(self, id, chatroom, sender = None, url=None, bytes=None):
        chatroom.hasOA = True
        return self.client._1VideoMessage(id, chatroom, Receiver.oA, sender=sender, url=url, bytes=bytes)
    
    def _1Update(self, chatroom):
        chatroom.hasOA = True
        return self.client._1Update(chatroom, Receiver.oA)
    
    def _1Unfollowed(self, chatroom):
        chatroom.hasOA = False
        return self.client._1Unfollowed(chatroom, Receiver.oA)
    
    def _1Followed(self, chatroom):
        chatroom.hasOA = True
        return self.client._1Followed(chatroom, Receiver.oA)

    def _1Joined(self, chatroom):
        chatroom.hasOA = True
        return self.client._1Joined(chatroom, Receiver.oA)
        
    def _1Left(self, chatroom):
        chatroom.hasOA = False
        return self.client._1Left(chatroom, Receiver.oA)
    
    def _1Invited(self, chatroom):
        chatroom.hasOA = False
        return self.client._1Invited( chatroom, Receiver.oA)

    
    def _1Report(self, msg):
        if len(self.adminObjs) > 0:
            return self.adminObjs[0].SendText(msg)
        elif len(self.adminIds) > 0:
            return self._2SendText(self.adminIds[0], msg) 
        raise Exception("[OAClient._1Report : No report Id]\n" + msg)
        
    def _1ReportAll(self, msg):
        if len(self.adminObjs) > 0:
            return self._1SendText(self.adminObjs, msg)
        elif len(self.adminIds) > 0:
            return self._2SendText(self.adminIds, msg)
        raise Exception("[OAClient._1Report : No report Id]\n" + msg)
        
        
    
    def _1GetContentRaw(self, msgId):
        for i in range(0, self.tries):
            try:
                return self._1client.get_message_content(msgId)
            except (timeout, ReadTimeout, Timeout):
                pass
        
    def _1GetContent(self, msgId):
        content = self._1GetContentRaw(msgId)
        if content is None:
            return None
        ret = bytes()
        for chunk in content.iter_content():
            ret = ret + bytes(chunk)
        return ret
    
    def _1Leave(self, room):
        if not room.hasOA:
            return False
        #if room.uObj:
        #    room.RemoveLink()
        if room.chatroomType == ChatroomType.room:
            return self._2LeaveRoom(room.id)
        if room.chatroomType == ChatroomType.group:
            return self._2LeaveGroup(room.id)
        raise Exception("[OAClient._1Leave] 'room' is a User")
    
    def _2LeaveRoom(self, lineId):
        ex = ''
        for i in range(0, self.tries):
            try:
                return self._1client.leave_room(lineId)
            except (timeout, ReadTimeout, Timeout):
                pass
        
    def _2LeaveGroup(self, lineId):
        ex = ''
        for i in range(0, self.tries):
            try:
                return self._1client.leave_group(lineId)
            except (timeout, ReadTimeout, Timeout):
                pass
                
    def _1GetProfile(self, user):
        profile0 = self._2GetProfile(user.id)
        user._1SetProfileAndTime(profile0)
        return user._1profile
    

    def _2GetProfile(self, lineId):
        ex = ''
        for i in range(0, self.tries):
            try:
                return self._1client.get_profile(lineId)
            except (timeout, ReadTimeout, Timeout):
                pass
        
        
        
    def _1SendButtons(self, to, buttons):
        if isinstance(to, list):
            for t in to:
                return self._1SendButtons(t, buttons)
        if not to.hasOA:
            raise Exception("[OAClient._1SendButtons] No OA Client")
        carsb = buttons.Build()
        for car in carsb[0]:
            colLen = len(car.template.columns)
            if colLen==0 or (colLen == 1 and len(car.template.columns[-1].actions) == 0):
                continue
            if len(car.template.columns[-1].actions) == 0:
                car.template.columns.remove(car.template.columns[-1])
            self._1PushMessage(to.id, car)
        if carsb[1] is not None:
            self._1PushMessage(to.id, carsb[1])
    
    def _1SendText(self, to, text):
        if isinstance(to, list):
            return self._2SendText([t.id for t in to], text)
        return self._2SendText(to.id, text)
        
        
    def _2SendText(self, to, text):
        if type(to) is list:
            return self._1Multicast(to, TextSendMessage(text=text))
        return self._1PushMessage(to, TextSendMessage(text=text))
    
    def _1SendImageWithBytes(self, to, bytes):
        if self.client.pyImgurKey is None:
            raise Exception("[OAClient._1SendImage] Client.pyImgurKey must be set")
        url = self.client.UploadPyImgur(bytes)
        return self._1SendImageWithUrl(to, url)
    
    def _1SendImageWithUrl(self, to, url):
        if type(to) is list:
            return self._2SendImageWithUrl([t.id for t in to], url)
        return self._2SendImageWithUrl(to.id, url)
    
    
    def _1SendSticker(self, to, packageId, stickerId):
        if type(to) is list:
            return self._1Multicast(to, StickerSendMessage(package_id=packageId, sticker_id=stickerId))
        return self._1PushMessage(to, StickerSendMessage(package_id=packageId, sticker_id=stickerId))
    
    def _1SendLocation(self, to, title, address, latitude, longitude, phone=None):
        if type(to) is list:
            return self._1Multicast(to, LocationSendMessage(title=title, address=address, latitude=latitude, longitude=longitude))
        return self._1PushMessage(to, LocationSendMessage(title=title, address=address, latitude=latitude, longitude=longitude))
    
    def _1SendVideoWithUrl(self, to, url, previewUrl="https://thumb7.shutterstock.com/display_pic_with_logo/677413/595756799/stock-vector-no-preview-rubber-stamp-595756799.jpg"):
        if type(to) is list:
            return self._1Multicast(to, VideoSendMessage(original_content_url=url, preview_image_url=previewUrl))
        return self._1PushMessage(to, VideoSendMessage(original_content_url=url, preview_image_url=previewUrl))
    
    def _1SendAudioWithUrl(self, to, url, duration=240000):
        if type(to) is list:
            return self._1Multicast(to, AudioSendMessage(original_content_url=url, duration=duration))
        return self._1PushMessage(to, AudioSendMessage(original_content_url=url, duration=duration))
        
        
    
    def _2SendImageWithUrl(self, to, url):
        if url.startswith("https://"):
            url = url[8:]
        elif url.startswith("http://"):
            url = url[7:]
        linka = ""
        linkb = ""
        if url.startswith('i.imgur.com'):
            if "?" in url:
                url = "https://" + url + "&"
            else:
                url = "https://" + url + "?"
            linka = url + "maxwidth=1024&maxheight=1024"
            linkb = url + "maxwidth=240&maxheight=240"
        elif url.startswith('memegen.link'):
            url = "https://" + url
            linka = url + "&width=1024&height=1024"
            linkb = url + "&width=240&height=240"
        elif not url.startswith('i.scaley.io'):
            url = "http://" + url
            linka = ScaleyUrl(url, max=1024) 
            linkb = ScaleyUrl(url, max=240)
        #self._2SendText(to, "LinkA : " + linka + "\nLinkB : " + linkb)
        if type(to) is list:
            return self._1Multicast(to, ImageSendMessage(original_content_url=linka, preview_image_url=linkb))
        return self._1PushMessage(to, ImageSendMessage(original_content_url=linka, preview_image_url=linkb))
    
    def _1Multicast(self, ids, msg):
        idslen = len(ids)
        if idslen == 0:
            return False
        if idslen == 1:
            return self._1PushMessage(ids[0], msg)
        
        userIds = []
        roomOrGroupIds = []
        for id in ids:
            t = id[:1]
            if t == 'U':
                userIds.append(id)
            else:
                roomOrGroupIds.append(id)

        ret = True
        if len(userIds) > 0:
            for i in range(0, self.tries):
                try:
                    self._1client.multicast(userIds, msg)
                    break
                except (timeout, ReadTimeout, Timeout):
                    pass
                except LineBotApiError:
                    if i == self.tries-1:
                        self.client.Report("[Multicast:Ids]\n" + str(userIds))
                        self.client.Report("[Multicast:Msg]\n" + str(msg))
                        self.client.Report("[Multicast:Exc]\n" + format_exc())
                        ret = False
                    
        for roomOrGroupId in roomOrGroupIds:
            ret = ret and self._1PushMessage(roomOrGroupId, msg)
        return ret
        
    def _1PushMessage(self, id, msg):
        for i in range(0, self.tries):
            try:
                self._1client.push_message(id, msg)
                return True
            except (timeout, ReadTimeout, Timeout):
                print("[OAClient._1PushMessage:Timeout]\n" + format_exc())
                pass
            except LineBotApiError:
                e = format_exc()
                print("[OAClient._1PushMessage:LineBotApiError:idnmsg]\n" + str(id) + "\n" + str(msg))
                print("[OAClient._1PushMessage:LineBotApiError]\n" + e)
                if i == self.tries-1:
                    if isinstance(msg, TextSendMessage):
                        text = msg.text
                        textLen = len(msg.text)
                        if textLen > 2000:
                            ret = True
                            while textLen > 2000:
                                ret = self._1PushMessage(id, TextSendMessage(text=text[:2000]))
                                text = text[2000:]
                                textLen = len(text)
                            return ret
                        elif msg.text[:12] == "[PushMessage":
                            continue
                    self.client.Report("[PushMessage:Id]\n" + str(id))
                    self.client.Report("[PushMessage:Msg]\n" + str(msg))
                    self.client.Report("[PushMessage:Exc]\n" + e)
                    raise
        return False
        
        
    def _1GetObjByLineId(self, id, msgId = None, hasOA=defaultParameter, init=True, messageText = '', userInChatroom=False):
        if id is None:
            return
        default=False
        if hasOA == defaultParameter:
            hasOA = True
            default=True
        with Acquire(self.lock):
            if id not in self.idLocks:
                self.idLocks[id] = Lock()
            lock = self.idLocks[id]
        with Acquire(lock):
            if id in self.client._1objectsByLineId:
                ret = self.client._1objectsByLineId[id]
                ret.TrySync()
                if msgId is None or ret.hasUser or (ret.chatroomType == ChatroomType.user and (not userInChatroom or not msgId or not (msgId in self.client._1objectsOAByMsgId or userInChatroom.hasUser))) or not self.client.hasUser:
                    return ret
                if messageText.startswith("[INITROOM]"):
                    key = messageText.rpartition(' ')[2]
                    room = self.client._1waitingRoom.pop(key, None)
                    if room:
                        room.Sync(ret)
                msgFound = False
                with Acquire(self.client.lock):
                    obj2 = None
                    if ret.chatroomType == ChatroomType.user:
                        if userInChatroom and msgId in self.client._1senderObjectsUserByMsgId:
                            obj2 = self.client._1senderObjectsUserByMsgId[msgId]
                    else:
                        if msgId in self.client._1objectsUserByMsgId:
                            obj2 = self.client._1objectsUserByMsgId[msgId]
                    if obj2:
                        print("Merging chatroom")
                        obj2.Sync(ret)
                        msgFound = True
                if not msgFound:
                    if self.client.db is not None:
                        with self.client.GetCursor() as cur:
                            cur.Execute("SELECT lineMid, hasUser, hasOA, id, uId FROM ChatRooms WHERE lineId=%s", (id,))
                            f = cur.FetchOne()
                            if f is not None:
                                if f[2] != hasOA:
                                    if default:
                                        ret.hasOA = f[2]
                                    else:
                                        cur.Execute("UPDATE ChatRooms SET hasOA=%s WHERE id=%s", (ret._2hasOA, f[3],))
                                        cur.Commit()
                                ret._2id = f[3]
                                if ret.chatroomType == ChatroomType.room:
                                    ret.uId = f[4]
                                ret.mid = f[0]
                                ret.hasUser = f[1]
                                if ret.mid:
                                    synced = False
                                    with Acquire(self.client.lock):
                                        if ret.mid in self.client._1objectsByLineMid:
                                            self.client._1objectsByLineMid[ret.mid].Sync(ret)
                                            synced = True
                    with Acquire(self.client.lock):
                        if ret.chatroomType == ChatroomType.user:
                            if userInChatroom and (msgId in self.client._1objectsOAByMsgId or userInChatroom.hasUser):
                                self.client._1senderObjectsOAByMsgId[msgId] = ret
                        else:
                            self.client._1objectsOAByMsgId[msgId] = ret
            else:
                #print("Creating new User for id " + str(id))
                isUser = id[0] == 'U'
                if isUser:
                    ret = User(id=id, client=self.client, init=init)
                    if msgId and userInChatroom and (msgId in self.client._1objectsOAByMsgId or userInChatroom.hasUser):
                        self.client._1senderObjectsOAByMsgId[msgId] = ret
                else:
                    if id[0] == 'R':
                        ret = Room(id=id, client=self.client, hasOA=hasOA, init=init)
                    elif id[0] == 'C':
                        ret = Group(id=id, client=self.client, hasOA=hasOA, init=init)
                    else:
                        raise Exception("[OAClient.GetObjByLineId : Invalid Id]\n" + id)
                    if msgId and self.client.hasUser:
                        self.client._1objectsOAByMsgId[msgId] = ret

                with Acquire(self.client.lock):
                    if id in self.client._1objectsByLineId:
                        return self._1GetObjByLineId(id)
                    self.client._1objectsByLineId[id] = ret
                    if ret.chatroomType == ChatroomType.user:
                        self.client.users.append(ret)
                    if ret.chatroomType == ChatroomType.room:
                        self.client.rooms.append(ret)
                    if ret.chatroomType == ChatroomType.group:
                        self.client.groups.append(ret)
                    

            if self.client.db is not None:
                with self.client.GetCursor() as cur:

                    cur.Execute("SELECT lineMid, hasOA, hasUser, id, uId FROM ChatRooms WHERE lineId=%s", (id,))
                    fLM = cur.FetchOne()
                    if fLM is None: 
                        b = False
                        if ret.chatroomType != ChatroomType.user and msgId is not None:
                            b = self._1CheckMsgId(ret, msgId)
                        if not b:
                            cur.Execute("INSERT INTO ChatRooms(lineId, type, hasOA) Values(%s, %s, %s) RETURNING id", (ret.id, ret.chatroomType, ret._2hasOA))
                            f = cur.FetchOne()
                            ret._2id = f[0]
                            cur.Commit()
                    else:
                        ret._2id = fLM[3]
                        ret.hasUser = fLM[2]
                        if fLM[1] != hasOA:
                            if default:
                                ret.hasOA = fLM[1]
                            else:
                                cur.Execute("UPDATE ChatRooms SET hasOA=%s WHERE id=%s", (ret._2hasOA, fLM[3],))
                                cur.Commit()
                        if IsEmpty(fLM[0]):
                            if ret.chatroomType != ChatroomType.user:
                                ret.mid = self._1CheckMsgId(ret, msgId)
                        else:
                            ret.mid = fLM[0]
                        if ret.chatroomType == ChatroomType.room:
                            ret.uId = fLM[4]
                        if self.client.hasUser and not IsEmpty(ret.mid):
                            with Acquire(self.client.lock):
                                if ret.mid in self.client._1objectsByLineMid:
                                    self.client._1objectsByLineMid[ret.mid].Sync(ret)
            ret.TrySync()
            return ret
    
    def _1CheckMsgId(self, obj, msgId):
        with self.client.GetCursor() as cur:
            if obj.chatroomType == ChatroomType.user:
                s = "Sender"
            else:
                s = ""
            cur.Execute("SELECT lineMid FROM " + s + "LineMidByMsgId WHERE msgId=%s", (msgId,))
            fLM = cur.FetchOne()
            ret = None
            if fLM is None:
                cur.Execute("INSERT INTO " + s + "LineIdByMsgId(msgId, lineId) Values(%s, %s) ON CONFLICT(msgId) DO UPDATE SET lineId=%s", (msgId, obj.id, obj.id,))
                cur.Commit()
            else:
                obj.mid = fLM[0]
                obj.hasUser = True
                if obj.mid in self.client._1objectsByLineMid:
                    self.client._1objectsByLineMid[obj.mid].Sync(obj)
                else:
                    obj.Sync()
            return obj.mid
        
    
    def HandleWebhook(self, environ, start_response):
        # check request method
        if environ['REQUEST_METHOD'] != 'POST':
            start_response('405 Method Not Allowed : ' + environ['REQUEST_METHOD'], [])
            return CreateBody('Method not allowed')

        # get X-Line-Signature header value
        signature = environ['HTTP_X_LINE_SIGNATURE']

        # get request body as text
        wsgi_input = environ['wsgi.input']
        content_length = int(environ['CONTENT_LENGTH'])
        body = wsgi_input.read(content_length).decode('utf-8')

        # parse webhook body
        try:
            events = self.parser.parse(body, signature)
        except InvalidSignatureError:
            start_response('400 Bad Request', [])
            return CreateBody('Bad request')

        # if event is MessageEvent and message is TextMessage, then echo text
        exc = ''
        msg = None
        for event in events:
            self.client.Thread(self.ParseEvent, [event])

        start_response('200 OK', [])
        return CreateBody('OK')

    
    def Start(self, thread=True, port=None):
        
        if self.thread is not None and self.thread.isAlive:
            return self.thread
        if port is None:
            port0 = os.environ.get("PORT", None)
            if port0 is None:
                return
            port = int(port0)
        self.running = True
        if thread:
            self.thread = self.client.Thread(self._1Main, [port])
            return self.thread
        self._1Main(port)
        self.running = False
    
    def _1Main(self, port=None):
        if port is None:
            port0 = os.environ.get("PORT", None)
            if port0 is None:
                return
            port = int(port0)

        self.running = True
        srv = make_server('0.0.0.0', port, self.HandleWebhook)
        srv.serve_forever()
        self.running = False
    
    def ParseEvent(self, event):
        while not self.client.started:
            with self.client.startCond:
                self.client.startCond.wait(1)
        try:
            msg = None
            if isinstance(event, MessageEvent):
                if event.message:
                    messageText = ''
                    if isinstance(event.message, _TextMessage):
                        messageText = event.message.text
                    chatroomObj = self._1GetObjByLineId(id=event.source.sender_id, msgId = event.message.id, messageText=messageText)
                    sender=None
                    if chatroomObj.chatroomType == ChatroomType.user:
                        sender = chatroomObj
                    if not sender and chatroomObj.chatroomType != ChatroomType.user:
                        try:
                            senderId = event.source.user_id
                        except Exception:
                            pass
                        if senderId:
                            sender = self._1GetObjByLineId(id=senderId, msgId = event.message.id, messageText=messageText, userInChatroom = chatroomObj)
                    if isinstance(event.message, _TextMessage):
                        msg = self._1TextMessage(id=event.message.id, text=event.message.text, chatroom = chatroomObj, sender=sender)
                    if isinstance(event.message, _StickerMessage):
                        msg = self._1StickerMessage(id=event.message.id, packageId=event.message.package_id, stickerId = event.message.sticker_id, chatroom = chatroomObj, sender=sender)
                    if isinstance(event.message, _LocationMessage):
                        msg = self._1LocationMessage(id=event.message.id, title=event.message.title, address=event.message.address, latitude=event.message.latitude, longitude=event.message.longitude, chatroom = chatroomObj, sender=sender)
                    if isinstance(event.message, _ImageMessage):
                        msg = self._1ImageMessage(id=event.message.id, chatroom = chatroomObj, sender=sender)
                    if isinstance(event.message, _AudioMessage):
                        msg = self._1AudioMessage(id=event.message.id, chatroom = chatroomObj, sender=sender)
                    if isinstance(event.message, _VideoMessage):
                        msg = self._1VideoMessage(id=event.message.id, chatroom = chatroomObj, sender=sender)
                else:
                    print("UNKNOWN MESSAGE " + str(event))
            else:
                chatroomObj = self._1GetObjByLineId(id=event.source.sender_id)
                if isinstance(event, LeaveEvent):
                    chatroomObj.hasOA = False
                    msg = self._1Left(chatroom = chatroomObj)
                elif isinstance(event, FollowEvent):
                    chatroomObj.hasOA = True
                    msg = self._1Followed(chatroom = chatroomObj)
                elif isinstance(event, UnfollowEvent):
                    chatroomObj.hasOA = False
                    msg = self._1Unfollowed(chatroom = chatroomObj)
                elif isinstance(event, JoinEvent):
                    chatroomObj.hasOA = True
                    msg = self._1Joined(chatroom = chatroomObj)
            if msg is not None and (msg.eventType != EventType.message or not (msg.chatroom.hasUser and self.client.userClient.running)):
                if self.client.main:
                    self.client.AddEvent(msg)
                else:
                    self.client.Thread(self.client.Handle, [msg, False])
        except Exception as ex:
            err = format_exc()
            print(err)
            self.client.Report("[OAClient.ParseEvent]\n" + err)
예제 #22
0
class LineServer(object):
    """Line bot server"""
    def __init__(self):
        line_config = ConfigParser()
        root_dir = os.environ.get('ROOT_DIR')
        line_config_path = os.path.join(root_dir, 'credential',
                                        'line_config.ini')
        line_config.read(line_config_path)
        if not line_config.has_option('Line Config', 'ACCESS_TOKEN'):
            print('Specify LINE_CHANNEL_SECRET as environment variable.')
            sys.exit(1)
        if not line_config.has_option('Line Config', 'SECRET'):
            print('Specify LINE_CHANNEL_ACCESS_TOKEN as environment variable.')
            sys.exit(1)
        channel_secret = line_config['Line Config']['SECRET']
        channel_access_token = line_config['Line Config']['ACCESS_TOKEN']
        self.line_bot_api = LineBotApi(channel_access_token)
        self.parser = WebhookParser(channel_secret)

    def __del__(self):
        print('Destroyed')

    def callback(self, environ, start_response):
        """Process every line message"""

        # check request path
        if environ['PATH_INFO'] != '/callback':
            start_response('404 Not Found', [])
            return self.create_body('Not Found')

        # check request method
        if environ['REQUEST_METHOD'] != 'POST':
            start_response('405 Method Not Allowed', [])
            return self.create_body('Method Not Allowed')

        # get X-Line-Signature header value
        signature = environ['HTTP_X_LINE_SIGNATURE']

        # get request body as text
        wsgi_input = environ['wsgi.input']
        content_length = int(environ['CONTENT_LENGTH'])
        body = wsgi_input.read(content_length).decode('utf-8')

        # parse webhook body
        try:
            events = self.parser.parse(body, signature)
        except InvalidSignatureError:
            start_response('400 Bad Request', [])
            return self.create_body('Bad Request')

        # database connect
        db = db_operator.DBConnector()
        table_name = 'USER'
        user_id = events[0].source.user_id

        # create user if not in database
        if not db.is_record(table_name, 'userID', user_id):
            data = {'userID': user_id}
            db.insert(table_name, data)

        # if event is MessageEvent and message is TextMessage, then echo text
        for event in events:
            if not isinstance(event, MessageEvent):
                continue
            if not isinstance(event.message, TextMessage):
                continue

            command = event.message.text.split()

            data = {'lastCmd': event.message.text}
            db.update(table_name, data, 'userID=\'{}\''.format(user_id))

            if command[0] == '天氣':
                if len(command) == 1:
                    fav = db.query(table_name, 'favorite',
                                   'userID=\'{}\''.format(user_id))
                    command += fav.split()
                elif len(command) == 2:
                    command.append(command[-1])
                display = weather.getWeather(command[1:])
            elif command[0] == '捷運':
                if len(command) < 3:
                    display = '請輸入兩個車站。'
                else:
                    display = metro.getDuration(command[1:])
            elif command[0] == '設定':
                data = {'favorite': ' '.join(command[1:])}
                db.update(table_name, data, 'userID=\'{}\''.format(user_id))
                display = '已經您的常用地點設為:{}'.format(' '.join(command[1:]))
            else:
                display = '我聽不懂你在說什麼,你可以試試:天氣 台北 大安'

            # Especially for Lion
            if user_id == 'U90101030d70543c2eb06911da7c7f93b':
                display = '獅子主人,底下是您查詢的結果:\n' + display

            self.line_bot_api.reply_message(event.reply_token,
                                            TextSendMessage(text=display))

        start_response('200 OK', [])
        return self.create_body('OK')

    def create_body(self, text):
        if PY3:
            return [bytes(text, 'utf-8')]
        else:
            return text
예제 #23
0
    def test_parse(self):
        file_dir = os.path.dirname(__file__)
        webhook_sample_json_path = os.path.join(file_dir, 'text', 'webhook.json')
        with open(webhook_sample_json_path) as fp:
            body = fp.read()

        parser = WebhookParser('a1b7349fed51378bae64e940012794db')
        # mock
        parser.signature_validator.validate = lambda a, b: True

        events = parser.parse(body, 'a1b7349fed51378bae64e940012794db')

        # MessageEvent, SourceUser, TextMessage
        self.assertIsInstance(events[0], MessageEvent)
        self.assertEqual(events[0].reply_token, '7u6uSOrfTJAqfs6gOM+DJ4zV5Mo3lV0mVlJ8qocjnGkTfz4jsJsqvGqnUCNL9EjwaS2tDzhTFn5QaMiL6rQge8x48zKcK/ceO0dXdepuiV+Y3vuBZ4GWVtlD0gOXOoNTN/3rKWvAmo7iqDUNHZC9aAdB04t89/1O/w1cDnyilFU=')
        self.assertEqual(events[0].type, 'message')
        self.assertEqual(events[0].timestamp, 1462629479859)
        self.assertIsInstance(events[0].source, SourceUser)
        self.assertEqual(events[0].source.type, 'user')
        self.assertEqual(events[0].source.user_id, 'U206d25c2ea6bd87c17655609a1c37cb8')
        self.assertEqual(events[0].source.sender_id, 'U206d25c2ea6bd87c17655609a1c37cb8')
        self.assertIsInstance(events[0].message, TextMessage)
        self.assertEqual(events[0].message.id, '325708')
        self.assertEqual(events[0].message.type, 'text')
        self.assertEqual(events[0].message.text, 'Hello, world')

        # MessageEvent, SourceRoom, TextMessage
        self.assertIsInstance(events[1], MessageEvent)
        self.assertEqual(events[1].reply_token, 'nHuyWiB7yP5Zw52FIkcQobQuGDXCTA')
        self.assertEqual(events[1].type, 'message')
        self.assertEqual(events[1].timestamp, 1462629479859)
        self.assertIsInstance(events[1].source, SourceRoom)
        self.assertEqual(events[1].source.type, 'room')
        self.assertEqual(events[1].source.room_id, 'U206d25c2ea6bd87c17655609a1c37cb8')
        self.assertEqual(events[1].source.sender_id, 'U206d25c2ea6bd87c17655609a1c37cb8')
        self.assertIsInstance(events[1].message, ImageMessage)
        self.assertEqual(events[1].message.id, '325708')
        self.assertEqual(events[1].message.type, 'image')

        # MessageEvent, SourceUser, VideoMessage
        self.assertIsInstance(events[2], MessageEvent)
        self.assertEqual(events[2].reply_token, 'nHuyWiB7yP5Zw52FIkcQobQuGDXCTA')
        self.assertEqual(events[2].type, 'message')
        self.assertEqual(events[2].timestamp, 1462629479859)
        self.assertIsInstance(events[2].source, SourceUser)
        self.assertEqual(events[2].source.type, 'user')
        self.assertEqual(events[2].source.user_id, 'U206d25c2ea6bd87c17655609a1c37cb8')
        self.assertEqual(events[2].source.sender_id, 'U206d25c2ea6bd87c17655609a1c37cb8')
        self.assertIsInstance(events[2].message, VideoMessage)
        self.assertEqual(events[2].message.id, '325708')
        self.assertEqual(events[2].message.type, 'video')

        # MessageEvent, SourceUser, AudioMessage
        self.assertIsInstance(events[3], MessageEvent)
        self.assertEqual(events[3].reply_token, 'nHuyWiB7yP5Zw52FIkcQobQuGDXCTA')
        self.assertEqual(events[3].type, 'message')
        self.assertEqual(events[3].timestamp, 1462629479859)
        self.assertIsInstance(events[3].source, SourceUser)
        self.assertEqual(events[3].source.type, 'user')
        self.assertEqual(events[3].source.user_id, 'U206d25c2ea6bd87c17655609a1c37cb8')
        self.assertEqual(events[3].source.sender_id, 'U206d25c2ea6bd87c17655609a1c37cb8')
        self.assertIsInstance(events[3].message, AudioMessage)
        self.assertEqual(events[3].message.id, '325708')
        self.assertEqual(events[3].message.type, 'audio')

        # MessageEvent, SourceUser, LocationMessage
        self.assertIsInstance(events[4], MessageEvent)
        self.assertEqual(events[4].reply_token, 'nHuyWiB7yP5Zw52FIkcQobQuGDXCTA')
        self.assertEqual(events[4].type, 'message')
        self.assertEqual(events[4].timestamp, 1462629479859)
        self.assertIsInstance(events[4].source, SourceUser)
        self.assertEqual(events[4].source.type, 'user')
        self.assertEqual(events[4].source.user_id, 'U206d25c2ea6bd87c17655609a1c37cb8')
        self.assertEqual(events[4].source.sender_id, 'U206d25c2ea6bd87c17655609a1c37cb8')
        self.assertIsInstance(events[4].message, LocationMessage)
        self.assertEqual(events[4].message.id, '325708')
        self.assertEqual(events[4].message.type, 'location')
        self.assertEqual(events[4].message.title, 'my location')
        self.assertEqual(events[4].message.address, 'Tokyo')
        self.assertEqual(events[4].message.latitude, 35.65910807942215)
        self.assertEqual(events[4].message.longitude, 139.70372892916203)

        # MessageEvent, SourceUser, StickerMessage
        self.assertIsInstance(events[5], MessageEvent)
        self.assertEqual(events[5].reply_token, 'nHuyWiB7yP5Zw52FIkcQobQuGDXCTA')
        self.assertEqual(events[5].type, 'message')
        self.assertEqual(events[5].timestamp, 1462629479859)
        self.assertIsInstance(events[5].source, SourceUser)
        self.assertEqual(events[5].source.type, 'user')
        self.assertEqual(events[5].source.user_id, 'U206d25c2ea6bd87c17655609a1c37cb8')
        self.assertEqual(events[5].source.sender_id, 'U206d25c2ea6bd87c17655609a1c37cb8')
        self.assertIsInstance(events[5].message, StickerMessage)
        self.assertEqual(events[5].message.id, '325708')
        self.assertEqual(events[5].message.type, 'sticker')
        self.assertEqual(events[5].message.package_id, '1')
        self.assertEqual(events[5].message.sticker_id, '1')

        # FollowEvent, SourceUser
        self.assertIsInstance(events[6], FollowEvent)
        self.assertEqual(events[6].reply_token, 'nHuyWiB7yP5Zw52FIkcQobQuGDXCTA')
        self.assertEqual(events[6].type, 'follow')
        self.assertEqual(events[6].timestamp, 1462629479859)
        self.assertIsInstance(events[6].source, SourceUser)
        self.assertEqual(events[6].source.type, 'user')
        self.assertEqual(events[6].source.user_id, 'U206d25c2ea6bd87c17655609a1c37cb8')
        self.assertEqual(events[6].source.sender_id, 'U206d25c2ea6bd87c17655609a1c37cb8')

        # UnfollowEvent, SourceUser
        self.assertIsInstance(events[7], UnfollowEvent)
        self.assertEqual(events[7].type, 'unfollow')
        self.assertEqual(events[7].timestamp, 1462629479859)
        self.assertIsInstance(events[7].source, SourceUser)
        self.assertEqual(events[7].source.type, 'user')
        self.assertEqual(events[7].source.user_id, 'U206d25c2ea6bd87c17655609a1c37cb8')
        self.assertEqual(events[7].source.sender_id, 'U206d25c2ea6bd87c17655609a1c37cb8')

        # JoinEvent, SourceGroup
        self.assertIsInstance(events[8], JoinEvent)
        self.assertEqual(events[8].reply_token, 'nHuyWiB7yP5Zw52FIkcQobQuGDXCTA')
        self.assertEqual(events[8].type, 'join')
        self.assertEqual(events[8].timestamp, 1462629479859)
        self.assertIsInstance(events[8].source, SourceGroup)
        self.assertEqual(events[8].source.type, 'group')
        self.assertEqual(events[8].source.group_id, 'cxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx')
        self.assertEqual(events[8].source.sender_id, 'cxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx')

        # LeaveEvent, SourceGroup
        self.assertIsInstance(events[9], LeaveEvent)
        self.assertEqual(events[9].type, 'leave')
        self.assertEqual(events[9].timestamp, 1462629479859)
        self.assertIsInstance(events[9].source, SourceGroup)
        self.assertEqual(events[9].source.type, 'group')
        self.assertEqual(events[9].source.group_id, 'cxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx')
        self.assertEqual(events[9].source.sender_id, 'cxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx')

        # PostbackEvent, SourceUser
        self.assertIsInstance(events[10], PostbackEvent)
        self.assertEqual(events[10].reply_token, 'nHuyWiB7yP5Zw52FIkcQobQuGDXCTA')
        self.assertEqual(events[10].type, 'postback')
        self.assertEqual(events[10].timestamp, 1462629479859)
        self.assertIsInstance(events[10].source, SourceUser)
        self.assertEqual(events[10].source.type, 'user')
        self.assertEqual(events[10].source.user_id, 'U206d25c2ea6bd87c17655609a1c37cb8')
        self.assertEqual(events[10].source.sender_id, 'U206d25c2ea6bd87c17655609a1c37cb8')
        self.assertEqual(events[10].postback.data, 'action=buyItem&itemId=123123&color=red')

        # BeaconEvent, SourceUser
        self.assertIsInstance(events[11], BeaconEvent)
        self.assertEqual(events[11].reply_token, 'nHuyWiB7yP5Zw52FIkcQobQuGDXCTA')
        self.assertEqual(events[11].type, 'beacon')
        self.assertEqual(events[11].timestamp, 1462629479859)
        self.assertIsInstance(events[11].source, SourceUser)
        self.assertEqual(events[11].source.type, 'user')
        self.assertEqual(events[11].source.user_id, 'U206d25c2ea6bd87c17655609a1c37cb8')
        self.assertEqual(events[11].source.sender_id, 'U206d25c2ea6bd87c17655609a1c37cb8')
        self.assertEqual(events[11].beacon.hwid, 'd41d8cd98f')
        self.assertEqual(events[11].beacon.type, 'enter')
예제 #24
0
class LineBotClient(BotClient):

    def __init__(self, argument_parser=None):
        BotClient.__init__(self, "line", argument_parser)

        self.get_tokens()

        self.create_line_bot()

        if logging.getLogger().isEnabledFor(logging.DEBUG):
            logging.debug("Line Client is running....")

    def set_environment(self):
        self.bot.brain.properties.add_property("env", 'line')

    def get_client_configuration(self):
        return LineConfiguration()

    def get_tokens(self):
        self._channel_secret = self.bot.license_keys.get_key("LINE_CHANNEL_SECRET")
        self._channel_access_token = self.bot.license_keys.get_key("LINE_ACCESS_TOKEN")

    def ask_question(self, clientid, question):
        response = ""
        try:
            response = self.bot.ask_question(clientid, question)
        except Exception as e:
            print(e)
        return response

    def create_line_bot(self):
        self._line_bot_api = LineBotApi(self._channel_access_token)
        self._parser = WebhookParser(self._channel_secret)

    def handle_text_message(self, event):
        question = event.message.text
        clientid = event.source.user_id

        answer = self.ask_question(clientid, question)

        self._line_bot_api.reply_message(event.reply_token, TextSendMessage(text=answer))

    def handle_unknown_event(self, event):
        self._line_bot_api.reply_message(event.reply_token, TextSendMessage(text="Sorry, I only handle text messages right now!"))

    def handle_unknown_message(self, event):
        self._line_bot_api.reply_message(event.reply_token, TextSendMessage(text="Sorry, I only handle text messages right now!"))

    def handle_message_request(self, body, signature):

        events = self._parser.parse(body, signature)

        for event in events:
            if isinstance(event, MessageEvent):
                if isinstance(event.message, TextMessage):
                    self.handle_text_message(event)
                else:
                    self.handle_unknown_message(event)
            else:
                self.handle_unknown_event(event)

    def handle_incoming(self, request):
        # get X-Line-Signature header value
        signature = request.headers['X-Line-Signature']

        # get request body as text
        body = request.get_data(as_text=True)

        # handle webhook body
        try:
            self.handle_message_request(body, signature)
        except InvalidSignatureError:
            abort(400)

        return 'OK'
예제 #25
0
class LineBotClient(FlaskRestBotClient):
    def __init__(self, argument_parser=None):
        FlaskRestBotClient.__init__(self, "line", argument_parser)

        self.create_line_bot()

        YLogger.debug(self, "Line Client is running....")

    def get_client_configuration(self):
        return LineConfiguration()

    def get_license_keys(self):
        self._channel_secret = self.license_keys.get_key("LINE_CHANNEL_SECRET")
        self._channel_access_token = self.license_keys.get_key(
            "LINE_ACCESS_TOKEN")

    def create_line_bot(self):
        self._line_bot_api = LineBotApi(self._channel_access_token)
        self._parser = WebhookParser(self._channel_secret)

    def handle_text_message(self, event):
        question = event.message.text
        userid = event.source.user_id

        answer = self.ask_question(userid, question)

        self._line_bot_api.reply_message(event.reply_token,
                                         TextSendMessage(text=answer))

    def get_unknown_response(self, userid):
        if self.configuration.client_configuration.unknown_command_srai is None:
            unknown_response = self.configuration.client_configuration.unknown_command
        else:
            unknown_response = self.ask_question(
                userid,
                self.configuration.client_configuration.unknown_command_srai)
            if unknown_response is None or unknown_response == "":
                unknown_response = self.configuration.client_configuration.unknown_command
        return unknown_response

    def handle_unknown_event(self, event):
        userid = ""
        unknown_response = self.get_unknown_response(userid)
        self._line_bot_api.reply_message(
            event.reply_token, TextSendMessage(text=unknown_response))

    def handle_unknown_message(self, event):
        userid = ""
        unknown_response = self.get_unknown_response(userid)
        self._line_bot_api.reply_message(
            event.reply_token, TextSendMessage(text=unknown_response))

    def handle_message_request(self, body, signature):

        events = self._parser.parse(body, signature)

        for event in events:
            if isinstance(event, MessageEvent):
                if isinstance(event.message, TextMessage):
                    self.handle_text_message(event)
                else:
                    self.handle_unknown_message(event)
            else:
                self.handle_unknown_event(event)

    def receive_message(self, request):

        if self.configuration.client_configuration.debug is True:
            self.dump_request(request)

        # get X-Line-Signature header value
        signature = request.headers['X-Line-Signature']

        # get request body as text
        body = request.get_data(as_text=True)

        # handle webhook body
        try:
            self.handle_message_request(body, signature)
        except InvalidSignatureError as excep:
            YLogger.exception(self, "Line error", excep)
            abort(500)

        return Response(status=200)
예제 #26
0
async def post(request):
    line_api = LineBotApi(channel_access_token=os.getenv("CHOCO_LINE_AT"))
    parser = WebhookParser(channel_secret=os.getenv("CHOCO_LINE_CS"))
    events = parser.parse((await request.body()).decode("utf-8"),
                          request.headers.get("X-Line-Signature", ""))
    for ev in events:
        match_text = [
            "チョコ", "ちょこ", "チョコレート", "ちょこれーと", "バレンタイン", "ばれんたいん", "🍫"
        ]
        tosend = False
        for text in match_text:
            if text in ev.message.text:
                tosend = True
                break
        if tosend:
            emojis = [
                {
                    "index": 0,
                    "productId": "5ac2213e040ab15980c9b447",
                    "emojiId": "058"
                },
                {
                    "index": 0,
                    "productId": "5ac2213e040ab15980c9b447",
                    "emojiId": "059"
                },
                {
                    "index": 0,
                    "productId": "5ac2213e040ab15980c9b447",
                    "emojiId": "178"
                },
                {
                    "index": 0,
                    "productId": "5ac2213e040ab15980c9b447",
                    "emojiId": "178"
                },
                {
                    "index": 0,
                    "productId": "5ac2213e040ab15980c9b447",
                    "emojiId": "178"
                },
                {
                    "index": 0,
                    "productId": "5ac2213e040ab15980c9b447",
                    "emojiId": "178"
                },
                {
                    "index": 0,
                    "productId": "5ac2211e031a6752fb806d61",
                    "emojiId": "201"
                },
                {
                    "index": 0,
                    "productId": "5ac1de17040ab15980c9b438",
                    "emojiId": "059"
                },
                {
                    "index": 0,
                    "productId": "5ac1de17040ab15980c9b438",
                    "emojiId": "061"
                },
                {
                    "index": 0,
                    "productId": "5ac1de17040ab15980c9b438",
                    "emojiId": "061"
                },
                {
                    "index": 0,
                    "productId": "5ac1de17040ab15980c9b438",
                    "emojiId": "061"
                },
                {
                    "index": 0,
                    "productId": "5ac1de17040ab15980c9b438",
                    "emojiId": "061"
                },
                {
                    "index": 0,
                    "productId": "5ac1de17040ab15980c9b438",
                    "emojiId": "061"
                },
                {
                    "index": 0,
                    "productId": "5ac2211e031a6752fb806d61",
                    "emojiId": "182"
                },
                {
                    "index": 0,
                    "productId": "5ac2197b040ab15980c9b43d",
                    "emojiId": "010"
                },
            ]
            line_api.reply_message(
                ev.reply_token,
                TextSendMessage(text="$",
                                emojis=[emojis[randint(0,
                                                       len(emojis) - 1)]]))
    return "ok"
예제 #27
0
class LYCLineBot(BaseBot):
    def __init__(self, access_token, secret):
        self.line_bot_api = LineBotApi(access_token)
        self.handler = WebhookHandler(secret)
        self.parser = WebhookParser(secret)

    def send_message(self, text, user_id):
        self.line_bot_api.push_message(user_id, TextSendMessage(text=text))

        return "Send"

    def reply_message(self, text, body, signature):
        try:
            events = self.parser.parse(body, signature)

            for event in events:
                return_message = self.special_reply(event.message)

                # 沒有特殊處理過的回應, 解析一下訊息在處理回應
                if not return_message:
                    return_message = self.analysis_message(event.message)

                self.line_bot_api.reply_message(event.reply_token,
                                                return_message)

        except InvalidSignatureError as e:
            return "authorization failed"
        except LineBotApiError as e:
            return e.error.message
        else:
            return "OK"

    def user_profile(self, user_id):
        line_profile = self.line_bot_api.get_profile(user_id)
        if not line_profile:
            return None

        profile = UserProfile()
        profile.id = line_profile.user_id
        profile.name = line_profile.display_name
        profile.description = line_profile.status_message
        profile.picture = line_profile.picture_url

        return profile

    def analysis_message(self, message):
        """解析使用者傳的訊息來決定回傳什麼東西給使用者
        
        Arguments:
            message {[MessageEvent.Message]} -- [the message event from user pass]
        
        Returns:
            [SendMessage] -- [the message what postback to the user.]
        """

        # 解析是不是有符合觸發事件
        if message.type == "text":
            seg_list = ", ".join(jieba.cut(message.text)).split(', ')
            match_event_message = analyzer.match(seg_list)
            match_event_message = list(
                filter(lambda x: x is not None, match_event_message))

            if match_event_message and len(match_event_message) > 0:
                return TextSendMessage(text=''.join(
                    filter(lambda x: x is not None, match_event_message)))

        # 沒有就去當鸚鵡吧
        allow_message_type = {
            "text": self.reply_by_text,
            "sticker": self.reply_by_sticker
        }

        func = allow_message_type.get(message.type, self.reply_default)
        return func(message)

    def reply_by_text(self, message):
        """reply a text
        
        Arguments:
            message {string} -- request message
        
        Returns:
            string -- response message
        """

        return TextSendMessage(text=message.text)

    def reply_by_sticker(self, message):
        """reply by a sticker
        
        Arguments:
            message {string} -- request message
        
        Returns:
            string  -- response sticker.
        """

        if int(message.package_id) > 4:
            return TextSendMessage(text="中文豪難喔,公蝦聽謀捏。")

        return StickerSendMessage(package_id=message.package_id,
                                  sticker_id=message.sticker_id)

    def reply_default(self, message):
        return TextSendMessage(text="中文豪難喔,公蝦聽謀捏。")

    def template_buttons(self, message):
        """produce template with buttons
        
        Arguments:
            message {[MessageEvent.Message]} -- [the message event from user pass]
        """
        buttons_template_message = TemplateSendMessage(
            alt_text='Buttons template',
            template=ButtonsTemplate(
                thumbnail_image_url='https://i.imgur.com/ZgVAAMV.jpg',
                title='LYC電玩展',
                text='您今天想看什麼任天堂Switch遊戲',
                actions=[
                    PostbackTemplateAction(label='最新的',
                                           text='最新的',
                                           data='action=buy&itemid=1'),
                    MessageTemplateAction(label='特價中的', text='特價中的'),
                    URITemplateAction(
                        label='我自己看吧',
                        uri='https://lycnsbot.herokuapp.com/games')
                ]))
        return buttons_template_message

    def template_confirm(self, message):
        """produce template with confirm button
        
        Arguments:
            message {[MessageEvent.Message]} -- [the message event from user pass]
        """
        confirm_template_message = TemplateSendMessage(
            alt_text='Confirm template',
            template=ConfirmTemplate(
                text='你準備好買更多的任天堂了嗎?',
                actions=[
                    PostbackTemplateAction(label='當然啊',
                                           text='我要買任天堂Switch',
                                           data='action=buy&itemid=1'),
                    MessageTemplateAction(label='不買行嗎', text='我不買任天堂Switch')
                ]))
        return confirm_template_message

    def template_carousel_buttons(self, message):
        """produce template with carousel buttons
        
        Arguments:
            message {[MessageEvent.Message]} -- [the message event from user pass]
        """
        carousel_template_message = TemplateSendMessage(
            alt_text='Carousel template',
            template=CarouselTemplate(columns=[
                CarouselColumn(
                    thumbnail_image_url='https://i.imgur.com/njZeeBz.jpg',
                    title='Splatoon 2',
                    text='花枝會打漆彈耶',
                    actions=[
                        MessageTemplateAction(label='哇嗚好像很好玩', text='真的不錯玩'),
                        MessageTemplateAction(label='我覺得不行',
                                              text='你不行? 你身上哪裡不行'),
                        URITemplateAction(
                            label='現在價錢如何',
                            uri='https://eshop-prices.com/games/260-splatoon-2'
                        )
                    ]),
                CarouselColumn(
                    thumbnail_image_url='https://i.imgur.com/p3ozN9s.jpg',
                    title='The Legend Of Zelda-Breath Of The Wild',
                    text='薩爾達傳說之精神時光屋',
                    actions=[
                        MessageTemplateAction(label='哇嗚好像很好玩', text='真的不錯玩'),
                        MessageTemplateAction(label='我覺得不行',
                                              text='你不行? 你身上哪裡不行'),
                        URITemplateAction(
                            label='現在價錢如何',
                            uri=
                            'https://eshop-prices.com/games/378-the-legend-of-zelda-breath-of-the-wild'
                        )
                    ])
            ]))
        return carousel_template_message

    def template_carousel_images(self, message):
        """produce template with carousel images
        
        Arguments:
            message {[MessageEvent.Message]} -- [the message event from user pass]
        """
        image_carousel_template_message = TemplateSendMessage(
            alt_text='ImageCarousel template',
            template=ImageCarouselTemplate(columns=[
                ImageCarouselColumn(
                    image_url='https://i.imgur.com/njZeeBz.jpg',
                    action=PostbackTemplateAction(label='Splatoon 2 漆彈大作戰',
                                                  text='快來打漆彈',
                                                  data='action=buy&itemid=1')),
                ImageCarouselColumn(
                    image_url='https://i.imgur.com/p3ozN9s.jpg',
                    action=PostbackTemplateAction(label='薩爾達傳說之精神時光屋',
                                                  text='人馬? 給虐嗎?',
                                                  data='action=buy&itemid=2'))
            ]))

        return image_carousel_template_message

    def special_reply(self, message):
        """特殊處理的回覆訊息
        
        Arguments:
            message {[MessageEvent.Message]} -- [the message event from user pass]
        
        Returns:
            [SendMessage] -- [the special message what postback to the user.]
        """

        match_stickers = {
            "1-10": self.template_buttons,
            "1-2": self.template_confirm,
            "1-4": self.template_carousel_buttons,
            "1-13": self.template_carousel_images
        }
        if message.type == "sticker":
            key = "{0}-{1}".format(message.package_id, message.sticker_id)
            func = match_stickers.get(key, lambda s: None)

            return func(message)

        return None
예제 #28
0
class LineAdapter(Adapter):
    """
    Adapter for LINE Messaging API

    Attributes
    ----------
    bot : minette.Minette
        Instance of Minette
    channel_secret : str
        Channel Secret
    channel_access_token : str
        Channel Access Token
    parser : WebhookParser
        WebhookParser
    api : LineBotApi
        LineBotApi
    config : minette.Config
        Configuration
    timezone : pytz.timezone
        Timezone
    logger : logging.Logger
        Logger
    threads : int
        Number of worker threads to process requests
    executor : ThreadPoolExecutor
        Thread pool of workers
    debug : bool
        Debug mode
    """
    def __init__(self,
                 bot=None,
                 *,
                 threads=None,
                 debug=False,
                 channel_secret=None,
                 channel_access_token=None,
                 **kwargs):
        """
        Parameters
        ----------
        bot : minette.Minette, default None
            Instance of Minette.
            If None, create new instance of Minette by using `**kwargs`
        channel_secret : str, default None
            Channel Secret
        channel_access_token : str, default None
            Channel Access Token
        threads : int, default None
            Number of worker threads to process requests
        debug : bool, default None
            Debug mode
        """
        super().__init__(bot=bot, threads=threads, debug=debug, **kwargs)
        self.channel_secret = channel_secret or \
            self.config.get(section="line_bot_api", key="channel_secret")
        self.channel_access_token = channel_access_token or \
            self.config.get(section="line_bot_api", key="channel_access_token")
        self.parser = WebhookParser(self.channel_secret)
        self.api = LineBotApi(self.channel_access_token)

    def handle_http_request(self, request_data, request_headers):
        """
        Interface to chat with LINE Bot

        Parameters
        ----------
        request_data : list of byte
            Request data from LINE Messaging API as string
        request_headers : dict
            Request headers from LINE Messaging API as dict

        Returns
        -------
        response : Response
            Response that shows queued status
        """
        try:
            events = self.parser.parse(
                request_data.decode("utf-8"),
                request_headers.get("X-Line-Signature", ""))
            for ev in events:
                if self.executor:
                    self.executor.submit(self.handle_event, ev)
                else:
                    self.handle_event(ev)
            return Response(messages=[Message(text="done", type="system")])
        except InvalidSignatureError as ise:
            self.logger.error("Request signiture is invalid: " + str(ise) +
                              "\n" + traceback.format_exc())
            return Response(
                messages=[Message(text="invalid signiture", type="system")])
        except Exception as ex:
            self.logger.error("Request parsing error: " + str(ex) + "\n" +
                              traceback.format_exc())
            return Response(messages=[
                Message(text="failure in parsing request", type="system")
            ])

    def handle_event(self, event):
        channel_messages, token = super().handle_event(event)
        for msg in channel_messages:
            if self.debug:
                self.logger.info(msg)
            else:
                self.logger.info("Minette> {}".format(
                    msg.text if hasattr(msg, "text") else msg.
                    alt_text if hasattr(msg, "alt_text") else msg.type))
        self.api.reply_message(token, channel_messages)

    def _extract_token(self, event):
        """
        Extract token from event

        Parameters
        ----------
        event : Event
            Event from LINE Messaging API

        Returns
        -------
        message : Message
            Request message object
        """
        return event.reply_token if hasattr(event, "reply_token") else ""

    def _to_minette_message(self, event):
        """
        Convert LINE Event object to Minette Message object

        Parameters
        ----------
        event : Event
            Event from LINE Messaging API

        Returns
        -------
        message : Message
            Request message object
        """
        msg = Message(
            type=event.type,
            token=event.reply_token if hasattr(event, "reply_token") else None,
            channel="LINE",
            channel_detail="Messaging",
            channel_user_id=event.source.user_id,
            channel_message=event,
            timestamp=datetime.now(self.timezone))
        if event.source.type in ["group", "room"]:
            if event.source.type == "group":
                msg.group = Group(id=event.source.group_id, type="group")
            elif event.source.type == "room":
                msg.group = Group(id=event.source.room_id, type="room")
        if isinstance(event, MessageEvent):
            msg.id = event.message.id
            msg.type = event.message.type
            if isinstance(event.message, TextMessage):
                msg.text = event.message.text
            elif isinstance(event.message,
                            (ImageMessage, VideoMessage, AudioMessage)):
                msg.payloads.append(
                    Payload(
                        content_type=event.message.type,
                        url="https://api.line.me/v2/bot/message/%s/content" %
                        event.message.id,
                        headers={
                            "Authorization":
                            "Bearer {%s}" % self.channel_access_token
                        }))
            elif isinstance(event.message, LocationMessage):
                msg.payloads.append(
                    Payload(content_type=event.message.type,
                            content={
                                "title": event.message.title,
                                "address": event.message.address,
                                "latitude": event.message.latitude,
                                "longitude": event.message.longitude
                            }))
            elif isinstance(event.message, StickerMessage):
                msg.payloads.append(
                    Payload(content_type=event.message.type,
                            content={
                                "package_id": event.message.package_id,
                                "sticker_id": event.message.sticker_id,
                            }))
        elif isinstance(event, PostbackEvent):
            msg.payloads.append(
                Payload(content_type="postback",
                        content={
                            "data": event.postback.data,
                            "params": event.postback.params
                        }))
        elif isinstance(event, FollowEvent):
            pass
        elif isinstance(event, UnfollowEvent):
            pass
        elif isinstance(event, JoinEvent):
            pass
        elif isinstance(event, LeaveEvent):
            pass
        elif isinstance(event, MemberJoinedEvent):
            pass
        elif isinstance(event, MemberLeftEvent):
            pass
        elif isinstance(event, BeaconEvent):
            pass
        else:
            pass
        return msg

    @staticmethod
    def _to_channel_message(message):
        """
        Convert Minette Message object to LINE SendMessage object

        Parameters
        ----------
        response : Message
            Response message object

        Returns
        -------
        response : SendMessage
            SendMessage object for LINE Messaging API
        """
        payload = next(
            iter([
                p for p in message.payloads if p.content_type != "quick_reply"
            ]), None)
        quick_reply = next(
            iter([
                p.content for p in message.payloads
                if p.content_type == "quick_reply"
            ]), None)
        if message.type == "text":
            return TextSendMessage(text=message.text, quick_reply=quick_reply)
        elif message.type == "image":
            return ImageSendMessage(original_content_url=payload.url,
                                    preview_image_url=payload.thumb,
                                    quick_reply=quick_reply)
        elif message.type == "audio":
            return AudioSendMessage(original_content_url=payload.url,
                                    duration=payload.content["duration"],
                                    quick_reply=quick_reply)
        elif message.type == "video":
            return VideoSendMessage(original_content_url=payload.url,
                                    preview_image_url=payload.thumb,
                                    quick_reply=quick_reply)
        elif message.type == "location":
            cont = payload.content
            return LocationSendMessage(title=cont["title"],
                                       address=cont["address"],
                                       latitude=cont["latitude"],
                                       longitude=cont["longitude"],
                                       quick_reply=quick_reply)
        elif message.type == "sticker":
            return StickerSendMessage(package_id=payload.content["package_id"],
                                      sticker_id=payload.content["sticker_id"],
                                      quick_reply=quick_reply)
        elif message.type == "imagemap":
            return ImagemapSendMessage(alt_text=message.text,
                                       base_url=payload.url,
                                       base_size=payload.content["base_size"],
                                       actions=payload.content["actions"],
                                       quick_reply=quick_reply)
        elif message.type == "template":
            return TemplateSendMessage(alt_text=message.text,
                                       template=payload.content,
                                       quick_reply=quick_reply)
        elif message.type == "flex":
            return FlexSendMessage(alt_text=message.text,
                                   contents=payload.content,
                                   quick_reply=quick_reply)
        else:
            return None
예제 #29
0
    def test_parse(self):
        file_dir = os.path.dirname(__file__)
        webhook_sample_json_path = os.path.join(file_dir, 'text', 'webhook.json')
        with open(webhook_sample_json_path) as fp:
            body = fp.read()

        parser = WebhookParser('channel_secret')
        # mock
        parser.signature_validator.validate = lambda a, b: True

        events = parser.parse(body, 'channel_secret')

        # MessageEvent, SourceUser, TextMessage
        self.assertIsInstance(events[0], MessageEvent)
        self.assertEqual(events[0].reply_token, 'nHuyWiB7yP5Zw52FIkcQobQuGDXCTA')
        self.assertEqual(events[0].type, 'message')
        self.assertEqual(events[0].timestamp, 1462629479859)
        self.assertIsInstance(events[0].source, SourceUser)
        self.assertEqual(events[0].source.type, 'user')
        self.assertEqual(events[0].source.user_id, 'U206d25c2ea6bd87c17655609a1c37cb8')
        self.assertEqual(events[0].source.sender_id, 'U206d25c2ea6bd87c17655609a1c37cb8')
        self.assertIsInstance(events[0].message, TextMessage)
        self.assertEqual(events[0].message.id, '325708')
        self.assertEqual(events[0].message.type, 'text')
        self.assertEqual(events[0].message.text, 'Hello, world')

        # MessageEvent, SourceRoom, TextMessage
        self.assertIsInstance(events[1], MessageEvent)
        self.assertEqual(events[1].reply_token, 'nHuyWiB7yP5Zw52FIkcQobQuGDXCTA')
        self.assertEqual(events[1].type, 'message')
        self.assertEqual(events[1].timestamp, 1462629479859)
        self.assertIsInstance(events[1].source, SourceRoom)
        self.assertEqual(events[1].source.type, 'room')
        self.assertEqual(events[1].source.room_id, 'Ra8dbf4673c4c812cd491258042226c99')
        self.assertEqual(events[1].source.user_id, None)
        self.assertEqual(events[1].source.sender_id, 'Ra8dbf4673c4c812cd491258042226c99')
        self.assertIsInstance(events[1].message, ImageMessage)
        self.assertEqual(events[1].message.id, '325708')
        self.assertEqual(events[1].message.type, 'image')

        # MessageEvent, SourceUser, VideoMessage
        self.assertIsInstance(events[2], MessageEvent)
        self.assertEqual(events[2].reply_token, 'nHuyWiB7yP5Zw52FIkcQobQuGDXCTA')
        self.assertEqual(events[2].type, 'message')
        self.assertEqual(events[2].timestamp, 1462629479859)
        self.assertIsInstance(events[2].source, SourceUser)
        self.assertEqual(events[2].source.type, 'user')
        self.assertEqual(events[2].source.user_id, 'U206d25c2ea6bd87c17655609a1c37cb8')
        self.assertEqual(events[2].source.sender_id, 'U206d25c2ea6bd87c17655609a1c37cb8')
        self.assertIsInstance(events[2].message, VideoMessage)
        self.assertEqual(events[2].message.id, '325708')
        self.assertEqual(events[2].message.type, 'video')

        # MessageEvent, SourceUser, AudioMessage
        self.assertIsInstance(events[3], MessageEvent)
        self.assertEqual(events[3].reply_token, 'nHuyWiB7yP5Zw52FIkcQobQuGDXCTA')
        self.assertEqual(events[3].type, 'message')
        self.assertEqual(events[3].timestamp, 1462629479859)
        self.assertIsInstance(events[3].source, SourceUser)
        self.assertEqual(events[3].source.type, 'user')
        self.assertEqual(events[3].source.user_id, 'U206d25c2ea6bd87c17655609a1c37cb8')
        self.assertEqual(events[3].source.sender_id, 'U206d25c2ea6bd87c17655609a1c37cb8')
        self.assertIsInstance(events[3].message, AudioMessage)
        self.assertEqual(events[3].message.id, '325708')
        self.assertEqual(events[3].message.type, 'audio')

        # MessageEvent, SourceUser, LocationMessage
        self.assertIsInstance(events[4], MessageEvent)
        self.assertEqual(events[4].reply_token, 'nHuyWiB7yP5Zw52FIkcQobQuGDXCTA')
        self.assertEqual(events[4].type, 'message')
        self.assertEqual(events[4].timestamp, 1462629479859)
        self.assertIsInstance(events[4].source, SourceUser)
        self.assertEqual(events[4].source.type, 'user')
        self.assertEqual(events[4].source.user_id, 'U206d25c2ea6bd87c17655609a1c37cb8')
        self.assertEqual(events[4].source.sender_id, 'U206d25c2ea6bd87c17655609a1c37cb8')
        self.assertIsInstance(events[4].message, LocationMessage)
        self.assertEqual(events[4].message.id, '325708')
        self.assertEqual(events[4].message.type, 'location')
        self.assertEqual(events[4].message.title, 'my location')
        self.assertEqual(events[4].message.address, 'Tokyo')
        self.assertEqual(events[4].message.latitude, 35.65910807942215)
        self.assertEqual(events[4].message.longitude, 139.70372892916203)

        # MessageEvent, SourceUser, StickerMessage
        self.assertIsInstance(events[5], MessageEvent)
        self.assertEqual(events[5].reply_token, 'nHuyWiB7yP5Zw52FIkcQobQuGDXCTA')
        self.assertEqual(events[5].type, 'message')
        self.assertEqual(events[5].timestamp, 1462629479859)
        self.assertIsInstance(events[5].source, SourceUser)
        self.assertEqual(events[5].source.type, 'user')
        self.assertEqual(events[5].source.user_id, 'U206d25c2ea6bd87c17655609a1c37cb8')
        self.assertEqual(events[5].source.sender_id, 'U206d25c2ea6bd87c17655609a1c37cb8')
        self.assertIsInstance(events[5].message, StickerMessage)
        self.assertEqual(events[5].message.id, '325708')
        self.assertEqual(events[5].message.type, 'sticker')
        self.assertEqual(events[5].message.package_id, '1')
        self.assertEqual(events[5].message.sticker_id, '1')

        # FollowEvent, SourceUser
        self.assertIsInstance(events[6], FollowEvent)
        self.assertEqual(events[6].reply_token, 'nHuyWiB7yP5Zw52FIkcQobQuGDXCTA')
        self.assertEqual(events[6].type, 'follow')
        self.assertEqual(events[6].timestamp, 1462629479859)
        self.assertIsInstance(events[6].source, SourceUser)
        self.assertEqual(events[6].source.type, 'user')
        self.assertEqual(events[6].source.user_id, 'U206d25c2ea6bd87c17655609a1c37cb8')
        self.assertEqual(events[6].source.sender_id, 'U206d25c2ea6bd87c17655609a1c37cb8')

        # UnfollowEvent, SourceUser
        self.assertIsInstance(events[7], UnfollowEvent)
        self.assertEqual(events[7].type, 'unfollow')
        self.assertEqual(events[7].timestamp, 1462629479859)
        self.assertIsInstance(events[7].source, SourceUser)
        self.assertEqual(events[7].source.type, 'user')
        self.assertEqual(events[7].source.user_id, 'U206d25c2ea6bd87c17655609a1c37cb8')
        self.assertEqual(events[7].source.sender_id, 'U206d25c2ea6bd87c17655609a1c37cb8')

        # JoinEvent, SourceGroup
        self.assertIsInstance(events[8], JoinEvent)
        self.assertEqual(events[8].reply_token, 'nHuyWiB7yP5Zw52FIkcQobQuGDXCTA')
        self.assertEqual(events[8].type, 'join')
        self.assertEqual(events[8].timestamp, 1462629479859)
        self.assertIsInstance(events[8].source, SourceGroup)
        self.assertEqual(events[8].source.type, 'group')
        self.assertEqual(events[8].source.group_id, 'Ca56f94637cc4347f90a25382909b24b9')
        self.assertEqual(events[8].source.user_id, None)
        self.assertEqual(events[8].source.sender_id, 'Ca56f94637cc4347f90a25382909b24b9')

        # LeaveEvent, SourceGroup
        self.assertIsInstance(events[9], LeaveEvent)
        self.assertEqual(events[9].type, 'leave')
        self.assertEqual(events[9].timestamp, 1462629479859)
        self.assertIsInstance(events[9].source, SourceGroup)
        self.assertEqual(events[9].source.type, 'group')
        self.assertEqual(events[9].source.group_id, 'Ca56f94637cc4347f90a25382909b24b9')
        self.assertEqual(events[9].source.user_id, None)
        self.assertEqual(events[9].source.sender_id, 'Ca56f94637cc4347f90a25382909b24b9')

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

        # BeaconEvent, SourceUser
        self.assertIsInstance(events[11], BeaconEvent)
        self.assertEqual(events[11].reply_token, 'nHuyWiB7yP5Zw52FIkcQobQuGDXCTA')
        self.assertEqual(events[11].type, 'beacon')
        self.assertEqual(events[11].timestamp, 1462629479859)
        self.assertIsInstance(events[11].source, SourceUser)
        self.assertEqual(events[11].source.type, 'user')
        self.assertEqual(events[11].source.user_id, 'U206d25c2ea6bd87c17655609a1c37cb8')
        self.assertEqual(events[11].source.sender_id, 'U206d25c2ea6bd87c17655609a1c37cb8')
        self.assertEqual(events[11].beacon.hwid, 'd41d8cd98f')
        self.assertEqual(events[11].beacon.type, 'enter')
        self.assertEqual(events[11].beacon.dm, None)
        self.assertEqual(events[11].beacon.device_message, None)

        # BeaconEvent, SourceUser (with device message)
        self.assertIsInstance(events[12], BeaconEvent)
        self.assertEqual(events[12].reply_token, 'nHuyWiB7yP5Zw52FIkcQobQuGDXCTA')
        self.assertEqual(events[12].type, 'beacon')
        self.assertEqual(events[12].timestamp, 1462629479859)
        self.assertIsInstance(events[12].source, SourceUser)
        self.assertEqual(events[12].source.type, 'user')
        self.assertEqual(events[12].source.user_id, 'U206d25c2ea6bd87c17655609a1c37cb8')
        self.assertEqual(events[12].source.sender_id, 'U206d25c2ea6bd87c17655609a1c37cb8')
        self.assertEqual(events[12].beacon.hwid, 'd41d8cd98f')
        self.assertEqual(events[12].beacon.type, 'enter')
        self.assertEqual(events[12].beacon.dm, '1234567890abcdef')
        self.assertEqual(events[12].beacon.device_message, bytearray(b'\x124Vx\x90\xab\xcd\xef'))

        # MessageEvent, SourceGroup with userId, TextMessage
        self.assertIsInstance(events[13], MessageEvent)
        self.assertEqual(events[13].reply_token, 'nHuyWiB7yP5Zw52FIkcQobQuGDXCTA')
        self.assertEqual(events[13].type, 'message')
        self.assertEqual(events[13].timestamp, 1462629479859)
        self.assertIsInstance(events[13].source, SourceGroup)
        self.assertEqual(events[13].source.type, 'group')
        self.assertEqual(events[13].source.group_id, 'Ca56f94637cc4347f90a25382909b24b9')
        self.assertEqual(events[13].source.user_id, 'U206d25c2ea6bd87c17655609a1c37cb8')
        self.assertEqual(events[13].source.sender_id, 'Ca56f94637cc4347f90a25382909b24b9')
        self.assertIsInstance(events[13].message, TextMessage)
        self.assertEqual(events[13].message.id, '325708')
        self.assertEqual(events[13].message.type, 'text')
        self.assertEqual(events[13].message.text, 'Hello, world')

        # MessageEvent, SourceRoom with userId, TextMessage
        self.assertIsInstance(events[14], MessageEvent)
        self.assertEqual(events[14].reply_token, 'nHuyWiB7yP5Zw52FIkcQobQuGDXCTA')
        self.assertEqual(events[14].type, 'message')
        self.assertEqual(events[14].timestamp, 1462629479859)
        self.assertIsInstance(events[14].source, SourceRoom)
        self.assertEqual(events[14].source.type, 'room')
        self.assertEqual(events[14].source.room_id, 'Ra8dbf4673c4c812cd491258042226c99')
        self.assertEqual(events[14].source.user_id, 'U206d25c2ea6bd87c17655609a1c37cb8')
        self.assertEqual(events[14].source.sender_id, 'Ra8dbf4673c4c812cd491258042226c99')
        self.assertIsInstance(events[14].message, TextMessage)
        self.assertEqual(events[14].message.id, '325708')
        self.assertEqual(events[14].message.type, 'text')
        self.assertEqual(events[14].message.text, 'Hello, world')

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

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

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

        # MessageEvent, SourceUser, FileMessage
        self.assertIsInstance(events[18], MessageEvent)
        self.assertEqual(events[18].reply_token, 'nHuyWiB7yP5Zw52FIkcQobQuGDXCTA')
        self.assertEqual(events[18].type, 'message')
        self.assertEqual(events[18].timestamp, 1462629479859)
        self.assertIsInstance(events[18].source, SourceUser)
        self.assertEqual(events[18].source.type, 'user')
        self.assertEqual(events[18].source.user_id, 'U206d25c2ea6bd87c17655609a1c37cb8')
        self.assertEqual(events[18].source.sender_id, 'U206d25c2ea6bd87c17655609a1c37cb8')
        self.assertIsInstance(events[18].message, FileMessage)
        self.assertEqual(events[18].message.id, '325708')
        self.assertEqual(events[18].message.type, 'file')
        self.assertEqual(events[18].message.file_name, "file.txt")
        self.assertEqual(events[18].message.file_size, 2138)