SpotifyAPIを使ってNowPlayingをTwitterにツイートする。【Python】

SpotifyのNowPlayingを作りたい！って言う人は結構いると思うのですが(僕とか)意外と記事が少ないので今回はPythonでSpotifyのNowPlayingをTwitterに自動ツイートするプログラムを書いていこうと思います。

**一番最後に完成形があるので完成形をみたい方はそちらへどうぞ～**

##前提
Spotifyの無料又は有料アカウントを持っている
「Pythonかんぜんにりかいした」といえる

##使用するライブラリ
SpotifyAPIを直で叩いてもいいのですが、公式サイトを見ていたら[いろんな言語のライブラリ](https://developer.spotify.com/documentation/web-api/libraries/#libraries)が掲載されていたので今回はここに書いてある、Spotipyを使ってみようと思います。
SpotipyのほうがStarが圧倒的に多く、共同開発なので安定していると考え今回は**Spotipy**を使用することにしました。
Readmeなどを見て自分にあうものを使ったらいいと思います。

ライブラリの製作者を見ていたら公式サイトに書いてあるライブラリ、どちらも**同じ人が作ってますね＾＾**Spotipyは共同開発、Tekoreは個人開発っぽいです。


##アプリケーションの登録をする
SpotifyAPIを使用するにはDashboardからアプリケーションを登録する必要があります。
ここから登録してください。
https://developer.spotify.com/dashboard/applications/
![スクリーンショット.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/372924/f4c35820-9b9b-4b3c-a52d-46f5ec8eb66e.png)

**CREATE AN APP**をクリックし、作成をします。
![スクリーンショット.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/372924/69b10fe5-a8e1-6fd6-7cd1-998739700ea2.png)

アプリケーションの名前と説明を入力し、利用規約に同意しアプリケーションを作成します。

アプリケーションを作成すると、**Your application 'アプリケーション名' has been successfully created.**と表示され、なんかかっけーページが開くと思います。

**Client ID**と**Client Secret**をメモしておいてください。

##Spotipyをインストールする
PIPでインストールすることができるので```pip install spotipy```でインストールします。

##試しにSpotipyを使って作曲者のサムネイル画像を取得してみる
今回は名前検索でGuianoさんのアイコンURLを取得してみます。
[Guiano](https://open.spotify.com/artist/1gIxoB0mBUoPr7rPyy31xf?si=AL65dSeYTKaVqnsqVjHLUw)さんの曲ぜひぜひぜひぜひ聞いてください。


```python

import spotipy
import sys

client_id = 'クライアントID'
client_secret = 'クライアントシークレットID'
client_credentials_manager = spotipy.oauth2.SpotifyClientCredentials(client_id, client_secret)
spotify = spotipy.Spotify(client_credentials_manager=client_credentials_manager)

if len(sys.argv) > 1:
    name = ' '.join(sys.argv[1:])
else:
    name = 'Guiano'

results = spotify.search(q='artist:' + name, type='artist')
items = results['artists']['items']
if len(items) > 0:
    artist = items[0]
    print(artist['name'], artist['images'][0]['url'])

```

また、ID指定でアイコンを取得することも出来ます。
アーティストのIDを取得するには、アーティストのプロフィールページに行き、...→シェア→SpotifyURLをコピーで取得することが出来ます。
![ArtistID.jpg](https://pbs.twimg.com/media/Eq06tPFVoAAq82Q?format=jpg)

##現在再生中の曲を取得する
現在再生中(個人ユーザーでの情報を取得する)の音楽の情報を取得するには自分のユーザー名と〇〇が必要なので取得していきます。

[アカウント情報](https://www.spotify.com/jp/account/overview/?utm_source=spotify&utm_medium=menu&utm_campaign=your_account)にアクセスし、**ユーザー名**をメモしておきます。
普通のアカウントの名前とは違うようなので注意してください。


```python
import spotipy

client_id = 'クライアントID'
client_secret = 'クライアントシークレットID'
client_credentials_manager = spotipy.oauth2.SpotifyClientCredentials(client_id, client_secret)
spotify = spotipy.Spotify(client_credentials_manager=client_credentials_manager)

token = spotipy.util.prompt_for_user_token(
    username = "ユーザー名",
    scope = "user-read-currently-playing",
    client_id = client_id,
    client_secret = client_secret,
    redirect_uri = "https://example.com/callback/"
)
spotify = spotipy.Spotify(auth=token)
current_playing = spotify.current_user_playing_track()

print(current_playing)
```

このままではコードを実行した際に**INVALID_CLIENT: Invalid redirect URI**と怒られてしまうので、Spotify DashboardからリダイレクトURLを設定します。
今回はコード内のリダイレクトURL(厳密にはURI)に**example.com/callback/**と設定しているので、Spotify Dashboardにも**example.com/callback/**を設定します。
Spotify Dashboardを開き、アプリケーション、SETTINGをクリックし、**Redirect URIs**に**https://example.com/callback/**と入力し、保存します。
example.comのまま行うとセキュリティ的にまずいかもしれないので自分のドメインにしたほうがいいかもしれません。

これでもう一度実行するとaccounts.spotify.com/なんちゃらかんちゃらに飛ぶのでアプリケーションを認証します。
![スクリーンショット.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/372924/e9eed62f-3428-52f5-a7d2-9e06287c0882.png)

そしたらもう一度実行してみます。
するとコンソールに

```
Couldn't read cache at: .cache-xxxxxxxxxx
Enter the URL you were redirected to:
```

と表示され、webページが開かれるので、そのURLをそのままコピーし、コンソールに貼り付けます。
そんでEnter!!!!!!

すると、な、な、なんと！
コンソールに再生中、又は前回再生した曲が！？
jsonみたいな形で返されるので['item']['name']みたいな感じで取り出します。
そのコードがこちら。

```python

import spotipy

client_id = 'クライアントID'
client_secret = 'クライアントシークレットID'
client_credentials_manager = spotipy.oauth2.SpotifyClientCredentials(client_id, client_secret)
spotify = spotipy.Spotify(client_credentials_manager=client_credentials_manager)

token = spotipy.util.prompt_for_user_token(
    username = "ユーザー名",
    scope = "user-read-currently-playing",
    client_id = client_id,
    client_secret = client_secret,
    redirect_uri = "https://example.com/callback/"
)
spotify = spotipy.Spotify(auth=token)
current_playing = spotify.current_user_playing_track()

print(current_playing['item']['name'])
```


これで実行すると～！
再生中の曲のタイトルが表示されると思います。

```
C:\Users\nixo\anaconda3\python.exe C:/Users/nixo/Desktop/NowPlaying/main.py
無題
```

こんな感じ。

##NowPlaingハッシュタグをつけてツイートする
今回は定番のTweepyを使ってツイートを行います。
Tweepyの使い方はこちら[Tweepyのいろいろ。ま♡と♡め♡](https://qiita.com/nikun/items/0d2b69c6361ab9ce5963)

```python
import spotipy
import tweepy

#SpotifyとTwitterへのAPI認証
client_id = 'クライアントID'
client_secret = 'クライアントシークレットID'
client_credentials_manager = spotipy.oauth2.SpotifyClientCredentials(client_id, client_secret)
spotify = spotipy.Spotify(client_credentials_manager=client_credentials_manager)

CK = "ここにConsumer Key"
CS = "ここにConsumer Secret"
AT = "ここにAccess Token"
ATS = "ここにAccess Token Secret"
auth = tweepy.OAuthHandler(CK, CS)
auth.set_access_token(AT, ATS)
api = tweepy.API(auth)
#認証おわり

token = spotipy.util.prompt_for_user_token(
    username = "ユーザー名",
    scope = "user-read-currently-playing",
    client_id = client_id,
    client_secret = client_secret,
    redirect_uri = "https://example.com/callback/"
)
spotify = spotipy.Spotify(auth=token)
current_playing = spotify.current_user_playing_track()

print(current_playing['item']['name'])
api.update_status(current_playing['item']['name'] + " #NowPlaying")
```

こうすることでNowPlayingをツイートすることが出来ます。
でもこれだけでは味気ないので、

##画像生成をしよう！(「Pythonかんぜんにりかいした」方向け)
Pythonかんぜんにりかいした方向けに、**cloudinary**というOGPの自動生成でお世話になっているサービスを使用します。
URLに文字を入力するとその画像を生成してくれるやつです。
海外のサービスですが珍しく日本語対応です！！！

###まずは土台画像をつくる
最近ペンタブを買ったのでCLIP STUDIOでかきました！！！！！！！
![なうぷれー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/372924/16f512da-b675-e3b6-9238-7ddbadb3f7ab.png)
今回はこの画像を土台に文字を載せます。
######あ、この画像自由に使っていいからね(1920x1080)

###Cloudinaryのアカウントをツクール
はい。作ってログインしてダッシュボードに行ってください。
そんで**Media Library**に行って土台の画像をドラッグ・アンド・ドロップします
そしたらこんな感じで表示されます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/372924/496a7423-3626-5f55-7bb6-22b838b56f68.png)
画像にカーソルを合わせるとCopyURLみたいなの出てくるのでそれクリックしてコピーします。
今回の画像はこんなURL
https://res.cloudinary.com/nixo/image/upload/v1609762642/%E3%81%AA%E3%81%86%E3%81%B7%E3%82%8C%E3%83%BC_vjxior.png
文字を入れるには```https://res.cloudinary.com/nixo/image/upload/ここ/v1609762642/%E3%81%AA%E3%81%86%E3%81%B7%E3%82%8C%E3%83%BC_vjxior.png```に色々書きます。

Catnoseさんの雑記ブログがわかりやすいと思います。
是非参考に。https://catnose99.com/cloudinary-dynamic-ogp-image/

**upload**と**vなんちゃらかんちゃら**の間に```l_text:Sawarabi%20Gothic_50_bold:{music_title},co_rgb:333,w_1300,c_fit```と入力します。
完全なURLはこれ

```
https://res.cloudinary.com/nixo/image/upload/l_text:Sawarabi%20Gothic_50_bold:{music_title},co_rgb:333,w_1300,c_fit/v1609762642/%E3%81%AA%E3%81%86%E3%81%B7%E3%82%8C%E3%83%BC_vjxior.png
```

###Pythonコードに組み込んでいく
ファイルを保存し、ツイートするようにします。(URL直指定はできない)
ちなみにURLに空白があるとURLにアクセスできなくなるのでスペースは除去するようにしています。
あとURLに日本語を含ませるのに数時間苦戦したので皆さんお気をつけて。

```python
import spotipy
import tweepy
import urllib.request
import urllib

#SpotifyとTwitterへのAPI認証
client_id = 'クライアントID'
client_secret = 'クライアントシークレットID'
client_credentials_manager = spotipy.oauth2.SpotifyClientCredentials(client_id, client_secret)
spotify = spotipy.Spotify(client_credentials_manager=client_credentials_manager)

CK = "ここにConsumer Key"
CS = "ここにConsumer Secret"
AT = "ここにAccess Token"
ATS = "ここにAccess Token Secret"
auth = tweepy.OAuthHandler(CK, CS)
auth.set_access_token(AT, ATS)
api = tweepy.API(auth)
#認証おわり

token = spotipy.util.prompt_for_user_token(
    username = "ユーザー名",
    scope = "user-read-currently-playing",
    client_id = client_id,
    client_secret = client_secret,
    redirect_uri = "https://example.com/callback/"
)
spotify = spotipy.Spotify(auth=token)
current_playing = spotify.current_user_playing_track()

music_title = current_playing['item']['name']
artist_name = current_playing['item']['artists'][0]['name']
music_title = music_title.replace(' ', '') #スペースがあると画像生成でエラー出るのでなくす。全角半角どっちとも。
music_title = music_title.replace('　', '')
artist_name = artist_name.replace(' ', '')
artist_name = artist_name.replace('　', '')

img_url = 'https://res.cloudinary.com/nixo/image/upload/l_text:Sawarabi%20Gothic_120_bold:' + urllib.parse.quote_plus(music_title, encoding='utf-8') + "-" + urllib.parse.quote_plus(artist_name, encoding='utf-8') + ',co_rgb:333,w_1300,c_fit/v1609768419/nowplay_kzuxtk.png'
img_url = img_url.replace(' ', '') #スペースがあると画像生成でエラー出るのでなくす
img_url = img_url.replace('　', '')
img_save_name = "music.png"
urllib.request.urlretrieve(str(img_url), img_save_name)

api.update_with_media(filename = "./music.png", status = f"SongTitle: {music_title}\nArtist: {artist_name}\n \n#NowPlaying")
```



##画像生成をしよう！(天才プログラマ向け)

今回はPillowを使用し、画像付きツイートにします。
**申し訳ございません現在書いてる途中です。**

##定期的にツイートする(time.sleepを使用)
Cloudinaryのやつがベースです。
scheduleライブラリを使用してもいいのですがこの場合一つ、かつtime.sleepのほうが直感的に短く処理できるので今回はtime.sleepを使用します。
Spotipyのドキュメントを探してみたのですが、曲が変わったとき、というイベントが無いようなので今回は曲の平均時間を指定します。
[カラオケで独りよがりにならないために～1曲の平均時間はどれくらい?～](https://chouseisan.com/l/post-53079/)によるとJPOPは平均4分から5分、ボカロは3分46秒が平均らしいので今回は**4分15秒**間隔に指定します。
これはシンプルにwhile Trueで囲って最後にtime.sleepするだけでいいのですが前回と曲が変わっていない場合はツイートしないようにします。

```python
import spotipy
import tweepy
import urllib.request
import urllib

#SpotifyとTwitterへのAPI認証
client_id = 'クライアントID'
client_secret = 'クライアントシークレットID'
client_credentials_manager = spotipy.oauth2.SpotifyClientCredentials(client_id, client_secret)
spotify = spotipy.Spotify(client_credentials_manager=client_credentials_manager)

CK = "ここにConsumer Key"
CS = "ここにConsumer Secret"
AT = "ここにAccess Token"
ATS = "ここにAccess Token Secret"
auth = tweepy.OAuthHandler(CK, CS)
auth.set_access_token(AT, ATS)
api = tweepy.API(auth)
#認証おわり

music_title = ""
msc = " "

while True:
    try:
        token = spotipy.util.prompt_for_user_token(
            username="ユーザー名",
            scope="user-read-currently-playing",
            client_id=client_id,
            client_secret=client_secret,
            redirect_uri="https://example.com/callback/"
        )
        
        spotify = spotipy.Spotify(auth=token)
        current_playing = spotify.current_user_playing_track()

        music_title = current_playing['item']['name']
        artist_name = current_playing['item']['artists'][0]['name']

        music_title = music_title.replace(' ', '')  # スペースがあると画像生成でエラー出るのでなくす。全角半角どっちとも。
        music_title = music_title.replace('　', '')
        artist_name = artist_name.replace(' ', '')
        artist_name = artist_name.replace('　', '')
        if music_title == msc:
            print("曲同じやんけ！")
            time.sleep(15)
        else:
            msc = music_title

            img_url = 'https://res.cloudinary.com/nixo/image/upload/l_text:Sawarabi%20Gothic_120_bold:' + urllib.parse.quote_plus(music_title, encoding='utf-8') + "-" + urllib.parse.quote_plus(artist_name, encoding='utf-8') + ',co_rgb:333,w_1300,c_fit/v1609768419/nowplay_kzuxtk.png'
            img_url = img_url.replace(' ', '') #スペースがあると画像生成でエラー出るのでなくす
            img_url = img_url.replace('　', '')
            img_save_name = "music.png"
            urllib.request.urlretrieve(str(img_url), img_save_name)

            api.update_with_media(filename = "./music.png", status = f"SongTitle: {music_title}\nArtist: {artist_name}\n \n#NowPlaying")

            time.sleep(255)#4分15秒
    except Exception as e:
        print("エラーが発生しました")
        print(e)
        time.sleep(15)
    time.sleep(60)
```

ループ開始時はおなじになってはいけないのでmscにスペースを代入したものを最初に準備しています。

##おわり
今回はこのへんで終わらせていただきます。
わからないところやここおかしくね？という所があればTwitterのDMやコメントで気軽に教えていただけるとありがたいです。