mirror of
https://github.com/RSS-Bridge/rss-bridge.git
synced 2025-02-16 23:29:56 +03:00
[SpotifyBridge] Add playlists feed (#3116)
* [SpotifyBridge] Add playlists feed * fix formatting * remove whitespace * merge artist and playlist feeds * fix lint errors
This commit is contained in:
parent
314d4c7a3f
commit
bef6fc5cbd
1 changed files with 128 additions and 69 deletions
|
@ -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'] = '<img style="width: 256px" src="'
|
||||
. $album['images'][0]['url']
|
||||
. '">';
|
||||
|
||||
if ($album['total_tracks'] > 1) {
|
||||
$item['content'] .= '<p>Total tracks: '
|
||||
. $album['total_tracks']
|
||||
. '</p>';
|
||||
}
|
||||
|
||||
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'] = '<img style="width: 256px" src="'
|
||||
. $track['track']['album']['images'][0]['url']
|
||||
. '">';
|
||||
|
||||
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'] = '<img style="width: 256px" src="'
|
||||
. $album['images'][0]['url']
|
||||
. '">';
|
||||
|
||||
if ($album['total_tracks'] > 1) {
|
||||
$item['content'] .= '<p>Total tracks: '
|
||||
. $album['total_tracks']
|
||||
. '</p>';
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue