fix: duplicated failed message (#559)

* fix: clear timeouts when disabled

* fix: check timeout maps

* fix: wrong link for panel
This commit is contained in:
SKINMAKER 2023-04-29 12:27:31 +09:00 committed by GitHub
parent afb26aa23a
commit 90b98cbebe
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -1,6 +1,5 @@
import { APIEmbed, ButtonStyle, Colors, ComponentType, DiscordAPIError, parseWebhookURL, Snowflake, WebhookClient } from 'discord.js' import { APIEmbed, ButtonStyle, Colors, ComponentType, DiscordAPIError, parseWebhookURL, Snowflake, WebhookClient } from 'discord.js'
import { setTimeout } from 'timers/promises'
import { get, update } from './Query' import { get, update } from './Query'
import { DiscordBot, ServerListDiscordBot, webhookClients } from './DiscordBot' import { DiscordBot, ServerListDiscordBot, webhookClients } from './DiscordBot'
import { DiscordEnpoints } from './Constants' import { DiscordEnpoints } from './Constants'
@ -16,6 +15,18 @@ type RelayOptions = {
secret: string, secret: string,
} }
const timeouts = new Map<Snowflake, Map<number, NodeJS.Timeout>>()
const clearTimeouts = (id: Snowflake) => {
if(timeouts.has(id)) {
timeouts.get(id).forEach(clearTimeout)
timeouts.delete(id)
return true
} else {
return false
}
}
async function sendRequest({ async function sendRequest({
retryCount, retryCount,
webhook, webhook,
@ -30,9 +41,8 @@ async function sendRequest({
const id = target.id const id = target.id
const isBot = payload.type === 'bot' const isBot = payload.type === 'bot'
if(retryCount) { timeouts.get(id)?.delete(payload.timestamp)
await setTimeout(Math.pow(2, retryCount + 1) * 1000)
}
const result = await relayedFetch({ const result = await relayedFetch({
dest: webhook.url, dest: webhook.url,
method: 'POST', method: 'POST',
@ -53,6 +63,7 @@ async function sendRequest({
await update.webhook(id, isBot ? 'bots' : 'servers', { failedSince: null }) await update.webhook(id, isBot ? 'bots' : 'servers', { failedSince: null })
return return
} else if((400 <= result.status && result.status < 500) || data.length !== 0) { } else if((400 <= result.status && result.status < 500) || data.length !== 0) {
if(!clearTimeouts(id)) return
await update.webhook(id, isBot ? 'bots' : 'servers', { await update.webhook(id, isBot ? 'bots' : 'servers', {
status: WebhookStatus.Disabled, status: WebhookStatus.Disabled,
failedSince: null, failedSince: null,
@ -68,6 +79,7 @@ async function sendRequest({
failedSince: Math.floor(Date.now() / 1000) failedSince: Math.floor(Date.now() / 1000)
}) })
} else if(Date.now() - webhook.failedSince * 1000 > 1000 * 60 * 60 * 24) { } else if(Date.now() - webhook.failedSince * 1000 > 1000 * 60 * 60 * 24) {
if(!clearTimeouts(id)) return
await update.webhook(id, isBot ? 'bots' : 'servers', { await update.webhook(id, isBot ? 'bots' : 'servers', {
status: WebhookStatus.Disabled, status: WebhookStatus.Disabled,
failedSince: null, failedSince: null,
@ -77,12 +89,19 @@ async function sendRequest({
} }
return return
} }
if(!timeouts.has(id)) {
timeouts.set(id, new Map())
}
timeouts.get(id).set(payload.timestamp, setTimeout(() => {
sendRequest({ sendRequest({
retryCount: retryCount + 1, retryCount: retryCount + 1,
webhook, webhook,
target, target,
payload payload
}) })
}, Math.pow(2, retryCount + 2) * 1000))
} }
export function destroyWebhookClient(id: string, type: 'bot' | 'server') { export function destroyWebhookClient(id: string, type: 'bot' | 'server') {
@ -115,7 +134,7 @@ const sendFailedMessage = async (target: Bot | Server): Promise<void> => {
title: '웹후크 전송 실패', title: '웹후크 전송 실패',
description: `\`\`${target.name}\`\`에 등록된 웹후크 주소가 올바르지 않거나, 제대로 동작하지 않아 비활성화되었습니다.\n` + description: `\`\`${target.name}\`\`에 등록된 웹후크 주소가 올바르지 않거나, 제대로 동작하지 않아 비활성화되었습니다.\n` +
'설정된 웹후크의 주소가 올바른지 확인해주세요.\n' + '설정된 웹후크의 주소가 올바른지 확인해주세요.\n' +
`[관리 패널](https://koreanbots.dev/${isBot ? 'bots' : 'servers'}/${target.id}/edit)에서 설정된 내용을 다시 저장하면 웹후크가 활성화됩니다.\n` + `[개발자 패널](${process.env.KOREANBOTS_URL}/developers/applications/${isBot ? 'bots' : 'servers'}/${target.id})에서 설정된 내용을 다시 저장하면 웹후크가 활성화됩니다.\n` +
(isBot ? '문제가 지속될 경우 본 DM을 통해 문의해주세요.' : '문제가 지속될 경우 한디리 공식 디스코드 서버에서 문의해주세요.'), (isBot ? '문제가 지속될 경우 본 DM을 통해 문의해주세요.' : '문제가 지속될 경우 한디리 공식 디스코드 서버에서 문의해주세요.'),
color: Colors.Red color: Colors.Red
} }
@ -261,7 +280,6 @@ function buildEmbed({payload, target}: {payload: WebhookPayload, target: Bot | S
} }
} }
type WebhookPayload = (BotWebhookPayload | ServerWebhookPayload) & { type WebhookPayload = (BotWebhookPayload | ServerWebhookPayload) & {
timestamp: number timestamp: number
} }