🎧

Spotifyで再生回数が1番多かった曲を共有する

2021/12/12に公開

こんにちは、11月に入社したかべです。

これはCAMPFIRE Advent Calendar 2021の12日目の記事です。

去年に比べて今年のアドベントカレンダーは業務に関係したものが多い…!
しかし入社したてでネタがない…!
なのでプライベートの開発を書きます!

音楽好きですか?

僕は好きです。

Spotifyは毎年12月になるとSpotifyまとめと題してユーザーの1年を振り返るプレイリストを公開してくれます!
嬉しい!

毎年これが楽しみなんですがもっと頻度高めに振り返りたい!
そんなわけでLast.fmと連携してログを取っています。
※連携することで日付を区切ってトップアーティストやトップトラックを確認することができます。

Twitterには音楽好きで繋がっているフォロワーの方が多いので、直近7日間で1番再生数が多かった曲を「今週聴いていた曲」としてTwitterに投稿し続けています。

遡ったら2年いかないぐらい続けてるみたいで、最初のツイートはこれでした。

今回はそれをコマンド1つで実行できるようにしていきます。

やりたいこと

具体的には

  1. Last.fmで人気のトラックを確認
  2. Spotifyから該当トラックのシェアURLを取得
  3. ツリーとして繋げるため固定ツイート(前回のツイート)のidを取得
  4. 文言を整えてツリーにする形で投稿
  5. 投稿したツイートを固定する

をコマンド1つで実行したい。

作ってみる

作りました。
waaaaall/this-week-listend-music

使ったものはざっくりこの辺り。

  • PHP
  • Last.fm Music Discovery API
  • Spotify Web APi
  • Twitter API v2

ちなみに5のツイート固定はAPIが公開されておらず…。
手動で対応するしかなさそうでした、残念。

コード全体

index.php
<?php
require 'vendor/autoload.php';

use Dotenv\Dotenv;
use GuzzleHttp\Client;
use SpotifyWebAPI\Session;
use SpotifyWebAPI\SpotifyWebAPI;
use Abraham\TwitterOAuth\TwitterOAuth;

$env = Dotenv::createImmutable(__DIR__);
$env->load();

// lastfmからtoptrackの取得
$client = new Client();
$params = [
    'query' =>
    [
        'method' => 'user.gettoptracks',
        'user' => $_ENV['LASTFM_USER'],
        'api_key' => $_ENV['LASTFM_API_KEY'],
        'period' => '7day',
        'limit' => 1,
        'format' => 'json'
    ]
];

$response = $client->request('get', 'http://ws.audioscrobbler.com/2.0', $params);
$response = $response->getBody()->getContents();
$response = json_decode($response);

$track = $response->toptracks->track[0]->name;
$artist = $response->toptracks->track[0]->artist->name;

$query = '"' . $track . '" ' . '"' . $artist . '"';

//spotifyでトラック情報の取得
$session = new Session(
    $_ENV['SPOTIFY_CLIENT_ID'],
    $_ENV['SPOTIFY_CLIENT_SECRET'],
);

$spotify = new SpotifyWebAPI();
$session->requestCredentialsToken();
$accessToken = $session->getAccessToken();
$spotify->setAccessToken($accessToken);

$result = $spotify->search($query, 'track', ['limit' => 1]);
$artist = $result->tracks->items[0]->artists[0]->name;
$track = $result->tracks->items[0]->name;
$url = $result->tracks->items[0]->external_urls->spotify;

//ツイートする
$twitter = new TwitterOAuth(
    $_ENV['TWITTER_API_KEY'],
    $_ENV['TWITTER_API_SCT'],
    $_ENV['TWITTER_ACCESS_TOKEN'],
    $_ENV['TWITTER_ACCESS_SECRET']
);

$twitter->setApiVersion('2');
$twitter->get('users', ['ids' => $_ENV['TWITTER_USER_ID'], 'expansions' => 'pinned_tweet_id']);
if ($twitter->getLastHttpCode() == 200) {
    $pinned_id = $twitter->getLastBody()->data[0]->pinned_tweet_id;
} else {
    exit();
}

$text = $track . ' by ' . $artist . ' ' . $url . '
今週聴いていた曲です';

$twitter->post(
    'tweets',
    [
        'text' => $text,
        'reply' => ['in_reply_to_tweet_id' => $pinned_id]
    ],
    true
);
if ($twitter->getLastHttpCode() === 201) {
    $tweet_id = $twitter->getLastBody()->data->id;
    echo "success! https://twitter.com/good_wall/status/$tweet_id\n";
} else {
    echo 'failed!';
}

どこからでも実行が出来るようaliasに登録します。

.bashrc
# 今週聴いていた曲
alias twlm='php ~/github/this-week-listend-music/index.php'

実行してみる

成功するとツイートのURLが表示されます。

実際に投稿されたのがこちら。

ちゃんと投稿されてますね!

後はツイートを固定してあげれば終わり!

工夫したこと

SpotifyのSearch API

Spotifyでの楽曲検索時でアーティスト名とトラック名の双方から絞り込みたかったんですがキーワードに対して

  • アーティストの検索結果
  • トラックの検索結果

をそれぞれ返してくる形だったので

  • トラックの検索結果の内、一致するアーティスト名のトラックを該当トラックとする

ようにしています。
あと日本語(マルチバイト)の検索のためにクエリを何度か調整したりしてました。

今後やっていきたいこと

共有するURLの種類を増やす

手動で投稿していたときは共有する際にYouTubeに動画があればそっちを優先していたんですが、今はSpotify一択なんで選べるようにしたい。
Spotifyだと未会員はショートしか聴けないのでフルで聴けるであろうYouTubeを優先してた感じです。
とはいえ公式が投稿していない場合は権利的に共有したくないのでその辺の判別が厄介そう。(自分で投稿してたときは普通に探せるけどYouTube APIとかだとどうなんだろう)

同じ曲を投稿しないための重複チェック

そもそも投稿の目的が「自分のログ兼フォロワーへの楽曲紹介」を兼ねているので、なるべく同じ曲を投稿しないようにしたいんですよね。
数ヶ月前に投稿してたものとかであればいいんですが、極稀に2週間連続で同じ曲をヘビロテすることがあるので、そういった場合は2番目に再生回数が多い曲を対象にできるようにしたいですね。

作業の自動化

毎週末に投稿してるものなので定期的に実行してもらおうと思ったんですが、作っただけで満足しちゃいました。
先述したやりたいことを含んだ上で1回Slack,Discord辺りを挟んで、

  • 共有するURLはYouTubeとSpotifyどっち?
  • 同じ曲だから2番目の曲にする?

とか選択できると色々良さそう。

技術周りの動機等ですが、

  • Spotify Web API
    触ってみたかった。
    ちなみにSpotifyにもTop Itemsみたいな形で再生回数の多い曲を取得するAPIがあるんですが、期間の指定がshort(4週間),medium(6ヶ月),long(全期間)で扱いづらく、これまで通りLast.fmを使うことにしました。

  • Twitter API
    つい先月v2を正式に主要APIとして提供始めたので触っておきたかった。
    固定ツイート周りはv2で提供されるようになったのでタイミングが良かった。

また主題には関係ないんですが、メインのWindowsを新調してから開発環境作ってなかったので丁度いい機会だと思いWSL2環境構築から始めてみました。
ざっくり環境構築1日、開発半日ぐらいでした。

最後に

CAMPFIREでは日々様々なプロジェクトが公開されています!
もちろん音楽のプロジェクトも!

CAMPFIREのアドベントカレンダーはまだまだ続きます!
他の記事もぜひ読んでみてください~!

参考

https://blog.geckour.com/posts/2020/0603-play-with-spotify-api/

Discussion