実現したいこと
Pythonとherokuを用いたオウム返しBOTを作りたいです。
また、トーク画面でレシピ検索ができるようにもしたいです。
前提
Pythonとherokuを用いたオウム返しBOTを作っています。
しかし、デプロイをしてメッセージを送ってみても正常に返信されません。
一応コードの137行目と150行目に問題があるとは思っているのですが治し方、どのようにコードを書き換えたらいいかわかりません。
pythonとHerokuを使っています。
発生している問題・エラーメッセージ
デプロイした後にメッセージが正常に返信されないです。
また、webhookを検証した後もボットサーバーから200以外のHTTPステータスコードが返されました。(503 Service Unavailable)と表示されます。
エラーメッセージ
Warning: heroku update available from 7.69.1 to 8.5.0.
2023-11-14T18:14:27.541284+00:00 app[web.1]: push()
2023-11-14T18:14:27.541321+00:00 app[web.1]: File "/app/main.py", line 137, in push
2023-11-14T18:14:27.541406+00:00 app[web.1]: (to_user,) = cur.fetchone()
2023-11-14T18:14:27.541445+00:00 app[web.1]: ^^^^^^^^^^
2023-11-14T18:14:27.541456+00:00 app[web.1]: TypeError: cannot unpack non-iterable NoneType object
2023-11-14T18:14:27.678846+00:00 heroku[web.1]: Process exited with status 1
2023-11-14T18:14:27.701793+00:00 heroku[web.1]: State changed from starting to crashed
2023-11-14T23:57:27.935597+00:00 heroku[web.1]: State changed from crashed to starting
2023-11-14T23:57:30.919958+00:00 heroku[web.1]: Starting process with command python main.py
2023-11-14T23:57:31.891688+00:00 app[web.1]: /app/main.py:19: LineBotSdkDeprecatedIn30: Call to deprecated class LineBotApi. (Use v3 class; linebot.v3.<feature>. See https://github.com/line/line-bot-sdk-python/blob/master/README.rst for more details.) -- Deprecated since version 3.0.0.
2023-11-14T23:57:31.891713+00:00 app[web.1]: line_bot_api = LineBotApi(LINE_CHANNEL_ACCESS_TOKEN)
2023-11-14T23:57:31.891728+00:00 app[web.1]: /app/main.py:20: LineBotSdkDeprecatedIn30: Call to deprecated class WebhookHandler. (Use 'from linebot.v3.webhook import WebhookHandler' instead. See https://github.com/line/line-bot-sdk-python/blob/master/README.rst for more details.) -- Deprecated since version 3.0.0.
2023-11-14T23:57:31.891728+00:00 app[web.1]: handler = WebhookHandler(LINE_CHANNEL_SECRET)
2023-11-14T23:57:31.920147+00:00 app[web.1]: Traceback (most recent call last):
2023-11-14T23:57:31.920148+00:00 app[web.1]: File "/app/main.py", line 150, in <module>
2023-11-14T23:57:31.920219+00:00 app[web.1]: push()
2023-11-14T23:57:31.920241+00:00 app[web.1]: File "/app/main.py", line 137, in push
2023-11-14T23:57:31.920287+00:00 app[web.1]: (to_user,) = cur.fetchone()
2023-11-14T23:57:31.920307+00:00 app[web.1]: ^^^^^^^^^^
2023-11-14T23:57:31.920318+00:00 app[web.1]: TypeError: cannot unpack non-iterable NoneType object
2023-11-14T23:57:32.011432+00:00 heroku[web.1]: Process exited with status 1
2023-11-14T23:57:32.032774+00:00 heroku[web.1]: State changed from starting to crashed
2023-11-15T05:57:53.033017+00:00 heroku[web.1]: State changed from crashed to starting
2023-11-15T05:57:56.222008+00:00 heroku[web.1]: Starting process with command python main.py
2023-11-15T05:57:57.322891+00:00 app[web.1]: /app/main.py:19: LineBotSdkDeprecatedIn30: Call to deprecated class LineBotApi. (Use v3 class; linebot.v3.<feature>. See https://github.com/line/line-bot-sdk-python/blob/master/README.rst for more details.) -- Deprecated since version 3.0.0.
2023-11-15T05:57:57.322903+00:00 app[web.1]: line_bot_api = LineBotApi(LINE_CHANNEL_ACCESS_TOKEN)
2023-11-15T05:57:57.322939+00:00 app[web.1]: /app/main.py:20: LineBotSdkDeprecatedIn30: Call to deprecated class WebhookHandler. (Use 'from linebot.v3.webhook import WebhookHandler' instead. See https://github.com/line/line-bot-sdk-python/blob/master/README.rst for more details.) -- Deprecated since version 3.0.0.
2023-11-15T05:57:57.322939+00:00 app[web.1]: handler = WebhookHandler(LINE_CHANNEL_SECRET)
2023-11-15T05:57:57.350404+00:00 app[web.1]: Traceback (most recent call last):
2023-11-15T05:57:57.350406+00:00 app[web.1]: File "/app/main.py", line 150, in <module>
2023-11-15T05:57:57.350512+00:00 app[web.1]: push()
2023-11-15T05:57:57.350539+00:00 app[web.1]: File "/app/main.py", line 137, in push
2023-11-15T05:57:57.350610+00:00 app[web.1]: (to_user,) = cur.fetchone()
2023-11-15T05:57:57.350649+00:00 app[web.1]: ^^^^^^^^^^
2023-11-15T05:57:57.350658+00:00 app[web.1]: TypeError: cannot unpack non-iterable NoneType object
2023-11-15T05:57:57.502129+00:00 heroku[web.1]: Process exited with status 1
2023-11-15T05:57:57.528893+00:00 heroku[web.1]: State changed from starting to crashed
2023-11-15T06:14:06.892234+00:00 heroku[router]: at=error code=H10 desc="App crashed" method=POST path="/callback" host=sotukenn-e1e02abe7625.herokuapp.com request_id=674a3891-f332-4d89-abbd-d62540f75cbf fwd="147.92.150.197" dyno= connect= service= status=503 bytes= protocol=https```
該当のソースコード
python
###ソースコード
from flask import Flask, request, abort
import requests, os
from linebot import LineBotApi, WebhookHandler
from linebot.exceptions import InvalidSignatureError
from linebot.models import MessageEvent, TextMessage, TextSendMessage, ImageMessage, ImageSendMessage, FollowEvent, UnfollowEvent
from PIL import Image
from io import BytesIO
import psycopg2
LINE_CHANNEL_ACCESS_TOKEN = os.environ["LINE_CHANNEL_ACCESS_TOKEN"]
LINE_CHANNEL_SECRET = os.environ["LINE_CHANNEL_SECRET"]
DATABASE_URL = os.environ["DATABASE_URL"]
HEROKU_APP_NAME = os.environ["HEROKU_APP_NAME"]
app = Flask(name)
Heroku = "https://{}.herokuapp.com/".format(HEROKU_APP_NAME)
line_bot_api = LineBotApi(LINE_CHANNEL_ACCESS_TOKEN)
handler = WebhookHandler(LINE_CHANNEL_SECRET)
header = {
"Content_Type": "application/json",
"Authorization": "Bearer " + LINE_CHANNEL_ACCESS_TOKEN
}
@app.route("/")
def hello_world():
return "hello world!"
アプリにPOSTがあったときの処理```ここに言語を入力
コード
@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: abort(400) return "OK" # botにメッセージを送ったときの処理 @handler.add(MessageEvent, message=TextMessage) def handle_message(event): line_bot_api.reply_message( event.reply_token, TextSendMessage(text=event.message.text)) print("返信完了!!\ntext:", event.message.text) # botに画像を送ったときの処理 @handler.add(MessageEvent, message=ImageMessage) def handle_image(event): print("画像を受信") message_id = event.message.id image_path = getImageLine(message_id) line_bot_api.reply_message( event.reply_token, ImageSendMessage( original_content_url = Heroku + image_path["main"], preview_image_url = Heroku + image_path["preview"] ) ) print("画像の送信完了!!") # 受信メッセージに添付された画像ファイルを取得 def getImageLine(id): line_url = f"https://api-data.line.me/v2/bot/message/{id}/content" result = requests.get(line_url, headers=header) print(result) img = Image.open(BytesIO(result.content)) w, h = img.size if w >= h: ratio_main, ratio_preview = w / 1024, w / 240 else: ratio_main, ratio_preview = h / 1024, h / 240 width_main, width_preview = int(w // ratio_main), int(w // ratio_preview) height_main, height_preview = int(h // ratio_main), int(h // ratio_preview) img_main = img.resize((width_main, height_main)) img_preview = img.resize((width_preview, height_preview)) image_path = { "main": f"static/images/image_{id}_main.jpg", "preview": f"static/images/image_{id}_preview.jpg" } img_main.save(image_path["main"]) img_preview.save(image_path["preview"]) return image_path # データベース接続 def get_connection(): return psycopg2.connect(DATABASE_URL, sslmode="require") # botがフォローされたときの処理 @handler.add(FollowEvent) def handle_follow(event): profile = line_bot_api.get_profile(event.source.user_id) with get_connection() as conn: with conn.cursor() as cur: conn.autocommit = True cur.execute('CREATE TABLE IF NOT EXISTS users(user_id TEXT)') cur.execute('INSERT INTO users (user_id) VALUES (%s)', [profile.user_id]) print('userIdの挿入OK!!') cur.execute('SELECT * FROM users') db = cur.fetchall() print("< データベース一覧 >") for db_check in db: print(db_check) # botがアンフォロー(ブロック)されたときの処理 @handler.add(UnfollowEvent) def handle_unfollow(event): with get_connection() as conn: with conn.cursor() as cur: conn.autocommit = True cur.execute('DELETE FROM users WHERE user_id = %s', [event.source.user_id]) print("userIdの削除OK!!") # データベースに登録されたLINEアカウントからランダムでひとりにプッシュ通知 def push(): with get_connection() as conn: with conn.cursor() as cur: cur.execute('SELECT * FROM users ORDER BY random() LIMIT 1') (to_user,) = cur.fetchone() line_bot_api.multicast([to_user], TextSendMessage(text="今日もお疲れさん!!")) # アプリの起動 if __name__ == "__main__": # 初回のみデータベースのテーブル作成 with get_connection() as conn: with conn.cursor() as cur: conn.autocommit = True cur.execute('CREATE TABLE IF NOT EXISTS users(user_id TEXT)') # LINE botをフォローしているアカウントのうちランダムで一人にプッシュ通知 push() port = int(os.getenv("PORT", 5000)) app.run(host="0.0.0.0", port=port) ### End
環境はWindowsを使用しています。
プロックファイルの中身は以下のようにしています・
web: python main.py
ここにより詳細な情報を記載してください。
