Initial commit.

This commit is contained in:
Markus Birth 2020-02-15 23:17:22 +01:00
commit 10ecf6477c
Signed by: mbirth
GPG Key ID: A9928D7A098C3A9A
6 changed files with 209 additions and 0 deletions

4
.htaccess Normal file
View File

@ -0,0 +1,4 @@
RewriteEngine on
#RewriteBase /BassDriveRSS
RewriteRule index.rss2$ genfeed.php?type=rss2

10
README.md Normal file
View File

@ -0,0 +1,10 @@
This is a script that fetches a directory listing from
[The BassDrive archives](http://archives.bassdrivearchive.com/)
and generates an RSS feed from the files located there.
It uses rsslogo.jpg for the RSS2 logo (max. 144x400px) and
biglogo.jpg for the iTunes logo (min. 1400x1400px). Also
intro.txt for the feed description.
Files' sizes are fetched via a HEAD request and cached. The
show length is calculated based upon assumed 128 kbps.

BIN
biglogo.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 286 KiB

189
genfeed.php Normal file
View File

@ -0,0 +1,189 @@
<?php
$baseUrl = 'https://rpi4.mbirth.de/electronicwarfare/';
$sourceUrl = 'http://archives.bassdrivearchive.com/6%20-%20Saturday/Electronic%20Warfare%20-%20The%20Overfiend/';
$src_data = file_get_contents($sourceUrl);
define('RFC_822', 'D, d M Y H:i:s T');
$dom = new DOMDocument();
$dom->loadHTML($src_data);
$anchors = $dom->getElementsByTagName('a');
$file_list = array();
foreach ($anchors as $anchor) {
$title = $anchor->nodeValue;
$href = $anchor->attributes->getNamedItem('href')->nodeValue;
if (substr($href, -4) !== '.mp3') {
continue;
}
$title = urldecode(substr($href, 0, -4)); // strip off ".mp3" file extension
$url = $sourceUrl . $href;
$file_list[$url] = trim($title);
}
unset($dom);
$namespaceURIs = [
'xmlns' => 'http://www.w3.org/2000/xmlns/',
'atom' => 'http://www.w3.org/2005/Atom',
'content' => 'http://purl.org/rss/1.0/modules/content/',
'itunes' => 'http://www.itunes.com/DTDs/Podcast-1.0.dtd',
'spotify' => 'http://www.spotify.com/ns/rss',
'psc' => 'https://podlove.org/simple-chapters/', // for chapter marks
'dcterms' => 'https://purl.org/dc/terms', // for validity periods
];
date_default_timezone_set('America/New_York');
$dom = new DOMDocument('1.0', 'utf-8');
$dom->formatOutput = true;
$root = $dom->createElement('rss');
$root->appendChild(new DOMAttr('version', '2.0'));
$root->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:atom', $namespaceURIs['atom']);
$root->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:content', $namespaceURIs['content']);
$root->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:itunes', $namespaceURIs['itunes']);
$root->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:spotify', $namespaceURIs['spotify']);
// $root->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:dcterms', $namespaceURIs['dcterms']);
$root->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:psc', $namespaceURIs['psc']);
$dom->appendChild($root);
$channel = $dom->createElement('channel');
$channel->appendChild($dom->createElement('title', 'Electronic Warfare'));
$channel->appendChild($dom->createElement('link', 'https://www.facebook.com/louis.overfiend'));
$channel->appendChild($dom->createElement('copyright', 'BassDrive.com / Louis Overfiend'));
$channel->appendChild($dom->createElement('itunes:author', 'BassDrive.com / Louis Overfiend'));
$atom_link = $dom->createElement('atom:link');
$atom_link->appendChild(new DOMAttr('href', $baseUrl . 'index.rss2'));
$atom_link->appendChild(new DOMAttr('rel', 'self'));
$atom_link->appendChild(new DOMAttr('type', 'application/rss+xml'));
$channel->appendChild($atom_link);
$channel->appendChild($dom->createElement('description', trim(str_replace('&', '&amp;', file_get_contents('intro.txt')))));
$channel->appendChild($dom->createElement('language', 'en-us'));
$image = $dom->createElement('image');
$image->appendChild($dom->createElement('url', $baseUrl . 'rsslogo.jpg')); // RSS spec says max. dimensions are 144x400
$image->appendChild($dom->createElement('title', 'Electronic Warfare'));
$image->appendChild($dom->createElement('link', 'https://www.facebook.com/louis.overfiend'));
$image->appendChild($dom->createElement('width', '144'));
$image->appendChild($dom->createElement('height', '144'));
$channel->appendChild($image);
$i_image = $dom->createElement('itunes:image');
$i_image->appendChild(new DOMAttr('href', $baseUrl . 'biglogo.jpg')); // Apple requires min.(!) size of 1400x1400, 1:1 aspect
$channel->appendChild($i_image);
$channel->appendChild($dom->createElement('lastBuildDate', date(RFC_822)));
$channel->appendChild($dom->createElement('docs', 'http://blogs.law.harvard.edu/tech/rss'));
$channel->appendChild($dom->createElement('generator', 'Handcrafted with love'));
$channel->appendChild($dom->createElement('managingEditor', 'markus@birth-online.de (Markus Birth)'));
$channel->appendChild($dom->createElement('webMaster', 'markus@birth-online.de (Markus Birth)'));
$channel->appendChild($dom->createElement('ttl', '60'));
$skipDays = $dom->createElement('skipDays');
$skipDays->appendChild($dom->createElement('day', 'Monday'));
$skipDays->appendChild($dom->createElement('day', 'Tuesday'));
$skipDays->appendChild($dom->createElement('day', 'Wednesday'));
$skipDays->appendChild($dom->createElement('day', 'Thursday'));
$skipDays->appendChild($dom->createElement('day', 'Friday'));
$skipDays->appendChild($dom->createElement('day', 'Sunday'));
$channel->appendChild($skipDays);
$i_cat = $dom->createElement('itunes:category');
$i_cat->appendChild(new DOMAttr('text', 'Music'));
$channel->appendChild($i_cat);
$channel->appendChild($dom->createElement('itunes:explicit', 'clean'));
$channel->appendChild($dom->createElement('itunes:complete', 'no')); // "yes" = show has ended, no further episodes
$channel->appendChild($dom->createElement('itunes:type', 'episodic')); // "serial" = to be consumed oldest to newest; "episodic" = can be consumed randomly
//$s_limit = $dom->createElement('spotify:limit');
//$s_limit->appendChild(new DOMAttr('recentCount', '3')); // At most this number of episodes appear in the client
//$channel->appendChild($s_limit);
//$channel->appendChild($dom->createElement('spotify:countryOfOrigin', 'us')); // set target market/territory by country, omit for "global"
$len_cache = array();
$cache_dirty = false;
if (file_exists('genfeed.cache')) {
$len_cache = json_decode(file_get_contents('genfeed.cache'), true);
}
function getSize($url)
{
global $len_cache, $cache_dirty;
if (isset($len_cache[$url])) {
return $len_cache[$url];
}
$context = stream_context_set_default(array(
'http' => array(
'method' => 'HEAD',
),
));
$headers = get_headers($url, 1);
$length = intval($headers['Content-Length']);
$len_cache[$url] = $length;
$cache_dirty = true;
return $length;
}
function getDuration($size)
{
// 70445111 Bytes = 01:13:22.80 = 73:22.80 = 4402.80 seconds (128 kb/s)
// 147530737 Bytes = 02:33:40.64 = 153:40.64 = 9220.64 seconds (128 kb/s)
$seconds = $size / (128000 / 8);
$hours = intdiv($seconds, 3600);
$seconds = $seconds % 3600;
$minutes = intdiv($seconds, 60);
$seconds = $seconds % 60;
return sprintf('%02d:%02d:%02d', $hours, $minutes, $seconds);
}
$latest_date = -1;
foreach ($file_list as $url => $title) {
$item = $dom->createElement('item');
$guid = $dom->createElement('guid', $url);
$guid->appendChild(new DOMAttr('isPermalink', 'true')); // guid is a static URL
$item->appendChild($guid);
$item->appendChild($dom->createElement('title', $title));
$size = getSize($url);
$enclosure = $dom->createElement('enclosure');
$enclosure->appendChild(new DOMAttr('type', 'audio/mpeg'));
$enclosure->appendChild(new DOMAttr('length', $size));
$enclosure->appendChild(new DOMAttr('url', $url));
$item->appendChild($enclosure);
$item->appendChild($dom->createElement('itunes:duration', getDuration($size)));
$datestr = substr($title, 1, 10);
$pubDate = mktime(11, 00, 00, intval(substr($datestr, 5, 2)), intval(substr($datestr, 8, 2)), intval(substr($datestr, 0, 4)));
$item->appendChild($dom->createElement('pubDate', date(RFC_822, $pubDate)));
if ($pubDate > $latest_date) {
$latest_date = $pubDate;
}
$channel->appendChild($item);
}
$channel->appendChild($dom->createElement('pubDate', date(RFC_822, $latest_date)));
$root->appendChild($channel);
$dom->save('podcast.rss2');
if ($cache_dirty) {
file_put_contents('genfeed.cache', json_encode($len_cache, JSON_PRETTY_PRINT));
}
header('Content-Type: application/rss+xml');
echo file_get_contents('podcast.rss2');

6
intro.txt Normal file
View File

@ -0,0 +1,6 @@
With a 19-year consecutive run on Bassdrive.com, Overfiend has earned his stripes in the
Drum & Bass scene. In addition to his show, which has featured the likes of Ed Oberon,
The Insiders, Ant TC1, Gerra and Stone, Actraiser, and more, he has also held multiple
residencies in New York City and Phildelphia throughout his DJ career. 2020 will be the start of
his 20th year on Bassdrive, and it promises to offer a healthy supply of the newest in
Drum & Bass music as well as a helping of the finest special guests that the scene has to offer.

BIN
rsslogo.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB