39514-vm/db/scdiscord.php
2026-04-08 16:29:33 +00:00

244 lines
7.5 KiB
PHP

<?php
require_once __DIR__ . '/config.php';
function scdiscord_bootstrap(): void
{
static $bootstrapped = false;
if ($bootstrapped) {
return;
}
$db = db();
$db->exec(
"CREATE TABLE IF NOT EXISTS tbl_scwebhooks (
cl_scwebhook_id INT(11) NOT NULL AUTO_INCREMENT,
cl_scwebhook_name VARCHAR(255) NOT NULL,
cl_scwebhook_url TEXT NOT NULL,
cl_scwebhook_is_forum TINYINT(1) NOT NULL DEFAULT 0,
PRIMARY KEY (cl_scwebhook_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci"
);
$db->exec(
"CREATE TABLE IF NOT EXISTS tbl_scbanners (
cl_scbanner_id INT(11) NOT NULL AUTO_INCREMENT,
cl_scbanner_name VARCHAR(255) NOT NULL,
cl_scbanner_url TEXT NOT NULL,
cl_scbanner_border_color VARCHAR(20) NOT NULL DEFAULT '#ffae00',
PRIMARY KEY (cl_scbanner_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci"
);
$columns_stmt = $db->query("SHOW COLUMNS FROM tbl_scbanners LIKE 'cl_scbanner_border_color'");
$has_border_color = (bool) $columns_stmt->fetch();
if (!$has_border_color) {
$db->exec("ALTER TABLE tbl_scbanners ADD COLUMN cl_scbanner_border_color VARCHAR(20) NOT NULL DEFAULT '#ffae00' AFTER cl_scbanner_url");
}
$db->exec(
"CREATE TABLE IF NOT EXISTS tbl_scnotifications (
cl_scnotification_id INT(11) NOT NULL AUTO_INCREMENT,
cl_scnotification_webhook_id INT(11) NOT NULL,
cl_scnotification_banner_id INT(11) DEFAULT NULL,
cl_scnotification_title VARCHAR(255) NOT NULL DEFAULT '',
cl_scnotification_message TEXT NOT NULL,
cl_scnotification_payload LONGTEXT NOT NULL,
cl_scnotification_response LONGTEXT DEFAULT NULL,
cl_scnotification_success TINYINT(1) NOT NULL DEFAULT 0,
cl_scnotification_created_by VARCHAR(190) NOT NULL,
cl_scnotification_created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (cl_scnotification_id),
KEY idx_scnotification_webhook (cl_scnotification_webhook_id),
KEY idx_scnotification_banner (cl_scnotification_banner_id),
CONSTRAINT fk_scnotification_webhook FOREIGN KEY (cl_scnotification_webhook_id)
REFERENCES tbl_scwebhooks (cl_scwebhook_id)
ON UPDATE CASCADE
ON DELETE RESTRICT,
CONSTRAINT fk_scnotification_banner FOREIGN KEY (cl_scnotification_banner_id)
REFERENCES tbl_scbanners (cl_scbanner_id)
ON UPDATE CASCADE
ON DELETE SET NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci"
);
$stmt_existing_red = $db->prepare('SELECT cl_scbanner_id FROM tbl_scbanners WHERE cl_scbanner_name = :name LIMIT 1');
$stmt_existing_red->execute(['name' => 'Alerte Rouge']);
$existing_red_banner = $stmt_existing_red->fetch(PDO::FETCH_ASSOC);
if ($existing_red_banner) {
$stmt_update_red = $db->prepare(
'UPDATE tbl_scbanners
SET cl_scbanner_border_color = CASE
WHEN cl_scbanner_border_color IS NULL OR cl_scbanner_border_color = "" OR cl_scbanner_border_color = "#ffae00"
THEN :border_color
ELSE cl_scbanner_border_color
END
WHERE cl_scbanner_id = :id'
);
$stmt_update_red->execute([
'border_color' => '#ff3b30',
'id' => $existing_red_banner['cl_scbanner_id'],
]);
}
$bootstrapped = true;
}
function scdiscord_mask_webhook_url(string $url): string
{
$trimmed = trim($url);
if ($trimmed === '') {
return '';
}
$length = strlen($trimmed);
if ($length <= 24) {
return str_repeat('•', max(8, $length));
}
return substr($trimmed, 0, 32) . str_repeat('•', 18) . substr($trimmed, -10);
}
function scdiscord_normalize_hex_color(string $color): string
{
$candidate = strtoupper(trim($color));
if ($candidate === '') {
return '#FFAE00';
}
if ($candidate[0] !== '#') {
$candidate = '#' . $candidate;
}
if (!preg_match('/^#[0-9A-F]{6}$/', $candidate)) {
return '#FFAE00';
}
return $candidate;
}
function scdiscord_hex_to_decimal(string $color): int
{
return hexdec(ltrim(scdiscord_normalize_hex_color($color), '#'));
}
function scdiscord_build_mentions(bool $notify_here, bool $notify_everyone): array
{
$parts = [];
if ($notify_here) {
$parts[] = '@here';
}
if ($notify_everyone) {
$parts[] = '@everyone';
}
return $parts;
}
function scdiscord_build_thread_name(string $title, string $location, string $start_date): string
{
$parts = [];
if ($title !== '') {
$parts[] = $title;
}
if ($location !== '') {
$parts[] = $location;
}
if ($start_date !== '') {
$parts[] = $start_date;
}
$thread_name = trim(implode(' • ', $parts));
if ($thread_name === '') {
$thread_name = 'Notification Discord';
}
return mb_substr($thread_name, 0, 100);
}
function scdiscord_post_webhook(string $webhook_url, array $payload): array
{
$target_url = $webhook_url;
$separator = (str_contains($target_url, '?')) ? '&' : '?';
$target_url .= $separator . 'wait=true';
$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.',
];
}
if (function_exists('curl_init')) {
$ch = curl_init($target_url);
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $json_payload,
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
'Content-Length: ' . strlen($json_payload),
],
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 20,
]);
$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,
];
}
$context = stream_context_create([
'http' => [
'method' => 'POST',
'header' => "Content-Type: application/json\r\n",
'content' => $json_payload,
'timeout' => 20,
'ignore_errors' => true,
],
]);
$response = @file_get_contents($target_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,
];
}