RSS_FEED_FILE_NAME = '.index.php'
RSS_FEED_INFO_EXTENSION = 'info'
RSS_FEED_SHOW_INDEX = 'index'
def RSS_FEED_CODE():
return r'''title;
$feed_description=$info->description;
$feed_logo=$info->image;
$feed_link=$info->link;
}
?>
'; // use php to output the "" ?>
\n";
echo " ".$info->title."\n";
echo " ".$info->description."\n";
echo " ".$info->guid."\n";
echo " ".$base_url.$info->filename."\n";
echo " filename."\" length=\"".$info->size."\" type=\"".$info->mimetype."\" />\n";
echo " filename."\" medium=\"".$info->medium."\" duration=\"".$info->duration."\" type=\"".$info->mimetype."\" />\n";
echo " ".$info->date."\n";
echo " ".$info->duration."\n";
echo " \n";
}
}
}
}
?>
'''
def RSS_INDEX_CODE(bin_path, config_name):
return r''' [options...]".PHP_EOL;
echo " commands: ".implode("|",CLI_COMMANDS).PHP_EOL;
die();
}
$settings=read(dirname(__FILE__)."/".SETTINGS_INFO);
$feeds=read(dirname(__FILE__)."/".FEEDS_INFO);
$SPODCAST_CONFIG=dirname(__FILE__)."/".SPODCAST_CONFIG;
$command=$argv[1];
if($command == "refresh") {
foreach ($feeds as $url => ["title"=>$title,"directory"=>$directory,"max"=>$max,"keep"=>$keep]) {
if ($max > 0) {
$output = add_feed($url, $max, true);
echo(implode(PHP_EOL, $output));
}
$episodes=get_episodes($directory);
if(count($episodes) > $keep) {
$to_delete=array_splice($episodes, $keep);
foreach ($to_delete as $episode) {
system("rm -f ".escapeshellarg($directory."/".$episode['filename'])." 2>&1");
system("rm -f ".escapeshellarg($directory."/".$episode['filename']).".".INFO." 2>&1");
}
}
}
}
die();
}
$feeds=get_feeds(dirname(__FILE__));
$settings=get_settings();
$ERROR_MESSAGE=null;
$ERROR_DETAILS=null;
function get_feeds($dir) {
$spodcast_url=(isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? "https" : "http")."://".$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
foreach(glob($dir."/*/".SHOW_INFO) as $show_info) {
$episodes=get_episodes(dirname($show_info));
$json=file_get_contents($show_info);
$info=json_decode($json);
$feeds[$info->link]['title']=$info->title;
$feeds[$info->link]['image']=$info->image;
$feeds[$info->link]['episodes']=count($episodes);
$feeds[$info->link]['last']=date("Y-m-d",strtotime($episodes[0]['date']));
$feeds[$info->link]['directory']=dirname($show_info);
$feeds[$info->link]['max']=$info->max ?? 2;
$feeds[$info->link]['keep']=$info->keep ?? 5;
$feeds[$info->link]['feed']=$spodcast_url.basename(dirname($show_info));
}
uasort($feeds, fn ($a, $b) => strnatcmp($a['title'], $b['title']));
store($feeds, FEEDS_INFO);
return $feeds;
}
function get_episodes($dir) {
foreach(glob($dir."/*.".INFO) as $episode_info) {
if(basename($episode_info) == SHOW_INFO) {
continue;
}
$json=file_get_contents($episode_info);
$info=json_decode($json);
$episodes[]=["filename"=>$info->filename,"date"=>$info->date,"title"=>$info->title];
}
usort($episodes, fn ($a, $b) => strtotime($b["date"]) - strtotime($a["date"]));
return $episodes;
}
function get_settings() {
$settings=read(SETTINGS_INFO);
$spodcast_url=(isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? "https" : "http")."://".$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
$settings['spodcast_url']=$settings['spodcast_url'] ?? $spodcast_url;
$settings['update_start']=$settings['update_start'] ?? 0;
$settings['update_rate']=$settings['update_rate'] ?? 1;
$settings['update_enabled']=$settings['update_enabled'] ?? false;
store($settings, SETTINGS_INFO);
return $settings;
}
function get(&$var, $default=null) {
return isset($var) ? $var : $default;
}
function read($file) {
if(file_exists($file)) {
$json=file_get_contents($file);
$info=json_decode($json, true);
} else {
$info=[];
}
return $info;
}
function store($info, $file) {
$f = fopen($file,'w');
fwrite($f, json_encode($info));
fclose($f);
}
function cron_signature($crontab, $CRON_SIGNATURE) {
$index = 0;
foreach ($crontab as $line) {
if (strpos($line, $CRON_SIGNATURE) !== false) {
return $index;
}
$index++;
}
return NOT_FOUND;
}
function debug($var) {
ob_start();
var_dump($var);
error_log(ob_get_clean());
}
function submit_crontab($crontab) {
$tempfile=system("mktemp");
file_put_contents($tempfile, implode(PHP_EOL,$crontab));
$command="crontab ".$tempfile;
exec($command);
unlink($tempfile);
}
function get_range($start, $rate) {
for ($i=0; $i < $rate; $i++) {
$arr[]=(($start%(24/$rate))+($i*(24/$rate)))%24;
}
return implode(",", $arr);
}
function update_scheduler($enable, $start, $rate) {
$CRON_SIGNATURE="SPODCAST:".dirname(__FILE__);
$crontab=null;
$retval=null;
exec("crontab -l", $crontab, $retval);
if ($retval == 0) {
$index=cron_signature($crontab, $CRON_SIGNATURE);
if ($enable == true) {
if($index !== NOT_FOUND) {
array_splice($crontab, $index, 1);
}
$crontab[]=sprintf("%d %s * * * php %s refresh # %s".PHP_EOL, rand(5,25), get_range($start, $rate), __FILE__, $CRON_SIGNATURE);
submit_crontab($crontab);
} else {
if ($index !== NOT_FOUND) {
array_splice($crontab, $index, 1);
$crontab[count($crontab)-1]=rtrim($crontab[count($crontab)-1]).PHP_EOL;
submit_crontab($crontab);
}
}
}
}
function login($username, $password, $return_output=false) {
$output = null;
$retval = null;
$tempfile=system("mktemp");
$SPODCAST_CONFIG=dirname(__FILE__)."/".SPODCAST_CONFIG;
file_put_contents($tempfile, "$username $password");
$command=SPODCAST." -c ".$SPODCAST_CONFIG." --log-level ".LOG_LEVEL." -l ".$tempfile." 2>&1";
exec($command, $output, $retval);
unlink($tempfile);
if ($retval > 0 || $return_output) {
return $output;
}
return SUCCESS;
}
function add_feed($url, $max, $return_output=false) {
$output = null;
$retval = null;
$SPODCAST_CONFIG=dirname(__FILE__)."/".SPODCAST_CONFIG;
$command=SPODCAST." -c ".$SPODCAST_CONFIG." --max-episodes ".$max." ".escapeshellarg($url)." 2>&1";
exec($command, $output, $retval);
if ($retval > 0 || $return_output) {
return $output;
}
return SUCCESS;
}
function delete_feed($url, $return_output=false) {
$output = null;
$retval = null;
$feeds=read(FEEDS_INFO);
$feed_dir=$feeds[$url]['directory'];
$command="rm -rf ".$feed_dir." 2>&1";
exec($command, $output, $retval);
if ($retval > 0 || $return_output) {
return $output;
}
return SUCCESS;
}
function update_show($url, $field, $value) {
if (array_search($field, UPDATEABLE) === false) {
return ["$field is not an updateable field"];
} else {
$feeds=read(FEEDS_INFO);
$show_dir=$feeds[$url]['directory'];
$show=read($show_dir."/".SHOW_INFO);
$show[$field]=(int) $value;
store($show, $show_dir."/".SHOW_INFO);
return SUCCESS;
}
}
function show_error($message, $details) {
header("Location: ./?action=error&message=".urlencode($message)."&details=".urlencode(implode(PHP_EOL,$details)));
die();
}
switch(get($_GET['action'])) {
case 'refresh':
case 'new':
$url = get($_GET['url']);
$result = add_feed($url, MAX_EPISODES);
if ($result !== SUCCESS) {
show_error("Add/refresh feed failed", $result);
}
header("Location: .");
die();
case 'delete':
$url = get($_GET['url']);
$result = delete_feed($url);
if ($result !== SUCCESS) {
show_error("Delete feed failed", $result);
}
header("Location: .");
die();
case 'update':
$url = get($_GET['url']);
$field = get($_GET['field']);
$value = get($_GET['value']);
$result=update_show($url, $field, $value);
if ($result !== SUCCESS) {
show_error("Update failed", $result);
}
header("Location: .");
die();
case 'login':
$username = get($_GET['username']);
$password = get($_GET['password']);
$result = login($username, $password);
if ($result !== SUCCESS) {
show_error("Login failed",$result);
}
header("Location: .");
die();
case 'schedule':
$enable = (get($_GET['enable']) == "true" ? true : false);
$start = (int) get($_GET['start']);
$rate = (int) get($_GET['rate']);
$settings['update_enabled'] = $enable;
$settings['update_start'] = $start;
$settings['update_rate'] = $rate;
store($settings, SETTINGS_INFO);
update_scheduler($enable, $start, $rate);
header("Location: .");
die();
case 'error':
$ERROR_MESSAGE = get($_GET['message']);
$ERROR_DETAILS = get($_GET['details']);
default:
break;
}
$UPDATE_ENABLED=$settings['update_enabled'];
$UPDATE_START=$settings['update_start'];
$UPDATE_RATE=$settings['update_rate'];
?>
Spodcast feed manager
["title"=>$title,"image"=>$image,"episodes"=>$episodes,"last"=>$last,"max"=>$max,"keep"=>$keep,"feed"=>$feed]): ?>
=$title?>
=$last?> (=$episodes?>)
sync
keep
Please wait...
This may take a while.
Refresh the page if this takes too long
'''