mirror of
https://github.com/koreanbots/core.git
synced 2025-12-15 14:10:22 +00:00
feat: retry webhook (#557)
* feat: retry webhook * fix: check condition to disable immediately * feat: start timeout from 2 squared * fix: not return for 5xx status code * chore: update docs --------- Co-authored-by: Eunwoo Choi <choi@eunwoo.dev>
This commit is contained in:
parent
468e1721b3
commit
f25fe50140
2
api-docs
2
api-docs
@ -1 +1 @@
|
||||
Subproject commit 093a4bbcecde9f3587fa90c60ed02b0972bacbbf
|
||||
Subproject commit 8b77196572399132ae3d9c10d27f5269ad819d39
|
||||
117
utils/Webhook.ts
117
utils/Webhook.ts
@ -1,10 +1,11 @@
|
||||
import { APIEmbed, ButtonStyle, Colors, ComponentType, DiscordAPIError, parseWebhookURL, Snowflake, WebhookClient } from 'discord.js'
|
||||
|
||||
import { setTimeout } from 'timers/promises'
|
||||
import { get, update } from './Query'
|
||||
import { DiscordBot, ServerListDiscordBot, webhookClients } from './DiscordBot'
|
||||
import { DiscordEnpoints } from './Constants'
|
||||
import fetch, { Response } from 'node-fetch'
|
||||
import { Bot, Server, WebhookStatus, WebhookType } from '@types'
|
||||
import { Bot, Server, Webhook, WebhookStatus, WebhookType } from '@types'
|
||||
import { makeBotURL, makeDiscordCodeblock, makeServerURL } from './Tools'
|
||||
import crypto from 'crypto'
|
||||
|
||||
@ -15,6 +16,75 @@ type RelayOptions = {
|
||||
secret: string,
|
||||
}
|
||||
|
||||
async function sendRequest({
|
||||
retryCount,
|
||||
webhook,
|
||||
target,
|
||||
payload,
|
||||
}: {
|
||||
retryCount: number
|
||||
webhook: Webhook
|
||||
target: Bot | Server
|
||||
payload: WebhookPayload
|
||||
}) {
|
||||
const id = target.id
|
||||
const isBot = payload.type === 'bot'
|
||||
|
||||
if(retryCount) {
|
||||
await setTimeout(Math.pow(2, retryCount + 2) * 1000)
|
||||
}
|
||||
const result = await relayedFetch({
|
||||
dest: webhook.url,
|
||||
method: 'POST',
|
||||
data: JSON.stringify(payload),
|
||||
secret: webhook.secret
|
||||
}).then(async r => {
|
||||
if(!r.ok) {
|
||||
return null
|
||||
}
|
||||
return r.json()
|
||||
}).catch(() => null)
|
||||
|
||||
if(result === null) return
|
||||
|
||||
if(result.success) {
|
||||
const data = result.data
|
||||
if((200 <= result.status && result.status < 300) && data.length === 0) {
|
||||
await update.webhook(id, isBot ? 'bots' : 'servers', { failedSince: null })
|
||||
return
|
||||
} else if((400 <= result.status && result.status < 500) || data.length !== 0) {
|
||||
await update.webhook(id, isBot ? 'bots' : 'servers', {
|
||||
status: WebhookStatus.Disabled,
|
||||
failedSince: null,
|
||||
secret: null
|
||||
})
|
||||
sendFailedMessage(target)
|
||||
return
|
||||
}
|
||||
}
|
||||
if(retryCount === 10) {
|
||||
if(!webhook.failedSince) {
|
||||
await update.webhook(id, isBot ? 'bots' : 'servers', {
|
||||
failedSince: Math.floor(Date.now() / 1000)
|
||||
})
|
||||
} else if(Date.now() - webhook.failedSince * 1000 > 1000 * 60 * 60 * 24) {
|
||||
await update.webhook(id, isBot ? 'bots' : 'servers', {
|
||||
status: WebhookStatus.Disabled,
|
||||
failedSince: null,
|
||||
secret: null
|
||||
})
|
||||
sendFailedMessage(target)
|
||||
}
|
||||
return
|
||||
}
|
||||
sendRequest({
|
||||
retryCount: retryCount + 1,
|
||||
webhook,
|
||||
target,
|
||||
payload
|
||||
})
|
||||
}
|
||||
|
||||
export function destroyWebhookClient(id: string, type: 'bot' | 'server') {
|
||||
const client = webhookClients[type].get(id)
|
||||
if(client) {
|
||||
@ -87,7 +157,7 @@ export const verifyWebhook = async(webhookURL: string): Promise<string | false |
|
||||
return false
|
||||
}
|
||||
|
||||
export const sendWebhook = async (target: Bot | Server, payload: WebhookPayload): Promise<boolean> => {
|
||||
export const sendWebhook = async (target: Bot | Server, payload: WebhookPayload): Promise<void> => {
|
||||
const id = target.id
|
||||
const isBot = payload.type === 'bot'
|
||||
|
||||
@ -118,43 +188,16 @@ export const sendWebhook = async (target: Bot | Server, payload: WebhookPayload)
|
||||
if(!result) {
|
||||
await update.webhook(id, isBot ? 'bots' : 'servers', { status: WebhookStatus.Disabled })
|
||||
sendFailedMessage(target)
|
||||
return false
|
||||
return
|
||||
}
|
||||
} else if(webhook.status === WebhookStatus.HTTP) {
|
||||
const result = await relayedFetch({
|
||||
dest: webhook.url,
|
||||
method: 'POST',
|
||||
data: JSON.stringify(payload),
|
||||
secret: webhook.secret
|
||||
}).then(async r => {
|
||||
if(!r.ok) {
|
||||
return null
|
||||
}
|
||||
return r.json()
|
||||
}).catch(() => null)
|
||||
if(result === null) return
|
||||
|
||||
if(result.success) {
|
||||
const data = result.data
|
||||
if((200 <= result.status && result.status < 300) && data.length === 0) {
|
||||
await update.webhook(id, isBot ? 'bots' : 'servers', { failedSince: null })
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
if(!webhook.failedSince) {
|
||||
await update.webhook(id, isBot ? 'bots' : 'servers', {
|
||||
failedSince: Math.floor(Date.now() / 1000)
|
||||
})
|
||||
} else if(Date.now() - webhook.failedSince * 1000 > 1000 * 60 * 60 * 24) {
|
||||
await update.webhook(id, isBot ? 'bots' : 'servers', {
|
||||
status: WebhookStatus.Disabled,
|
||||
failedSince: null,
|
||||
secret: null
|
||||
})
|
||||
sendFailedMessage(target)
|
||||
}
|
||||
return false
|
||||
sendRequest({
|
||||
retryCount: 0,
|
||||
webhook,
|
||||
target,
|
||||
payload
|
||||
})
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user