• File: jano-radio-manifest.php
  • Full Path: /home/verita/rdrive/manager-20260605151338/jano-radio-manifest.php
  • Date Modified: 05/25/2026 9:33 PM
  • File size: 4.77 KB
  • MIME-type: text/x-php
  • Charset: utf-8
<?php
/**
 * Jano Radio Manifest Generator
 *
 * Usage web:
 *   1) Copy this file into the folder that contains your audio files.
 *   2) Open https://example.com/music/jano-radio-manifest.php
 *   3) In WordPress > Jano Radio > Morceaux, import that URL.
 *
 * Optional protection:
 *   Set $token = 'choose-a-long-secret'; then call:
 *   https://example.com/music/jano-radio-manifest.php?token=choose-a-long-secret
 *
 * Usage CLI:
 *   php jano-radio-manifest.php > index.json
 */

$token = ''; // Optional: put a secret here, for example 'change-this-long-secret'.
$audioExtensions = array('mp3', 'm4a', 'aac', 'ogg', 'oga', 'opus', 'wav', 'flac');
$defaultDuration = 180;
$maxFiles = 5000;
$recursive = true;

if (PHP_SAPI !== 'cli') {
    if ($token !== '' && (!isset($_GET['token']) || hash_equals($token, (string) $_GET['token']) === false)) {
        http_response_code(403);
        header('Content-Type: text/plain; charset=utf-8');
        echo "Forbidden\n";
        exit;
    }
    if (isset($_GET['duration'])) {
        $defaultDuration = max(1, (int) $_GET['duration']);
    }
    if (isset($_GET['max'])) {
        $maxFiles = min(20000, max(1, (int) $_GET['max']));
    }
    if (isset($_GET['recursive'])) {
        $recursive = (string) $_GET['recursive'] !== '0';
    }
}

$root = realpath(__DIR__);
if ($root === false || !is_dir($root)) {
    output_manifest(array(), $defaultDuration);
    exit;
}

$files = collect_audio_files($root, $audioExtensions, $recursive, $maxFiles);
natcasesort($files);
$files = array_values($files);

$tracks = array();
foreach ($files as $relativePath) {
    $tracks[] = array(
        'url' => encode_relative_url($relativePath),
        'title' => title_from_filename($relativePath),
        'artist' => '',
        'duration' => $defaultDuration,
    );
}

output_manifest($tracks, $defaultDuration);

function collect_audio_files($root, $audioExtensions, $recursive, $maxFiles)
{
    $out = array();
    $root = rtrim(str_replace('\\', '/', $root), '/');

    if ($recursive) {
        $iterator = new RecursiveIteratorIterator(
            new RecursiveDirectoryIterator($root, FilesystemIterator::SKIP_DOTS),
            RecursiveIteratorIterator::SELF_FIRST
        );
        foreach ($iterator as $fileInfo) {
            if (!$fileInfo->isFile()) {
                continue;
            }
            $path = str_replace('\\', '/', $fileInfo->getRealPath());
            if (should_skip_path($path, $root)) {
                continue;
            }
            $ext = strtolower(pathinfo($path, PATHINFO_EXTENSION));
            if (!in_array($ext, $audioExtensions, true)) {
                continue;
            }
            $out[] = ltrim(substr($path, strlen($root)), '/');
            if (count($out) >= $maxFiles) {
                break;
            }
        }
    } else {
        foreach (scandir($root) as $name) {
            if ($name === '.' || $name === '..' || substr($name, 0, 1) === '.') {
                continue;
            }
            $path = $root . '/' . $name;
            if (!is_file($path)) {
                continue;
            }
            $ext = strtolower(pathinfo($path, PATHINFO_EXTENSION));
            if (!in_array($ext, $audioExtensions, true)) {
                continue;
            }
            $out[] = $name;
            if (count($out) >= $maxFiles) {
                break;
            }
        }
    }

    return $out;
}

function should_skip_path($path, $root)
{
    $relative = ltrim(substr($path, strlen($root)), '/');
    foreach (explode('/', $relative) as $segment) {
        if ($segment === '' || substr($segment, 0, 1) === '.') {
            return true;
        }
    }
    return false;
}

function encode_relative_url($relativePath)
{
    $relativePath = str_replace('\\', '/', $relativePath);
    $parts = explode('/', $relativePath);
    $encoded = array();
    foreach ($parts as $part) {
        $encoded[] = rawurlencode($part);
    }
    return implode('/', $encoded);
}

function title_from_filename($relativePath)
{
    $base = basename(str_replace('\\', '/', $relativePath));
    $base = preg_replace('/\.[a-z0-9]{2,8}$/i', '', $base);
    $base = rawurldecode($base);
    $base = str_replace(array('_', '-'), ' ', $base);
    $base = preg_replace('/\s+/', ' ', $base);
    return trim($base) !== '' ? trim($base) : 'Morceau audio';
}

function output_manifest($tracks, $defaultDuration)
{
    $manifest = array(
        'generated_at' => gmdate('c'),
        'default_duration' => $defaultDuration,
        'tracks' => $tracks,
    );

    if (PHP_SAPI !== 'cli') {
        header('Content-Type: application/json; charset=utf-8');
        header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
    }

    echo json_encode($manifest, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
    echo "\n";
}