Fix non-PK messages from PK users being flaky
This commit is contained in:
@@ -5,9 +5,9 @@ const {discord, select, db} = passthrough
|
||||
|
||||
const DEBUG_SPEEDBUMP = false
|
||||
|
||||
function debugSpeedbump(message) {
|
||||
function debugSpeedbump(...args) {
|
||||
if (DEBUG_SPEEDBUMP) {
|
||||
console.log(message)
|
||||
console.log(...args)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,11 @@ const KNOWN_BOTS = new Set([
|
||||
"466378653216014359" // PluralKit
|
||||
])
|
||||
|
||||
const CONTEXT_ENUM = {
|
||||
create: "create",
|
||||
update: "update"
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch new speedbump data for the channel and put it in the database as cache
|
||||
* @param {string} channelID
|
||||
@@ -34,55 +39,68 @@ async function updateCache(channelID, lastChecked) {
|
||||
db.prepare("UPDATE channel_room SET speedbump_id = ?, speedbump_webhook_id = ?, speedbump_checked = ? WHERE channel_id = ?").run(foundApplication, foundWebhook, now, channelID)
|
||||
}
|
||||
|
||||
/** @type {Map<string, number>} messageID -> number of gateway events currently bumping */
|
||||
/**
|
||||
* @typedef BumpingEntry
|
||||
* @prop {number} number number of gateway events currently bumping for this message ID
|
||||
* @prop {boolean} hasCreate whether there was a message create within the events currently bumping
|
||||
*/
|
||||
|
||||
/** @type {Map<string, BumpingEntry>} messageID -> BumpingEntry */
|
||||
const bumping = new Map()
|
||||
|
||||
/**
|
||||
* Slow down a message. After it passes the speedbump, return whether it's okay or if it's been deleted.
|
||||
* @param {keyof typeof CONTEXT_ENUM} context
|
||||
* @param {string} messageID
|
||||
* @returns whether it was deleted
|
||||
*/
|
||||
async function doSpeedbump(messageID) {
|
||||
let value = (bumping.get(messageID) ?? 0) + 1
|
||||
bumping.set(messageID, value)
|
||||
debugSpeedbump(`[speedbump] WAIT ${messageID}++ = ${value}`)
|
||||
async function doSpeedbump(context, messageID) {
|
||||
const entry = bumping.get(messageID) ?? (() => {
|
||||
const entry = {number: 0, hasCreate: false}
|
||||
bumping.set(messageID, entry)
|
||||
return entry
|
||||
})()
|
||||
|
||||
entry.number++
|
||||
if (context === "create") entry.hasCreate = true
|
||||
|
||||
debugSpeedbump(`[speedbump] WAIT ${messageID}++ =`, entry)
|
||||
|
||||
await new Promise(resolve => setTimeout(resolve, SPEEDBUMP_SPEED))
|
||||
|
||||
if (!bumping.has(messageID)) {
|
||||
debugSpeedbump(`[speedbump] DELETED ${messageID}`)
|
||||
return true
|
||||
return {skip: true, hasCreate: null}
|
||||
}
|
||||
value = (bumping.get(messageID) ?? 0) - 1
|
||||
if (value <= 0) {
|
||||
debugSpeedbump(`[speedbump] OK ${messageID}-- = ${value}`)
|
||||
|
||||
if (--entry.number <= 0) {
|
||||
debugSpeedbump(`[speedbump] OK ${messageID}-- =`, entry)
|
||||
bumping.delete(messageID)
|
||||
return false
|
||||
return {skip: false, hasCreate: entry.hasCreate}
|
||||
} else {
|
||||
debugSpeedbump(`[speedbump] MULTI ${messageID}-- = ${value}`)
|
||||
bumping.set(messageID, value)
|
||||
return true
|
||||
debugSpeedbump(`[speedbump] MULTI ${messageID}-- =`, entry)
|
||||
return {skip: true, hasCreate: null}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether to slow down a message, and do it. After it passes the speedbump, return whether it's okay or if it's been deleted.
|
||||
* @param {string} channelID
|
||||
* @param {string} messageID
|
||||
* @param {string} [userID] if provided, only slow down the message when the user has used PK before
|
||||
* @param {keyof typeof CONTEXT_ENUM} context
|
||||
* @param {{id: string, channel_id: string, author: {id: string}, backfill?: boolean}} message uses the ID to identify, and the userID to only slow down the message when the user has used PK before
|
||||
* @returns whether it was deleted, and data about the channel's (not thread's) speedbump
|
||||
*/
|
||||
async function maybeDoSpeedbump(channelID, messageID, userID) {
|
||||
let row = select("channel_room", ["room_id", "thread_parent", "speedbump_id", "speedbump_webhook_id"], {channel_id: channelID}).get()
|
||||
async function maybeDoSpeedbump(context, message) {
|
||||
let row = select("channel_room", ["room_id", "thread_parent", "speedbump_id", "speedbump_webhook_id"], {channel_id: message.channel_id}).get()
|
||||
if (row?.thread_parent) row = select("channel_room", ["room_id", "thread_parent", "speedbump_id", "speedbump_webhook_id"], {channel_id: row.thread_parent}).get() // webhooks belong to the channel, not the thread
|
||||
if (!row?.speedbump_webhook_id) return {affected: false, row: null} // channel not affected, no speedbump
|
||||
if (userID) {
|
||||
if (row.speedbump_webhook_id === userID) return {affected: false, row} // shortcut
|
||||
const userHasProxy = select("sim_proxy", "user_id", {proxy_owner_id: userID}).pluck().get()
|
||||
if (!userHasProxy) return {affected: false, row} // user has not used PK before, no speedbump
|
||||
}
|
||||
const affected = await doSpeedbump(messageID)
|
||||
return {affected, row} // maybe affected, and there is a speedbump
|
||||
if (!row?.speedbump_webhook_id || !row?.speedbump_id) return {skip: false, proxyWebhook: null} // channel not affected, no speedbump
|
||||
|
||||
let proxyWebhook = {userID: row.speedbump_id, webhookID: row.speedbump_webhook_id}
|
||||
if (message.backfill) return {skip: false, proxyWebhook} // don't slow messages during backfill
|
||||
if (proxyWebhook.webhookID === message.author.id) return {skip: false, proxyWebhook} // shortcut
|
||||
const userHasProxy = select("sim_proxy", "user_id", {proxy_owner_id: message.author.id}).pluck().get()
|
||||
if (!userHasProxy) return {skip: false, proxyWebhook} // user has not used PK before, no speedbump
|
||||
const {skip, hasCreate} = await doSpeedbump(context, message.id)
|
||||
return {skip, hasCreate, proxyWebhook} // maybe affected, and there is a speedbump
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user