From fb07ff7d2ea36254d41929e7d467316041ceb112 Mon Sep 17 00:00:00 2001 From: Flatlogic Bot Date: Thu, 9 Apr 2026 00:13:43 +0000 Subject: [PATCH] Autosave: 20260409-001343 --- db/config.php | 4 + db/scdiscord.php | 203 +++++++++++++++++++++++++++++++++++++++++++++ scnotification.php | 55 +++++++----- 3 files changed, 242 insertions(+), 20 deletions(-) diff --git a/db/config.php b/db/config.php index 845f555..aa3b566 100644 --- a/db/config.php +++ b/db/config.php @@ -5,6 +5,10 @@ define('DB_NAME', 'app_39514'); define('DB_USER', 'app_39514'); define('DB_PASS', 'ee6da88c-09af-4b48-b728-7a55edfb4e42'); +if (!defined('DISCORD_BOT_TOKEN')) { + define('DISCORD_BOT_TOKEN', 'MTQyNTgwNjIxOTMwNTY4MTAxOA.GGq1cp.CjHC7vQogGrX_HS2WnuXLf4XOLAnWLC5Cm-XA4'); +} + function db() { static $pdo; if (!$pdo) { diff --git a/db/scdiscord.php b/db/scdiscord.php index 59a58a4..8a894f5 100644 --- a/db/scdiscord.php +++ b/db/scdiscord.php @@ -241,3 +241,206 @@ function scdiscord_post_webhook(string $webhook_url, array $payload): array 'response' => $response === false ? 'Erreur lors de la requête HTTP.' : $response, ]; } + +function scdiscord_get_bot_token(): string +{ + $candidates = []; + + if (defined('DISCORD_BOT_TOKEN') && is_string(DISCORD_BOT_TOKEN)) { + $candidates[] = DISCORD_BOT_TOKEN; + } + + foreach (['DISCORD_BOT_TOKEN', 'SC_DISCORD_BOT_TOKEN', 'BOT_TOKEN'] as $env_key) { + $value = getenv($env_key); + if ($value !== false) { + $candidates[] = $value; + } + } + + foreach ($candidates as $candidate) { + $token = trim((string) $candidate); + if ($token !== '') { + return $token; + } + } + + return ''; +} + +function scdiscord_decode_json_response(?string $response): array +{ + if (!is_string($response) || trim($response) === '') { + return []; + } + + $decoded = json_decode($response, true); + return is_array($decoded) ? $decoded : []; +} + +function scdiscord_bot_request(string $method, string $url, string $bot_token, ?array $payload = null): array +{ + $headers = [ + 'Authorization: Bot ' . $bot_token, + ]; + + $json_payload = null; + if ($payload !== null) { + $json_payload = json_encode($payload, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); + if ($json_payload === false) { + return [ + 'success' => false, + 'http_code' => 0, + 'response' => 'Erreur d\'encodage JSON.', + ]; + } + $headers[] = 'Content-Type: application/json'; + $headers[] = 'Content-Length: ' . strlen($json_payload); + } + + if (function_exists('curl_init')) { + $ch = curl_init($url); + curl_setopt_array($ch, [ + CURLOPT_CUSTOMREQUEST => strtoupper($method), + CURLOPT_HTTPHEADER => $headers, + CURLOPT_RETURNTRANSFER => true, + CURLOPT_TIMEOUT => 20, + ]); + + if ($json_payload !== null) { + curl_setopt($ch, CURLOPT_POSTFIELDS, $json_payload); + } + + $response = curl_exec($ch); + $http_code = (int) curl_getinfo($ch, CURLINFO_HTTP_CODE); + $curl_error = curl_error($ch); + curl_close($ch); + + if ($response === false) { + return [ + 'success' => false, + 'http_code' => $http_code, + 'response' => $curl_error !== '' ? $curl_error : 'Erreur CURL inconnue.', + ]; + } + + return [ + 'success' => $http_code >= 200 && $http_code < 300, + 'http_code' => $http_code, + 'response' => $response, + ]; + } + + $header_lines = implode("\r\n", $headers) . "\r\n"; + $context = stream_context_create([ + 'http' => [ + 'method' => strtoupper($method), + 'header' => $header_lines, + 'content' => $json_payload ?? '', + 'timeout' => 20, + 'ignore_errors' => true, + ], + ]); + + $response = @file_get_contents($url, false, $context); + $http_code = 0; + if (isset($http_response_header) && is_array($http_response_header)) { + foreach ($http_response_header as $header_line) { + if (preg_match('#^HTTP/\S+\s+(\d{3})#', $header_line, $matches)) { + $http_code = (int) $matches[1]; + break; + } + } + } + + return [ + 'success' => $response !== false && $http_code >= 200 && $http_code < 300, + 'http_code' => $http_code, + 'response' => $response === false ? 'Erreur lors de la requête HTTP.' : $response, + ]; +} + +function scdiscord_apply_bot_actions(array $message_data, bool $use_reactions, bool $use_publicthread, string $thread_name): array +{ + if (!$use_reactions && !$use_publicthread) { + return [ + 'success' => true, + 'http_code' => 200, + 'response' => 'Aucune action bot demandée.', + 'details' => [], + ]; + } + + $message_id = trim((string) ($message_data['id'] ?? '')); + $channel_id = trim((string) ($message_data['channel_id'] ?? '')); + + if ($message_id === '' || $channel_id === '') { + return [ + 'success' => false, + 'http_code' => 0, + 'response' => 'Réponse Discord invalide : id de message ou channel_id manquant.', + 'details' => [], + ]; + } + + $bot_token = scdiscord_get_bot_token(); + if ($bot_token === '') { + return [ + 'success' => false, + 'http_code' => 0, + 'response' => 'Token bot Discord manquant. Définis DISCORD_BOT_TOKEN côté serveur.', + 'details' => [], + ]; + } + + $details = []; + $failed = false; + $last_http_code = 200; + + if ($use_reactions) { + foreach (['👍', '⌛', '❔', '👎'] as $emoji) { + $url = 'https://discord.com/api/v10/channels/' . rawurlencode($channel_id) . '/messages/' . rawurlencode($message_id) . '/reactions/' . rawurlencode($emoji) . '/@me'; + $result = scdiscord_bot_request('PUT', $url, $bot_token); + $details[] = [ + 'action' => 'reaction', + 'emoji' => $emoji, + 'success' => !empty($result['success']), + 'http_code' => (int) ($result['http_code'] ?? 0), + 'response' => (string) ($result['response'] ?? ''), + ]; + $last_http_code = (int) ($result['http_code'] ?? $last_http_code); + if (empty($result['success'])) { + $failed = true; + break; + } + usleep(300000); + } + } + + if (!$failed && $use_publicthread) { + $thread_payload = [ + 'name' => $thread_name !== '' ? $thread_name : 'Discussion - Opération', + 'auto_archive_duration' => 1440, + 'type' => 11, + ]; + $url = 'https://discord.com/api/v10/channels/' . rawurlencode($channel_id) . '/messages/' . rawurlencode($message_id) . '/threads'; + $result = scdiscord_bot_request('POST', $url, $bot_token, $thread_payload); + $details[] = [ + 'action' => 'thread', + 'success' => !empty($result['success']), + 'http_code' => (int) ($result['http_code'] ?? 0), + 'response' => (string) ($result['response'] ?? ''), + ]; + $last_http_code = (int) ($result['http_code'] ?? $last_http_code); + if (empty($result['success'])) { + $failed = true; + } + } + + return [ + 'success' => !$failed, + 'http_code' => $failed ? $last_http_code : 200, + 'response' => json_encode($details, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), + 'details' => $details, + ]; +} + diff --git a/scnotification.php b/scnotification.php index 03febb3..db7467c 100644 --- a/scnotification.php +++ b/scnotification.php @@ -172,9 +172,6 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { $fields[] = ['name' => 'Source', 'value' => '[Ouvrir la source](' . $cl_scnotification_source_url . ')', 'inline' => false]; } - if ($show_reactions) { - $fields[] = ['name' => 'Réactions', 'value' => '👍 / ⏳ / ❓ / 👎', 'inline' => false]; - } $embed = [ 'description' => mb_substr($cl_scnotification_message, 0, 4096), @@ -212,23 +209,39 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { $payload['allowed_mentions'] = ['parse' => ['everyone']]; } - $is_forum_webhook = ((int) ($webhook['cl_scwebhook_is_forum'] ?? 0) === 1); - if ($is_forum_webhook) { - $payload['thread_name'] = scdiscord_build_thread_name( + $thread_name = $show_thread + ? ('Discussion - ' . scdiscord_build_thread_name( $cl_scnotification_title, $cl_scnotification_location, $cl_scnotification_start_date - ); - } elseif ($show_thread) { - $embed['fields'][] = [ - 'name' => 'Fil de discussion', - 'value' => 'Le webhook sélectionné n’est pas de type forum.', - 'inline' => false, - ]; - $payload['embeds'] = [$embed]; - } + )) + : ''; $result = scdiscord_post_webhook((string) $webhook['cl_scwebhook_url'], $payload); + $bot_actions = [ + 'success' => true, + 'http_code' => 200, + 'response' => 'Aucune action bot demandée.', + ]; + + if (!empty($result['success']) && ($show_reactions || $show_thread)) { + $message_data = scdiscord_decode_json_response((string) ($result['response'] ?? '')); + $bot_actions = scdiscord_apply_bot_actions($message_data, $show_reactions, $show_thread, $thread_name); + } + + $log_response = json_encode([ + 'webhook' => [ + 'success' => !empty($result['success']), + 'http_code' => (int) ($result['http_code'] ?? 0), + 'response' => (string) ($result['response'] ?? ''), + ], + 'bot_actions' => [ + 'success' => !empty($bot_actions['success']), + 'http_code' => (int) ($bot_actions['http_code'] ?? 0), + 'response' => (string) ($bot_actions['response'] ?? ''), + 'details' => $bot_actions['details'] ?? [], + ], + ], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); $stmt_log = $db->prepare( 'INSERT INTO tbl_scnotifications ( @@ -257,16 +270,18 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { 'title' => $cl_scnotification_title, 'message' => $cl_scnotification_message, 'payload' => json_encode($payload, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), - 'response' => (string) ($result['response'] ?? ''), - 'success' => !empty($result['success']) ? 1 : 0, + 'response' => $log_response !== false ? $log_response : (string) ($result['response'] ?? ''), + 'success' => (!empty($result['success']) && !empty($bot_actions['success'])) ? 1 : 0, 'created_by' => $current_session_user !== '' ? $current_session_user : 'Inconnu', ]); - if (!empty($result['success'])) { + if (empty($result['success'])) { + auth_flash_set('error', 'Échec de l’envoi Discord (HTTP ' . (int) ($result['http_code'] ?? 0) . ').'); + } elseif (empty($bot_actions['success'])) { + auth_flash_set('error', 'Notification envoyée, mais échec des actions bot Discord : ' . (string) ($bot_actions['response'] ?? 'Erreur inconnue.')); + } else { unset($_SESSION['scnotification_old']); auth_flash_set('success', 'Notification Discord envoyée avec succès.'); - } else { - auth_flash_set('error', 'Échec de l’envoi Discord (HTTP ' . (int) ($result['http_code'] ?? 0) . ').'); } header('Location: scnotification.php');