test 1.2 de la récupération de pp discord sur site web

This commit is contained in:
KIRITO_KMA 2026-02-08 22:31:31 +01:00
parent d2bcf00ee7
commit 42db666026
4 changed files with 525 additions and 3 deletions

View file

@ -1,5 +1,17 @@
# Sécurisation minimale # Désactiver l'affichage des dossiers
Options -Indexes Options -Indexes
# Page 404 personnalisée <IfModule mod_rewrite.c>
ErrorDocument 404 omegakube/pages/404.html RewriteEngine On
# Si fichier/dossier n'existe pas → afficher 404.php
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^ pages/404.php [L]
# Si c'est un dossier sans index → afficher 404.php
RewriteCond %{REQUEST_FILENAME} -d
RewriteCond %{REQUEST_FILENAME}/index.html !-f
RewriteCond %{REQUEST_FILENAME}/index.php !-f
RewriteRule ^ pages/404.php [L]
</IfModule>

View file

@ -1,3 +1,5 @@
<?php http_response_code(404); ?>
<!DOCTYPE html> <!DOCTYPE html>
<html lang="fr" data-theme="dark"> <html lang="fr" data-theme="dark">
<head> <head>

49
pages/test.html Normal file
View file

@ -0,0 +1,49 @@
<div id="member1"></div>
<div id="member2"></div>
<div id="member3"></div>
<div id="member4"></div>
<script>
function showMember(userId, divId) {
fetch(`http://localhost:5000/api/user/${userId}`)
.then(res => res.json())
.then(data => {
document.getElementById(divId).innerHTML = `
<img src="${data.avatar_url}" width="80">
<p>${data.username}</p>
`;
})
.catch(() => {
document.getElementById(divId).innerHTML = `
<img src="https://cdn.discordapp.com/embed/avatars/0.png" width="80">
<p>Utilisateur inconnu</p>
`;
});
}
showMember(971446412690722826, "member1");
showMember(353942721997832195, "member2");
showMember(534003230435442690, "member3");
showMember(561485865562406914, "member4");
</script>
<div id="partners"></div>
<script>
fetch("http://localhost:5000/api/partners")
.then(res => res.json())
.then(partners => {
const container = document.getElementById("partners");
partners.forEach(server => {
const icon = server.icon_url || "https://cdn.discordapp.com/embed/avatars/0.png";
container.innerHTML += `
<div class="partner">
<img src="${icon}" width="80" style="border-radius:50%">
<h3>${server.name}</h3>
<p>${server.member_count} membres</p>
</div>
`;
});
});
</script>

459
pages/test2.html Normal file
View file

@ -0,0 +1,459 @@
<!doctype html>
<html lang="fr">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
<title>Kuby API Dashboard</title>
<style>
:root {
--bg: #0b1220;
--panel: #111a2e;
--panel2: #0f172a;
--text: #e5e7eb;
--muted: #9ca3af;
--accent: #60a5fa;
--ok: #34d399;
--bad: #f87171;
--border: rgba(255,255,255,.08);
}
body {
margin: 0;
font-family: ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Arial;
background: radial-gradient(1200px 700px at 15% 10%, rgba(96,165,250,.18), transparent 60%),
radial-gradient(900px 600px at 90% 15%, rgba(52,211,153,.14), transparent 55%),
var(--bg);
color: var(--text);
}
header {
padding: 24px 20px 10px;
border-bottom: 1px solid var(--border);
background: linear-gradient(180deg, rgba(255,255,255,.03), transparent);
}
h1 { margin: 0 0 6px; font-size: 20px; letter-spacing: .2px; }
.sub { color: var(--muted); font-size: 13px; }
.wrap { max-width: 1100px; margin: 0 auto; padding: 18px 20px 34px; }
.grid {
display: grid;
grid-template-columns: 1fr;
gap: 14px;
}
@media (min-width: 900px) {
.grid { grid-template-columns: 1fr 1fr; }
.span2 { grid-column: span 2; }
}
.card {
background: rgba(17,26,46,.75);
border: 1px solid var(--border);
border-radius: 14px;
padding: 14px;
box-shadow: 0 10px 30px rgba(0,0,0,.25);
backdrop-filter: blur(8px);
}
.card h2 {
margin: 0 0 10px;
font-size: 15px;
color: #f3f4f6;
display: flex;
align-items: center;
justify-content: space-between;
gap: 10px;
}
.row { display: flex; gap: 10px; flex-wrap: wrap; align-items: center; }
input, button, select {
background: rgba(15,23,42,.85);
border: 1px solid var(--border);
color: var(--text);
border-radius: 10px;
padding: 10px 10px;
font-size: 14px;
outline: none;
}
input::placeholder { color: rgba(156,163,175,.7); }
button {
cursor: pointer;
background: linear-gradient(180deg, rgba(96,165,250,.22), rgba(96,165,250,.06));
border-color: rgba(96,165,250,.35);
}
button:hover { border-color: rgba(96,165,250,.55); }
button:disabled { opacity: .6; cursor: not-allowed; }
.pill {
font-size: 12px;
padding: 5px 9px;
border-radius: 999px;
border: 1px solid var(--border);
color: var(--muted);
background: rgba(15,23,42,.7);
white-space: nowrap;
}
.pill.ok { color: #a7f3d0; border-color: rgba(52,211,153,.35); background: rgba(52,211,153,.10); }
.pill.bad { color: #fecaca; border-color: rgba(248,113,113,.35); background: rgba(248,113,113,.10); }
pre {
margin: 10px 0 0;
background: rgba(15,23,42,.75);
border: 1px solid var(--border);
border-radius: 12px;
padding: 12px;
overflow: auto;
max-height: 360px;
font-size: 12px;
color: #d1d5db;
}
.muted { color: var(--muted); font-size: 13px; }
.list {
margin-top: 10px;
display: grid;
grid-template-columns: 1fr;
gap: 10px;
}
@media (min-width: 700px) {
.list { grid-template-columns: 1fr 1fr; }
}
.item {
display: flex;
gap: 12px;
align-items: center;
padding: 10px;
border-radius: 12px;
border: 1px solid var(--border);
background: rgba(15,23,42,.60);
}
.avatar, .icon {
width: 44px; height: 44px;
border-radius: 12px;
background: rgba(255,255,255,.06);
border: 1px solid var(--border);
object-fit: cover;
flex: 0 0 auto;
}
.item .meta { min-width: 0; }
.name { font-weight: 650; font-size: 14px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.small { font-size: 12px; color: var(--muted); }
.right { margin-left: auto; display:flex; gap:8px; align-items:center; }
a.link {
color: #bfdbfe;
text-decoration: none;
border-bottom: 1px dashed rgba(191,219,254,.35);
}
.err { color: #fecaca; }
.oktxt { color: #a7f3d0; }
</style>
</head>
<body>
<header>
<div class="wrap">
<h1>Kuby API Dashboard</h1>
<div class="sub">
Affiche les réponses de l’API Flask: <code>/api/status</code>, <code>/api/user/&​lt;id&​gt;</code>, <code>/api/guilds</code>, <code>/api/guild/&​lt;id&​gt;</code>
</div>
</div>
</header>
<div class="wrap">
<div class="grid">
<section class="card">
<h2>
Statut du bot
<span id="statusPill" class="pill">non chargé</span>
</h2>
<div class="row">
<button id="btnStatus">Charger /api/status</button>
<span class="muted">Affiche le statut global.</span>
</div>
<pre id="statusOut">{}</pre>
</section>
<section class="card">
<h2>
Rechercher un utilisateur
<span id="userPill" class="pill">/api/user/&​lt;id&​gt;</span>
</h2>
<div class="row">
<input id="userId" type="number" placeholder="User ID (ex: 123...)" />
<button id="btnUser">Charger</button>
</div>
<div id="userCard" class="list" style="grid-template-columns: 1fr; display:none;">
<div class="item">
<img id="userAvatar" class="avatar" alt="avatar" />
<div class="meta">
<div id="userName" class="name">—</div>
<div id="userAvatarUrl" class="small">—</div>
</div>
<div class="right">
<a id="userAvatarLink" class="link" href="#" target="_blank" rel="noreferrer">Ouvrir avatar</a>
</div>
</div>
</div>
<pre id="userOut">{}</pre>
</section>
<section class="card span2">
<h2>
Serveurs du bot
<span id="guildsPill" class="pill">/api/guilds</span>
</h2>
<div class="row">
<button id="btnGuilds">Charger la liste</button>
<span class="muted">Clique un serveur pour charger ses détails.</span>
</div>
<div id="guildsList" class="list"></div>
<pre id="guildsOut">{}</pre>
</section>
<section class="card span2">
<h2>
Détails d’un serveur
<span id="guildPill" class="pill">/api/guild/&​lt;id&​gt;</span>
</h2>
<div class="row">
<input id="guildId" type="number" placeholder="Guild ID (ex: 123...)" />
<button id="btnGuild">Charger</button>
<span id="guildHint" class="muted">Astuce: tu peux aussi cliquer un serveur dans la liste au-dessus.</span>
</div>
<div id="guildCard" class="list" style="grid-template-columns: 1fr; display:none;"></div>
<pre id="guildOut">{}</pre>
</section>
</div>
</div>
<script>
// Change ici si ton API est ailleurs (ex: http://localhost:5000)
const API_BASE = "http://127.0.0.1:5000";
const $ = (id) => document.getElementById(id);
function pretty(obj) {
return JSON.stringify(obj, null, 2);
}
async function apiGet(path) {
const url = API_BASE + path;
const res = await fetch(url, { method: "GET" });
let data = null;
try {
data = await res.json();
} catch (e) {
// si la réponse n'est pas JSON
const text = await res.text();
throw new Error(`Réponse non JSON (${res.status}) depuis ${url}: ${text}`);
}
if (!res.ok) {
const msg = (data && (data.error || data.message)) ? (data.error || data.message) : `HTTP ${res.status}`;
const err = new Error(msg);
err.status = res.status;
err.data = data;
throw err;
}
return data;
}
function setPill(el, kind, text) {
el.classList.remove("ok", "bad");
if (kind === "ok") el.classList.add("ok");
if (kind === "bad") el.classList.add("bad");
el.textContent = text;
}
// STATUS
$("btnStatus").addEventListener("click", async () => {
$("btnStatus").disabled = true;
setPill($("statusPill"), "", "chargement...");
try {
const data = await apiGet("/api/status");
$("statusOut").textContent = pretty(data);
setPill($("statusPill"), data.status === "online" ? "ok" : "", data.status || "ok");
} catch (e) {
$("statusOut").textContent = pretty({ error: e.message, status: e.status || null, data: e.data || null });
setPill($("statusPill"), "bad", "erreur");
} finally {
$("btnStatus").disabled = false;
}
});
// USER
$("btnUser").addEventListener("click", async () => {
const id = $("userId").value?.trim();
$("userCard").style.display = "none";
$("btnUser").disabled = true;
setPill($("userPill"), "", "chargement...");
try {
if (!id) throw new Error("Tu dois renseigner un user_id.");
const data = await apiGet(`/api/user/${encodeURIComponent(id)}`);
$("userOut").textContent = pretty(data);
$("userName").textContent = data.username ?? "—";
$("userAvatar").src = data.avatar_url ?? "https://cdn.discordapp.com/embed/avatars/0.png";
$("userAvatarUrl").textContent = data.avatar_url ?? "—";
$("userAvatarLink").href = data.avatar_url ?? "#";
$("userCard").style.display = "grid";
setPill($("userPill"), "ok", "ok");
} catch (e) {
$("userOut").textContent = pretty({ error: e.message, status: e.status || null, data: e.data || null });
setPill($("userPill"), "bad", "erreur");
} finally {
$("btnUser").disabled = false;
}
});
// GUILDS LIST
$("btnGuilds").addEventListener("click", async () => {
$("btnGuilds").disabled = true;
setPill($("guildsPill"), "", "chargement...");
$("guildsList").innerHTML = "";
try {
const data = await apiGet("/api/guilds");
$("guildsOut").textContent = pretty(data);
for (const g of data) {
const div = document.createElement("div");
div.className = "item";
div.style.cursor = "pointer";
div.title = "Cliquer pour charger /api/guild/<id>";
const img = document.createElement("img");
img.className = "icon";
img.alt = "icon";
img.src = g.icon_url || "https://cdn.discordapp.com/embed/avatars/0.png";
const meta = document.createElement("div");
meta.className = "meta";
const name = document.createElement("div");
name.className = "name";
name.textContent = g.name || "Sans nom";
const small = document.createElement("div");
small.className = "small";
small.textContent = `ID: ${g.id} | Membres: ${g.member_count ?? "?"}`;
meta.appendChild(name);
meta.appendChild(small);
const right = document.createElement("div");
right.className = "right";
const pill = document.createElement("span");
pill.className = "pill";
pill.textContent = "voir détails";
right.appendChild(pill);
div.appendChild(img);
div.appendChild(meta);
div.appendChild(right);
div.addEventListener("click", async () => {
$("guildId").value = g.id;
await loadGuild(g.id);
});
$("guildsList").appendChild(div);
}
setPill($("guildsPill"), "ok", `${data.length} serveurs`);
} catch (e) {
$("guildsOut").textContent = pretty({ error: e.message, status: e.status || null, data: e.data || null });
setPill($("guildsPill"), "bad", "erreur");
} finally {
$("btnGuilds").disabled = false;
}
});
async function loadGuild(id) {
$("guildCard").style.display = "none";
$("btnGuild").disabled = true;
setPill($("guildPill"), "", "chargement...");
try {
if (!id) throw new Error("Tu dois renseigner un guild_id.");
const data = await apiGet(`/api/guild/${encodeURIComponent(id)}`);
$("guildOut").textContent = pretty(data);
// carte “propre” comme user
const html = `
<div class="item">
<img class="icon" alt="icon" src="${(data.icon_url || "https://cdn.discordapp.com/embed/avatars/0.png")}" />
<div class="meta">
<div class="name">${escapeHtml(data.name || "Sans nom")}</div>
<div class="small">ID: ${data.id} | Membres: ${data.member_count ?? "?"} | Owner: ${data.owner_id ?? "?"}</div>
<div class="small">${data.description ? escapeHtml(data.description) : ""}</div>
</div>
<div class="right">
${data.icon_url ? `<a class="link" href="${data.icon_url}" target="_blank" rel="noreferrer">Ouvrir icône</a>` : ""}
</div>
</div>
<div class="item" style="align-items:flex-start;">
<div class="meta" style="width:100%;">
<div class="name">Channels (${(data.channels || []).length})</div>
<div class="small">${renderChannels(data.channels || [])}</div>
</div>
</div>
<div class="item" style="align-items:flex-start;">
<div class="meta" style="width:100%;">
<div class="name">Roles (${(data.roles || []).length})</div>
<div class="small">${renderRoles(data.roles || [])}</div>
</div>
</div>
`;
$("guildCard").innerHTML = html;
$("guildCard").style.display = "grid";
setPill($("guildPill"), "ok", "ok");
} catch (e) {
$("guildOut").textContent = pretty({ error: e.message, status: e.status || null, data: e.data || null });
setPill($("guildPill"), "bad", "erreur");
} finally {
$("btnGuild").disabled = false;
}
}
$("btnGuild").addEventListener("click", async () => {
const id = $("guildId").value?.trim();
await loadGuild(id);
});
function escapeHtml(s) {
return String(s)
.replaceAll("&", "&​amp;")
.replaceAll("<", "&​lt;")
.replaceAll(">", "&​gt;")
.replaceAll('"', "&​quot;")
.replaceAll("'", "&​#039;");
}
function renderChannels(channels) {
if (!channels.length) return "Aucun channel (ou non accessible).";
// limiter pour pas exploser l’UI
const shown = channels.slice(0, 40);
const more = channels.length > shown.length ? ` (+${channels.length - shown.length})` : "";
return shown
.map(c => {
const cat = c.category ? ` / ${escapeHtml(c.category)}` : "";
return `#${escapeHtml(c.name)} (${escapeHtml(c.type)})${cat}`;
})
.join("<br/>") + more;
}
function renderRoles(roles) {
if (!roles.length) return "Aucun rôle (ou non accessible).";
// trier par position desc si pas déjà
const sorted = [...roles].sort((a,b) => (b.position ?? 0) - (a.position ?? 0));
const shown = sorted.slice(0, 40);
const more = sorted.length > shown.length ? ` (+${sorted.length - shown.length})` : "";
return shown
.map(r => `${escapeHtml(r.name)} — membres: ${r.member_count ?? "?"} (pos ${r.position ?? "?"})`)
.join("<br/>") + more;
}
// Auto-load status au démarrage (optionnel)
$("btnStatus").click();
</script>
</body>
</html>