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-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 ;
}
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 ) ;
if ( args [ 0 ] ? . toLowerCase ( ) === 'stop' ) {
isAutoDeleteActive = false ;
2025-02-05 23:29:59 -05:00
2025-02-05 23:07:05 -05:00
for ( const [ messageId , timer ] of messageTimers ) {
clearTimeout ( timer ) ;
console . log ( ` [AUTODELETE] Cleared timer for message: ${ messageId } ` ) ;
}
2025-02-05 23:29:59 -05:00
2025-02-05 23:07:05 -05:00
messageTimers . clear ( ) ;
deleteQueue = [ ] ;
isProcessingQueue = false ;
isFirstDeletion = true ;
2025-02-05 23:29:59 -05:00
2025-04-10 15:07:02 -04:00
DELETE _INTERVAL _MIN = 8000 ;
DELETE _INTERVAL _MAX = 15000 ;
currentBatchCount = 0 ;
2025-02-05 23:07:05 -05:00
console . log ( '[AUTODELETE] System deactivated - All timers cleared' ) ;
message . channel . send ( 'Auto-delete has been deactivated.' )
2025-02-05 23:29:59 -05:00
. then ( msg => setTimeout ( ( ) => msg . delete ( ) . catch ( ( ) => { } ) , deleteTimeout ) ) ;
2025-02-05 23:07:05 -05:00
return ;
}
2025-04-10 15:07:02 -04:00
if ( args [ 0 ] ? . toLowerCase ( ) === 'delay' && args [ 1 ] ) {
const newDelay = parseInt ( args [ 1 ] , 10 ) ;
if ( ! isNaN ( newDelay ) && newDelay >= 1 ) {
const oldDelay = Math . round ( DELETION _DELAY / 1000 / 60 ) ;
DELETION _DELAY = newDelay * 1000 * 60 ;
message . channel . send ( ` Auto-delete delay changed from ${ oldDelay } to ${ newDelay } minutes. ` )
. then ( msg => setTimeout ( ( ) => msg . delete ( ) . catch ( ( ) => { } ) , deleteTimeout ) ) ;
return ;
} else {
message . channel . send ( 'Please provide a valid delay in minutes (minimum 1 minute).' )
. then ( msg => setTimeout ( ( ) => msg . delete ( ) . catch ( ( ) => { } ) , deleteTimeout ) ) ;
return ;
}
}
if ( args [ 0 ] ? . toLowerCase ( ) === 'speed' ) {
if ( args [ 1 ] ? . toLowerCase ( ) === 'slow' ) {
DELETE _INTERVAL _MIN = 15000 ;
DELETE _INTERVAL _MAX = 30000 ;
PAUSE _CHANCE = 0.25 ;
message . channel . send ( 'Auto-delete speed set to slow mode (very human-like with frequent pauses).' )
. then ( msg => setTimeout ( ( ) => msg . delete ( ) . catch ( ( ) => { } ) , deleteTimeout ) ) ;
return ;
} else if ( args [ 1 ] ? . toLowerCase ( ) === 'medium' ) {
DELETE _INTERVAL _MIN = 8000 ;
DELETE _INTERVAL _MAX = 15000 ;
PAUSE _CHANCE = 0.15 ;
message . channel . send ( 'Auto-delete speed set to medium mode (balanced human-like behavior).' )
. then ( msg => setTimeout ( ( ) => msg . delete ( ) . catch ( ( ) => { } ) , deleteTimeout ) ) ;
return ;
} else if ( args [ 1 ] ? . toLowerCase ( ) === 'fast' ) {
DELETE _INTERVAL _MIN = 5000 ;
DELETE _INTERVAL _MAX = 10000 ;
PAUSE _CHANCE = 0.05 ;
message . channel . send ( 'Auto-delete speed set to fast mode (less human-like but quicker progress).' )
. then ( msg => setTimeout ( ( ) => msg . delete ( ) . catch ( ( ) => { } ) , deleteTimeout ) ) ;
return ;
} else {
message . channel . send ( 'Please specify a valid speed: slow, medium, or fast.' )
. then ( msg => setTimeout ( ( ) => msg . delete ( ) . catch ( ( ) => { } ) , deleteTimeout ) ) ;
return ;
}
}
2025-02-05 23:07:05 -05:00
if ( ! isAutoDeleteActive ) {
isAutoDeleteActive = true ;
isFirstDeletion = true ;
2025-04-10 15:07:02 -04:00
currentBatchCount = 0 ;
2025-02-05 23:07:05 -05:00
console . log ( '[AUTODELETE] System activated - Now tracking new messages' ) ;
message . client . removeListener ( 'messageCreate' , handleNewMessage ) ;
message . client . on ( 'messageCreate' , handleNewMessage ) ;
2025-04-10 15:07:02 -04:00
const delayInMinutes = Math . round ( DELETION _DELAY / 1000 / 60 ) ;
message . channel . send (
` Auto-delete activated. Messages will be deleted after ~ ${ delayInMinutes } minutes ` +
` with human-like timing. Use \` .autodelete speed slow/medium/fast \` to adjust deletion speed. `
) . then ( msg => setTimeout ( ( ) => msg . delete ( ) . catch ( ( ) => { } ) , deleteTimeout ) ) ;
2025-02-05 23:07:05 -05:00
} else {
2025-04-10 15:07:02 -04:00
const delayInMinutes = Math . round ( DELETION _DELAY / 1000 / 60 ) ;
message . channel . send (
` Auto-delete is already active. Current delay: ~ ${ delayInMinutes } minutes. ` +
` Use \` .autodelete speed slow/medium/fast \` to adjust deletion speed. `
) . then ( msg => setTimeout ( ( ) => msg . delete ( ) . catch ( ( ) => { } ) , deleteTimeout ) ) ;
2025-02-05 23:07:05 -05:00
}
} ,
} ;