diff --git a/bridges/SpotifyBridge.php b/bridges/SpotifyBridge.php new file mode 100644 index 00000000..298fd3d8 --- /dev/null +++ b/bridges/SpotifyBridge.php @@ -0,0 +1,238 @@ + array( + 'name' => 'Client ID', + 'type' => 'text', + 'required' => true + ), + 'clientsecret' => array( + 'name' => 'Client secret', + 'type' => 'text', + 'required' => true + ), + 'spotifyuri' => array( + 'name' => 'Spotify URIs', + 'type' => 'text', + 'required' => true, + 'exampleValue' => 'spotify:artist:4lianjyuR1tqf6oUX8kjrZ [,spotify:artist:3JsMj0DEzyWc0VDlHuy9Bx]', + ), + 'albumtype' => array( + 'name' => 'Album type', + 'type' => 'text', + 'required' => false, + 'exampleValue' => 'album,single,appears_on,compilation', + 'defaultValue' => 'album,single' + ), + 'country' => array( + '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/'; + + private $uri = ''; + private $name = ''; + private $token = ''; + private $artists = array(); + private $albums = array(); + + public function getURI() { + if(empty($this->uri)) + $this->getArtist(); + + return $this->uri; + } + + public function getName() { + if(empty($this->name)) + $this->getArtist(); + + return $this->name; + } + + public function getIcon() { + return 'https://www.scdn.co/i/_global/favicon.png'; + } + + private function getId($artist) { + return explode(':', $artist)[2]; + } + + private function getDate($album_date) { + if(strlen($album_date) == 4) + $album_date .= '-01-01'; + elseif(strlen($album_date) == 7) + $album_date .= '-01'; + + return DateTime::createFromFormat('Y-m-d', $album_date)->getTimestamp(); + } + + private function getAlbumType() { + return $this->getInput('albumtype'); + } + + private function getCountry() { + return $this->getInput('country'); + } + + private function getToken() { + $cacheFac = new CacheFactory(); + $cacheFac->setWorkingDir(PATH_LIB_CACHES); + $cache = $cacheFac->create(Configuration::getConfig('cache', 'type')); + $cache->setScope(get_called_class()); + $cache->setKey(array('token')); + + if($cache->getTime()) { + $time = (new DateTime)->getTimestamp() - $cache->getTime(); + Debug::log('Token time: ' . $time); + } + + if($cache->getTime() == false || $time >= 3600) { + Debug::log('Fetching token from Spotify'); + $this->fetchToken(); + $cache->saveData($this->token); + } else { + Debug::log('Loading token from cache'); + $this->token = $cache->loadData(); + } + + Debug::log('Token: ' . $this->token); + } + + private function getArtist() { + 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'; + } else { + $this->uri = parent::getURI(); + $this->name = parent::getName(); + } + } + + private function getAllArtists() { + Debug::log('Parsing all artists'); + $this->artists = explode(',', $this->getInput('spotifyuri')); + } + + private function getAllAlbums() { + $this->albums = array(); + + $this->getAllArtists(); + + Debug::log('Fetching all albums'); + foreach($this->artists as $artist) { + $fetch = true; + $offset = 0; + + while($fetch) { + $partial_albums = $this->fetchContent(self::APIURI . 'artists/' + . $this->getId($artist) + . '/albums?limit=50&include_groups=' + . $this->getAlbumType() + . '&country=' + . $this->getCountry() + . '&offset=' + . $offset); + + if(!empty($partial_albums['items'])) + $this->albums = array_merge($this->albums, + $partial_albums['items']); + else + $fetch = false; + + $offset += 50; + } + } + } + + private function fetchToken() { + $curl = curl_init(); + + curl_setopt($curl, CURLOPT_URL, self::TOKENURI); + curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($curl, CURLOPT_POST, 1); + curl_setopt($curl, CURLOPT_POSTFIELDS, 'grant_type=client_credentials'); + curl_setopt($curl, CURLOPT_HTTPHEADER, array('Authorization: Basic ' + . base64_encode($this->getInput('clientid') + . ':' + . $this->getInput('clientsecret')))); + + $json = curl_exec($curl); + $json = json_decode($json)->access_token; + curl_close($curl); + + $this->token = $json; + } + + private function fetchContent($url) { + $this->getToken(); + $curl = curl_init(); + + curl_setopt($curl, CURLOPT_URL, $url); + curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($curl, CURLOPT_HTTPHEADER, array('Authorization: Bearer ' + . $this->token)); + + Debug::log('Fetching content from ' . $url); + $json = curl_exec($curl); + $json = json_decode($json, true); + curl_close($curl); + + return $json; + } + + private function sortAlbums() { + Debug::log('Sorting albums'); + usort($this->albums, function($album1, $album2) { + if($this->getDate($album1['release_date']) < $this->getDate($album2['release_date'])) + return 1; + else + return -1; + }); + } + + public function collectData() { + $offset = 0; + + $this->getAllAlbums(); + $this->sortAlbums(); + + Debug::log('Building RSS feed'); + foreach($this->albums as $album) { + $item = array(); + $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'] = array($album['album_type']); + + $item['content'] = ''; + + if($album['total_tracks'] > 1) + $item['content'] .= '

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

'; + + $this->items[] = $item; + + if(count($this->items) >= 10) + break; + } + } +}