![]() Server : Apache/2 System : Linux server-15-235-50-60 5.15.0-164-generic #174-Ubuntu SMP Fri Nov 14 20:25:16 UTC 2025 x86_64 User : gositeme ( 1004) PHP Version : 8.2.29 Disable Function : exec,system,passthru,shell_exec,proc_close,proc_open,dl,popen,show_source,posix_kill,posix_mkfifo,posix_getpwuid,posix_setpgid,posix_setsid,posix_setuid,posix_setgid,posix_seteuid,posix_setegid,posix_uname Directory : /home/gositeme/.cursor-server/data/User/History/-6fee586/ |
<?php
// Track Status Verification and Fix Tool
// This tool helps identify and fix tracks with incorrect statuses
// Handle AJAX actions
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action'])) {
header('Content-Type: application/json');
$action = $_POST['action'];
$response = ['success' => false, 'message' => 'Unknown action'];
try {
if ($action === 'check_track') {
$track_id = intval($_POST['track_id'] ?? 0);
if (!$track_id) {
throw new Exception('Track ID required');
}
// Get track from database
$stmt = $pdo->prepare("SELECT id, title, status, task_id, api_task_id, created_at, user_id, metadata FROM music_tracks WHERE id = ?");
$stmt->execute([$track_id]);
$track = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$track) {
throw new Exception('Track not found');
}
// Check API status
$task_id = $track['task_id'] ?? $track['api_task_id'] ?? null;
$api_status = null;
$api_data = null;
$error_message = null;
if ($task_id && $task_id !== 'unknown' && !str_starts_with($task_id, 'temp_') && !str_starts_with($task_id, 'retry_')) {
$api_key = '63edba40620216c5aa2c04240ac41dbd';
$api_url = 'https://api.api.box/api/v1/status/' . $task_id;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $api_url);
curl_setopt($ch, CURLOPT_HTTPGET, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Authorization: Bearer ' . $api_key,
'Content-Type: application/json',
'User-Agent: SoundStudioPro/1.0'
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
$api_response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($http_code === 200 && $api_response) {
$api_data = json_decode($api_response, true);
if ($api_data) {
$api_status = $api_data['status'] ?? null;
// Check for error codes
if (isset($api_data['code']) && ($api_data['code'] == 400 || $api_data['code'] == 531 || $api_data['code'] >= 400)) {
$api_status = 'failed';
$error_message = $api_data['msg'] ?? $api_data['error'] ?? $api_data['error_msg'] ?? 'Generation failed';
} elseif ($api_status === 'failed' || $api_status === 'error' || $api_status === 'rejected') {
$error_message = $api_data['error'] ?? $api_data['msg'] ?? $api_data['error_msg'] ?? 'Generation failed';
}
}
}
}
$response = [
'success' => true,
'track' => $track,
'api_status' => $api_status,
'api_data' => $api_data,
'error_message' => $error_message,
'needs_fix' => ($track['status'] === 'processing' && ($api_status === 'failed' || $api_status === 'rejected' || $api_status === 'error'))
];
} elseif ($action === 'fix_track') {
$track_id = intval($_POST['track_id'] ?? 0);
$new_status = $_POST['new_status'] ?? 'failed';
$error_message = $_POST['error_message'] ?? 'Track generation failed';
if (!$track_id) {
throw new Exception('Track ID required');
}
// Get track
$stmt = $pdo->prepare("SELECT id, user_id, status FROM music_tracks WHERE id = ?");
$stmt->execute([$track_id]);
$track = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$track) {
throw new Exception('Track not found');
}
// Update status
$error_metadata = json_encode([
'code' => 531,
'msg' => $error_message,
'error_type' => 'generation_failed',
'timestamp' => date('Y-m-d H:i:s'),
'fixed_by' => 'admin_tool'
]);
$update_stmt = $pdo->prepare("UPDATE music_tracks SET status = ?, metadata = ?, updated_at = NOW() WHERE id = ?");
$update_stmt->execute([$new_status, $error_metadata, $track_id]);
// Refund credit if status changed from processing to failed
if ($track['status'] === 'processing' && $new_status === 'failed') {
$refund_stmt = $pdo->prepare("UPDATE users SET credits = credits + 1 WHERE id = ?");
$refund_stmt->execute([$track['user_id']]);
// Record refund transaction
$check_stmt = $pdo->prepare("SELECT COUNT(*) FROM credit_transactions WHERE user_id = ? AND type = 'refund' AND description LIKE ?");
$check_stmt->execute([$track['user_id'], "%Track fixed: {$track_id}%"]);
if ($check_stmt->fetchColumn() == 0) {
$trans_stmt = $pdo->prepare("
INSERT INTO credit_transactions (user_id, amount, type, description, created_at)
VALUES (?, 1, 'refund', 'Track fixed by admin: {$track_id}', NOW())
");
$trans_stmt->execute([$track['user_id']]);
}
}
$response = [
'success' => true,
'message' => 'Track status updated successfully'
];
} elseif ($action === 'bulk_check') {
$track_ids = $_POST['track_ids'] ?? [];
if (empty($track_ids) || !is_array($track_ids)) {
throw new Exception('Track IDs required');
}
$results = [];
foreach ($track_ids as $track_id) {
$track_id = intval($track_id);
if (!$track_id) continue;
// Get track
$stmt = $pdo->prepare("SELECT id, title, status, task_id, api_task_id, created_at FROM music_tracks WHERE id = ?");
$stmt->execute([$track_id]);
$track = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$track) continue;
// Check API if processing
$api_status = null;
if ($track['status'] === 'processing') {
$task_id = $track['task_id'] ?? $track['api_task_id'] ?? null;
if ($task_id && $task_id !== 'unknown' && !str_starts_with($task_id, 'temp_') && !str_starts_with($task_id, 'retry_')) {
$api_key = '63edba40620216c5aa2c04240ac41dbd';
$api_url = 'https://api.api.box/api/v1/status/' . $task_id;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $api_url);
curl_setopt($ch, CURLOPT_HTTPGET, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Authorization: Bearer ' . $api_key,
'Content-Type: application/json'
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 5);
$api_response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($http_code === 200 && $api_response) {
$api_data = json_decode($api_response, true);
if ($api_data) {
if (isset($api_data['code']) && ($api_data['code'] == 400 || $api_data['code'] == 531 || $api_data['code'] >= 400)) {
$api_status = 'failed';
} else {
$api_status = $api_data['status'] ?? null;
}
}
}
}
}
$results[] = [
'track_id' => $track_id,
'title' => $track['title'],
'db_status' => $track['status'],
'api_status' => $api_status,
'needs_fix' => ($track['status'] === 'processing' && ($api_status === 'failed' || $api_status === 'rejected' || $api_status === 'error'))
];
}
$response = [
'success' => true,
'results' => $results
];
} elseif ($action === 'bulk_fix') {
$track_ids = $_POST['track_ids'] ?? [];
if (empty($track_ids) || !is_array($track_ids)) {
throw new Exception('Track IDs required');
}
$fixed_count = 0;
$errors = [];
foreach ($track_ids as $track_id) {
$track_id = intval($track_id);
if (!$track_id) continue;
try {
// Get track
$stmt = $pdo->prepare("SELECT id, user_id, status FROM music_tracks WHERE id = ?");
$stmt->execute([$track_id]);
$track = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$track || $track['status'] !== 'processing') continue;
// Update to failed
$error_metadata = json_encode([
'code' => 531,
'msg' => 'Track generation failed (fixed by admin bulk tool)',
'error_type' => 'generation_failed',
'timestamp' => date('Y-m-d H:i:s'),
'fixed_by' => 'admin_bulk_tool'
]);
$update_stmt = $pdo->prepare("UPDATE music_tracks SET status = 'failed', metadata = ?, updated_at = NOW() WHERE id = ?");
$update_stmt->execute([$error_metadata, $track_id]);
// Refund credit
if ($track['user_id']) {
$refund_stmt = $pdo->prepare("UPDATE users SET credits = credits + 1 WHERE id = ?");
$refund_stmt->execute([$track['user_id']]);
}
$fixed_count++;
} catch (Exception $e) {
$errors[] = "Track {$track_id}: " . $e->getMessage();
}
}
$response = [
'success' => true,
'message' => "Fixed {$fixed_count} track(s)",
'fixed_count' => $fixed_count,
'errors' => $errors
];
}
} catch (Exception $e) {
$response = [
'success' => false,
'message' => $e->getMessage()
];
}
echo json_encode($response);
exit;
}
// Get tracks that might have status issues
$issue_filter = $_GET['filter'] ?? 'processing_old'; // processing_old, all_processing, all_failed
$where_conditions = [];
$params = [];
switch ($issue_filter) {
case 'processing_old':
// Tracks processing for more than 5 minutes
$where_conditions[] = "mt.status = 'processing'";
$where_conditions[] = "mt.created_at < DATE_SUB(NOW(), INTERVAL 5 MINUTE)";
break;
case 'all_processing':
$where_conditions[] = "mt.status = 'processing'";
break;
case 'all_failed':
$where_conditions[] = "mt.status = 'failed'";
break;
case 'all':
default:
// All tracks with potential issues
$where_conditions[] = "(mt.status = 'processing' OR mt.status = 'failed')";
break;
}
$where_clause = !empty($where_conditions) ? "WHERE " . implode(" AND ", $where_conditions) : "";
// Get tracks with potential issues
try {
$stmt = $pdo->prepare("
SELECT
mt.id,
mt.title,
mt.status,
mt.task_id,
mt.api_task_id,
mt.created_at,
mt.updated_at,
mt.metadata,
u.name as user_name,
u.email as user_email,
u.id as user_id,
TIMESTAMPDIFF(MINUTE, mt.created_at, NOW()) as minutes_processing
FROM music_tracks mt
LEFT JOIN users u ON mt.user_id = u.id
$where_clause
ORDER BY mt.created_at DESC
LIMIT 200
");
$stmt->execute($params);
$tracks = $stmt->fetchAll(PDO::FETCH_ASSOC);
} catch (Exception $e) {
$tracks = [];
error_log("Error fetching tracks: " . $e->getMessage());
}
// Get statistics
$stats = $pdo->query("
SELECT
COUNT(*) as total_tracks,
COUNT(CASE WHEN status = 'processing' THEN 1 END) as processing_tracks,
COUNT(CASE WHEN status = 'processing' AND created_at < DATE_SUB(NOW(), INTERVAL 5 MINUTE) THEN 1 END) as old_processing,
COUNT(CASE WHEN status = 'failed' THEN 1 END) as failed_tracks
FROM music_tracks
")->fetch();
?>
<style>
.track-status-tool {
padding: 2rem;
}
.stats-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 1rem;
margin-bottom: 2rem;
}
.stat-card {
background: rgba(255, 255, 255, 0.05);
border-radius: 12px;
padding: 1.5rem;
border: 1px solid rgba(102, 126, 234, 0.2);
}
.stat-card h3 {
font-size: 2rem;
margin: 0;
color: #667eea;
}
.stat-card p {
margin: 0.5rem 0 0 0;
color: #a0aec0;
font-size: 0.9rem;
}
.filter-bar {
display: flex;
gap: 1rem;
margin-bottom: 2rem;
align-items: center;
flex-wrap: wrap;
}
.filter-bar select {
padding: 0.8rem 1.2rem;
background: rgba(255, 255, 255, 0.05);
border: 1px solid rgba(102, 126, 234, 0.3);
border-radius: 8px;
color: white;
font-size: 1rem;
}
.filter-bar button {
padding: 0.8rem 1.5rem;
background: linear-gradient(135deg, #667eea, #764ba2);
border: none;
border-radius: 8px;
color: white;
font-weight: 600;
cursor: pointer;
transition: all 0.3s ease;
}
.filter-bar button:hover {
transform: translateY(-2px);
box-shadow: 0 4px 15px rgba(102, 126, 234, 0.4);
}
.tracks-table {
width: 100%;
background: rgba(255, 255, 255, 0.03);
border-radius: 12px;
overflow: hidden;
border: 1px solid rgba(102, 126, 234, 0.2);
}
.tracks-table table {
width: 100%;
border-collapse: collapse;
}
.tracks-table th {
background: rgba(102, 126, 234, 0.2);
padding: 1rem;
text-align: left;
font-weight: 600;
color: #667eea;
border-bottom: 2px solid rgba(102, 126, 234, 0.3);
}
.tracks-table td {
padding: 1rem;
border-bottom: 1px solid rgba(255, 255, 255, 0.05);
color: #e0e0e0;
}
.tracks-table tr:hover {
background: rgba(102, 126, 234, 0.1);
}
.status-badge {
display: inline-block;
padding: 0.4rem 0.8rem;
border-radius: 6px;
font-size: 0.85rem;
font-weight: 600;
}
.status-processing {
background: rgba(245, 158, 11, 0.2);
color: #f59e0b;
}
.status-failed {
background: rgba(239, 68, 68, 0.2);
color: #ef4444;
}
.status-complete {
background: rgba(16, 185, 129, 0.2);
color: #10b981;
}
.action-buttons {
display: flex;
gap: 0.5rem;
}
.btn-small {
padding: 0.5rem 1rem;
border: none;
border-radius: 6px;
font-size: 0.85rem;
cursor: pointer;
transition: all 0.3s ease;
}
.btn-check {
background: rgba(59, 130, 246, 0.2);
color: #3b82f6;
border: 1px solid rgba(59, 130, 246, 0.3);
}
.btn-check:hover {
background: rgba(59, 130, 246, 0.3);
}
.btn-fix {
background: rgba(16, 185, 129, 0.2);
color: #10b981;
border: 1px solid rgba(16, 185, 129, 0.3);
}
.btn-fix:hover {
background: rgba(16, 185, 129, 0.3);
}
.bulk-actions {
margin-bottom: 1rem;
padding: 1rem;
background: rgba(102, 126, 234, 0.1);
border-radius: 8px;
display: flex;
gap: 1rem;
align-items: center;
flex-wrap: wrap;
}
.bulk-actions input[type="checkbox"] {
width: 18px;
height: 18px;
cursor: pointer;
}
.loading {
display: inline-block;
width: 16px;
height: 16px;
border: 2px solid rgba(255, 255, 255, 0.3);
border-top-color: #667eea;
border-radius: 50%;
animation: spin 0.8s linear infinite;
}
@keyframes spin {
to { transform: rotate(360deg); }
}
.message {
padding: 1rem;
border-radius: 8px;
margin-bottom: 1rem;
}
.message-success {
background: rgba(16, 185, 129, 0.2);
color: #10b981;
border: 1px solid rgba(16, 185, 129, 0.3);
}
.message-error {
background: rgba(239, 68, 68, 0.2);
color: #ef4444;
border: 1px solid rgba(239, 68, 68, 0.3);
}
</style>
<div class="track-status-tool">
<h2 style="color: white; margin-bottom: 2rem;">
<i class="fas fa-check-circle"></i> Track Status Verification & Fix Tool
</h2>
<div class="stats-grid">
<div class="stat-card">
<h3><?= number_format($stats['total_tracks']) ?></h3>
<p>Total Tracks</p>
</div>
<div class="stat-card">
<h3><?= number_format($stats['processing_tracks']) ?></h3>
<p>Processing</p>
</div>
<div class="stat-card">
<h3><?= number_format($stats['old_processing']) ?></h3>
<p>Processing > 5 min</p>
</div>
<div class="stat-card">
<h3><?= number_format($stats['failed_tracks']) ?></h3>
<p>Failed</p>
</div>
</div>
<div class="filter-bar">
<select id="filterSelect" onchange="window.location.href='?tab=track-status-verify&filter=' + this.value">
<option value="processing_old" <?= $issue_filter === 'processing_old' ? 'selected' : '' ?>>Processing > 5 min</option>
<option value="all_processing" <?= $issue_filter === 'all_processing' ? 'selected' : '' ?>>All Processing</option>
<option value="all_failed" <?= $issue_filter === 'all_failed' ? 'selected' : '' ?>>All Failed</option>
<option value="all" <?= $issue_filter === 'all' ? 'selected' : '' ?>>All Issues</option>
</select>
<button onclick="bulkCheck()">
<i class="fas fa-sync"></i> Check Selected
</button>
<button onclick="bulkFix()" style="background: linear-gradient(135deg, #10b981, #059669);">
<i class="fas fa-wrench"></i> Fix Selected
</button>
<button onclick="checkAll()" style="background: linear-gradient(135deg, #3b82f6, #2563eb);">
<i class="fas fa-search"></i> Check All Visible
</button>
</div>
<div id="messageContainer"></div>
<div class="tracks-table">
<table>
<thead>
<tr>
<th><input type="checkbox" id="selectAll" onchange="toggleAll(this)"></th>
<th>ID</th>
<th>Title</th>
<th>User</th>
<th>Status</th>
<th>Task ID</th>
<th>Created</th>
<th>Time</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<?php if (empty($tracks)): ?>
<tr>
<td colspan="9" style="text-align: center; padding: 2rem; color: #a0aec0;">
No tracks found with current filter.
</td>
</tr>
<?php else: ?>
<?php foreach ($tracks as $track): ?>
<tr data-track-id="<?= $track['id'] ?>">
<td>
<input type="checkbox" class="track-checkbox" value="<?= $track['id'] ?>">
</td>
<td><?= $track['id'] ?></td>
<td><?= htmlspecialchars($track['title'] ?: 'Untitled') ?></td>
<td>
<?= htmlspecialchars($track['user_name'] ?: 'Unknown') ?><br>
<small style="color: #718096;"><?= htmlspecialchars($track['user_email'] ?: '') ?></small>
</td>
<td>
<span class="status-badge status-<?= $track['status'] ?>">
<?= strtoupper($track['status']) ?>
</span>
</td>
<td>
<small style="color: #718096; font-family: monospace;">
<?= htmlspecialchars(substr($track['task_id'] ?: $track['api_task_id'] ?: 'N/A', 0, 20)) ?>
</small>
</td>
<td><?= date('Y-m-d H:i', strtotime($track['created_at'])) ?></td>
<td>
<?php if ($track['status'] === 'processing'): ?>
<span style="color: #f59e0b;">
<?= number_format($track['minutes_processing']) ?> min
</span>
<?php else: ?>
-
<?php endif; ?>
</td>
<td>
<div class="action-buttons">
<button class="btn-small btn-check" onclick="checkTrack(<?= $track['id'] ?>)">
<i class="fas fa-search"></i> Check
</button>
<?php if ($track['status'] === 'processing'): ?>
<button class="btn-small btn-fix" onclick="fixTrack(<?= $track['id'] ?>)">
<i class="fas fa-wrench"></i> Fix
</button>
<?php endif; ?>
</div>
</td>
</tr>
<?php endforeach; ?>
<?php endif; ?>
</tbody>
</table>
</div>
</div>
<script>
function showMessage(message, type = 'success') {
const container = document.getElementById('messageContainer');
container.innerHTML = `<div class="message message-${type}">${message}</div>`;
setTimeout(() => {
container.innerHTML = '';
}, 5000);
}
function toggleAll(checkbox) {
const checkboxes = document.querySelectorAll('.track-checkbox');
checkboxes.forEach(cb => cb.checked = checkbox.checked);
}
function getSelectedTracks() {
const checkboxes = document.querySelectorAll('.track-checkbox:checked');
return Array.from(checkboxes).map(cb => cb.value);
}
async function checkTrack(trackId) {
const button = event.target.closest('button');
const originalHTML = button.innerHTML;
button.innerHTML = '<span class="loading"></span> Checking...';
button.disabled = true;
try {
const formData = new FormData();
formData.append('action', 'check_track');
formData.append('track_id', trackId);
const response = await fetch('', {
method: 'POST',
body: formData
});
const data = await response.json();
if (data.success) {
let message = `Track ${trackId}: DB Status = ${data.track.status}, API Status = ${data.api_status || 'N/A'}`;
if (data.needs_fix) {
message += ' ⚠️ NEEDS FIX';
}
showMessage(message, data.needs_fix ? 'error' : 'success');
// Update row if status changed
if (data.api_status && data.api_status !== data.track.status) {
const row = document.querySelector(`tr[data-track-id="${trackId}"]`);
if (row) {
const statusCell = row.querySelector('.status-badge');
if (statusCell) {
statusCell.className = `status-badge status-${data.api_status}`;
statusCell.textContent = data.api_status.toUpperCase();
}
}
}
} else {
showMessage('Error: ' + data.message, 'error');
}
} catch (error) {
showMessage('Error checking track: ' + error.message, 'error');
} finally {
button.innerHTML = originalHTML;
button.disabled = false;
}
}
async function fixTrack(trackId) {
if (!confirm(`Fix track ${trackId}? This will mark it as failed and refund the user's credit.`)) {
return;
}
const button = event.target.closest('button');
const originalHTML = button.innerHTML;
button.innerHTML = '<span class="loading"></span> Fixing...';
button.disabled = true;
try {
const formData = new FormData();
formData.append('action', 'fix_track');
formData.append('track_id', trackId);
formData.append('new_status', 'failed');
formData.append('error_message', 'Track generation failed (fixed by admin)');
const response = await fetch('', {
method: 'POST',
body: formData
});
const data = await response.json();
if (data.success) {
showMessage('Track fixed successfully!', 'success');
// Reload page after 1 second
setTimeout(() => window.location.reload(), 1000);
} else {
showMessage('Error: ' + data.message, 'error');
}
} catch (error) {
showMessage('Error fixing track: ' + error.message, 'error');
} finally {
button.innerHTML = originalHTML;
button.disabled = false;
}
}
async function bulkCheck() {
const trackIds = getSelectedTracks();
if (trackIds.length === 0) {
showMessage('Please select tracks to check', 'error');
return;
}
showMessage(`Checking ${trackIds.length} track(s)...`, 'success');
try {
const formData = new FormData();
formData.append('action', 'bulk_check');
trackIds.forEach(id => formData.append('track_ids[]', id));
const response = await fetch('', {
method: 'POST',
body: formData
});
const data = await response.json();
if (data.success) {
let needsFix = data.results.filter(r => r.needs_fix);
let message = `Checked ${data.results.length} track(s). `;
if (needsFix.length > 0) {
message += `${needsFix.length} need(s) fixing.`;
} else {
message += 'All tracks are OK.';
}
showMessage(message, needsFix.length > 0 ? 'error' : 'success');
} else {
showMessage('Error: ' + data.message, 'error');
}
} catch (error) {
showMessage('Error: ' + error.message, 'error');
}
}
async function bulkFix() {
const trackIds = getSelectedTracks();
if (trackIds.length === 0) {
showMessage('Please select tracks to fix', 'error');
return;
}
if (!confirm(`Fix ${trackIds.length} track(s)? This will mark them as failed and refund credits.`)) {
return;
}
showMessage(`Fixing ${trackIds.length} track(s)...`, 'success');
try {
const formData = new FormData();
formData.append('action', 'bulk_fix');
trackIds.forEach(id => formData.append('track_ids[]', id));
const response = await fetch('', {
method: 'POST',
body: formData
});
const data = await response.json();
if (data.success) {
showMessage(`Fixed ${data.fixed_count} track(s)!`, 'success');
setTimeout(() => window.location.reload(), 1500);
} else {
showMessage('Error: ' + data.message, 'error');
}
} catch (error) {
showMessage('Error: ' + error.message, 'error');
}
}
async function checkAll() {
const checkboxes = document.querySelectorAll('.track-checkbox');
checkboxes.forEach(cb => cb.checked = true);
await bulkCheck();
}
</script>