2025-02-05 23:07:05 -05:00
let isAutoDeleteActive = false ;
let deleteQueue = [ ] ;
let isProcessingQueue = false ;
let messageTimers = new Map ( ) ;
let ignoredMessages = new Set ( ) ;
let isFirstDeletion = true ;
2025-02-06 08:29:28 -05:00
let deletedMessages = new Set ( ) ;
const CACHE _CLEANUP _INTERVAL = 30 * 60 * 1000 ;
2025-04-10 15:50:25 -04:00
const { sendCommandResponse } = require ( '../utils/messageUtils' ) ;
2025-02-05 23:07:05 -05:00
const DELETION _DELAY = 5 * 60 * 1000 ;
2025-04-10 15:07:02 -04:00
let DELETE _INTERVAL _MIN = 8000 ;
let DELETE _INTERVAL _MAX = 15000 ;
let JITTER _FACTOR = 0.4 ;
let PAUSE _CHANCE = 0.15 ;
let PAUSE _LENGTH _MIN = 30000 ;
let PAUSE _LENGTH _MAX = 120000 ;
let BATCH _SIZE = 3 ;
let currentBatchCount = 0 ;
2025-02-05 23:07:05 -05:00
2025-02-06 08:29:28 -05:00
setInterval ( ( ) => {
if ( deletedMessages . size > 1000 ) {
console . log ( ` [AUTODELETE] Cleaning message cache (size: ${ deletedMessages . size } ) ` ) ;
deletedMessages . clear ( ) ;
}
} , CACHE _CLEANUP _INTERVAL ) ;
2025-04-10 15:07:02 -04:00
const getHumanlikeDelay = ( ) => {
const baseInterval = Math . floor ( Math . random ( ) * ( DELETE _INTERVAL _MAX - DELETE _INTERVAL _MIN + 1 ) ) + DELETE _INTERVAL _MIN ;
const jitterAmount = baseInterval * JITTER _FACTOR ;
const jitter = Math . random ( ) * jitterAmount * 2 - jitterAmount ;
return Math . max ( 1000 , Math . floor ( baseInterval + jitter ) ) ;
} ;
const shouldTakePause = ( ) => {
currentBatchCount ++ ;
if ( currentBatchCount >= BATCH _SIZE ) {
currentBatchCount = 0 ;
return Math . random ( ) < PAUSE _CHANCE ;
}
return false ;
} ;
const getPauseDuration = ( ) => {
return Math . floor ( Math . random ( ) * ( PAUSE _LENGTH _MAX - PAUSE _LENGTH _MIN + 1 ) ) + PAUSE _LENGTH _MIN ;
2025-02-05 23:07:05 -05:00
} ;
const processDeleteQueue = async ( ) => {
if ( ! isProcessingQueue || deleteQueue . length === 0 ) return ;
try {
const messageToDelete = deleteQueue . shift ( ) ;
if ( ! messageToDelete ) return ;
2025-02-06 08:29:28 -05:00
if ( deletedMessages . has ( messageToDelete . id ) ) {
console . log ( ` [AUTODELETE] Message ${ messageToDelete . id } already deleted (cached), skipping ` ) ;
if ( deleteQueue . length > 0 && isProcessingQueue ) {
2025-04-10 15:07:02 -04:00
scheduleNextDeletion ( ) ;
2025-02-06 08:29:28 -05:00
} else {
isProcessingQueue = false ;
}
return ;
}
2025-04-10 15:07:02 -04:00
const preDeleteDelay = Math . floor ( Math . random ( ) * 1500 ) + 500 ; // 500-2000ms
await new Promise ( resolve => setTimeout ( resolve , preDeleteDelay ) ) ;
2025-02-05 23:29:59 -05:00
2025-04-10 15:07:02 -04:00
if ( isFirstDeletion || Math . random ( ) < 0.35 ) {
2025-02-05 23:07:05 -05:00
console . log ( ` [AUTODELETE] Checking message ${ messageToDelete . id } existence ${ isFirstDeletion ? ' (first deletion)' : '' } ` ) ;
const exists = await messageToDelete . fetch ( ) . catch ( ( ) => null ) ;
if ( ! exists ) {
2025-02-06 08:29:28 -05:00
console . log ( ` [AUTODELETE] Message ${ messageToDelete . id } no longer exists, adding to cache ` ) ;
deletedMessages . add ( messageToDelete . id ) ;
2025-02-05 23:07:05 -05:00
isFirstDeletion = false ;
2025-04-10 15:07:02 -04:00
2025-02-05 23:29:59 -05:00
if ( deleteQueue . length > 0 && isProcessingQueue ) {
2025-04-10 15:07:02 -04:00
scheduleNextDeletion ( ) ;
2025-02-05 23:29:59 -05:00
} else {
isProcessingQueue = false ;
}
2025-02-05 23:07:05 -05:00
return ;
}
}
2025-04-10 15:07:02 -04:00
if ( Math . random ( ) < 0.25 ) {
const readingDelay = Math . floor ( Math . random ( ) * 3000 ) + 1000 ; // 1-4 seconds "reading" delay
console . log ( ` [AUTODELETE] Taking ${ readingDelay } ms to "read" before deleting ` ) ;
await new Promise ( resolve => setTimeout ( resolve , readingDelay ) ) ;
}
2025-02-06 08:29:28 -05:00
await messageToDelete . delete ( ) . catch ( ( error ) => {
if ( error . code === 10008 ) {
console . log ( ` [AUTODELETE] Message ${ messageToDelete . id } already deleted, adding to cache ` ) ;
deletedMessages . add ( messageToDelete . id ) ;
2025-04-10 15:07:02 -04:00
} else if ( error . code === 429 ) {
console . log ( ` [AUTODELETE] Rate limited when deleting ${ messageToDelete . id } . Will retry later. ` ) ;
deleteQueue . push ( messageToDelete ) ;
DELETE _INTERVAL _MIN = Math . min ( DELETE _INTERVAL _MIN * 1.5 , 25000 ) ;
DELETE _INTERVAL _MAX = Math . min ( DELETE _INTERVAL _MAX * 1.5 , 45000 ) ;
console . log ( ` [AUTODELETE] Increased deletion intervals to ${ DELETE _INTERVAL _MIN } - ${ DELETE _INTERVAL _MAX } ms ` ) ;
2025-02-06 08:29:28 -05:00
} else {
console . log ( ` [AUTODELETE] Couldn't delete message ${ messageToDelete . id } : ` , error ) ;
}
2025-02-05 23:07:05 -05:00
} ) ;
2025-02-05 23:29:59 -05:00
2025-02-06 08:29:28 -05:00
if ( ! deletedMessages . has ( messageToDelete . id ) ) {
deletedMessages . add ( messageToDelete . id ) ;
2025-04-10 15:07:02 -04:00
console . log ( ` [AUTODELETE] Successfully deleted message ${ messageToDelete . id } ` ) ;
if ( Math . random ( ) < 0.1 ) {
DELETE _INTERVAL _MIN = Math . max ( DELETE _INTERVAL _MIN * 0.95 , 8000 ) ;
DELETE _INTERVAL _MAX = Math . max ( DELETE _INTERVAL _MAX * 0.95 , 15000 ) ;
}
2025-02-06 08:29:28 -05:00
}
2025-04-10 15:07:02 -04:00
2025-02-05 23:07:05 -05:00
isFirstDeletion = false ;
} catch ( error ) {
console . log ( '[AUTODELETE] Error processing queue:' , error ) ;
}
if ( deleteQueue . length > 0 && isProcessingQueue ) {
2025-04-10 15:07:02 -04:00
scheduleNextDeletion ( ) ;
2025-02-05 23:07:05 -05:00
} else {
isProcessingQueue = false ;
}
} ;
2025-04-10 15:07:02 -04:00
const scheduleNextDeletion = ( ) => {
if ( shouldTakePause ( ) ) {
const pauseDuration = getPauseDuration ( ) ;
console . log ( ` [AUTODELETE] Taking a break for ${ Math . round ( pauseDuration / 1000 ) } seconds before continuing deletion. Queue size: ${ deleteQueue . length } ` ) ;
setTimeout ( processDeleteQueue , pauseDuration ) ;
} else {
let nextInterval = getHumanlikeDelay ( ) ;
if ( deleteQueue . length > 15 ) {
nextInterval = Math . max ( Math . floor ( nextInterval * 0.8 ) , 5000 ) ;
}
else if ( deleteQueue . length <= 2 ) {
nextInterval = Math . floor ( nextInterval * 1.2 ) ;
}
console . log ( ` [AUTODELETE] Next deletion in ${ nextInterval } ms | Queue size: ${ deleteQueue . length } ` ) ;
setTimeout ( processDeleteQueue , nextInterval ) ;
}
} ;
2025-02-05 23:07:05 -05:00
const startQueueProcessing = ( ) => {
if ( ! isProcessingQueue && deleteQueue . length > 0 ) {
isProcessingQueue = true ;
2025-04-10 15:07:02 -04:00
currentBatchCount = 0 ;
2025-02-05 23:07:05 -05:00
processDeleteQueue ( ) ;
}
} ;
const handleNewMessage = ( message ) => {
if ( ! isAutoDeleteActive || message . author . id !== message . client . user . id ) return ;
2025-02-05 23:29:59 -05:00
2025-02-06 08:29:28 -05:00
if ( ignoredMessages . has ( message . id ) || deletedMessages . has ( message . id ) ) {
console . log ( ` [AUTODELETE] Skipping cached/ignored message: ${ message . id } ` ) ;
2025-02-05 23:07:05 -05:00
return ;
}
if ( message . content . startsWith ( '.autodelete' ) ) {
console . log ( ` [AUTODELETE] Skipping command message: ${ message . id } ` ) ;
2025-04-10 15:07:02 -04:00
ignoredMessages . add ( message . id ) ;
2025-02-05 23:07:05 -05:00
return ;
}
2025-04-11 06:48:39 -04:00
if ( message . content . includes ( '```' ) && message . content . length > 100 ) {
console . log ( ` [AUTODELETE] Skipping command response message: ${ message . id } ` ) ;
ignoredMessages . add ( message . id ) ;
return ;
}
if ( message . scheduledForDeletion ) {
console . log ( ` [AUTODELETE] Skipping message already scheduled for deletion: ${ message . id } ` ) ;
ignoredMessages . add ( message . id ) ;
return ;
}
2025-02-05 23:07:05 -05:00
console . log ( ` [AUTODELETE] New message tracked: ${ message . id } ` ) ;
console . log ( ` [AUTODELETE] Content preview: ${ message . content . slice ( 0 , 30 ) } ... ` ) ;
2025-04-10 15:07:02 -04:00
const variableDelay = DELETION _DELAY + ( Math . random ( ) * 60000 ) - 30000 ; // +/- 30 seconds
2025-02-05 23:07:05 -05:00
const timer = setTimeout ( ( ) => {
if ( isAutoDeleteActive ) {
2025-04-10 15:07:02 -04:00
console . log ( ` [AUTODELETE] Timer completed for message: ${ message . id } after ~ ${ Math . round ( variableDelay / 1000 / 60 ) } minutes ` ) ;
2025-02-06 08:29:28 -05:00
if ( ! deletedMessages . has ( message . id ) ) {
deleteQueue . push ( message ) ;
messageTimers . delete ( message . id ) ;
startQueueProcessing ( ) ;
}
2025-02-05 23:07:05 -05:00
}
2025-04-10 15:07:02 -04:00
} , variableDelay ) ;
2025-02-05 23:07:05 -05:00
messageTimers . set ( message . id , timer ) ;
} ;
module . exports = {
name : 'autodelete' ,
2025-04-10 15:07:02 -04:00
description : 'Automatically deletes your messages after a set time' ,
2025-02-05 23:07:05 -05:00
async execute ( message , args , deleteTimeout ) {
ignoredMessages . add ( message . id ) ;
2025-04-10 15:50:25 -04:00
if ( args . length === 0 || args [ 0 ] . toLowerCase ( ) === 'status' ) {
const statusText = isAutoDeleteActive
? ` Auto-delete is ON - Messages will be deleted after approximately ${ Math . round ( DELETION _DELAY / 1000 / 60 ) } minutes. `
: 'Auto-delete is OFF.' ;
await sendCommandResponse (
message ,
` ${ statusText } \n Queue size: ${ deleteQueue . length } messages | Tracked messages: ${ messageTimers . size } ` ,
deleteTimeout ,
true
) ;
return ;
}
const command = args [ 0 ] . toLowerCase ( ) ;
if ( command === 'on' || command === 'start' || command === 'enable' ) {
if ( isAutoDeleteActive ) {
await sendCommandResponse ( message , 'Auto-delete is already active.' , deleteTimeout , true ) ;
return ;
}
isAutoDeleteActive = true ;
message . client . on ( 'messageCreate' , handleNewMessage ) ;
await sendCommandResponse (
message ,
` Auto-delete enabled. Your messages will be deleted after approximately ${ Math . round ( DELETION _DELAY / 1000 / 60 ) } minutes. ` ,
deleteTimeout ,
true
) ;
return ;
}
if ( command === 'off' || command === 'stop' || command === 'disable' ) {
if ( ! isAutoDeleteActive ) {
await sendCommandResponse ( message , 'Auto-delete is not active.' , deleteTimeout , true ) ;
return ;
}
2025-02-05 23:07:05 -05:00
isAutoDeleteActive = false ;
2025-04-10 15:50:25 -04:00
message . client . off ( 'messageCreate' , handleNewMessage ) ;
2025-02-05 23:29:59 -05:00
2025-04-10 15:50:25 -04:00
for ( const timer of messageTimers . values ( ) ) {
2025-02-05 23:07:05 -05:00
clearTimeout ( timer ) ;
}
messageTimers . clear ( ) ;
2025-02-05 23:29:59 -05:00
2025-04-10 15:50:25 -04:00
await sendCommandResponse ( message , 'Auto-delete disabled. Messages will no longer be automatically deleted.' , deleteTimeout , true ) ;
2025-02-05 23:07:05 -05:00
return ;
}
2025-04-10 15:50:25 -04:00
if ( command === 'clear' ) {
const queueSize = deleteQueue . length ;
const trackCount = messageTimers . size ;
deleteQueue = [ ] ;
for ( const timer of messageTimers . values ( ) ) {
clearTimeout ( timer ) ;
2025-04-10 15:07:02 -04:00
}
2025-04-10 15:50:25 -04:00
messageTimers . clear ( ) ;
currentBatchCount = 0 ;
await sendCommandResponse ( message , ` Cleared auto-delete queue ( ${ queueSize } pending, ${ trackCount } tracked). ` , deleteTimeout , true ) ;
return ;
2025-04-10 15:07:02 -04:00
}
2025-04-10 15:50:25 -04:00
if ( command === 'speed' ) {
const speedOption = args [ 1 ] ? . toLowerCase ( ) ;
if ( ! speedOption || ! [ 'slow' , 'normal' , 'fast' ] . includes ( speedOption ) ) {
await sendCommandResponse ( message , 'Please specify a valid speed: slow, normal, or fast.' , deleteTimeout , true ) ;
2025-04-10 15:07:02 -04:00
return ;
2025-04-10 15:50:25 -04:00
}
if ( speedOption === 'slow' ) {
DELETE _INTERVAL _MIN = 12000 ;
DELETE _INTERVAL _MAX = 25000 ;
JITTER _FACTOR = 0.5 ;
PAUSE _CHANCE = 0.25 ;
PAUSE _LENGTH _MIN = 45000 ;
PAUSE _LENGTH _MAX = 180000 ;
BATCH _SIZE = 2 ;
} else if ( speedOption === 'fast' ) {
2025-04-10 15:07:02 -04:00
DELETE _INTERVAL _MIN = 5000 ;
DELETE _INTERVAL _MAX = 10000 ;
2025-04-10 15:50:25 -04:00
JITTER _FACTOR = 0.3 ;
PAUSE _CHANCE = 0.1 ;
PAUSE _LENGTH _MIN = 15000 ;
PAUSE _LENGTH _MAX = 60000 ;
BATCH _SIZE = 5 ;
2025-04-10 15:07:02 -04:00
} else {
2025-04-10 15:50:25 -04:00
DELETE _INTERVAL _MIN = 8000 ;
DELETE _INTERVAL _MAX = 15000 ;
JITTER _FACTOR = 0.4 ;
PAUSE _CHANCE = 0.15 ;
PAUSE _LENGTH _MIN = 30000 ;
PAUSE _LENGTH _MAX = 120000 ;
BATCH _SIZE = 3 ;
2025-04-10 15:07:02 -04:00
}
2025-04-10 15:50:25 -04:00
await sendCommandResponse ( message , ` Auto-delete speed set to ${ speedOption } . ` , deleteTimeout , true ) ;
return ;
2025-04-10 15:07:02 -04:00
}
2025-04-10 15:50:25 -04:00
await sendCommandResponse (
message ,
'Unknown command. Available options: on/off, status, clear, speed [slow/normal/fast]' ,
deleteTimeout ,
true
) ;
2025-02-05 23:07:05 -05:00
} ,
} ;