mirror of
https://github.com/koreanbots/core.git
synced 2025-12-16 14:30: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
|
||||||
115
utils/Webhook.ts
115
utils/Webhook.ts
@ -1,10 +1,11 @@
|
|||||||
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'
|
||||||
import fetch, { Response } from 'node-fetch'
|
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 { makeBotURL, makeDiscordCodeblock, makeServerURL } from './Tools'
|
||||||
import crypto from 'crypto'
|
import crypto from 'crypto'
|
||||||
|
|
||||||
@ -15,6 +16,75 @@ type RelayOptions = {
|
|||||||
secret: string,
|
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') {
|
export function destroyWebhookClient(id: string, type: 'bot' | 'server') {
|
||||||
const client = webhookClients[type].get(id)
|
const client = webhookClients[type].get(id)
|
||||||
if(client) {
|
if(client) {
|
||||||
@ -87,7 +157,7 @@ export const verifyWebhook = async(webhookURL: string): Promise<string | false |
|
|||||||
return 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 id = target.id
|
||||||
const isBot = payload.type === 'bot'
|
const isBot = payload.type === 'bot'
|
||||||
|
|
||||||
@ -118,43 +188,16 @@ export const sendWebhook = async (target: Bot | Server, payload: WebhookPayload)
|
|||||||
if(!result) {
|
if(!result) {
|
||||||
await update.webhook(id, isBot ? 'bots' : 'servers', { status: WebhookStatus.Disabled })
|
await update.webhook(id, isBot ? 'bots' : 'servers', { status: WebhookStatus.Disabled })
|
||||||
sendFailedMessage(target)
|
sendFailedMessage(target)
|
||||||
return false
|
return
|
||||||
}
|
}
|
||||||
} else if(webhook.status === WebhookStatus.HTTP) {
|
} else if(webhook.status === WebhookStatus.HTTP) {
|
||||||
const result = await relayedFetch({
|
sendRequest({
|
||||||
dest: webhook.url,
|
retryCount: 0,
|
||||||
method: 'POST',
|
webhook,
|
||||||
data: JSON.stringify(payload),
|
target,
|
||||||
secret: webhook.secret
|
payload
|
||||||
}).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) {
|
return
|
||||||
await update.webhook(id, isBot ? 'bots' : 'servers', {
|
|
||||||
status: WebhookStatus.Disabled,
|
|
||||||
failedSince: null,
|
|
||||||
secret: null
|
|
||||||
})
|
|
||||||
sendFailedMessage(target)
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user