feat: sanitize post metadata and implement webhook fallback for 400 errors

This commit is contained in:
암냥 2026-05-23 23:22:59 +09:00
commit e25ae8607e
No known key found for this signature in database

View file

@ -76,25 +76,63 @@ async function sendDiscordNotification(payload: {
return; return;
} }
const safeTitle = (payload.title || "New post").slice(0, 256);
const safeAuthor = (payload.author || "unknown").slice(0, 256);
const safeTags = (payload.tags.join(", ") || "None").slice(0, 1024);
const isValidHttpUrl = (value?: string) => {
if (!value) return false;
try {
const parsed = new URL(value);
return parsed.protocol === "http:" || parsed.protocol === "https:";
} catch {
return false;
}
};
const safeUrl = isValidHttpUrl(payload.url) ? payload.url : undefined;
const safeImageUrl = isValidHttpUrl(payload.imageUrl) ? payload.imageUrl : undefined;
const embed: Record<string, unknown> = {
title: safeTitle,
author: { name: safeAuthor },
fields: [{ name: "Tags", value: safeTags }],
color: 0x00ff00,
};
if (safeUrl) embed.url = safeUrl;
if (safeImageUrl) embed.image = { url: safeImageUrl };
const body = {
content: `${safeTitle}${safeUrl ? `\n${safeUrl}` : ""}`,
embeds: [embed],
};
try { try {
const response = await fetch(webhookUrl, { const response = await fetch(webhookUrl, {
method: "POST", method: "POST",
headers: { "Content-Type": "application/json" }, headers: { "Content-Type": "application/json" },
body: JSON.stringify({ body: JSON.stringify(body),
embeds: [{
title: payload.title,
url: payload.url,
author: { name: payload.author },
fields: [{ name: "Tags", value: payload.tags.join(", ") || "None" }],
image: payload.imageUrl ? { url: payload.imageUrl } : undefined,
color: 0x00ff00,
}],
}),
}); });
if (!response.ok) { if (!response.ok) {
const errorText = await response.text().catch(() => ""); const errorText = await response.text().catch(() => "");
console.error(`[Discord Webhook] failed status=${response.status} body=${errorText}`); console.error(`[Discord Webhook] failed status=${response.status} body=${errorText}`);
if (response.status === 400) {
const fallbackResponse = await fetch(webhookUrl, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
content: `${safeTitle}${safeUrl ? `\n${safeUrl}` : ""}\nAuthor: ${safeAuthor}\nTags: ${safeTags}`,
}),
});
if (!fallbackResponse.ok) {
const fallbackErrorText = await fallbackResponse.text().catch(() => "");
console.error(`[Discord Webhook] fallback failed status=${fallbackResponse.status} body=${fallbackErrorText}`);
}
}
} }
} catch (error) { } catch (error) {
console.error("[Discord Webhook Error]", error); console.error("[Discord Webhook Error]", error);