[SpotifyBridge] Add podcasts feed (#3329)

Co-authored-by: Matteo Parolin <matteoparolin99@gmail.com>
This commit is contained in:
Paroleen 2023-03-24 20:34:51 +01:00 committed by GitHub
parent 249133204e
commit 8486c0f8ca
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -4,7 +4,7 @@ class SpotifyBridge extends BridgeAbstract
{ {
const NAME = 'Spotify'; const NAME = 'Spotify';
const URI = 'https://spotify.com/'; const URI = 'https://spotify.com/';
const DESCRIPTION = 'Fetches the latest albums from one or more artists or the latest tracks from one or more playlists'; const DESCRIPTION = 'Fetches the latest items from one or more artists, playlists or podcasts';
const MAINTAINER = 'Paroleen'; const MAINTAINER = 'Paroleen';
const CACHE_TIMEOUT = 3600; const CACHE_TIMEOUT = 3600;
const PARAMETERS = [ [ const PARAMETERS = [ [
@ -19,7 +19,7 @@ class SpotifyBridge extends BridgeAbstract
'required' => true 'required' => true
], ],
'country' => [ 'country' => [
'name' => 'Country', 'name' => 'Country/Market',
'type' => 'text', 'type' => 'text',
'required' => false, 'required' => false,
'exampleValue' => 'US', 'exampleValue' => 'US',
@ -36,7 +36,7 @@ class SpotifyBridge extends BridgeAbstract
'name' => 'Spotify URIs', 'name' => 'Spotify URIs',
'type' => 'text', 'type' => 'text',
'required' => true, 'required' => true,
'exampleValue' => 'spotify:artist:4lianjyuR1tqf6oUX8kjrZ [,spotify:playlist:37i9dQZF1DXcBWIGoYBM5M]', 'exampleValue' => 'spotify:artist:4lianjyuR1tqf6oUX8kjrZ [,spotify:playlist:37i9dQZF1DXcBWIGoYBM5M,spotify:show:6ShFMYxeDNMo15COLObDvC]',
], ],
'albumtype' => [ 'albumtype' => [
'name' => 'Album type', 'name' => 'Album type',
@ -47,8 +47,18 @@ class SpotifyBridge extends BridgeAbstract
] ]
] ]; ] ];
const TOKENURI = 'https://accounts.spotify.com/api/token'; const TOKEN_URI = 'https://accounts.spotify.com/api/token';
const APIURI = 'https://api.spotify.com/v1/'; const API_URI = 'https://api.spotify.com/v1/';
const TYPE_ALBUM = 'artist';
const TYPE_PLAYLIST = 'playlist';
const TYPE_PODCAST = 'show';
const ENTRY_ALBUM = 'album';
const ENTRY_PLAYLIST = 'track';
const ENTRY_PODCAST = 'episode';
const NOT_SUPPORTED = 'Spotify URI not supported';
private $uri = ''; private $uri = '';
private $name = ''; private $name = '';
@ -89,14 +99,31 @@ class SpotifyBridge extends BridgeAbstract
return explode(':', $uri)[2]; return explode(':', $uri)[2];
} }
private function getEntryType($type)
{
$entry_types = [
self::TYPE_ALBUM => self::ENTRY_ALBUM,
self::TYPE_PLAYLIST => self::ENTRY_PLAYLIST,
self::TYPE_PODCAST => self::ENTRY_PODCAST,
];
if (isset($entry_types[$type])) {
return $entry_types[$type];
} else {
throw new \Exception(self::NOT_SUPPORTED);
}
}
private function getDate($entry) private function getDate($entry)
{ {
if ($entry['type'] === 'album') { if (isset($entry['type'])) {
$date = $entry['release_date']; $type = 'release_date';
} else { } else {
$date = $entry['added_at']; $type = 'added_at';
} }
$date = $entry[$type];
if (strlen($date) == 4) { if (strlen($date) == 4) {
$date .= '-01-01'; $date .= '-01-01';
} elseif (strlen($date) == 7) { } elseif (strlen($date) == 7) {
@ -148,9 +175,15 @@ class SpotifyBridge extends BridgeAbstract
private function getFirstEntry() private function getFirstEntry()
{ {
if (!is_null($this->getInput('spotifyuri')) && strpos($this->getInput('spotifyuri'), ',') === false) { if (!is_null($this->getInput('spotifyuri')) && strpos($this->getInput('spotifyuri'), ',') === false) {
$type = $this->getUriType($this->uris[0]) . 's'; $type = $this->getUriType($this->uris[0]);
$item = $this->fetchContent(self::APIURI . $type . '/' $uri = self::API_URI . $type . 's/' . $this->getId($this->uris[0]);
. $this->getId($this->uris[0]));
if ($type === self::TYPE_PODCAST) {
$uri = $uri . '?market=' . $this->getCountry();
}
$item = $this->fetchContent($uri);
$this->uri = $item['external_urls']['spotify']; $this->uri = $item['external_urls']['spotify'];
$this->name = $item['name'] . ' - Spotify'; $this->name = $item['name'] . ' - Spotify';
} else { } else {
@ -173,19 +206,20 @@ class SpotifyBridge extends BridgeAbstract
Debug::log('Fetching all entries'); Debug::log('Fetching all entries');
foreach ($this->uris as $uri) { foreach ($this->uris as $uri) {
$type = $this->getUriType($uri) . 's'; $type = $this->getUriType($uri);
$entry_type = $type === 'artists' ? 'albums' : 'tracks'; $entry_type = $this->getEntryType($type);
$fetch = true; $fetch = true;
$offset = 0; $offset = 0;
$api_url = self::APIURI . $type . '/' $api_url = self::API_URI . $type . 's/'
. $this->getId($uri) . $this->getId($uri)
. '/' . $entry_type . '/' . $entry_type
. '?limit=50&country=' . 's?limit=50';
. $this->getCountry();
if ($type === 'artists') { if ($type === self::TYPE_ALBUM) {
$api_url = $api_url . '&include_groups=' . $this->getAlbumType(); $api_url = $api_url . '&country=' . $this->getCountry() . '&include_groups=' . $this->getAlbumType();
} else {
$api_url = $api_url . '&market=' . $this->getCountry();
} }
while ($fetch) { while ($fetch) {
@ -211,7 +245,7 @@ class SpotifyBridge extends BridgeAbstract
{ {
$curl = curl_init(); $curl = curl_init();
curl_setopt($curl, CURLOPT_URL, self::TOKENURI); curl_setopt($curl, CURLOPT_URL, self::TOKEN_URI);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_POST, 1); curl_setopt($curl, CURLOPT_POST, 1);
curl_setopt($curl, CURLOPT_POSTFIELDS, 'grant_type=client_credentials'); curl_setopt($curl, CURLOPT_POSTFIELDS, 'grant_type=client_credentials');
@ -298,6 +332,33 @@ class SpotifyBridge extends BridgeAbstract
return $item; return $item;
} }
private function getEpisodeData($episode)
{
$item = [];
$item['title'] = $episode['name'];
$item['uri'] = $episode['external_urls']['spotify'];
$item['timestamp'] = $this->getDate($episode);
$item['content'] = '<img style="width: 256px" src="'
. $episode['images'][0]['url']
. '">';
if (isset($episode['description'])) {
$item['content'] = $item['content'] . '<p>'
. $episode['description']
. '</p>';
}
if (isset($episode['audio_preview_url'])) {
$item['content'] = $item['content'] . '<audio controls src="'
. $episode['audio_preview_url']
. '"></audio>';
}
return $item;
}
public function collectData() public function collectData()
{ {
$offset = 0; $offset = 0;
@ -307,10 +368,14 @@ class SpotifyBridge extends BridgeAbstract
Debug::log('Building RSS feed'); Debug::log('Building RSS feed');
foreach ($this->entries as $entry) { foreach ($this->entries as $entry) {
if ($entry['type'] === 'album') { if (! isset($entry['type'])) {
$item = $this->getAlbumData($entry);
} else {
$item = $this->getTrackData($entry); $item = $this->getTrackData($entry);
} else if ($entry['type'] === self::ENTRY_ALBUM) {
$item = $this->getAlbumData($entry);
} else if ($entry['type'] === self::ENTRY_PODCAST) {
$item = $this->getEpisodeData($entry);
} else {
throw new \Exception(self::NOT_SUPPORTED);
} }
$this->items[] = $item; $this->items[] = $item;