From 107991518331c951663dcfb0a50db3e7827c191b Mon Sep 17 00:00:00 2001 From: vicholp Date: Mon, 11 Dec 2023 03:12:28 -0300 Subject: [PATCH] feat: add tracks in order --- app/Http/Resources/ReleaseResource.php | 2 +- app/Models/Track.php | 2 + app/Services/Api/MusicBrainzService.php | 29 +++++++++++++ app/Services/SynchronizationService.php | 41 +++++++++++-------- ...050006_add_mb_track_id_to_tracks_table.php | 27 ++++++++++++ resources/js/components/album.vue | 2 +- resources/js/store/player/actions.js | 25 ++++++++--- 7 files changed, 102 insertions(+), 26 deletions(-) create mode 100644 database/migrations/2023_12_11_050006_add_mb_track_id_to_tracks_table.php diff --git a/app/Http/Resources/ReleaseResource.php b/app/Http/Resources/ReleaseResource.php index 8b5d1cc..a4831ae 100644 --- a/app/Http/Resources/ReleaseResource.php +++ b/app/Http/Resources/ReleaseResource.php @@ -18,7 +18,7 @@ public function toArray($request): array return [ 'id' => $this->id, 'title' => $this->title, - 'tracks' => new TrackCollection($this->tracks->load('release')), + 'tracks' => new TrackCollection($this->tracks->load('release')->sortBy('track_position')), 'art' => $this->artUrl(), ]; } diff --git a/app/Models/Track.php b/app/Models/Track.php index c9fcd68..3c932f7 100644 --- a/app/Models/Track.php +++ b/app/Models/Track.php @@ -83,6 +83,8 @@ class Track extends Model 'mb_recording_id', 'title', 'mb_data', + 'track_position', + 'mb_track_id', ]; /** diff --git a/app/Services/Api/MusicBrainzService.php b/app/Services/Api/MusicBrainzService.php index 41edd59..d5782cf 100644 --- a/app/Services/Api/MusicBrainzService.php +++ b/app/Services/Api/MusicBrainzService.php @@ -20,6 +20,35 @@ private function getHttp(): PendingRequest return Http::withHeaders(['User-Agent' => 'Spotifynt/dev (hello@vicho.dev)']); } + public function getTrack(string $releaseId, string $trackId): array|false + { + // $cache = Cache::get('mb_track_' . $trackId); + + // if ($cache) { + // return $cache; + // } + + $release = $this->getRelease($releaseId); + + $medias = $release['media']; + + foreach ($medias as $media) { + $tracks = $media['tracks']; + + foreach ($tracks as $track) { + if ($track['id'] == $trackId) { + // Cache::put('mb_track_' . $trackId, $track); + + return $track; + } + } + } + + + + return false; + } + public function getRecording(string $id): array { $cache = Cache::get('mb_recording_' . $id); diff --git a/app/Services/SynchronizationService.php b/app/Services/SynchronizationService.php index 05a0f74..6026e8d 100644 --- a/app/Services/SynchronizationService.php +++ b/app/Services/SynchronizationService.php @@ -24,19 +24,6 @@ public function __construct( // } - private function searchRecordingInRelease(Release $release, string $id): array|false - { - $data = json_decode($release->mb_data, true)['media'][0]['tracks']; - - foreach ($data as $track) { - if ($track['recording']['id'] == $id) { - return $track; - } - } - - return false; - } - public function syncServer(Server $server): void { $beets = new BeetsService($server); @@ -80,7 +67,7 @@ public function syncAlbumFromBeets(BeetsService $beets, Server $server, string $ SyncArtJob::dispatch($release, $server)->onQueue('low'); foreach ($beets_tracks as $beets_track) { - $track = $this->syncTrack($release, $beets_track['mb_trackid']); + $track = $this->syncTrack($release, $beets_track['mb_releasetrackid']); $server->tracks()->attach($track, [ 'path' => $beets_track['path'], 'beets_id' => $beets_track['id'], @@ -88,16 +75,34 @@ public function syncAlbumFromBeets(BeetsService $beets, Server $server, string $ } } - public function syncTrack(Release $release, string $id): Track + public function syncTrack(Release $release, string $trackId): Track { - $recording = $this->musicBrainzService->getRecording($id); + $mbTrack = $this->musicBrainzService->getTrack($release->mb_release_id, $trackId); + $recordingId = $mbTrack['recording']['id']; + + $recording = $this->musicBrainzService->getRecording($recordingId); + + $track = Track::whereMbRecordingId($recordingId) + ->whereMbTrackId(null)->first(); + + if ($track) { + $track->update([ + 'mb_track_id' => $mbTrack['id'], + 'mb_data' => json_encode($mbTrack), + ]); + + + return $track; + } $track = Track::updateOrCreate([ - 'mb_recording_id' => $recording['id'], + 'mb_track_id' => $mbTrack['id'], ], [ 'title' => $recording['title'], + 'track_position' => $mbTrack['position'], 'release_id' => $release->id, - 'mb_data' => json_encode($recording), + 'mb_recording_id' => $recordingId, + 'mb_data' => json_encode($mbTrack), ]); return $track; diff --git a/database/migrations/2023_12_11_050006_add_mb_track_id_to_tracks_table.php b/database/migrations/2023_12_11_050006_add_mb_track_id_to_tracks_table.php new file mode 100644 index 0000000..fa87d20 --- /dev/null +++ b/database/migrations/2023_12_11_050006_add_mb_track_id_to_tracks_table.php @@ -0,0 +1,27 @@ +string('mb_track_id', 500)->nullable(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('tracks', function (Blueprint $table) { + $table->dropColumn('mb_track_id'); + }); + } +}; diff --git a/resources/js/components/album.vue b/resources/js/components/album.vue index 95726f1..2ece7c3 100644 --- a/resources/js/components/album.vue +++ b/resources/js/components/album.vue @@ -36,7 +36,7 @@ export default { }, methods: { addAlbum(albumId) { - this.playerStore.playlistAddAlbum(albumId); + this.playerStore.playlistAddRelease(albumId); }, }, }; diff --git a/resources/js/store/player/actions.js b/resources/js/store/player/actions.js index ee524ef..2318cf2 100644 --- a/resources/js/store/player/actions.js +++ b/resources/js/store/player/actions.js @@ -21,15 +21,28 @@ export default { this.playlistAddTrack(track); }, - async playlistAddAlbum(albumId) { - const album = (await ReleaseApi.show(albumId)).data.data; + async playlistAddRelease(releaseId) { + const release = (await ReleaseApi.show(releaseId)).data.data; + const serverStore = ServerStore(); + const serverId = serverStore.activeServer.id; - album.tracks.forEach(track => { - this.playlistAddTrackById(track.id); - }); + // first add the first track to the playlist, + // for performance reasons + let firstTrackId = release.tracks[0].id; + this.playlistAddTrack( + (await ServerTrackApi.show(serverId, firstTrackId)).data.data, + ); + + // then add the rest of the tracks in a async loop + for (let i = 1; i < release.tracks.length; i++) { + let track = release.tracks[i]; + this.playlistAddTrack( + (await ServerTrackApi.show(serverId, track.id)).data.data, + ); + } const messagesStore = MessagesStore(); - messagesStore.addedTracks(album.tracks.length); + messagesStore.addedTracks(release.tracks.length); }, async playlistSetIndex(int, relative) {