Rearranged things and improved code to allow for multiple feeds.

This commit is contained in:
Markus Birth 2020-02-16 02:28:57 +01:00
parent 10ecf6477c
commit 0f87cffb77
Signed by: mbirth
GPG Key ID: A9928D7A098C3A9A
15 changed files with 468 additions and 195 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
filesize.cache
/feed_*.rss2

View File

@ -1,189 +0,0 @@
<?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');

13
global.ini Normal file
View File

@ -0,0 +1,13 @@
[config]
; Public URL to this folder incl. trailing slash(!)
base_url = "https://rpi4.mbirth.de/bassdrive-rss/"
; Used for schedule times of shows
time_zone = "America/New_York"
; Format: mail@address.net (Full Name)
managing_editor = "markus@birth-online.de (Markus Birth)"
webmaster = "markus@birth-online.de (Markus Birth)"
; How long before sites may refetch RSS (minutes)
caching_ttl = 60

74
index.php Normal file
View File

@ -0,0 +1,74 @@
<?php
/**
* BassDrive RSS Feed Generator
* @author Markus Birth <markus@birth-online.de>
*/
require_once 'lib/BDAParser.php';
require_once 'lib/RSSGenerator.php';
use \BassDrive\BDAParser;
use \BassDrive\RSSGenerator;
$config = parse_ini_file('global.ini', true);
if ($config === false) {
die('global.ini not found or invalid syntax. See https://www.php.net/manual/en/function.parse-ini-file .');
}
date_default_timezone_set($config['config']['time_zone']);
$base_url = $config['config']['base_url'];
if (!array_key_exists('show', $_GET)) {
header('Content-Type: text/html');
echo '<html><body>No show selected. Available shows (RSS feeds):<br/>';
echo '<ul>';
$dirs = glob('shows/*', GLOB_ONLYDIR);
foreach ($dirs as $dir) {
$show = basename($dir);
$show_conf = parse_ini_file($dir . '/config.ini', true);
if ($show_conf === false) {
echo '<li>No config found or invalid: <strong>' . $show . '</strong></li>';
continue;
}
echo '<li>';
echo '<a href="' . $base_url . '?show=' . $show . '">';
echo $show_conf['show']['title'] . ' (' . $show . ')';
echo '</a>';
echo '</li>';
}
echo '</ul>';
echo '</body></html>';
exit();
}
// If we get here, a show was selected
$show = $_GET['show'];
$show_dir = realpath('shows/' . $show) . '/';
$show_conf = parse_ini_file($show_dir . 'config.ini', true);
if ($show_conf === false) {
die('Couldn\'t read (or parse) show\'s config.ini. See https://www.php.net/manual/en/function.parse-ini-file .');
}
// PARSE BASSDRIVE ARCHIVE
$show_data = new BDAParser($show_dir, $show_conf['archive']['url'], $show_conf['archive']['mp3_bitrate']);
$file_list = $show_data->fetchFiles();
// GENERATE RSS XML
$rss_gen = new RSSGenerator($base_url . '?show=' . $show, $base_url . 'shows/' . $show . '/');
$rss_gen->setGlobalConfig($config);
$rss_gen->setShowConfig($show_conf);
$rss_gen->setShowIntro(file_get_contents($show_dir . 'intro.txt'));
foreach ($file_list as $f) {
$rss_gen->addItem($f['url'], $f['title'], $f['size'], $f['duration'], $f['date']);
}
// OUTPUT RSS
$rss = $rss_gen->getRss();
file_put_contents('feed_' . $show . '.rss2', $rss);
header('Content-Type: application/rss+xml');
echo $rss;

View File

@ -1,6 +0,0 @@
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.

111
lib/BDAParser.php Normal file
View File

@ -0,0 +1,111 @@
<?php
namespace BassDrive;
/**
* BassDrive Archive Parser class
* @author Markus Birth <markus@birth-online.de>
*/
class BDAParser
{
const RFC_822 = 'D, d M Y H:i:s T';
public function __construct($show_dir, $archive_url, $mp3_bitrate = 128)
{
$this->show_dir = $show_dir;
$this->archive_url = $archive_url;
$this->mp3_bitrate = $mp3_bitrate;
$this->cachefile = $show_dir . 'filesize.cache';
$this->initCache();
}
private function initCache()
{
$this->len_cache = array();
$this->cache_dirty = false;
if (file_exists($this->cachefile)) {
$this->len_cache = json_decode(file_get_contents($this->cachefile), true);
}
}
public function __destruct()
{
// Flush filesize cache if needed
if ($this->cache_dirty) {
file_put_contents($this->cachefile, json_encode($this->len_cache, JSON_PRETTY_PRINT), LOCK_EX);
}
}
public function fetchFiles()
{
$src_data = file_get_contents($this->archive_url);
$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 = $this->archive_url . $href;
$size = $this->getSize($url);
array_push($file_list, array(
'url' => $url,
'title' => trim($title),
'size' => $size,
'duration' => $this->getDuration($size),
'date' => $this->getDateFromTitle(trim($title)),
));
}
return $file_list;
}
public function getSize($url)
{
if (isset($this->len_cache[$url])) {
return $this->len_cache[$url];
}
$context = stream_context_set_default(array(
'http' => array(
'method' => 'HEAD',
),
));
$headers = get_headers($url, 1);
$length = intval($headers['Content-Length']);
$this->len_cache[$url] = $length;
$this->cache_dirty = true;
return $length;
}
public 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)
$bitrate = intval($this->mp3_bitrate) * 1000;
$seconds = $size / ($bitrate / 8);
$hours = intdiv($seconds, 3600);
$seconds = $seconds % 3600;
$minutes = intdiv($seconds, 60);
$seconds = $seconds % 60;
return sprintf('%02d:%02d:%02d', $hours, $minutes, $seconds);
}
public function getDateFromTitle($title)
{
$datestr = substr($title, 1, 10);
$iso_date = substr($datestr, 0, 4) . '-' . substr($datestr, 5, 2) . '-' . substr($datestr, 8, 2);
return $iso_date;
}
}

176
lib/RSSGenerator.php Normal file
View File

@ -0,0 +1,176 @@
<?php
namespace BassDrive;
/**
* BassDrive RSS Feed Generator class
* @author Markus Birth <markus@birth-online.de>
*/
class RSSGenerator
{
const RFC_822 = 'D, d M Y H:i:s T';
const NAMESPACE_URIS = [
'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
];
public function __construct($feed_url, $show_url)
{
$this->self_url = $feed_url;
$this->show_url = $show_url;
$this->items = array();
}
public function setGlobalConfig($config_arr)
{
$this->global_conf = $config_arr;
}
public function setShowConfig($config_arr)
{
$this->show_conf = $config_arr;
}
public function setShowIntro($intro_text)
{
$this->show_intro = $intro_text;
}
public function addItem($url, $title, $size_bytes, $duration_secs, $pub_date)
{
array_push($this->items, array(
'url' => $url,
'title' => $title,
'size' => $size_bytes,
'duration' => $duration_secs,
'date' => $pub_date,
));
}
public function getRss()
{
$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', self::NAMESPACE_URIS['atom']);
$root->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:content', self::NAMESPACE_URIS['content']);
$root->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:itunes', self::NAMESPACE_URIS['itunes']);
$root->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:spotify', self::NAMESPACE_URIS['spotify']);
// $root->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:dcterms', self::NAMESPACE_URIS['dcterms']);
$root->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:psc', self::NAMESPACE_URIS['psc']);
$dom->appendChild($root);
$channel = $dom->createElement('channel');
$channel->appendChild($dom->createElement('title', $this->show_conf['show']['title']));
$channel->appendChild($dom->createElement('link', $this->show_conf['show']['link']));
$channel->appendChild($dom->createElement('copyright', $this->show_conf['show']['author']));
$channel->appendChild($dom->createElement('itunes:author', $this->show_conf['show']['author']));
$atom_link = $dom->createElement('atom:link');
$atom_link->appendChild(new \DOMAttr('href', $this->self_url));
$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;', $this->show_intro))));
$channel->appendChild($dom->createElement('language', $this->show_conf['show']['language']));
$image = $dom->createElement('image');
$image->appendChild($dom->createElement('url', $this->show_url . $this->show_conf['show']['small_logo'])); // RSS spec says max. dimensions are 144x400
$image->appendChild($dom->createElement('title', $this->show_conf['show']['title']));
$image->appendChild($dom->createElement('link', $this->show_conf['show']['link']));
$image->appendChild($dom->createElement('width', $this->show_conf['show']['small_logo_width']));
$image->appendChild($dom->createElement('height', $this->show_conf['show']['small_logo_height']));
$channel->appendChild($image);
$i_image = $dom->createElement('itunes:image');
$i_image->appendChild(new \DOMAttr('href', $this->show_url . $this->show_conf['show']['big_logo'])); // Apple requires min.(!) size of 1400x1400, 1:1 aspect
$channel->appendChild($i_image);
$channel->appendChild($dom->createElement('lastBuildDate', date(self::RFC_822)));
$channel->appendChild($dom->createElement('docs', 'http://blogs.law.harvard.edu/tech/rss'));
$channel->appendChild($dom->createElement('generator', 'ew-rss 2020-02-15 by Markus Birth'));
$channel->appendChild($dom->createElement('managingEditor', $this->global_conf['config']['managing_editor']));
$channel->appendChild($dom->createElement('webMaster', $this->global_conf['config']['webmaster']));
$channel->appendChild($dom->createElement('ttl', $this->global_conf['config']['caching_ttl']));
$skipDays = $dom->createElement('skipDays');
$days_on = explode(',', $this->show_conf['show']['schedule_days']);
if (!in_array('Mo', $days_on)) {
$skipDays->appendChild($dom->createElement('day', 'Monday'));
}
if (!in_array('Tu', $days_on)) {
$skipDays->appendChild($dom->createElement('day', 'Tuesday'));
}
if (!in_array('We', $days_on)) {
$skipDays->appendChild($dom->createElement('day', 'Wednesday'));
}
if (!in_array('Th', $days_on)) {
$skipDays->appendChild($dom->createElement('day', 'Thursday'));
}
if (!in_array('Fr', $days_on)) {
$skipDays->appendChild($dom->createElement('day', 'Friday'));
}
if (!in_array('Sa', $days_on)) {
$skipDays->appendChild($dom->createElement('day', 'Saturday'));
}
if (!in_array('Su', $days_on)) {
$skipDays->appendChild($dom->createElement('day', 'Sunday'));
}
$channel->appendChild($skipDays);
$i_cat = $dom->createElement('itunes:category');
$i_cat->appendChild(new \DOMAttr('text', $this->show_conf['show']['category']));
$channel->appendChild($i_cat);
$channel->appendChild($dom->createElement('itunes:explicit', $this->show_conf['show']['explicit']));
$channel->appendChild($dom->createElement('itunes:complete', $this->show_conf['show']['complete']));
$channel->appendChild($dom->createElement('itunes:type', $this->show_conf['show']['type']));
//$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);
if (array_key_exists('country_of_origin', $this->show_conf['show'])) {
// set target market/territory by country, omit for "global"
$channel->appendChild($dom->createElement('spotify:countryOfOrigin', $this->show_conf['show']['country_of_origin']));
}
$latest_date = -1;
foreach ($this->items as $i) {
$item = $dom->createElement('item');
$guid = $dom->createElement('guid', $i['url']);
$guid->appendChild(new \DOMAttr('isPermalink', 'true')); // guid is a static URL
$item->appendChild($guid);
$item->appendChild($dom->createElement('title', $i['title']));
$enclosure = $dom->createElement('enclosure');
$enclosure->appendChild(new \DOMAttr('type', 'audio/mpeg'));
$enclosure->appendChild(new \DOMAttr('length', $i['size']));
$enclosure->appendChild(new \DOMAttr('url', $i['url']));
$item->appendChild($enclosure);
$item->appendChild($dom->createElement('itunes:duration', $i['duration']));
$dt = explode('-', $i['date']);
$tt = explode(':', $this->show_conf['show']['schedule_time']);
$pubDate = mktime($tt[0], $tt[1], $tt[2], $dt[1], $dt[2], $dt[0]);
$item->appendChild($dom->createElement('pubDate', date(self::RFC_822, $pubDate)));
if ($pubDate > $latest_date) {
$latest_date = $pubDate;
}
$channel->appendChild($item);
}
$channel->appendChild($dom->createElement('pubDate', date(self::RFC_822, $latest_date)));
$root->appendChild($channel);
return $dom->saveXML();
}
}

View File

Before

Width:  |  Height:  |  Size: 286 KiB

After

Width:  |  Height:  |  Size: 286 KiB

36
shows/ew/config.ini Normal file
View File

@ -0,0 +1,36 @@
[archive]
url = "http://archives.bassdrivearchive.com/6%20-%20Saturday/Electronic%20Warfare%20-%20The%20Overfiend/"
; MP3 bitrate for duration calculation (in 1000k, e.g. 96, 128, 192, 256)
mp3_bitrate = 128
[show]
title = "Electronic Warfare"
link = "https://www.facebook.com/louis.overfiend"
author = "BassDrive.com / Louis Overfiend"
language = "en-us"
; Country code of origin for target market/region (comment out to target globally)
;country_of_origin = us
; Apple Podcasts Connect category, see https://help.apple.com/itc/podcasts_connect/#/itc9267a2f12
category = "Music"
; Day(s) the show is on-air (Mo, Tu, We, Th, Fr, Sa, Su) - combine multiple days with comma, e.g. "Tu,Th,Sa"
schedule_days = "Sa"
schedule_time = "11:00:00"
; Contains explicit stuff? "yes" or "clean" if not.
explicit = "clean"
; Show is complete (no new episodes)? "yes" or "no"
complete = "no"
; Files can be consumed randomly ("episodic") or should be consumed in order ("serial")
type = "episodic"
small_logo = "rsslogo.jpg"
small_logo_width = 144
small_logo_height = 144
big_logo = "biglogo.jpg"

5
shows/ew/intro.txt Normal file
View File

@ -0,0 +1,5 @@
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.

View File

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 34 KiB

BIN
shows/xposure/biglogo.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 MiB

36
shows/xposure/config.ini Normal file
View File

@ -0,0 +1,36 @@
[archive]
url = "http://archives.bassdrivearchive.com/2%20-%20Tuesday/XPOSURE%20Records%20Show%20-%20Ben%20XO/"
; MP3 bitrate for duration calculation (in 1000k, e.g. 96, 128, 192, 256)
mp3_bitrate = 128
[show]
title = "XPOSURE Records Show"
link = "https://xo.am/"
author = "BassDrive.com / Ben XO"
language = "en-us"
; Country code of origin for target market/region (comment out to target globally)
;country_of_origin = us
; Apple Podcasts Connect category, see https://help.apple.com/itc/podcasts_connect/#/itc9267a2f12
category = "Music"
; Day(s) the show is on-air (Mo, Tu, We, Th, Fr, Sa, Su) - combine multiple days with comma, e.g. "Tu,Th,Sa"
schedule_days = "Tu"
schedule_time = "15:00:00"
; Contains explicit stuff? "yes" or "clean" if not.
explicit = "clean"
; Show is complete (no new episodes)? "yes" or "no"
complete = "no"
; Files can be consumed randomly ("episodic") or should be consumed in order ("serial")
type = "episodic"
small_logo = "rsslogo.jpg"
small_logo_width = 144
small_logo_height = 144
big_logo = "biglogo.jpg"

15
shows/xposure/intro.txt Normal file
View File

@ -0,0 +1,15 @@
Ben XO is a drum and bass and electro house DJ from London UK. He runs to this day the Internet's longest running drum
and bass show, which airs on http://www.bassdrive.com/, starting in 2001. Since 2010 he has also had an Electro House
radio show on DI.FM.
Growing up on a diet of pirate radio in north London, UK, Ben XO began DJing in 1998 and is well known for his series
of DJ demos that are regularly released onto the internet.
Career highlights include a guest slot on Adam Fs Kiss FM show in 2005, a mix CD for the cover of Knowledge magazine
in 2006, guest slots on national radio in Norway, Hungary and Estonia, and being interviewed on the subject of how the
internet has changed drumn'bass for Brian Belle-Fortunes book “All Crews Muss Big Up”.
He was the webmaster for both www.bassdrive.com and www.dogsonacid.com for over 3 years. He is now lead web developer
at Last.fm.
He also owns the record label Xposure Records.

BIN
shows/xposure/rsslogo.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB