Skip to content

Commit 2267b4e

Browse files
committed
add webhook message for signal error
1 parent c578957 commit 2267b4e

File tree

3 files changed

+173
-1
lines changed

3 files changed

+173
-1
lines changed

html/error-template.html

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,156 @@
1919
<div class="error-type">ERROR_TYPE</div>
2020
<div id="error-message" class="error-message">ERROR_MESSAGE</div>
2121
<img class="gif" src="ERROR_GIF" alt="Error illustration">
22+
<button id="open-report-modal" data-site="MySite" data-link="https://example.com">Signaler une erreur</button>
2223
</div>
24+
<script>
25+
// Front script - creates modal, grabs data, calls the worker, shows banner
26+
// ====== helpers ======
27+
const getErrorCodeFromPage = () => {
28+
const idEl = document.querySelector('#error-code');
29+
if (idEl && idEl.textContent.trim()) return idEl.textContent.trim();
30+
const bodyAttr = document.body?.getAttribute('data-error-code');
31+
if (bodyAttr) return bodyAttr.trim();
32+
const meta = document.querySelector('meta[name="error-code"]');
33+
if (meta && meta.getAttribute('content')) return meta.getAttribute('content').trim();
34+
const p = new URLSearchParams(location.search).get('errorCode');
35+
if (p) return p.trim();
36+
return 'N/A';
37+
};
38+
const showTopAlert = msg => {
39+
const bar = document.createElement('div');
40+
bar.textContent = msg;
41+
bar.setAttribute('role', 'status');
42+
bar.style.position = 'fixed';
43+
bar.style.top = '0';
44+
bar.style.left = '0';
45+
bar.style.right = '0';
46+
bar.style.padding = '12px 16px';
47+
bar.style.textAlign = 'center';
48+
bar.style.fontWeight = '600';
49+
bar.style.background = '#16a34a';
50+
bar.style.color = 'white';
51+
bar.style.zIndex = '2147483647';
52+
document.body.appendChild(bar);
53+
setTimeout(() => bar.remove(), 4000);
54+
};
55+
const ensureModal = () => {
56+
if (document.getElementById('report-error-modal')) return;
57+
const overlay = document.createElement('div');
58+
overlay.id = 'report-error-modal';
59+
overlay.style.position = 'fixed';
60+
overlay.style.inset = '0';
61+
overlay.style.background = 'rgba(0,0,0,0.4)';
62+
overlay.style.display = 'none';
63+
overlay.style.alignItems = 'center';
64+
overlay.style.justifyContent = 'center';
65+
overlay.style.zIndex = '2147483646';
66+
const box = document.createElement('div');
67+
box.style.background = 'white';
68+
box.style.borderRadius = '12px';
69+
box.style.padding = '20px';
70+
box.style.width = 'min(92vw, 420px)';
71+
box.style.boxShadow = '0 10px 30px rgba(0,0,0,0.25)';
72+
box.style.fontFamily = 'system-ui, -apple-system, Segoe UI, Roboto, sans-serif';
73+
const title = document.createElement('h2');
74+
title.textContent = '🆘 Erreur signalée';
75+
title.style.margin = '0 0 12px 0';
76+
title.style.fontSize = '20px';
77+
const label = document.createElement('label');
78+
label.textContent = 'Nom / Prénom';
79+
label.style.display = 'block';
80+
label.style.fontSize = '14px';
81+
label.style.marginBottom = '6px';
82+
const input = document.createElement('input');
83+
input.type = 'text';
84+
input.placeholder = 'Ex: Jane Doe';
85+
input.required = true;
86+
input.style.width = '100%';
87+
input.style.boxSizing = 'border-box';
88+
input.style.padding = '10px 12px';
89+
input.style.fontSize = '16px';
90+
input.style.border = '1px solid #d1d5db';
91+
input.style.borderRadius = '8px';
92+
input.id = 'reporter-fullname';
93+
const actions = document.createElement('div');
94+
actions.style.display = 'flex';
95+
actions.style.gap = '8px';
96+
actions.style.marginTop = '16px';
97+
const cancel = document.createElement('button');
98+
cancel.type = 'button';
99+
cancel.textContent = 'Annuler';
100+
cancel.style.flex = '1';
101+
cancel.style.padding = '10px 12px';
102+
cancel.style.border = '1px solid #d1d5db';
103+
cancel.style.borderRadius = '8px';
104+
cancel.style.background = 'white';
105+
cancel.onclick = () => hideModal();
106+
const submit = document.createElement('button');
107+
submit.type = 'button';
108+
submit.textContent = 'Signaler';
109+
submit.style.flex = '1';
110+
submit.style.padding = '10px 12px';
111+
submit.style.border = '0';
112+
submit.style.borderRadius = '8px';
113+
submit.style.background = '#ef4444';
114+
submit.style.color = 'white';
115+
submit.style.fontWeight = '600';
116+
submit.onclick = async () => {
117+
const fullName = input.value.trim();
118+
if (!fullName) {
119+
input.focus();
120+
return;
121+
}
122+
const trigger = document.getElementById('open-report-modal');
123+
const redirectUrl = trigger?.getAttribute('data-link') || location.href;
124+
const siteName = trigger?.getAttribute('data-site') || location.hostname;
125+
const errorCode = getErrorCodeFromPage();
126+
try {
127+
const res = await fetch('/report-error', {
128+
method: 'POST',
129+
headers: { 'content-type': 'application/json' },
130+
body: JSON.stringify({ fullName, errorCode, siteName, redirectUrl })
131+
});
132+
const data = await res.json().catch(() => ({}));
133+
if (!res.ok || !data.ok) throw new Error(data.error || 'send failed');
134+
hideModal();
135+
showTopAlert('Erreur signalée !');
136+
} catch (e) {
137+
hideModal();
138+
showTopAlert('Envoi impossible');
139+
console.error('Discord webhook failed', e);
140+
}
141+
};
142+
actions.appendChild(cancel);
143+
actions.appendChild(submit);
144+
box.appendChild(title);
145+
box.appendChild(label);
146+
box.appendChild(input);
147+
box.appendChild(actions);
148+
overlay.appendChild(box);
149+
document.body.appendChild(overlay);
150+
};
151+
const showModal = () => {
152+
ensureModal();
153+
const overlay = document.getElementById('report-error-modal');
154+
const input = document.getElementById('reporter-fullname');
155+
overlay.style.display = 'flex';
156+
setTimeout(() => input?.focus(), 0);
157+
};
158+
const hideModal = () => {
159+
const overlay = document.getElementById('report-error-modal');
160+
if (overlay) overlay.style.display = 'none';
161+
};
162+
const wireButton = () => {
163+
ensureModal();
164+
const btn = document.getElementById('open-report-modal');
165+
if (!btn) return;
166+
btn.addEventListener('click', e => {
167+
e.preventDefault();
168+
showModal();
169+
});
170+
};
171+
document.addEventListener('DOMContentLoaded', wireButton);
172+
</script>
23173
</body>
24174
</html>

worker.js

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,8 @@ async function injectBanner(response, bannerMessage) {
8181

8282
export default {
8383
async fetch(request, env, ctx) {
84-
const host = request.headers.get('host');
8584
const url = new URL(request.url);
85+
const host = request.headers.get('host');
8686

8787
// Read state (cache by default)
8888
let state = await getMaintenanceState(env, host);
@@ -133,6 +133,27 @@ export default {
133133
return await injectBanner(response, bannerMessage);
134134
}
135135

136+
// Report error endpoint
137+
if (url.pathname === '/report-error' && request.method === 'POST') {
138+
const { fullName, errorCode, siteName, redirectUrl } = await request.json();
139+
const webhookUrl = env.DISCORD_WEBHOOK_URL;
140+
if (!webhookUrl) {
141+
return new Response(JSON.stringify({ ok: false, error: 'Webhook URL not configured' }), { status: 500 });
142+
}
143+
const payload = {
144+
content: `🚨 **Erreur signalée**\n- **Nom**: ${fullName}\n- **Code d'erreur**: ${errorCode}\n- **Site**: ${siteName}\n- **URL**: ${redirectUrl}`
145+
};
146+
const res = await fetch(webhookUrl, {
147+
method: 'POST',
148+
headers: { 'Content-Type': 'application/json' },
149+
body: JSON.stringify(payload)
150+
});
151+
if (!res.ok) {
152+
return new Response(JSON.stringify({ ok: false, error: 'Failed to send webhook' }), { status: 500 });
153+
}
154+
return new Response(JSON.stringify({ ok: true }), { status: 200 });
155+
}
156+
136157
return response;
137158
}
138159
}

wrangler.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ ENABLE_CACHE = true
2323
# Cache duration in ms (default: 60000 = 1 minute)
2424
CACHE_TTL_MS = 60000
2525

26+
DISCORD_WEBHOOK_URL = "https://discord.com/api/webhooks/1411329377538674870/Y4ikyN_RCGFCu5DfRbGuxhIdA8mqLFckpu_zmHY5t6ewEehd9VRHxuz-VeGTE6t6bssC"
2627

2728

2829

0 commit comments

Comments
 (0)