From f902466fdb6caaf2b189da4c0dac1e04ea8fe917 Mon Sep 17 00:00:00 2001 From: zefie Date: Tue, 21 Apr 2026 09:34:58 -0400 Subject: [PATCH] add ragen --- .../ServiceVault/wtv-music/ragen/catchall.js | 83 +++++++++++++++++++ zefie_wtvp_minisrv/includes/config.json | 3 +- 2 files changed, 85 insertions(+), 1 deletion(-) create mode 100644 zefie_wtvp_minisrv/includes/ServiceVault/wtv-music/ragen/catchall.js diff --git a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-music/ragen/catchall.js b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-music/ragen/catchall.js new file mode 100644 index 00000000..be87d097 --- /dev/null +++ b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-music/ragen/catchall.js @@ -0,0 +1,83 @@ +const minisrv_service_file = true; + +if (!minisrv_config.services['pnm']) { + throw ("ERROR: pnm service not defined in config!"); +} + + +const pnmVaults = []; +// Check pnm service vault for .ra and .rm files +if (minisrv_config.config.ServiceVaults) { + Object.keys(minisrv_config.config.ServiceVaults).forEach(function (k) { + const service_vault = wtvshared.getAbsolutePath(minisrv_config.config.ServiceVaults[k]); + pnmVaults.push(service_vault + "/pnm"); + }) +} else { + throw ("ERROR: No Service Vaults defined!"); +} + +const url_path = request_headers.request_url.split('?')[0]; +const pathParts = url_path.split('/').filter(p => p); +const serviceName = pathParts.length > 0 ? pathParts[0] : ''; +const remainingPath = '/' + pathParts.slice(1).join('/'); +const filename = remainingPath.split('/').pop().replace('.ram', ''); +const directory = remainingPath.endsWith('/') || !filename ? remainingPath.replace(/\/$/, '') : remainingPath.substring(0, remainingPath.lastIndexOf('/')); + + +let fileFound = false; +const extensions = ['.ra', '.rm']; +let resolvedPath = null; + +// Check if request is for a directory listing (no filename or ends with /) +if (!filename || (request_headers.request_url.endsWith('/') && minisrv_config.services['pnm'].allow_indexing !== false)) { + const listingDir = filename ? directory : directory || '/'; + const allFiles = []; + + for (const pnmVault of pnmVaults) { + const targetDir = path.join(pnmVault, listingDir); + console.log("DEBUG: Listing files in", targetDir); + if (fs.existsSync(targetDir) && fs.statSync(targetDir).isDirectory()) { + const files = fs.readdirSync(targetDir); + files.forEach(file => { + const fullPath = path.join(targetDir, file); + if (fs.statSync(fullPath).isFile() && (file.endsWith('.ra') || file.endsWith('.rm'))) { + const baseFileName = file.substring(0, file.lastIndexOf('.')); + allFiles.push(baseFileName + '.ram'); + } + }); + } + } + + if (allFiles.length > 0) { + headers = `200 OK +Content-type: text/html`; + data = `

RealAudio Files on this minisrv

`; + } else { + headers = `404 Not Found +Content-type: text/html`; + data = `

No files found

`; + } +} else { + // Original file search logic + for (const pnmVault of pnmVaults) { + for (const ext of extensions) { + const filePath = path.join(pnmVault, filename + ext); + console.log("DEBUG: Checking for file", filePath); + if (fs.existsSync(filePath)) { + fileFound = true; + resolvedPath = filePath; + break; + } + } + if (fileFound) break; + } + + if (!fileFound) { + headers = `404 Not Found +Content-type: text/html`; + } else { + headers = `200 OK +Content-type: audio/x-pn-realaudio` + data = `pnm://${minisrv_config.config.service_ip}:${minisrv_config.services['pnm'].port}/${filename + path.extname(resolvedPath)}`; + } +} \ No newline at end of file diff --git a/zefie_wtvp_minisrv/includes/config.json b/zefie_wtvp_minisrv/includes/config.json index 404f2f14..9fb48db5 100644 --- a/zefie_wtvp_minisrv/includes/config.json +++ b/zefie_wtvp_minisrv/includes/config.json @@ -401,7 +401,8 @@ "protocol_handler": "pnm", "descriptor_after_hello_ms": 85, "burst_prestart_ms": 5000, - "debug": false + "debug": false, + "allow_indexing": true } }, "favorites": {