つまらないオウムBOTに用はない
はじめに
前回までの記事で、オウム返しBOTの作り方、その仕組みについて書きました。
ただ、オウム返しするだけのBOTって、つまらないですよね。。。
もっと機能欲しい。。。
そこでこの記事では、前半にMessaging APIでできることを紹介し、後半でその機能を実装して行きます。
⚠︎まだオウム返しBOTを作っていない人は、こちらを先にお読みください。
Messaging APIでできること
Messaging APIでできることを一部紹介します。
1. テキストメッセージ
2. 画像メッセージ
3. 動画メッセージ
4. 音声メッセージ
5. 位置情報メッセージ
6. スタンプメッセージ
1. テキストメッセージ
テキストメッセージを送るには、送りたいテキストをメッセージオブジェクトに含めます。
TextSendMessage
text (String) メッセージのテキスト
text_message = TextSendMessage(text='Hello world')
2. 画像メッセージ
画像を送るには、画像と、その画像よりも小さなプレビュー画像のURLをメッセージオブジェクトに含めます。プレビュー画像がトーク画面に表示され、画像をタップするとフルサイズの画像が表示されます。なお、URLにはHTTPSのみ指定できます。
ImageSendMessage
original_content_url (String) 画像のURL
HTTPS,JPEG,最大画像サイズ1024×1024 ,最大ファイルサイズ1MB
preview_image_url(String) プレビュー画像のURL
HTTPS,JPEG,最大画像サイズ240×240 ,最大ファイルサイズ1MB
image_message = ImageSendMessage(
original_content_url='https://example.com/original.jpg',
preview_image_url='https://example.com/preview.jpg'
)
3. 動画メッセージ
動画を送るには、動画ファイルのURLとプレビュー画像のURLをメッセージオブジェクトに含めます。プレビュー画像をタップすると動画を再生できます。なお、URLにはHTTPSのみ指定できます。
VideoSendMessage
original_content_url(String) 動画ファイルのURL
HTTPS, mp4, 最大長 1分 ,最大ファイルサイズ 10MB
preview_image_url(String) プレビュー画像のURL
HTTPS,JPEG,最大画像サイズ240×240 ,最大ファイルサイズ1MB
video_message = VideoSendMessage(
original_content_url='https://example.com/original.mp4',
preview_image_url='https://example.com/preview.jpg'
)
4. 音声メッセージ
音声ファイルを送るには、ファイルのURLと再生時間をメッセージオブジェクトに含めます。なお、URLにはHTTPSのみ指定できます。
AudioSendMessage
original_content_url(String) 音声ファイルのURL
HTTPS, m4a, 最大長 1分 ,最大ファイルサイズ 10MB
duration (Number) 音声ファイルの長さ(ミリ秒)
audio_message = AudioSendMessage(
original_content_url='https://example.com/original.m4a',
duration=240000
)
5. 位置情報メッセージ
位置情報を送るには、タイトルと住所、そして緯度と経度の座標をメッセージオブジェクトに含めます。
LocationSendMessage
title (String) タイトル 最大文字数 100
address (String) 住所 最大文字数 100
latitude (String) 緯度
longitude (String) 経度
location_message = LocationSendMessage(
title='my location',
address='Tokyo',
latitude=35.65910807942215,
longitude=139.70372892916203
)
6. スタンプメッセージ
より表現に富みユーザーを惹きつけるボットを作るには、スタンプが効果的です。スタンプを送るには、送りたいスタンプのパッケージIDとスタンプIDをメッセージオブジェクトに含めます。
StickerSendMessage
package_id (String) スタンプセットのパッケージID。パッケージIDについては、スタンプリストを参照
sticker_id (String) スタンプID。Messaging APIで送信できるスタンプのスタンプIDについては、スタンプリストを参照
sticker_message = StickerSendMessage(
package_id='1',
sticker_id='1'
)
オウムBOTに実装
ここからは、上で紹介した機能実装します。
前回作ったオウム返しBOTのコードを一部変更します。
こちらがオウム返しBOTコードの全体像です。
#オウム返しBOT
# インポートするライブラリ
from flask import Flask, request, abort
from linebot import (
LineBotApi, WebhookHandler
)
from linebot.exceptions import (
InvalidSignatureError
)
from linebot.models import (
FollowEvent, MessageEvent, TextMessage, TextSendMessage, ImageMessage, ImageSendMessage, TemplateSendMessage, ButtonsTemplate, PostbackTemplateAction, MessageTemplateAction, URITemplateAction
)
import os
# 軽量なウェブアプリケーションフレームワーク:Flask
app = Flask(__name__)
#環境変数からLINE Access Tokenを設定
LINE_CHANNEL_ACCESS_TOKEN = os.environ["LINE_CHANNEL_ACCESS_TOKEN"]
#環境変数からLINE Channel Secretを設定
LINE_CHANNEL_SECRET = os.environ["LINE_CHANNEL_SECRET"]
line_bot_api = LineBotApi(LINE_CHANNEL_ACCESS_TOKEN)
handler = WebhookHandler(LINE_CHANNEL_SECRET)
@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'
# MessageEvent
@handler.add(MessageEvent, message=TextMessage)
def handle_message(event):
line_bot_api.reply_message(
event.reply_token,
TextSendMessage(text=event.message.text)
)
if __name__ == "__main__":
port = int(os.getenv("PORT"))
app.run(host="0.0.0.0", port=port)
変更する部分は下記の2箇所です。
インポートするライブラリ
MessageEvent
変更点1 インポートするライブラリ
変更する前は、
TextSendMessage,ImageSendMessage
2つのメッセージオブジェクトが既にimportされています。
#変更前
from linebot.models import (
FollowEvent, MessageEvent, TextMessage, TextSendMessage, ImageMessage, ImageSendMessage, TemplateSendMessage, ButtonsTemplate, PostbackTemplateAction, MessageTemplateAction, URITemplateAction
)
今回はさらに、動画、音声、位置情報、スタンプメッセージを利用したいので、下記4つもimportしましょう。
VideoSendMessage, AudioSendMessage, LocationSendMessage, StickerSendMessage
#変更後
from linebot.models import (
FollowEvent, MessageEvent, TextMessage, TextSendMessage, ImageMessage, ImageSendMessage,VideoSendMessage,AudioSendMessage, LocationSendMessage,StickerSendMessage,TemplateSendMessage, ButtonsTemplate, PostbackTemplateAction, MessageTemplateAction, URITemplateAction
)
変更点2 MessageEvent
オウム返しBOTの時は、受け取った文字データをそのまま返信していました。
# MessageEvent
@handler.add(MessageEvent, message=TextMessage)
def handle_message(event):
line_bot_api.reply_message(
event.reply_token,
TextSendMessage(text=event.message.text)
)
今回は、Messaging APIで使える機能を全て実装します。
オウムBOTに、
image というテキストメッセージが送信されると画像が、
video というテキストメッセージが送信されると動画が、
audio というテキストメッセージが送信されると音声が、
location というテキストメッセージが送信されると位置情報が、
sticker というテキストメッセージが送信されるとスタンプが、
上記以外が送信されると、オウム返しするBOTを作ります。
まずはメッセージの定義をします。
詳しい条件は前半に書いてあるので、そこを参照しながらコーディングしてください。
# MessageEvent
@handler.add(MessageEvent, message=TextMessage)
def handle_message(event):
# メッセージの定義
text_message = TextSendMessage(text=event.message.text)
image_message = ImageSendMessage(
original_content_url='https://i0.wp.com/s3-ap-northeast-1.amazonaws.com/media.gamepedia/pokemon.gamepedia.com/wp-content/uploads/sites/4/2018/11/15210933/poke_180713_02.png?fit=784%2C480&ssl=1&resize=240%2C240',
preview_image_url='https://i0.wp.com/s3-ap-northeast-1.amazonaws.com/media.gamepedia/pokemon.gamepedia.com/wp-content/uploads/sites/4/2018/11/15210933/poke_180713_02.png?fit=784%2C480&ssl=1&resize=240%2C240'
)
video_message = VideoSendMessage(
original_content_url='https://d3auje5car4oak.cloudfront.net/v/12763/12753049_a-01.mp4',
preview_image_url='https://i2.wp.com/s3-ap-northeast-1.amazonaws.com/media.gamepedia/pokemon-kg/wp-content/uploads/2017/09/20110310/198.png?fit=475%2C475&ssl=1&resize=240%2C240'
)
audio_message = AudioSendMessage(
original_content_url='https://soundeffect-lab.info/sound/animal/mp3/corvus-macrorhynchos-cry1.mp3',
duration=2000
)
location_message = LocationSendMessage(
title='my location',
address='Tokyo',
latitude=35.65910807942215,
longitude=139.70372892916203
)
sticker_message = StickerSendMessage(
package_id='1',
sticker_id='1'
)
次に条件分岐の処理を書いていきます。
送られてきたテキストメッセージによって処理を変えています。
# 処理
if event.message.text == "image":
line_bot_api.reply_message(
event.reply_token,image_message)
elif event.message.text == "video":
line_bot_api.reply_message(
event.reply_token,video_message)
elif event.message.text == "audio":
line_bot_api.reply_message(
event.reply_token,audio_message)
elif event.message.text == "location":
line_bot_api.reply_message(
event.reply_token,location_message)
elif event.message.text == "sticker":
line_bot_api.reply_message(
event.reply_token,sticker_message)
else:
line_bot_api.reply_message(
event.reply_token,text_message)
変更後のコードの全体像
#オウム返しBOT(改良版)
# インポートするライブラリ
from flask import Flask, request, abort
from linebot import (LineBotApi, WebhookHandler)
from linebot.exceptions import (InvalidSignatureError)
from linebot.models import (FollowEvent, MessageEvent, TextMessage, TextSendMessage, ImageMessage, ImageSendMessage,VideoSendMessage,AudioSendMessage, LocationSendMessage,StickerSendMessage,TemplateSendMessage, ButtonsTemplate, PostbackTemplateAction, MessageTemplateAction, URITemplateAction)
import os
# 軽量なウェブアプリケーションフレームワーク:Flask
app = Flask(__name__)
#環境変数からLINE Access Tokenを設定
LINE_CHANNEL_ACCESS_TOKEN = os.environ["LINE_CHANNEL_ACCESS_TOKEN"]
#環境変数からLINE Channel Secretを設定
LINE_CHANNEL_SECRET = os.environ["LINE_CHANNEL_SECRET"]
line_bot_api = LineBotApi(LINE_CHANNEL_ACCESS_TOKEN)
handler = WebhookHandler(LINE_CHANNEL_SECRET)
@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'
# MessageEvent
@handler.add(MessageEvent, message=TextMessage)
def handle_message(event):
# メッセージの定義
text_message = TextSendMessage(text=event.message.text)
image_message = ImageSendMessage(
original_content_url='https://i0.wp.com/s3-ap-northeast-1.amazonaws.com/media.gamepedia/pokemon.gamepedia.com/wp-content/uploads/sites/4/2018/11/15210933/poke_180713_02.png?fit=784%2C480&ssl=1&resize=240%2C240',
preview_image_url='https://i0.wp.com/s3-ap-northeast-1.amazonaws.com/media.gamepedia/pokemon.gamepedia.com/wp-content/uploads/sites/4/2018/11/15210933/poke_180713_02.png?fit=784%2C480&ssl=1&resize=240%2C240'
)
video_message = VideoSendMessage(
original_content_url='https://d3auje5car4oak.cloudfront.net/v/12763/12753049_a-01.mp4',
preview_image_url='https://i2.wp.com/s3-ap-northeast-1.amazonaws.com/media.gamepedia/pokemon-kg/wp-content/uploads/2017/09/20110310/198.png?fit=475%2C475&ssl=1&resize=240%2C240'
)
audio_message = AudioSendMessage(
original_content_url='https://soundeffect-lab.info/sound/animal/mp3/corvus-macrorhynchos-cry1.mp3',
duration=2000
)
location_message = LocationSendMessage(
title='my location',
address='Tokyo',
latitude=35.65910807942215,
longitude=139.70372892916203
)
sticker_message = StickerSendMessage(
package_id='1',
sticker_id='1'
)
# 処理
if event.message.text == "image":
line_bot_api.reply_message(
event.reply_token,image_message)
elif event.message.text == "video":
line_bot_api.reply_message(
event.reply_token,video_message)
elif event.message.text == "audio":
line_bot_api.reply_message(
event.reply_token,audio_message)
elif event.message.text == "location":
line_bot_api.reply_message(
event.reply_token,location_message)
elif event.message.text == "sticker":
line_bot_api.reply_message(
event.reply_token,sticker_message)
else:
line_bot_api.reply_message(
event.reply_token,text_message)
if __name__ == "__main__":
port = int(os.getenv("PORT"))
app.run(host="0.0.0.0", port=port)
完成
まとめと感想
うまく動きましたでしょうか?
既読がついてもBOTから反応がない場合は、下記のコードでherokuのログの中から、エラー文を見つけて、エラーを解決してください。
heroku logs -t
僕は、画像のサイズが大きすぎたり、HTTPSでなければいけない部分がHTTPだったためエラーが発生しました。
ここから先は
¥ 100
サポートするのは有料なので大丈夫です。代わりに無料でできる記事へのコメントやシェアをしていただけると、とても嬉しいです!