##はじめに
PythonでDropboxAPIの利用,Linebotにファイル送信機能を追加する方法を紹介したいと思います。
今回は,月ごとのカレンダーの画像をDropbox経由で送ってくれるLinebotを作成します。
Linebotの作成そのものに関しては,参考になるサイトが沢山あるので,ここでは省略します。
[PythonでLINEBotはじめました] (https://uepon.hatenadiary.com/entry/2018/06/19/222537)
[FlaskでLINE botを実装し,herokuにdeployするまで]
(https://qiita.com/suigin/items/0deb9451f45e351acf92)
##何が必要か?
言語:python 3.7.4
ライブラリ(Linebot):Flask 1.1.1, line-bot-sdk 1.16.0,
ライブラリ(Dropbox):dropbox 9.5.0
##ライブラリインスト―ル
下記の3つpipコマンドでインストールします。
pip install Flask
pip install line-bot-sdk
pip install dropbox
インストールが完了したら実践です。
##実践(Dropbox使用)
まず,DropboxAPIの簡単な使用方法について紹介いたします。
Dropboxの開発者登録,アクセストークンの取得は,Dropbox API app 開発者登録の手順を参考に各自で行って下さい。
以下では,DropboxAPIを利用した画像のアップロード,共有リンクの作成までを行います。
好きなカレンダーの画像をインターネットからダウンロードして,それらを順に1.jpg, 2.jpg, ...というように名前を変更しておいて下さい。
import dropbox
import os
#1.DropboxAPIの利用
DBX_ACCESS_TOKEN = ***********************
dbx = dropbox.Dropbox(DBX_ACCESS_TOKEN)
#2.Dropboxへのファイルアップロードと共有リンクの作成
for month in range(1,13):
local_path = '%s.jpg' %month
dbx_path = "/" + local_path
#2-1.ファイルアップロード(解説1)
f = open(local_path, 'rb')
dbx.files_upload(f.read(),dbx_path, mode=dropbox.files.WriteMode.overwrite)
f.close()
#2-2.共有リンク作成(解説2)
setting = dropbox.sharing.SharedLinkSettings(requested_visibility=dropbox.sharing.RequestedVisibility.public)
try:
link = dbx.sharing_create_shared_link_with_settings(path=dbx_path, settings=setting)
except:
print("既に共有されています。")
else:
url = link[0].url
print(url)
解説1
files_uploadのmodeは,デフォルトでは,WriteMode.addとなっています。
その場合には,アップロードするファイルと同じ名前のファイルが既に存在する場合,ファイル名(1).拡張子という名前で保存されます。
上書きしたい場合は,modeをoverwirteとして下さい。
解説2
SharedLinkSettingsでは,public, team_only, password(アクセスにパスワードが必要)の3種類の共有方法があります。他には,共有期限,パスワードなどを決定することができます。
より詳しく知りたい方は,[Dropbox for Python]
(https://dropbox-sdk-python.readthedocs.io/en/latest/index.html)をご覧下さい。
##Linebotへの組み込み
上記の手順で作成した共有リンクを使い,メッセージに応じて共有リンクを返すというLinebotを作成します。
下記のコードのほとんどは,GitHub line-bot-sdk-python examplesに記載されているものと同じです。
from flask import Flask, request, abort
import os
import dropbox
from linebot import (
LineBotApi, WebhookHandler
)
from linebot.exceptions import (
InvalidSignatureError
)
from linebot.models import (
MessageEvent, TextMessage, TextSendMessage,
)
app = Flask(__name__)
DBX_ACCESS_TOKEN = ***********************
dbx = dropbox.Dropbox(DBX_ACCESS_TOKEN)
#----------------------------ここから解説1
values = []
for month in range(1,13):
local_path = '%s.jpg' %month
dbx_path = "/" + local_path
link = dbx.sharing_list_shared_links(path=dbx_path).links
url = link[0].url
url = url.replace('www.dropbox','dl.dropboxusercontent').replace('?dl=0','')
values.append(url)
keys = [1,2,3,4,5,6,7,8,9,10,11,12]
pic_id = dict(zip(keys, values))
#----------------------------ここまで解説1
#環境変数取得
YOUR_CHANNEL_ACCESS_TOKEN = ***********************
YOUR_CHANNEL_SECRET = ***********************
line_bot_api = LineBotApi(YOUR_CHANNEL_ACCESS_TOKEN)
handler = WebhookHandler(YOUR_CHANNEL_SECRET)
@app.route("/")
def hello_world():
return "hello world!"
@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'
#----------------------------ここから解説2
@handler.add(MessageEvent, message=TextMessage)
def handle_message(event):
words = [12,11,10,9,8,7,6,5,4,3,2,1]
text = event.message.text
for word in words:
msg = 'カレンダー' + str(word)
if msg in text:
a = word - 1
key = keys[a]
line_bot_api.reply_message(
event.reply_token,[
TextSendMessage(text = key + '月のカレンダーだよ!'),
TextSendMessage(text = pic_id[key])
])
#----------------------------ここまで解説2
if __name__ == "__main__":
# app.run()
port = int(os.getenv("PORT"))
app.run(host="0.0.0.0", port=port)
解説1
カレンダーの月とURLを紐付けした辞書を作成します。
sharing_list_shared_links(path=dbx_path).linksでは,該当パスのリンク以外にも,ファイル情報を含んだ配列が返されます。(リンクは,一番最初に格納されている。)
url.replacedは,共有リンク内のwww.dropbox
をdl.dropboxusercontent
に変更,?dl=0
を消去しています。ブラウザ上で,共有リンクを表示するために必要な処理です。
解説2
Linebotがメッセージに応じて画像リンクを送信するようにif文で条件分岐させています。(ホームページ上部の画像参照)
wordsに,1月から順に[1,2,...12]というように格納してしまうと,「カレンダー12月」というメッセージを送った際に,「カレンダー1」が先に読み込まれてしまい1月のカレンダーがLinebotから帰ってきます。そのため,wordsには,[12,11,...1]というように格納しています。
より詳しく知りたい方は,[Dropbox for Python]
(https://dropbox-sdk-python.readthedocs.io/en/latest/index.html),[line-bot-sdk-python]
(https://line-bot-sdk-python.readthedocs.io/en/stable/index.html)をご覧下さい。
##参考
Linebot
[PythonでLINEBotはじめました] (https://uepon.hatenadiary.com/entry/2018/06/19/222537)
[FlaskでLINE botを実装し,herokuにdeployするまで]
(https://qiita.com/suigin/items/0deb9451f45e351acf92)
Dropbox
Dropbox API app 開発者登録の手順
[DropboxのAPIを利用して、ファイルアップロードと共有リンクの作成と共有リンクの取得を行う]
(https://qiita.com/Fortinbras/items/f77984e5a7c2b3045473)
公式ドキュメント
[Dropbox for Python]
(https://dropbox-sdk-python.readthedocs.io/en/latest/index.html)
[line-bot-sdk-python]
(https://line-bot-sdk-python.readthedocs.io/en/stable/index.html)