38550-vm/api/interactions.php
2026-02-18 05:42:57 +00:00

165 lines
4.9 KiB
PHP

<?php
declare(strict_types=1);
require_once __DIR__ . '/../includes/app.php';
// Set response header
header('Content-Type: application/json');
function verify_signature($publicKey): bool {
$signature = $_SERVER['HTTP_X_SIGNATURE_ED25519'] ?? null;
$timestamp = $_SERVER['HTTP_X_SIGNATURE_TIMESTAMP'] ?? null;
$body = file_get_contents('php://input');
if (!$signature || !$timestamp || !$body) {
return false;
}
$message = $timestamp . $body;
try {
return sodium_crypto_sign_verify_detached(
hex2bin($signature),
$message,
hex2bin($publicKey)
);
} catch (Exception $e) {
return false;
}
}
$settings = get_settings();
$publicKey = $settings['discord_public_key'] ?? '';
if (empty($publicKey)) {
http_response_code(500);
echo json_encode(['error' => 'Public key not configured']);
exit;
}
if (!verify_signature($publicKey)) {
http_response_code(401);
echo json_encode(['error' => 'Invalid request signature']);
exit;
}
$input = file_get_contents('php://input');
$data = json_decode($input, true);
if (!$data) {
http_response_code(400);
echo json_encode(['error' => 'Invalid JSON']);
exit;
}
// Type 1: PING
if ($data['type'] === 1) {
echo json_encode(['type' => 1]);
exit;
}
// Type 2: APPLICATION_COMMAND
if ($data['type'] === 2) {
$commandName = $data['data']['name'];
$user = $data['member']['user']['username'] ?? $data['user']['username'] ?? 'Unknown';
$userId = $data['member']['user']['id'] ?? $data['user']['id'] ?? '0';
$guildId = $data['guild_id'] ?? 'DM';
$userRoles = $data['member']['roles'] ?? [];
// Permission check removed as per user request (no DJ role needed)
switch ($commandName) {
case 'play':
$query = '';
foreach ($data['data']['options'] as $opt) {
if ($opt['name'] === 'query') {
$query = $opt['value'];
break;
}
}
if (empty($query)) {
echo json_encode([
'type' => 4,
'data' => ['content' => 'Please provide a song query.']
]);
exit;
}
// Add to database queue
$pdo = db();
$stmt = $pdo->prepare('INSERT INTO music_requests (guild_name, requester_name, query_text, source_type, status) VALUES (:guild, :user, :query, :source, "queued")');
$stmt->execute([
':guild' => $guildId,
':user' => $user,
':query' => $query,
':source' => 'discord_slash'
]);
add_log($user, 'slash_command', "Played: $query", $guildId);
echo json_encode([
'type' => 4,
'data' => ['content' => "✅ Added to queue: **$query**"]
]);
break;
case 'queue':
$pdo = db();
$requests = $pdo->query('SELECT query_text, status FROM music_requests WHERE status IN ("queued", "playing") ORDER BY id ASC LIMIT 5')->fetchAll();
if (empty($requests)) {
$content = "The queue is currently empty.";
} else {
$content = "🎶 **Current Queue:**\n";
foreach ($requests as $index => $req) {
$prefix = ($req['status'] === 'playing') ? "▶️" : ($index + 1) . ".";
$content .= "$prefix {$req['query_text']} ({$req['status']})\n";
}
}
echo json_encode([
'type' => 4,
'data' => ['content' => $content]
]);
break;
case 'skip':
$pdo = db();
$stmt = $pdo->prepare('UPDATE music_requests SET status = "skipped" WHERE status = "playing" LIMIT 1');
$stmt->execute();
if ($stmt->rowCount() > 0) {
$msg = "⏭️ Skipped the current song.";
add_log($user, 'slash_command', "Skipped current song", $guildId);
} else {
$msg = "There is no song currently playing to skip.";
}
echo json_encode([
'type' => 4,
'data' => ['content' => $msg]
]);
break;
case 'stop':
$pdo = db();
$pdo->exec('UPDATE music_requests SET status = "failed" WHERE status IN ("queued", "playing")');
add_log($user, 'slash_command', "Stopped and cleared queue", $guildId);
echo json_encode([
'type' => 4,
'data' => ['content' => "🛑 Music stopped and queue cleared."]
]);
break;
default:
echo json_encode([
'type' => 4,
'data' => ['content' => "Unknown command: $commandName"]
]);
break;
}
}