T.ME/BIBIL_0DAY
CasperSecurity


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/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Current File : /home/gositeme/.cursor-server/data/User/History/-6fee586/uYsp.php
<?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>







CasperSecurity Mini