Sindbad~EG File Manager
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JamOnRadio Mixcloud Sets</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.5.0/dist/css/bootstrap.min.css" rel="stylesheet" />
</head>
<body>
<div class="container py-4">
<h1>JamOnRadio Sets</h1>
<div id="setsList" class="row g-3">
<!-- sets will be loaded here -->
</div>
<!-- Modal for tracklist -->
<div class="modal fade" id="trackModal" tabindex="-1">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="modalTitle">Tracklist</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<div id="playerEmbed" class="mb-3"></div>
<ul id="trackList" class="list-group"></ul>
</div>
</div>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.5.0/dist/js/bootstrap.bundle.min.js"></script>
<script>
const user = 'JamOnRadio';
async function fetchSets() {
const resp = await fetch(`https://api.mixcloud.com/${user}/cloudcasts/`);
if (!resp.ok) throw new Error(`HTTP error! status: ${resp.status}`);
const data = await resp.json();
return data.data; // array of shows/sets
}
async function fetchSetDetails(setUrl) {
const resp = await fetch(setUrl);
if (!resp.ok) throw new Error(`HTTP error! status: ${resp.status}`);
const data = await resp.json();
return data;
}
function showSets(sets) {
const container = document.getElementById('setsList');
container.innerHTML = ''; // clear first
sets.forEach(s => {
const col = document.createElement('div');
col.className = 'col-md-4';
col.innerHTML = `
<div class="card h-100">
<img src="${s.pictures?.thumbnail || 'https://via.placeholder.com/150'}" class="card-img-top" alt="${s.name}">
<div class="card-body d-flex flex-column">
<h5 class="card-title">${s.name}</h5>
<p class="card-text">${s.description ? s.description.substring(0, 100) + (s.description.length > 100 ? '...' : '') : ''}</p>
<button class="btn btn-primary btn-sm mt-auto" onclick="openSet('${s.key}', '${s.name}')">Open</button>
</div>
</div>
`;
container.appendChild(col);
});
}
async function openSet(setKey, setName) {
const apiUrl = `https://api.mixcloud.com${setKey}`;
try {
const details = await fetchSetDetails(apiUrl);
document.getElementById('modalTitle').textContent = setName;
// Embed player iframe
const embed = `<iframe width="100%" height="120" src="https://www.mixcloud.com/widget/iframe/?feed=https://www.mixcloud.com${setKey}" frameborder="0" allow="autoplay"></iframe>`;
document.getElementById('playerEmbed').innerHTML = embed;
const listEl = document.getElementById('trackList');
listEl.innerHTML = '';
if (details.trackinfo && details.trackinfo.length > 0) {
details.trackinfo.forEach((t, idx) => {
const li = document.createElement('li');
li.className = 'list-group-item';
// Format duration as mm:ss if exists
let durationStr = '';
if (t.duration) {
const minutes = Math.floor(t.duration / 60);
const seconds = String(t.duration % 60).padStart(2, '0');
durationStr = ` — ${minutes}:${seconds}`;
}
li.textContent = `${idx + 1}. ${t.title || 'Untitled Track'}${durationStr}`;
listEl.appendChild(li);
});
} else {
listEl.innerHTML = '<li class="list-group-item">No track info available</li>';
}
const modal = new bootstrap.Modal(document.getElementById('trackModal'));
modal.show();
} catch (err) {
alert('Failed to load track info.');
console.error(err);
}
}
// on load
fetchSets()
.then(showSets)
.catch(err => {
console.error('Error fetching sets', err);
document.getElementById('setsList').innerHTML = '<p class="text-danger">Failed to load.</p>';
});
</script>
</body>
</html>
Sindbad File Manager Version 1.0, Coded By Sindbad EG ~ The Terrorists