auto embed cleanup
This commit is contained in:
@@ -42,11 +42,14 @@ var BARE_OS_DISCORD_KNOWN_UNITS = [
|
||||
]
|
||||
var BARE_OS_DISCORD_EDIT_CHUNK = 4000
|
||||
var BARE_OS_DISCORD_EDIT_MAX_CHUNKS = 5
|
||||
var BARE_OS_DISCORD_EDIT_TTL_MS = 15 * 60 * 1000
|
||||
var BARE_OS_DISCORD_IDLE_MS = 2 * 60 * 1000
|
||||
var BARE_OS_DISCORD_EDIT_TTL_MS = BARE_OS_DISCORD_IDLE_MS
|
||||
var BARE_OS_DISCORD_EDIT_SESSIONS = Object.create(null)
|
||||
var BARE_OS_DISCORD_FM_PAGE = 20
|
||||
var BARE_OS_DISCORD_FM_TTL_MS = 20 * 60 * 1000
|
||||
var BARE_OS_DISCORD_FM_TTL_MS = BARE_OS_DISCORD_IDLE_MS
|
||||
var BARE_OS_DISCORD_FM_SESSIONS = Object.create(null)
|
||||
var BARE_OS_DISCORD_LIVE = Object.create(null)
|
||||
var BARE_OS_DISCORD_IDLE_SEQ = 0
|
||||
var BARE_OS_DISCORD_EDIT_SUGGEST = [
|
||||
'~/notes.txt',
|
||||
'~/.barerc',
|
||||
@@ -430,7 +433,7 @@ function discordEmbed(opts) {
|
||||
const e = {
|
||||
color: o.color == null ? BARE_OS_DISCORD_COLOR : o.color,
|
||||
timestamp: new Date().toISOString(),
|
||||
footer: { text: o.footer || 'Bare OS · session identity' }
|
||||
footer: { text: o.footer || 'Bare OS · expires after 2m idle' }
|
||||
}
|
||||
if (o.title) e.title = String(o.title).slice(0, 256)
|
||||
if (o.desc) e.description = discordCmdClip(discordCmdRedact(o.desc), 1800)
|
||||
@@ -2195,7 +2198,7 @@ function discordCreatePicker(ctx) {
|
||||
}
|
||||
|
||||
var BARE_OS_DISCORD_SET_SESSIONS = Object.create(null)
|
||||
var BARE_OS_DISCORD_SET_TTL_MS = 20 * 60 * 1000
|
||||
var BARE_OS_DISCORD_SET_TTL_MS = BARE_OS_DISCORD_IDLE_MS
|
||||
var BARE_OS_DISCORD_THEME_FALLBACK = [
|
||||
'catppuccin_mocha',
|
||||
'default',
|
||||
@@ -3381,6 +3384,163 @@ async function discordBeginCreate(ctx, interaction, rawPath) {
|
||||
}
|
||||
}
|
||||
|
||||
function discordIdleNow() {
|
||||
return Date.now()
|
||||
}
|
||||
|
||||
function discordIdleSchedule(fn, ms) {
|
||||
const tfn = typeof setTimeout === 'function' ? setTimeout : globalThis.setTimeout
|
||||
if (typeof tfn !== 'function') return null
|
||||
const t = tfn(fn, ms)
|
||||
if (t && typeof t.unref === 'function') t.unref()
|
||||
return t
|
||||
}
|
||||
|
||||
function discordIdleClearTimer(t) {
|
||||
const cfn = typeof clearTimeout === 'function' ? clearTimeout : globalThis.clearTimeout
|
||||
if (t != null && typeof cfn === 'function') cfn(t)
|
||||
}
|
||||
|
||||
function discordIdleExpiredEmbeds(embeds) {
|
||||
const out = []
|
||||
if (!Array.isArray(embeds)) return out
|
||||
for (let i = 0; i < embeds.length; i++) {
|
||||
const e = embeds[i] || {}
|
||||
const n = {}
|
||||
for (const k in e) n[k] = e[k]
|
||||
n.footer = { text: 'Expired after 2 minutes idle' }
|
||||
n.color = BARE_OS_DISCORD_COLOR_WARN
|
||||
out.push(n)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
function discordIdleForgetSessions(userId) {
|
||||
if (!userId) return
|
||||
for (const k in BARE_OS_DISCORD_LIVE) {
|
||||
const r = BARE_OS_DISCORD_LIVE[k]
|
||||
if (r && r.userId === userId) return
|
||||
}
|
||||
delete BARE_OS_DISCORD_EDIT_SESSIONS[userId]
|
||||
delete BARE_OS_DISCORD_FM_SESSIONS[userId]
|
||||
delete BARE_OS_DISCORD_SET_SESSIONS[userId]
|
||||
}
|
||||
|
||||
function discordUnwrapMessage(sent) {
|
||||
if (!sent || typeof sent !== 'object') return null
|
||||
if (sent.resource && sent.resource.message) return sent.resource.message
|
||||
if (sent.message && (sent.message.id || typeof sent.message.edit === 'function')) {
|
||||
return sent.message
|
||||
}
|
||||
if (sent.id || typeof sent.delete === 'function' || typeof sent.edit === 'function') return sent
|
||||
return null
|
||||
}
|
||||
|
||||
async function discordResolvePostedMessage(interaction, sent) {
|
||||
const unwrapped = discordUnwrapMessage(sent)
|
||||
if (unwrapped) return unwrapped
|
||||
if (interaction && interaction.message && (interaction.message.id || typeof interaction.message.delete === 'function')) {
|
||||
return interaction.message
|
||||
}
|
||||
if (interaction && typeof interaction.fetchReply === 'function') {
|
||||
try {
|
||||
const m = await interaction.fetchReply()
|
||||
return discordUnwrapMessage(m) || m
|
||||
} catch {
|
||||
return null
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
function discordIdleArm(msg, payload, userId) {
|
||||
if (!msg) return null
|
||||
const hasUi =
|
||||
(payload && payload.embeds && payload.embeds.length) ||
|
||||
(payload && payload.components && payload.components.length)
|
||||
if (!hasUi) return null
|
||||
const id = String(msg.id || '') || 'anon:' + ++BARE_OS_DISCORD_IDLE_SEQ
|
||||
const prev = BARE_OS_DISCORD_LIVE[id]
|
||||
if (prev) discordIdleClearTimer(prev.timer)
|
||||
const rec = {
|
||||
id: id,
|
||||
message: msg,
|
||||
userId: userId || '',
|
||||
embeds: payload && payload.embeds ? payload.embeds : null,
|
||||
atMs: discordIdleNow(),
|
||||
timer: null
|
||||
}
|
||||
BARE_OS_DISCORD_LIVE[id] = rec
|
||||
rec.timer = discordIdleSchedule(function () {
|
||||
Promise.resolve(discordIdleExpire(id)).catch(function () {})
|
||||
}, BARE_OS_DISCORD_IDLE_MS)
|
||||
return rec
|
||||
}
|
||||
|
||||
async function discordIdleExpire(id) {
|
||||
const rec = BARE_OS_DISCORD_LIVE[id]
|
||||
if (!rec) return false
|
||||
delete BARE_OS_DISCORD_LIVE[id]
|
||||
discordIdleClearTimer(rec.timer)
|
||||
rec.timer = null
|
||||
const msg = rec.message
|
||||
let cleaned = false
|
||||
if (msg && typeof msg.delete === 'function') {
|
||||
try {
|
||||
await msg.delete()
|
||||
cleaned = true
|
||||
} catch {
|
||||
cleaned = false
|
||||
}
|
||||
}
|
||||
if (!cleaned && msg && typeof msg.edit === 'function') {
|
||||
try {
|
||||
const body = { components: [] }
|
||||
if (rec.embeds && rec.embeds.length) body.embeds = discordIdleExpiredEmbeds(rec.embeds)
|
||||
await msg.edit(body)
|
||||
cleaned = true
|
||||
} catch {
|
||||
cleaned = false
|
||||
}
|
||||
}
|
||||
discordIdleForgetSessions(rec.userId)
|
||||
return cleaned
|
||||
}
|
||||
|
||||
function discordIdleSweep() {
|
||||
const now = discordIdleNow()
|
||||
const due = []
|
||||
for (const k in BARE_OS_DISCORD_LIVE) {
|
||||
const r = BARE_OS_DISCORD_LIVE[k]
|
||||
if (!r || now - r.atMs >= BARE_OS_DISCORD_IDLE_MS) due.push(k)
|
||||
}
|
||||
for (let i = 0; i < due.length; i++) {
|
||||
Promise.resolve(discordIdleExpire(due[i])).catch(function () {})
|
||||
}
|
||||
}
|
||||
|
||||
function discordIdleTouch(interaction) {
|
||||
const mid = interaction && interaction.message && interaction.message.id
|
||||
if (!mid) return
|
||||
const rec = BARE_OS_DISCORD_LIVE[String(mid)]
|
||||
if (!rec) return
|
||||
if (discordIdleNow() - rec.atMs >= BARE_OS_DISCORD_IDLE_MS) return
|
||||
rec.atMs = discordIdleNow()
|
||||
}
|
||||
|
||||
async function discordIdleWatch(interaction, payload, sent) {
|
||||
if (!payload) return
|
||||
if (
|
||||
payload.flags === BARE_OS_DISCORD_FLAG_EPHEMERAL &&
|
||||
!(payload.embeds && payload.embeds.length) &&
|
||||
!(payload.components && payload.components.length)
|
||||
) {
|
||||
return
|
||||
}
|
||||
const msg = await discordResolvePostedMessage(interaction, sent)
|
||||
discordIdleArm(msg, payload, discordInteractionUserId(interaction))
|
||||
}
|
||||
|
||||
async function discordSendResult(ctx, interaction, result) {
|
||||
if (result && result.editPath) {
|
||||
const prev = discordEditGet(interaction)
|
||||
@@ -3461,15 +3621,16 @@ async function discordSendResult(ctx, interaction, result) {
|
||||
(typeof interaction.isButton === 'function' && interaction.isButton()) ||
|
||||
(typeof interaction.isStringSelectMenu === 'function' &&
|
||||
interaction.isStringSelectMenu())
|
||||
let sent = null
|
||||
try {
|
||||
if (isComp && typeof interaction.update === 'function' && !interaction.replied && !interaction.deferred) {
|
||||
await interaction.update(payload)
|
||||
sent = await interaction.update(payload)
|
||||
} else if (interaction.deferred && typeof interaction.editReply === 'function') {
|
||||
await interaction.editReply(payload)
|
||||
sent = await interaction.editReply(payload)
|
||||
} else if (interaction.replied && typeof interaction.followUp === 'function') {
|
||||
await interaction.followUp(payload)
|
||||
sent = await interaction.followUp(Object.assign({ fetchReply: true }, payload))
|
||||
} else {
|
||||
await interaction.reply(payload)
|
||||
sent = await interaction.reply(Object.assign({ fetchReply: true }, payload))
|
||||
}
|
||||
} catch (err) {
|
||||
if (ctx && ctx.console && typeof ctx.console.error === 'function') {
|
||||
@@ -3477,6 +3638,12 @@ async function discordSendResult(ctx, interaction, result) {
|
||||
'discord-bot: reply failed: ' + ((err && err.message) || err)
|
||||
)
|
||||
}
|
||||
return
|
||||
}
|
||||
try {
|
||||
await discordIdleWatch(interaction, payload, sent)
|
||||
} catch {
|
||||
/* tracking must not break the bot */
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4052,6 +4219,8 @@ async function discordDispatchModal(ctx, interaction) {
|
||||
async function discordDispatchInteraction(ctx, interaction) {
|
||||
if (!interaction) return false
|
||||
discordSyncSessionIdentity(ctx)
|
||||
discordIdleTouch(interaction)
|
||||
discordIdleSweep()
|
||||
if (typeof interaction.isAutocomplete === 'function' && interaction.isAutocomplete()) {
|
||||
if (!discordUserAllowed(ctx, discordInteractionUserId(interaction))) {
|
||||
try {
|
||||
@@ -4151,7 +4320,14 @@ var bareOsDiscordCommands = {
|
||||
settingsCurrent: discordSettingsCurrent,
|
||||
uniqueComponents: discordUniqueComponents,
|
||||
navRows: discordNavRows,
|
||||
result: discordResult
|
||||
result: discordResult,
|
||||
idleMs: BARE_OS_DISCORD_IDLE_MS,
|
||||
idleExpire: discordIdleExpire,
|
||||
idleSweep: discordIdleSweep,
|
||||
idleArm: discordIdleArm,
|
||||
idleLive: function () {
|
||||
return BARE_OS_DISCORD_LIVE
|
||||
}
|
||||
}
|
||||
if (typeof module !== 'undefined' && module.exports) {
|
||||
module.exports = bareOsDiscordCommands
|
||||
|
||||
Reference in New Issue
Block a user