LoginSignup
5
5

More than 3 years have passed since last update.

PythonでLinebot作成&ファイル共有

Last updated at Posted at 2020-04-22

はじめに

PythonでDropboxAPIの利用,Linebotにファイル送信機能を追加する方法を紹介したいと思います。
今回は,月ごとのカレンダーの画像をDropbox経由で送ってくれるLinebotを作成します。


↓こんな感じ
Linebot参照.jpg

Linebotの作成そのものに関しては,参考になるサイトが沢山あるので,ここでは省略します。

PythonでLINEBotはじめました
FlaskでLINE botを実装し,herokuにdeployするまで

何が必要か?

言語: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をご覧下さい。

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.dropboxdl.dropboxusercontentに変更,?dl=0を消去しています。ブラウザ上で,共有リンクを表示するために必要な処理です。

解説2
Linebotがメッセージに応じて画像リンクを送信するようにif文で条件分岐させています。(ホームページ上部の画像参照)
wordsに,1月から順に[1,2,...12]というように格納してしまうと,「カレンダー12月」というメッセージを送った際に,「カレンダー1」が先に読み込まれてしまい1月のカレンダーがLinebotから帰ってきます。そのため,wordsには,[12,11,...1]というように格納しています。

より詳しく知りたい方は,Dropbox for Pythonline-bot-sdk-pythonをご覧下さい。

参考

Linebot
PythonでLINEBotはじめました
FlaskでLINE botを実装し,herokuにdeployするまで

Dropbox
Dropbox API app 開発者登録の手順
DropboxのAPIを利用して、ファイルアップロードと共有リンクの作成と共有リンクの取得を行う

公式ドキュメント
Dropbox for Python
line-bot-sdk-python

5
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
5