feat: sanitize post metadata and implement webhook fallback for 400 errors
This commit is contained in:
parent
d196a73d85
commit
e25ae8607e
1 changed files with 48 additions and 10 deletions
|
|
@ -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);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue