-
-
Save jahir07/27d0ab5891131a3ff7b9221fd5265109 to your computer and use it in GitHub Desktop.
This is an idea to create a playlist from an Icecast server storing the songdata and cover image into a database.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Class IceCastPlaylist | |
* See https://stackoverflow.com/questions/60502076/how-to-get-icecast-server-songs-history/60798774#60798774 for context | |
* | |
* This class can be used as follows: | |
* global $wpdb | |
* $playlistClass = new IceCastPlaylist($wpdb); | |
* $playlistClass->fetchSongInfo(); | |
* $playlist = $songInfoClass->getPlaylist(); | |
* header('Content-Type: application/json;charset=utf-8'); | |
* echo $playlist; | |
* die(); | |
*/ | |
class IceCastPlaylist { | |
/** | |
* @var wpdb | |
*/ | |
protected $db; | |
/** | |
* @var string | |
*/ | |
protected $table = '[replace with playlist table]'; | |
/** | |
* Replace this with your server URL | |
* @var string | |
*/ | |
protected $songDataUrl = 'https://serveraddress:portnumber/stream.xspf'; | |
/** | |
* @var string | |
*/ | |
protected $albumCoverUrl = 'https://itunes.apple.com/search?entity=musicTrack&term='; | |
/** | |
* Replace this with your storage path | |
* @var string | |
*/ | |
protected $albumCoverPath = '[absolute_path_to_cover_images_folder e.g /media/covers/]'; | |
/** | |
* Replace with your site URL | |
* Most of the time you will want to set the URL to the site dynamically, | |
* so we do this in the constructor | |
*/ | |
protected $siteUrl = ''; | |
/** | |
* Replace this with the desired length of your playlist | |
* @var int | |
*/ | |
protected $playlistLength = 20; | |
/** | |
* IceCastPlaylist constructor. | |
* In this case, I used WordPress wpdb, but it can be replaced with another DB instance | |
* When using something else than wpdb, the query functions will need to be adjusted | |
* | |
* @param $db | |
*/ | |
public function __construct(wpdb $db) { | |
$this->db = $db; | |
// If you need to set the site URL via a function, you can set it here in the constructor | |
$this->siteUrl = get_site_url() . '/wp-content/media/covers/'; | |
} | |
public function getPlaylist() { | |
$result = $this->db->get_results("SELECT * FROM {$this->table} as songs ORDER BY `songs`.`id` DESC LIMIT {$this->playlistLength}"); | |
return json_encode($result); | |
} | |
/** | |
* [ | |
* 'playedat' => 'H:i', | |
* 'title' => 'title', | |
* 'artist' => 'bla', | |
* 'coverImage' => 'linkToCoverArt', | |
* 'created_at' => 'Y-m-d', | |
* ] | |
* @param array $entry | |
*/ | |
public function storeEntry(array $entry) { | |
$this->db->insert($this->table, $entry); | |
} | |
/** | |
* @return mixed | |
* @throws Exception | |
*/ | |
public function fetchSongInfo() { | |
$rawData = file_get_contents($this->songDataUrl); | |
$now = new DateTime('now'); | |
if(!$rawData) { | |
throw new Exception('Error retrieving song data'); | |
} | |
$xml = new SimpleXMLElement($rawData); | |
$titleArtist = preg_split("/\s-\s/", (string) $xml->trackList->track->title); | |
if($this->isNewSong($titleArtist[1])) { | |
$stream['playedAt'] = $now->format('H:i'); | |
$stream['title'] = $titleArtist[1]; | |
$stream['artist'] = $titleArtist[0]; | |
$stream['coverImage'] = $this->getCoverArt($xml->trackList->track->title); | |
$stream['created_at'] = $now->format('Y-m-d H:i:s'); | |
$this->storeEntry($stream); | |
} | |
} | |
/** | |
* Use in your daily cleanup cron | |
*/ | |
public function dailyCleanup() { | |
$this->db->query("TRUNCATE TABLE {$this->table}"); | |
} | |
/** | |
* @param string $title | |
* | |
* @return bool | |
*/ | |
private function isNewSong(string $title) { | |
$result = $this->db->get_results("SELECT * FROM {$this->table} as songs ORDER BY `songs`.`id` DESC LIMIT 1"); | |
if(empty($result)) { | |
return true; | |
} | |
return $result[0]->title !== $title; | |
} | |
/** | |
* Take the raw 'songtitle - artist' and try to find cover art | |
* @param string $title | |
* | |
* @return string|null | |
*/ | |
private function getCoverArt(string $title) { | |
$itunesData = wp_remote_get($this->albumCoverUrl . urlencode($title), array( | |
'timeout' => 45, | |
'redirection' => 5, | |
'httpversion' => '1.0', | |
'blocking' => true, | |
'headers' => array( | |
'accept-encoding' => 'gzip, deflate, br', | |
'pragma' => 'no-cache', | |
'accept-language' => 'en-US,en;q=0.8', | |
'user-agent' => 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.101 Safari/537.36', | |
'accept' => 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8' | |
), | |
'cookies' => array(), | |
)); | |
$songInfo = json_decode(trim(wp_remote_retrieve_body($itunesData))); | |
$imageHash = ''; | |
if(isset($songInfo->results[0])) { | |
$coverImage = str_replace('100x100bb.jpg', '', $songInfo->results[0]->artworkUrl100); | |
$imageHash = md5($title) . '.jpg'; | |
if(!file_exists($this->albumCoverPath . $imageHash) && $coverImage !== '') { | |
$img = file_get_contents($coverImage . '200x200bb.jpg'); | |
file_put_contents($this->albumCoverPath . $imageHash, $img); | |
} | |
} | |
return (empty($imageHash)) ? null : $this->siteUrl . $imageHash; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment