Q&A

pythonのLineBotApiでImageSendMessageができない。

linebotのmessagingapiで指定されたテキストに対して画像を送信したいのですが、line上で指定のテキストを送るとエラーが出て、画像が送られません。どうすれば画像を送れるでしょうか。

Traceback (most recent call last):
  File "c:\anaconda3\envs\spyder4\lib\site-packages\flask\app.py", line 2073, in wsgi_app
    response = self.full_dispatch_request()
  File "c:\anaconda3\envs\spyder4\lib\site-packages\flask\app.py", line 1518, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "c:\anaconda3\envs\spyder4\lib\site-packages\flask\app.py", line 1516, in full_dispatch_request
    rv = self.dispatch_request()
  File "c:\anaconda3\envs\spyder4\lib\site-packages\flask\app.py", line 1502, in dispatch_request
    return self.ensure_sync(self.view_functions[rule.endpoint])(**req.view_args)   
  File "C:\Users\Name\Documents\Name\linebot.002\app.py", line 36, in callback     
    handler.handle(body, signature)
  File "c:\anaconda3\envs\spyder4\lib\site-packages\linebot\webhook.py", line 259, 
in handle
    self.__invoke_func(func, event, payload)
  File "c:\anaconda3\envs\spyder4\lib\site-packages\linebot\webhook.py", line 271, 
in __invoke_func
    func(event)
  File "C:\Users\Name\Documents\Name\linebot.002\app.py", line 62, in handle_message
    line_bot_api.reply_message(
  File "c:\anaconda3\envs\spyder4\lib\site-packages\linebot\api.py", line 109, in reply_message
    self._post(
  File "c:\anaconda3\envs\spyder4\lib\site-packages\linebot\api.py", line 1620, in 
_post
    self.__check_error(response)
  File "c:\anaconda3\envs\spyder4\lib\site-packages\linebot\api.py", line 1656, in 
__check_error
    raise LineBotApiError(
linebot.exceptions.LineBotApiError: LineBotApiError: status_code=400, request_id=XXXXXXXXXXXXXXX, error_response={"details": [{"message": "May not be empty", "property": "messages[0].previewImageUrl"}], "message": "The request body has 1 error(s)"}, headers={'Server': 'openresty', 'Date': 'Fri, 17 Dec 2021 22:53:09 GMT', 'Content-Type': 'application/json', 'Content-Length': '129', 'Connection': 'keep-alive', 'cache-control': 'no-cache, no-store, max-age=0, must-revalidate', 'expires': '0', 'pragma': 'no-cache', 'x-content-type-options': 'nosniff', 'x-frame-options': 'DENY', 'x-line-request-id': 'XXXXXXXXXXXXXXXXXXXXXXXXXX', 'x-xss-protection': '1; mode=block'}
127.0.0.1 - - [18/Dec/2021 07:53:04] "POST /callback HTTP/1.1" 500 -

↑以上のものが、テキストを送ると帰ってきます。app.pyのコードは以下の通りです。

from flask import Flask, request, abort

from linebot import (
    LineBotApi, WebhookHandler
)
from linebot.exceptions import (
    InvalidSignatureError
)
from linebot.models import (
    MessageEvent, TextMessage, TextSendMessage,ImageMessage,ImageSendMessage
)
from linebot.models.responses import Content
from werkzeug.datastructures import ContentSecurityPolicy
from werkzeug.wrappers import response

app = Flask(__name__)

line_bot_api = LineBotApi('XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX')
handler = WebhookHandler('XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX')

@app.route("/")
def test():
    return "OK"

@app.route("/callback", methods=['POST'])
def callback():
    # get X-Line-Signature header value
    signature = request.headers['X-Line-Signature']

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

    # handle webhook body
    try:
        handler.handle(body, signature)
    except InvalidSignatureError:
        print("Invalid signature. Please check your channel access token/channel secret.")
        abort(400)

    return 'OK'


@handler.add(MessageEvent, message=TextMessage)
def handle_message(event):
    if event.message.text=="@start":
        orurl="https://drive.google.com/uc?id=ImageId"
        prurl="https://drive.google.com/uc?id=ImageId"
    line_bot_api.reply_message(
        event.reply_token,
        ImageSendMessage(
            original_content_url=orurl,
            preview_content_url=prurl))



if __name__ == "__main__":
    app.run()

python上でjsonのオブジェクトを使うなどしてみましたが、同じ結果でした。

バージョン情報: Windows 10 Home Python 3.8.12 64-bit('spyder4':conda) ngrok Windows(64-bit)

  • 0
  • 4
  • 4621
  • twitter facebook

なるほど、見落としていました。ありがとうございます。 正常に動きました!

  • 1

あーすみません、よく見たらpreview_content_urlなんてオプションありませんね・・・ 正しくは、preview_image_url でした

  • 0

ご回答ありがとうございます。いただいたご指摘も含め、handle_message関数の部分を書き換えてみました。

@handler.add(MessageEvent, message=TextMessage)
def handle_message(event):
    if event.message.text=="@start":
        url="https://drive.google.com/uc?id=ImageId"
        line_bot_api.reply_message(
            event.reply_token,
            ImageSendMessage(
                original_content_url=url,
                preview_content_url=url))
    else:
        reply_message="@startを入力してください。"
        line_bot_api.reply_message(
            event.reply_token,
            TextSendMessage(text=reply_message))

しかし、依然としてエラーが出ます。

url="https://drive.google.com/uc?id=ImageId" の部分は、以下のサンプルと同様に作っていて、 LINE Bot Designerで確認すると正常に画像として拾えました。ドライブの画像に共有のリンクを作ったあと、画像単体で表示されるようにしています。 https://drive.google.com/uc?id=1ks5KMBzYeFcAr-yaqKUKMhscF4ENtx4B

エラーは以下の通りです。

Traceback (most recent call last):
  File "c:\anaconda3\envs\spyder4\lib\site-packages\flask\app.py", line 2073, in wsgi_app
    response = self.full_dispatch_request()
  File "c:\anaconda3\envs\spyder4\lib\site-packages\flask\app.py", line 1518, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "c:\anaconda3\envs\spyder4\lib\site-packages\flask\app.py", line 1516, in full_dispatch_request
    rv = self.dispatch_request()
  File "c:\anaconda3\envs\spyder4\lib\site-packages\flask\app.py", line 1502, in dispatch_request
    return self.ensure_sync(self.view_functions[rule.endpoint])(**req.view_args)    
  File "C:\Users\Name\Documents\Name\linebot.002\app.py", line 39, in callback      
    handler.handle(body, signature)
  File "c:\anaconda3\envs\spyder4\lib\site-packages\linebot\webhook.py", line 259, in handle
    self.__invoke_func(func, event, payload)
  File "c:\anaconda3\envs\spyder4\lib\site-packages\linebot\webhook.py", line 271, in __invoke_func
    func(event)
  File "C:\Users\Name\Documents\Name\linebot.002\app.py", line 53, in handle_message    line_bot_api.reply_message(
  File "c:\anaconda3\envs\spyder4\lib\site-packages\linebot\api.py", line 109, in reply_message
    self._post(
  File "c:\anaconda3\envs\spyder4\lib\site-packages\linebot\api.py", line 1620, in _post
    self.__check_error(response)
  File "c:\anaconda3\envs\spyder4\lib\site-packages\linebot\api.py", line 1656, in __check_error
    raise LineBotApiError(
linebot.exceptions.LineBotApiError: LineBotApiError: status_code=400, request_id=XXXXXXXXXXXXX, error_response={"details": [{"message": "May not 
be empty", "property": "messages[0].previewImageUrl"}], "message": "The request body has 1 error(s)"}, headers={'Server': 'openresty', 'Date': 'Sat, 18 Dec 2021 23:43:05 GMT', 'Content-Type': 'application/json', 'Content-Length': '129', 'Connection': 'keep-alive', 'cache-control': 'no-cache, no-store, max-age=0, must-revalidate', 'expires': '0', 'pragma': 'no-cache', 'x-content-type-options': 'nosniff', 'x-frame-options': 'DENY', 'x-line-request-id': 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX', 'x-xss-protection': '1; mode=block'}
127.0.0.1 - - [19/Dec/2021 08:43:00] "POST /callback HTTP/1.1" 500 -

どう修正すれば良いでしょうか。

  • 0

エラーメッセージから見ると、handle_message関数のif文が不適切です。 line_bot_api.reply_messageがif文のブロック内に入ってないので特定のテキスト(今回だと@start)以外のメッセージだとorurlprurlが何もないのでエラーになっています。

@handler.add(MessageEvent, message=TextMessage)
def handle_message(event):
    if event.message.text=="@start":
        orurl="https://drive.google.com/uc?id=ImageId"
        prurl="https://drive.google.com/uc?id=ImageId"
        line_bot_api.reply_message(
            event.reply_token,
            ImageSendMessage(
                original_content_url=orurl,
                preview_content_url=prurl))

あと、余計なことですが、google Driveの画像ってそのまま送信できましたっけ?もし送信できなさそうならサーバーに画像を保存してURLを付与してあげるとできるかと思います。 やり方は以下の記事のやり方を参考にしてもらえるといいかと思います。 https://qiita.com/tamago324/items/4df361fd6ac5b51a8a07

  • 0
本当によろしいですか? question.vm