1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【Python】LINEからYoutubeの曲や動画を落としたい2/3

Last updated at Posted at 2020-07-21

#概要
【Python】LINEからYoutubeの曲や動画を落としたい1/3
【Python】LINEからYoutubeの曲や動画を落としたい2/3
【Python】LINEからYoutubeの曲や動画を落としたい3/3

GitHubへアップロードしました。

・Zennの記事の方が最新です。
https://zenn.dev/trusted_dream/articles/6fbb229fb71216

#LINEへの返答、GoogleDriveへのアップロード部分の作成
前回では、youtubeやsoundcloud、ニコニコ動画に対応するダウンローダーのプログラムを作成しました。
今回はyoutube-dlを使い実際にLINEに応答を返したりGoogleDriveへアップロードする部分を作成します。

まず、始める前にGoogleDriveへアップロードできるか確認しておきましょう。
##GoogleDriveへのアップロードができるか確認する(手順は大きく3つ)
①GoogleDriveで共有のフォルダを一つ作成する。
GoogleDrive上で右クリック → 新しいフォルダ → 名前を入力 → 名前を付けたフォルダを右クリック →
共有可能なリンクを取得 → [制限付き▼]をクリック → リンクを知っている全員に変えておく。
※ここを変えておかないと、LINEから直接音楽を聴いたりができなくなります。
(LINEサーバ上にデータは保管されず、あくまでストリーミングとしてGoogleDrive上の音楽を取得しに行ってるからです。)

②共有フォルダーのフォルダーIDを確認する。
フォルダーを作成できたらそのフォルダを開く → URLを確認 → https://drive.google.com/drive/folders/
以降のランダムな文字列がフォルダーIDになります。

③GoogleDriveへのアップロードを行う部分のテストプログラムを作成して確認する
前回作成したyoutube.pyと同じディレクトリ上で作業します。

・client_idとclient_secret、GoogleDriveAPIの有効化が必要です。参考

ID.PNG
※[JSONをダウンロード]も実施して名前を「client_secrets.json」に変更し、$HOME/lineに設置します。

####まずはsettings.yamlファイルを作成します

cd $HOME/line
vim settings.yaml
settings.yaml
client_config_backend: settings
client_config:
  client_id: "ここにGoogleClientID"
  client_secret: "ここにSecretID"

save_credentials: True
save_credentials_backend: file
save_credentials_file: credentials.json

get_refresh_token: True

oauth_scope:
  - https://www.googleapis.com/auth/drive.file
  - https://www.googleapis.com/auth/drive.install

####次にyoutube-dlを使用してGoogleDriveへのアップロードまでのプログラム

vim upload.py
upload.py
#!/bin/env python
import youtube
import os
from pydrive.auth import GoogleAuth
from pydrive.drive import GoogleDrive

#ダウンロードディレクトリ
dl_dir = "youtube/"
#GoogleFolderID
folder_id = 'フォルダーID'
#GoogleDrive認証設定
gauth = GoogleAuth()
gauth.CommandLineAuth()
drive = GoogleDrive(gauth)

message = "/mp3 GoogleDriveへアップロードしたいyoutubeの曲"
url = message.split()[1]
transaction = message.split()[0]

file_name = youtube.main(transaction,url,dl_dir)

for i in range(len(file_name)):
    f = drive.CreateFile({'title': file_name[i],
        'mimeType': 'audio/mpeg',
        'parents': [{'kind': 'drive#fileLink', 'id':folder_id}]})
    f.SetContentFile(dl_dir + f['title'])

    #UploadGoogleDrive
    f.Upload()

ここまでできたら、実行してアップロードできるか確認してみましょう。

$ chmod +x upload.py
$ ./upload.py

問題なくアップロードできたら、次にLINE BOTアプリを作成していきます。
##LINE BOTアプリを作成する

###環境変数に登録する

//未登録であることを確認
export -p
//登録を実施
echo 'export LINE_CHANNEL_ACCESS_TOKEN="ここにアクセストークン"' >> ~/.bash_profile
echo 'export LINE_CHANNEL_SECRET="ここにチャンネルシークレット"' >> ~/.bash_profile
source ~/.bash_profile
//登録されていることを確認
export -p

アプリの作成

vim app.py
app.py
#!/bin/env python
import os
import re
import youtube
import math
from flask import Flask, request, abort
from linebot import LineBotApi, WebhookHandler
from linebot.exceptions import InvalidSignatureError
from linebot.models import (
   MessageEvent, TextMessage, TextSendMessage,
   AudioSendMessage
)
from pydrive.auth import GoogleAuth
from pydrive.drive import GoogleDrive
from mutagen.mp3 import MP3

#アプリケーションフレームワーク
app = Flask(__name__)
#LINE Channel Secret
LINE_CHANNEL_SECRET = os.environ['LINE_CHANNEL_SECRET']
#LINE Access Token
LINE_CHANNEL_ACCESS_TOKEN = os.environ['LINE_CHANNEL_ACCESS_TOKEN']

line_bot_api = LineBotApi(LINE_CHANNEL_ACCESS_TOKEN)
handler = WebhookHandler(LINE_CHANNEL_SECRET)

#DownloadDirectory
dl_dir = "youtube/"
os.makedirs(dl_dir, exist_ok=True)

#GoogleDriveAuthSettings
gauth = GoogleAuth()
gauth.CommandLineAuth()
drive = GoogleDrive(gauth)

#GoogleFolderShareID
folder_id = 'GoogleDriveの共有フォルダーIDを記入'

@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'

#Message
def messagebox(event,transaction,url):
    transaction_dict = {
        '/mp3':'',
        '/mov':'本の動画',
        '/nomov':'本の動画'
    }
    set_transaction = transaction_dict.get(transaction)
    if "&list=" in url:
        line_bot_api.reply_message(event.reply_token,
                TextSendMessage(text="プレイリストの" + set_transaction
                    + "をGoogleDriveにアップロードします。\n"
                    + "処理に時間が掛かる場合があります。"))
    elif "nicovideo" in url:
        line_bot_api.reply_message(event.reply_token,
                TextSendMessage(text="ニコニコ動画は処理に時間が掛かる場合があります。"))
    else:
        line_bot_api.reply_message(event.reply_token,
                TextSendMessage(text="1" + set_transaction  + "をGoogleDriveにアップロードします。"))

#Music
def music(get_id,file_name):
    for i in range(len(file_name)):
        f = drive.CreateFile({'title': file_name[i],
                      'mimeType': 'audio/mpeg',
                      'parents': [{'kind': 'drive#fileLink', 'id':folder_id}]})
        f.SetContentFile(dl_dir + f['title'])

        #UploadGoogleDrive
        f.Upload()

        file_id = drive.ListFile({'q': 'title =\"' + file_name[i] +  '\"'}).GetList()[0]['id']

        if len(file_name) == 1 :
            file_length = MP3(dl_dir + file_name[i]).info.length
            link = "https://drive.google.com/uc?export=view&id=" + file_id
            dur = math.floor(file_length * 1000)
            line_bot_api.push_message(get_id,messages=(
                        TextSendMessage(text=file_name[i]),
                        AudioSendMessage(original_content_url=link,duration=dur)))

            line_bot_api.push_message(get_id,messages=(TextSendMessage(text=link)))
            os.remove(dl_dir + file_name[i])
            break

        os.remove(dl_dir + file_name[i])

    else:
        line_bot_api.push_message(get_id,messages=(
            TextSendMessage(text=str(len(file_name))
                + "曲をGoogleDriveにアップロードしました。\n"
                + "https://drive.google.com/drive/folders/" + folder_id)))
#Video
def video(get_id,file_name):
    video_ext_dicts = {
        '.mp4':'video/mp4',
        '.webm':'video/webm',
        '.mkv':'video/x-matroska'
    }
    for i in range(len(file_name)):
        root, ext = os.path.splitext(file_name[i])
        mimeType = video_ext_dicts.get(ext)

        f = drive.CreateFile({'title': file_name[i],
                      'mimeType': mimeType,
                      'parents': [{'kind': 'drive#fileLink', 'id':folder_id}]})
        f.SetContentFile(dl_dir + f['title'])

        #UploadGoogleDrive
        f.Upload()
        os.remove(dl_dir + file_name[i])

    line_bot_api.push_message(get_id,messages=(
        TextSendMessage(text=str(len(file_name))
            + "本をGoogleDriveにアップロードしました。\n"
            + "https://drive.google.com/drive/folders/" + folder_id)))

@handler.add(MessageEvent, message=(TextMessage))
def contents(event):
    #LINE Message
    message = event.message.text
    try:
        get_id = event.source.group_id
    except AttributeError:
        get_id = event.source.user_id

    param = ["/mp3","/mov","/nomov"]
    prm = [l for l in param if message.split()[0] in l]

    try:
        if message.startswith(prm[0]):
            url = message.split()[1]
            messagebox(event,prm[0],url)

            #youtube-dl
            file_name = youtube.main(prm[0],url,dl_dir)
            if str(file_name) in "ERROR" or file_name == []:
                line_bot_api.push_message(get_id,messages=(
                    TextSendMessage(text="ダウンロード処理に失敗しました。")))
            if prm[0] == "/mp3":
                music(get_id,file_name)
            else:
                video(get_id,file_name)
    except IndexError: pass
							
if __name__ == "__main__":
    app.run(host="127.0.0.1", port="9000")

ここまでできればほぼ完成です。あとはシェルスクリプトを書いて、挙動を確認して終了です。
ではまた次回でお会いしましょう。

1
1
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
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?