diff --git a/bridges/SpotifyBridge.php b/bridges/SpotifyBridge.php index b3204dfc..408239ca 100644 --- a/bridges/SpotifyBridge.php +++ b/bridges/SpotifyBridge.php @@ -4,7 +4,7 @@ class SpotifyBridge extends BridgeAbstract { const NAME = 'Spotify'; const URI = 'https://spotify.com/'; - const DESCRIPTION = 'Fetches the latest ten albums from one or more artists'; + const DESCRIPTION = 'Fetches the latest albums from one or more artists or the latest tracks from one or more playlists'; const MAINTAINER = 'Paroleen'; const CACHE_TIMEOUT = 3600; const PARAMETERS = [ [ @@ -18,11 +18,25 @@ class SpotifyBridge extends BridgeAbstract 'type' => 'text', 'required' => true ], + 'country' => [ + 'name' => 'Country', + 'type' => 'text', + 'required' => false, + 'exampleValue' => 'US', + 'defaultValue' => 'US' + ], + 'limit' => [ + 'name' => 'Limit', + 'type' => 'number', + 'required' => false, + 'exampleValue' => 10, + 'defaultValue' => 10 + ], 'spotifyuri' => [ 'name' => 'Spotify URIs', 'type' => 'text', 'required' => true, - 'exampleValue' => 'spotify:artist:4lianjyuR1tqf6oUX8kjrZ [,spotify:artist:3JsMj0DEzyWc0VDlHuy9Bx]', + 'exampleValue' => 'spotify:artist:4lianjyuR1tqf6oUX8kjrZ [,spotify:playlist:37i9dQZF1DXcBWIGoYBM5M]', ], 'albumtype' => [ 'name' => 'Album type', @@ -30,15 +44,8 @@ class SpotifyBridge extends BridgeAbstract 'required' => false, 'exampleValue' => 'album,single,appears_on,compilation', 'defaultValue' => 'album,single' - ], - 'country' => [ - 'name' => 'Country', - 'type' => 'text', - 'required' => false, - 'exampleValue' => 'US', - 'defaultValue' => 'US' ] - ]]; + ] ]; const TOKENURI = 'https://accounts.spotify.com/api/token'; const APIURI = 'https://api.spotify.com/v1/'; @@ -46,13 +53,13 @@ class SpotifyBridge extends BridgeAbstract private $uri = ''; private $name = ''; private $token = ''; - private $artists = []; - private $albums = []; + private $uris = []; + private $entries = []; public function getURI() { if (empty($this->uri)) { - $this->getArtist(); + $this->getFirstEntry(); } return $this->uri; @@ -61,7 +68,7 @@ class SpotifyBridge extends BridgeAbstract public function getName() { if (empty($this->name)) { - $this->getArtist(); + $this->getFirstEntry(); } return $this->name; @@ -72,20 +79,35 @@ class SpotifyBridge extends BridgeAbstract return 'https://www.scdn.co/i/_global/favicon.png'; } - private function getId($artist) + private function getUriType($uri) { - return explode(':', $artist)[2]; + return explode(':', $uri)[1]; } - private function getDate($album_date) + private function getId($uri) { - if (strlen($album_date) == 4) { - $album_date .= '-01-01'; - } elseif (strlen($album_date) == 7) { - $album_date .= '-01'; + return explode(':', $uri)[2]; + } + + private function getDate($entry) + { + if ($entry['type'] === 'album') { + $date = $entry['release_date']; + } else { + $date = $entry['added_at']; } - return DateTime::createFromFormat('Y-m-d', $album_date)->getTimestamp(); + if (strlen($date) == 4) { + $date .= '-01-01'; + } elseif (strlen($date) == 7) { + $date .= '-01'; + } + + if (strlen($date) > 10) { + return DateTime::createFromFormat('Y-m-d\TH:i:s\Z', $date)->getTimestamp(); + } + + return DateTime::createFromFormat('Y-m-d', $date)->getTimestamp(); } private function getAlbumType() @@ -123,50 +145,58 @@ class SpotifyBridge extends BridgeAbstract Debug::log('Token: ' . $this->token); } - private function getArtist() + private function getFirstEntry() { if (!is_null($this->getInput('spotifyuri')) && strpos($this->getInput('spotifyuri'), ',') === false) { - $artist = $this->fetchContent(self::APIURI . 'artists/' - . $this->getId($this->artists[0])); - $this->uri = $artist['external_urls']['spotify']; - $this->name = $artist['name'] . ' - Spotify'; + $type = $this->getUriType($this->uris[0]) . 's'; + $item = $this->fetchContent(self::APIURI . $type . '/' + . $this->getId($this->uris[0])); + $this->uri = $item['external_urls']['spotify']; + $this->name = $item['name'] . ' - Spotify'; } else { $this->uri = parent::getURI(); $this->name = parent::getName(); } } - private function getAllArtists() + private function getAllUris() { - Debug::log('Parsing all artists'); - $this->artists = explode(',', $this->getInput('spotifyuri')); + Debug::log('Parsing all uris'); + $this->uris = explode(',', $this->getInput('spotifyuri')); } - private function getAllAlbums() + private function getAllEntries() { - $this->albums = []; + $this->entries = []; - $this->getAllArtists(); + $this->getAllUris(); - Debug::log('Fetching all albums'); - foreach ($this->artists as $artist) { + Debug::log('Fetching all entries'); + foreach ($this->uris as $uri) { + $type = $this->getUriType($uri) . 's'; + $entry_type = $type === 'artists' ? 'albums' : 'tracks'; $fetch = true; $offset = 0; + $api_url = self::APIURI . $type . '/' + . $this->getId($uri) + . '/' . $entry_type + . '?limit=50&country=' + . $this->getCountry(); + + if ($type === 'artists') { + $api_url = $api_url . '&include_groups=' . $this->getAlbumType(); + } + while ($fetch) { - $partial_albums = $this->fetchContent(self::APIURI . 'artists/' - . $this->getId($artist) - . '/albums?limit=50&include_groups=' - . $this->getAlbumType() - . '&country=' - . $this->getCountry() + $partial = $this->fetchContent($api_url . '&offset=' . $offset); - if (!empty($partial_albums['items'])) { - $this->albums = array_merge( - $this->albums, - $partial_albums['items'] + if (!empty($partial['items'])) { + $this->entries = array_merge( + $this->entries, + $partial['items'] ); } else { $fetch = false; @@ -215,11 +245,11 @@ class SpotifyBridge extends BridgeAbstract return $json; } - private function sortAlbums() + private function sortEntries() { - Debug::log('Sorting albums'); - usort($this->albums, function ($album1, $album2) { - if ($this->getDate($album1['release_date']) < $this->getDate($album2['release_date'])) { + Debug::log('Sorting entries'); + usort($this->entries, function ($entry1, $entry2) { + if ($this->getDate($entry1) < $this->getDate($entry2)) { return 1; } else { return -1; @@ -227,36 +257,65 @@ class SpotifyBridge extends BridgeAbstract }); } + private function getAlbumData($album) + { + $item = []; + $item['title'] = $album['name']; + $item['uri'] = $album['external_urls']['spotify']; + + $item['timestamp'] = $this->getDate($album); + $item['author'] = $album['artists'][0]['name']; + $item['categories'] = [$album['album_type']]; + + $item['content'] = ''; + + if ($album['total_tracks'] > 1) { + $item['content'] .= '

Total tracks: ' + . $album['total_tracks'] + . '

'; + } + + return $item; + } + + private function getTrackData($track) + { + $item = []; + + $item['title'] = $track['track']['name']; + $item['uri'] = $track['track']['external_urls']['spotify']; + + $item['timestamp'] = $this->getDate($track); + $item['author'] = $track['track']['artists'][0]['name']; + $item['categories'] = ['track']; + + $item['content'] = ''; + + return $item; + } + public function collectData() { $offset = 0; - $this->getAllAlbums(); - $this->sortAlbums(); + $this->getAllEntries(); + $this->sortEntries(); Debug::log('Building RSS feed'); - foreach ($this->albums as $album) { - $item = []; - $item['title'] = $album['name']; - $item['uri'] = $album['external_urls']['spotify']; - - $item['timestamp'] = $this->getDate($album['release_date']); - $item['author'] = $album['artists'][0]['name']; - $item['categories'] = [$album['album_type']]; - - $item['content'] = ''; - - if ($album['total_tracks'] > 1) { - $item['content'] .= '

Total tracks: ' - . $album['total_tracks'] - . '

'; + foreach ($this->entries as $entry) { + if ($entry['type'] === 'album') { + $item = $this->getAlbumData($entry); + } else { + $item = $this->getTrackData($entry); } $this->items[] = $item; - if (count($this->items) >= 10) { + if ($this->getInput('limit') > 0 && count($this->items) >= $this->getInput('limit')) { break; } }