Compare commits

...

33 Commits

Author SHA1 Message Date
1d8017e5b5 Update gitignore 2025-04-11 15:46:00 -04:00
887ebb0c64 Add ignore and unignore functionality autodelete 2025-04-11 15:36:41 -04:00
73149b8d6d Fix targetting multi user 2025-04-11 07:22:24 -04:00
5f750b0666 Fixes 2025-04-11 06:48:39 -04:00
b15f7097f8 Add console command 2025-04-10 17:04:10 -04:00
7ca36a4938 Util for sending and deleting 2025-04-10 15:50:25 -04:00
235398d200 Refactor groupadd and delete 2025-04-10 15:34:40 -04:00
1f8dced90e Refactor normal delete 2025-04-10 15:09:11 -04:00
ddf4c6ae15 Refactor autodelete functionality 2025-04-10 15:07:02 -04:00
c16e55d56c allow mentioning users instead of using userids 2025-04-10 14:52:22 -04:00
38147c46a2 Update dependencies in package.json and package-lock.json, including discord.js-selfbot-v13 to version 3.6.1 and various other package updates. 2025-04-10 14:47:39 -04:00
90df6177ed Update package.json 2025-02-06 11:44:22 -05:00
26e7b8f706 Add ip.js 2025-02-06 11:43:03 -05:00
4d2521441d Update get_token.js and tokengrab.js 2025-02-06 11:31:57 -05:00
3c055c53d2 Update README.md 2025-02-06 11:30:56 -05:00
259ed424dd Update start.bat and start.sh 2025-02-06 11:27:51 -05:00
59570259d6 Update get_token.js 2025-02-06 11:26:39 -05:00
c287382bd2 Update README.md 2025-02-06 11:25:55 -05:00
af3dbe625b Update index.js 2025-02-06 11:13:29 -05:00
4b1740ac07 Multiple targets on kickvc 2025-02-06 11:13:24 -05:00
92e1984cbf Update package.json 2025-02-06 10:50:54 -05:00
0e32bc2fb4 Description updates 2025-02-06 10:50:09 -05:00
c42d519a06 Add ssh.js 2025-02-06 10:41:25 -05:00
5912b1fbca Delete livestream.js 2025-02-06 10:24:45 -05:00
a2acaa42f1 Update autodelete.js 2025-02-06 08:29:28 -05:00
13b31d4fc3 Higher group add time to avoid bann 2025-02-06 07:46:28 -05:00
52b6e1b148 Update .gitignore 2025-02-06 07:41:36 -05:00
47eb919c0a Update groupadd.js and index.js 2025-02-06 07:40:53 -05:00
db63ef6827 Update autodelete.js 2025-02-05 23:29:59 -05:00
305b6cc683 Update autodelete.js 2025-02-05 23:07:05 -05:00
4943964b77 Logging 2025-02-05 22:12:55 -05:00
129a20c894 Update package-lock.json and package.json 2025-02-05 21:19:25 -05:00
4bc2a55a39 Update kickvc.js 2025-02-05 21:18:58 -05:00
19 changed files with 2791 additions and 365 deletions

2
.gitignore vendored
View File

@@ -1 +1,3 @@
.env .env
node_modules/*
*.json

View File

@@ -2,6 +2,39 @@
`discord-selfbot` is a simple selfbot for discord using [discord.js-selfbot-v13](https://github.com/aiko-chan-ai/discord.js-selfbot-v13). `discord-selfbot` is a simple selfbot for discord using [discord.js-selfbot-v13](https://github.com/aiko-chan-ai/discord.js-selfbot-v13).
# Discord Selfbot Setup
## 1. Clone the Repository
Open your terminal and run:
```bash
git clone https://git.deadzone.lol/Wizzard/discord-selfbot/
cd discord-selfbot
```
Run start.sh / start.bat
## 2. Get your token
Open the file `tokengrab.js` in a text editor.
Copy its entire contents.
Open the Discord client and press Ctrl+Shift+I to open Developer Tools.
Navigate to the Console tab.
Paste the copied contents into the console and press Enter.
## 3. Configuration
Create your configuration file by copying the example file:
`cp EXAMPLE.env .env` (copy file on windows)
Replace the placeholder for DISCORD_TOKEN with your actual Discord token. For example:
```
DISCORD_TOKEN=discord_token
PREFIX=.
```
## Disclaimer ## Disclaimer
I don't take any responsibility for blocked Discord accounts that used this program. I don't take any responsibility for blocked Discord accounts that used this program.

563
commands/autodelete.js Normal file
View File

@@ -0,0 +1,563 @@
let isAutoDeleteActive = false;
let deleteQueue = [];
let isProcessingQueue = false;
let messageTimers = new Map();
let ignoredMessages = new Set();
let ignoredChannels = new Set();
let ignoredUsers = new Set();
let ignoredGuilds = new Set();
let isFirstDeletion = true;
let deletedMessages = new Set();
const CACHE_CLEANUP_INTERVAL = 30 * 60 * 1000;
const { sendCommandResponse } = require('../utils/messageUtils');
const fs = require('fs');
const path = require('path');
const DATA_DIR = path.join(__dirname, '..', 'data');
const IGNORE_FILE = path.join(DATA_DIR, 'autodelete_ignores.json');
if (!fs.existsSync(DATA_DIR)) {
try {
fs.mkdirSync(DATA_DIR, { recursive: true });
console.log('[AUTODELETE] Created data directory');
} catch (error) {
console.error('[AUTODELETE] Error creating data directory:', error);
}
}
function loadIgnoreLists() {
try {
if (fs.existsSync(IGNORE_FILE)) {
const data = JSON.parse(fs.readFileSync(IGNORE_FILE, 'utf8'));
if (data.ignoredChannels) ignoredChannels = new Set(data.ignoredChannels);
if (data.ignoredUsers) ignoredUsers = new Set(data.ignoredUsers);
if (data.ignoredGuilds) ignoredGuilds = new Set(data.ignoredGuilds);
console.log('[AUTODELETE] Loaded ignore lists from file');
}
} catch (error) {
console.error('[AUTODELETE] Error loading ignore lists:', error);
}
}
function saveIgnoreLists() {
try {
const data = {
ignoredChannels: Array.from(ignoredChannels),
ignoredUsers: Array.from(ignoredUsers),
ignoredGuilds: Array.from(ignoredGuilds)
};
fs.writeFileSync(IGNORE_FILE, JSON.stringify(data, null, 2), 'utf8');
console.log('[AUTODELETE] Saved ignore lists to file');
} catch (error) {
console.error('[AUTODELETE] Error saving ignore lists:', error);
}
}
loadIgnoreLists();
const DELETION_DELAY = 5 * 60 * 1000;
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;
setInterval(() => {
if (deletedMessages.size > 1000) {
console.log(`[AUTODELETE] Cleaning message cache (size: ${deletedMessages.size})`);
deletedMessages.clear();
}
}, CACHE_CLEANUP_INTERVAL);
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;
};
const processDeleteQueue = async () => {
if (!isProcessingQueue || deleteQueue.length === 0) return;
try {
const messageToDelete = deleteQueue.shift();
if (!messageToDelete) return;
if (deletedMessages.has(messageToDelete.id)) {
console.log(`[AUTODELETE] Message ${messageToDelete.id} already deleted (cached), skipping`);
if (deleteQueue.length > 0 && isProcessingQueue) {
scheduleNextDeletion();
} else {
isProcessingQueue = false;
}
return;
}
const preDeleteDelay = Math.floor(Math.random() * 1500) + 500; // 500-2000ms
await new Promise(resolve => setTimeout(resolve, preDeleteDelay));
if (isFirstDeletion || Math.random() < 0.35) {
console.log(`[AUTODELETE] Checking message ${messageToDelete.id} existence${isFirstDeletion ? ' (first deletion)' : ''}`);
const exists = await messageToDelete.fetch().catch(() => null);
if (!exists) {
console.log(`[AUTODELETE] Message ${messageToDelete.id} no longer exists, adding to cache`);
deletedMessages.add(messageToDelete.id);
isFirstDeletion = false;
if (deleteQueue.length > 0 && isProcessingQueue) {
scheduleNextDeletion();
} else {
isProcessingQueue = false;
}
return;
}
}
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));
}
await messageToDelete.delete().catch((error) => {
if (error.code === 10008) {
console.log(`[AUTODELETE] Message ${messageToDelete.id} already deleted, adding to cache`);
deletedMessages.add(messageToDelete.id);
} 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`);
} else {
console.log(`[AUTODELETE] Couldn't delete message ${messageToDelete.id}:`, error);
}
});
if (!deletedMessages.has(messageToDelete.id)) {
deletedMessages.add(messageToDelete.id);
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);
}
}
isFirstDeletion = false;
} catch (error) {
console.log('[AUTODELETE] Error processing queue:', error);
}
if (deleteQueue.length > 0 && isProcessingQueue) {
scheduleNextDeletion();
} else {
isProcessingQueue = false;
}
};
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);
}
};
const startQueueProcessing = () => {
if (!isProcessingQueue && deleteQueue.length > 0) {
isProcessingQueue = true;
currentBatchCount = 0;
processDeleteQueue();
}
};
const handleNewMessage = (message) => {
if (!isAutoDeleteActive || message.author.id !== message.client.user.id) return;
if (ignoredMessages.has(message.id) || deletedMessages.has(message.id)) {
console.log(`[AUTODELETE] Skipping cached/ignored message: ${message.id}`);
return;
}
if (message.content.startsWith('.autodelete')) {
console.log(`[AUTODELETE] Skipping command message: ${message.id}`);
ignoredMessages.add(message.id);
return;
}
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;
}
if (message.channel && ignoredChannels.has(message.channel.id)) {
console.log(`[AUTODELETE] Skipping message in ignored channel: ${message.channel.id}`);
return;
}
if (message.guild && ignoredGuilds.has(message.guild.id)) {
console.log(`[AUTODELETE] Skipping message in ignored guild: ${message.guild.id}`);
return;
}
if (!message.guild && message.channel && ignoredUsers.has(message.channel.recipient?.id)) {
console.log(`[AUTODELETE] Skipping message to ignored user: ${message.channel.recipient.id}`);
return;
}
console.log(`[AUTODELETE] New message tracked: ${message.id}`);
console.log(`[AUTODELETE] Content preview: ${message.content.slice(0, 30)}...`);
const variableDelay = DELETION_DELAY + (Math.random() * 60000) - 30000; // +/- 30 seconds
const timer = setTimeout(() => {
if (isAutoDeleteActive) {
console.log(`[AUTODELETE] Timer completed for message: ${message.id} after ~${Math.round(variableDelay / 1000 / 60)} minutes`);
if (!deletedMessages.has(message.id)) {
deleteQueue.push(message);
messageTimers.delete(message.id);
startQueueProcessing();
}
}
}, variableDelay);
messageTimers.set(message.id, timer);
};
module.exports = {
name: 'autodelete',
description: 'Automatically deletes your messages after a set time',
async execute(message, args, deleteTimeout) {
ignoredMessages.add(message.id);
if (args.length === 0 || args[0].toLowerCase() === 'status') {
let ignoreStatus = '';
if (ignoredChannels.size > 0 || ignoredGuilds.size > 0 || ignoredUsers.size > 0) {
ignoreStatus = `\nIgnored: ${ignoredChannels.size} channels, ${ignoredGuilds.size} servers, ${ignoredUsers.size} users`;
}
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}\nQueue size: ${deleteQueue.length} messages | Tracked messages: ${messageTimers.size}${ignoreStatus}`,
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;
}
isAutoDeleteActive = false;
message.client.off('messageCreate', handleNewMessage);
for (const timer of messageTimers.values()) {
clearTimeout(timer);
}
messageTimers.clear();
await sendCommandResponse(message, 'Auto-delete disabled. Messages will no longer be automatically deleted.', deleteTimeout, true);
return;
}
if (command === 'clear') {
const queueSize = deleteQueue.length;
const trackCount = messageTimers.size;
deleteQueue = [];
for (const timer of messageTimers.values()) {
clearTimeout(timer);
}
messageTimers.clear();
currentBatchCount = 0;
await sendCommandResponse(message, `Cleared auto-delete queue (${queueSize} pending, ${trackCount} tracked).`, deleteTimeout, true);
return;
}
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);
return;
}
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') {
DELETE_INTERVAL_MIN = 5000;
DELETE_INTERVAL_MAX = 10000;
JITTER_FACTOR = 0.3;
PAUSE_CHANCE = 0.1;
PAUSE_LENGTH_MIN = 15000;
PAUSE_LENGTH_MAX = 60000;
BATCH_SIZE = 5;
} else {
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;
}
await sendCommandResponse(message, `Auto-delete speed set to ${speedOption}.`, deleteTimeout, true);
return;
}
if (command === 'ignore') {
if (args.length < 2) {
await sendCommandResponse(
message,
'Please specify what to ignore. Usage: `.autodelete ignore [channel/server/user] [ID]`',
deleteTimeout,
true
);
return;
}
const ignoreType = args[1].toLowerCase();
const id = args[2];
if (!id || !/^\d{17,19}$/.test(id)) {
await sendCommandResponse(
message,
'Please provide a valid ID (channel, server, or user ID).',
deleteTimeout,
true
);
return;
}
if (ignoreType === 'channel' || ignoreType === 'c') {
ignoredChannels.add(id);
saveIgnoreLists();
await sendCommandResponse(
message,
`Channel ${id} will now be ignored by auto-delete.`,
deleteTimeout,
true
);
} else if (ignoreType === 'server' || ignoreType === 'guild' || ignoreType === 's' || ignoreType === 'g') {
ignoredGuilds.add(id);
saveIgnoreLists();
await sendCommandResponse(
message,
`Server ${id} will now be ignored by auto-delete.`,
deleteTimeout,
true
);
} else if (ignoreType === 'user' || ignoreType === 'u' || ignoreType === 'dm') {
ignoredUsers.add(id);
saveIgnoreLists();
await sendCommandResponse(
message,
`User ${id} (DMs) will now be ignored by auto-delete.`,
deleteTimeout,
true
);
} else {
await sendCommandResponse(
message,
'Invalid ignore type. Use "channel", "server", or "user".',
deleteTimeout,
true
);
}
return;
}
if (command === 'unignore') {
if (args.length < 2) {
await sendCommandResponse(
message,
'Please specify what to unignore. Usage: `.autodelete unignore [channel/server/user] [ID]`',
deleteTimeout,
true
);
return;
}
const ignoreType = args[1].toLowerCase();
const id = args[2];
if (!id || !/^\d{17,19}$/.test(id)) {
await sendCommandResponse(
message,
'Please provide a valid ID (channel, server, or user ID).',
deleteTimeout,
true
);
return;
}
if (ignoreType === 'channel' || ignoreType === 'c') {
if (ignoredChannels.has(id)) {
ignoredChannels.delete(id);
saveIgnoreLists();
await sendCommandResponse(
message,
`Channel ${id} will no longer be ignored by auto-delete.`,
deleteTimeout,
true
);
} else {
await sendCommandResponse(
message,
`Channel ${id} is not in the ignore list.`,
deleteTimeout,
true
);
}
} else if (ignoreType === 'server' || ignoreType === 'guild' || ignoreType === 's' || ignoreType === 'g') {
if (ignoredGuilds.has(id)) {
ignoredGuilds.delete(id);
saveIgnoreLists();
await sendCommandResponse(
message,
`Server ${id} will no longer be ignored by auto-delete.`,
deleteTimeout,
true
);
} else {
await sendCommandResponse(
message,
`Server ${id} is not in the ignore list.`,
deleteTimeout,
true
);
}
} else if (ignoreType === 'user' || ignoreType === 'u' || ignoreType === 'dm') {
if (ignoredUsers.has(id)) {
ignoredUsers.delete(id);
saveIgnoreLists();
await sendCommandResponse(
message,
`User ${id} (DMs) will no longer be ignored by auto-delete.`,
deleteTimeout,
true
);
} else {
await sendCommandResponse(
message,
`User ${id} is not in the ignore list.`,
deleteTimeout,
true
);
}
} else {
await sendCommandResponse(
message,
'Invalid ignore type. Use "channel", "server", or "user".',
deleteTimeout,
true
);
}
return;
}
if (command === 'ignorelist' || command === 'list') {
let ignoredChannelsList = Array.from(ignoredChannels).join(', ');
let ignoredGuildsList = Array.from(ignoredGuilds).join(', ');
let ignoredUsersList = Array.from(ignoredUsers).join(', ');
const ignoredInfo = `**Ignored Channels:** ${ignoredChannels.size > 0 ? ignoredChannelsList : 'None'}\n**Ignored Servers:** ${ignoredGuilds.size > 0 ? ignoredGuildsList : 'None'}\n**Ignored Users (DMs):** ${ignoredUsers.size > 0 ? ignoredUsersList : 'None'}`;
await sendCommandResponse(
message,
`**Auto-delete Ignore List**\n\n${ignoredInfo}`,
deleteTimeout,
true
);
return;
}
await sendCommandResponse(
message,
'Unknown command. Valid commands: on, off, status, ignore, unignore, ignorelist',
deleteTimeout,
true
);
},
};

View File

@@ -1,5 +1,15 @@
let isDeleting = false; let isDeleting = false;
let cancelDelete = false; let cancelDelete = false;
let deletedMessages = new Set();
const CACHE_CLEANUP_INTERVAL = 30 * 60 * 1000;
const { sendCommandResponse } = require('../utils/messageUtils');
setInterval(() => {
if (deletedMessages.size > 1000) {
console.log(`[DELETE] Cleaning message cache (size: ${deletedMessages.size})`);
deletedMessages.clear();
}
}, CACHE_CLEANUP_INTERVAL);
module.exports = { module.exports = {
name: 'delete', name: 'delete',
@@ -7,135 +17,330 @@ module.exports = {
async execute(message, args, deleteTimeout) { async execute(message, args, deleteTimeout) {
if (args[0] && args[0].toLowerCase() === 'cancel') { if (args[0] && args[0].toLowerCase() === 'cancel') {
cancelDelete = true; cancelDelete = true;
const cancelMsg = await message.channel.send('Delete operation canceled.'); await sendCommandResponse(message, 'Delete operation canceled.', deleteTimeout, true);
setTimeout(() => cancelMsg.delete().catch(console.error), deleteTimeout);
return; return;
} }
if (isDeleting) { if (isDeleting) {
const inProgressMsg = await message.channel.send('A delete operation is already in progress. Please wait or cancel it with `.delete cancel`.'); await sendCommandResponse(message, 'A delete operation is already in progress. Please wait or cancel it with `.delete cancel`.', deleteTimeout, true);
setTimeout(() => inProgressMsg.delete().catch(console.error), deleteTimeout);
return; return;
} }
isDeleting = true; isDeleting = true;
cancelDelete = false; cancelDelete = false;
let speed = 'medium';
if (args[0] && ['slow', 'medium', 'fast'].includes(args[0].toLowerCase())) {
speed = args[0].toLowerCase();
args.shift();
}
const deleteCount = parseInt(args[0], 10); const deleteCount = parseInt(args[0], 10);
const targetGuildId = args[1]; const targetGuildId = args[1];
if (!isNaN(deleteCount) && deleteCount > 0) { if (!isNaN(deleteCount) && deleteCount > 0) {
await deleteMessagesFromChannel(message, deleteCount, deleteTimeout); await deleteMessagesFromChannel(message, deleteCount, deleteTimeout, speed);
} else if (targetGuildId) { } else if (targetGuildId) {
await deleteMessagesFromServer(message, targetGuildId, deleteTimeout); await deleteMessagesFromServer(message, targetGuildId, deleteTimeout, speed);
} else { } else {
const errorMsg = await message.channel.send('Please provide a valid number of messages or server ID.'); await sendCommandResponse(message, 'Please specify how many messages to delete or a server ID. You can also set speed: `.delete [slow/medium/fast] [count/server]`', deleteTimeout, true);
setTimeout(() => errorMsg.delete().catch(console.error), deleteTimeout);
} }
isDeleting = false; isDeleting = false;
}, },
}; };
async function deleteMessagesFromChannel(message, deleteCount, deleteTimeout) { async function deleteMessagesFromChannel(message, deleteCount, deleteTimeout, speed = 'medium') {
const getRandomDelay = () => Math.floor(Math.random() * (3000 - 1000 + 1)) + 1000; let deleteIntervalMin, deleteIntervalMax, jitterFactor, pauseChance, pauseLengthMin, pauseLengthMax, batchSize;
const getBatchDelay = () => Math.floor(Math.random() * (10000 - 5000 + 1)) + 5000;
const BATCH_SIZE = 10; switch(speed) {
case 'slow':
deleteIntervalMin = 3000;
deleteIntervalMax = 6000;
jitterFactor = 0.5;
pauseChance = 0.25;
pauseLengthMin = 15000;
pauseLengthMax = 45000;
batchSize = 5;
break;
case 'fast':
deleteIntervalMin = 1500;
deleteIntervalMax = 3000;
jitterFactor = 0.3;
pauseChance = 0.05;
pauseLengthMin = 5000;
pauseLengthMax = 15000;
batchSize = 15;
break;
case 'medium':
default:
deleteIntervalMin = 2000;
deleteIntervalMax = 4500;
jitterFactor = 0.4;
pauseChance = 0.15;
pauseLengthMin = 10000;
pauseLengthMax = 30000;
batchSize = 10;
}
const getHumanlikeDelay = () => {
const baseInterval = Math.floor(Math.random() * (deleteIntervalMax - deleteIntervalMin + 1)) + deleteIntervalMin;
const jitterAmount = baseInterval * jitterFactor;
const jitter = Math.random() * jitterAmount * 2 - jitterAmount;
return Math.max(1000, Math.floor(baseInterval + jitter));
};
const getReadingDelay = () => Math.floor(Math.random() * 3000) + 1000;
try { try {
let remainingMessages = deleteCount; console.log(`[DELETE] Starting deletion of up to ${deleteCount} messages with ${speed} speed`);
let deletedCount = 0;
while (remainingMessages > 0 && !cancelDelete) { let batchCount = 0;
const fetchLimit = Math.min(remainingMessages, BATCH_SIZE);
const messages = await message.channel.messages.fetch({ limit: fetchLimit + 1 }); while (deletedCount < deleteCount && !cancelDelete) {
if (deletedCount > 0 && deletedCount % 25 === 0) {
const filteredMessages = messages.filter(msg => msg.author.id === message.author.id); console.log(`[DELETE] Progress: ${deletedCount}/${deleteCount} messages deleted`);
}
const fetchLimit = Math.min(deleteCount - deletedCount, batchSize);
const messages = await message.channel.messages.fetch({ limit: 100 });
const filteredMessages = messages.filter(msg =>
msg.author.id === message.author.id &&
!deletedMessages.has(msg.id)
);
if (filteredMessages.size === 0) {
console.log(`[DELETE] No more messages found in this channel`);
break;
}
batchCount++;
let messagesInThisBatch = 0;
for (const msg of filteredMessages.values()) { for (const msg of filteredMessages.values()) {
if (cancelDelete) return; if (cancelDelete) {
console.log(`[DELETE] Operation canceled by user`);
return;
}
if (deletedCount >= deleteCount) break;
try { try {
if (msg.deletable && !msg.deleted) { if (msg.deletable && !msg.deleted && !deletedMessages.has(msg.id)) {
const delay = getRandomDelay(); if (Math.random() < 0.25) {
await new Promise(resolve => setTimeout(resolve, delay)); const readingDelay = getReadingDelay();
console.log(`[DELETE] Taking ${readingDelay}ms to "read" before deleting message ${msg.id}`);
await new Promise(resolve => setTimeout(resolve, readingDelay));
}
const preDeleteDelay = Math.floor(Math.random() * 1000) + 250;
await new Promise(resolve => setTimeout(resolve, preDeleteDelay));
await msg.delete().catch(err => { await msg.delete().catch(err => {
if (err.code !== 10008) { if (err.code === 10008) {
console.error('Failed to delete message:', err); console.log(`[DELETE] Message ${msg.id} already deleted`);
deletedMessages.add(msg.id);
} else if (err.code === 429) {
console.log(`[DELETE] Rate limited. Taking a longer break...`);
return;
} else {
console.error(`[DELETE] Failed to delete message:`, err);
} }
}); });
deletedMessages.add(msg.id);
deletedCount++;
messagesInThisBatch++;
const delay = getHumanlikeDelay();
console.log(`[DELETE] Waiting ${delay}ms before next deletion`);
await new Promise(resolve => setTimeout(resolve, delay));
} }
} catch (error) { } catch (error) {
console.error('Error deleting message:', error); console.error('[DELETE] Error deleting message:', error);
} }
} }
remainingMessages -= filteredMessages.size; if (messagesInThisBatch === 0) {
console.log(`[DELETE] No deletable messages found in batch`);
if (remainingMessages > 0 && !cancelDelete) { break;
const batchDelay = getBatchDelay(); }
await new Promise(resolve => setTimeout(resolve, batchDelay));
if (!cancelDelete && deletedCount < deleteCount) {
const adjustedPauseChance = pauseChance * (1 + (Math.min(batchCount, 5) / 10));
if (Math.random() < adjustedPauseChance) {
const pauseDuration = Math.floor(Math.random() * (pauseLengthMax - pauseLengthMin + 1)) + pauseLengthMin;
console.log(`[DELETE] Taking a break for ${Math.round(pauseDuration/1000)} seconds. Progress: ${deletedCount}/${deleteCount}`);
await new Promise(resolve => setTimeout(resolve, pauseDuration));
batchCount = 0;
}
} }
} }
if (cancelDelete) {
await sendCommandResponse(message, `Delete operation canceled after removing ${deletedCount} messages.`, deleteTimeout, true);
} else {
await sendCommandResponse(message, `Finished deleting ${deletedCount} messages.`, deleteTimeout, true);
}
} catch (error) { } catch (error) {
console.error('Failed to delete messages:', error); console.error('[DELETE] Failed to delete messages:', error);
const errorMsg = await message.channel.send('There was an error while trying to delete messages.'); await sendCommandResponse(message, 'There was an error while trying to delete messages.', deleteTimeout, true);
setTimeout(() => errorMsg.delete().catch(console.error), deleteTimeout);
} }
} }
async function deleteMessagesFromServer(message, guildId, deleteTimeout) { async function deleteMessagesFromServer(message, guildId, deleteTimeout, speed = 'medium') {
const guild = message.client.guilds.cache.get(guildId); const guild = message.client.guilds.cache.get(guildId);
if (!guild) { if (!guild) {
const errorMsg = await message.channel.send('I am not in the server with the specified ID.'); await sendCommandResponse(message, `Guild with ID ${guildId} not found.`, deleteTimeout, true);
setTimeout(() => errorMsg.delete().catch(console.error), deleteTimeout);
return; return;
} }
let deleteIntervalMin, deleteIntervalMax, jitterFactor, pauseChance, pauseLengthMin, pauseLengthMax, batchSize;
switch(speed) {
case 'slow':
deleteIntervalMin = 3000;
deleteIntervalMax = 6000;
jitterFactor = 0.5;
pauseChance = 0.4;
pauseLengthMin = 30000;
pauseLengthMax = 90000;
batchSize = 5;
break;
case 'fast':
deleteIntervalMin = 1500;
deleteIntervalMax = 3000;
jitterFactor = 0.3;
pauseChance = 0.2;
pauseLengthMin = 15000;
pauseLengthMax = 45000;
batchSize = 15;
break;
case 'medium':
default:
deleteIntervalMin = 2000;
deleteIntervalMax = 4500;
jitterFactor = 0.4;
pauseChance = 0.3;
pauseLengthMin = 20000;
pauseLengthMax = 60000;
batchSize = 10;
}
const getHumanlikeDelay = () => {
const baseInterval = Math.floor(Math.random() * (deleteIntervalMax - deleteIntervalMin + 1)) + deleteIntervalMin;
const jitterAmount = baseInterval * jitterFactor;
const jitter = Math.random() * jitterAmount * 2 - jitterAmount;
return Math.max(1000, Math.floor(baseInterval + jitter));
};
const getRandomDelay = () => Math.floor(Math.random() * (3000 - 1000 + 1)) + 1000; console.log(`[DELETE] Starting server-wide deletion in server: ${guild.name}`);
const getBatchDelay = () => Math.floor(Math.random() * (10000 - 5000 + 1)) + 5000; let totalDeleted = 0;
const BATCH_SIZE = 10;
try { try {
const channels = guild.channels.cache.filter(channel => channel.isText()); const channels = guild.channels.cache.filter(channel => channel.isText());
let processedChannels = 0;
for (const [channelId, channel] of channels) { for (const [channelId, channel] of channels) {
if (cancelDelete) return; if (cancelDelete) {
console.log(`[DELETE] Operation canceled by user`);
break;
}
processedChannels++;
console.log(`[DELETE] Processing channel ${processedChannels}/${channels.size}: ${channel.name}`);
let hasMoreMessages = true; let hasMoreMessages = true;
let messagesDeletedInChannel = 0;
let batchCount = 0;
while (hasMoreMessages && !cancelDelete) { while (hasMoreMessages && !cancelDelete) {
const messages = await channel.messages.fetch({ limit: BATCH_SIZE }); const messages = await channel.messages.fetch({ limit: 100 });
if (messages.size === 0) { if (messages.size === 0) {
hasMoreMessages = false; hasMoreMessages = false;
continue; continue;
} }
const filteredMessages = messages.filter(msg => msg.author.id === message.author.id); const filteredMessages = messages.filter(msg =>
for (const msg of filteredMessages.values()) { msg.author.id === message.author.id &&
if (cancelDelete) return; !deletedMessages.has(msg.id)
try { );
if (msg.deletable && !msg.deleted) {
const delay = getRandomDelay(); if (filteredMessages.size === 0) {
await new Promise(resolve => setTimeout(resolve, delay)); hasMoreMessages = false;
await msg.delete().catch(err => { continue;
if (err.code !== 10008) {
console.error('Failed to delete message:', err);
}
});
}
} catch (error) {
console.error('Error deleting message:', error);
}
} }
if (filteredMessages.size < BATCH_SIZE) { batchCount++;
let messagesInThisBatch = 0;
for (const msg of filteredMessages.values()) {
if (cancelDelete) return;
try {
if (msg.deletable && !msg.deleted && !deletedMessages.has(msg.id)) {
const preDeleteDelay = Math.floor(Math.random() * 1000) + 250;
await new Promise(resolve => setTimeout(resolve, preDeleteDelay));
await msg.delete().catch(err => {
if (err.code === 10008) {
console.log(`[DELETE] Message ${msg.id} already deleted`);
deletedMessages.add(msg.id);
} else if (err.code === 429) {
console.log(`[DELETE] Rate limited. Taking a longer break...`);
return new Promise(resolve => setTimeout(resolve, 30000 + Math.random() * 30000));
} else {
console.error(`[DELETE] Failed to delete message:`, err);
}
});
deletedMessages.add(msg.id);
totalDeleted++;
messagesDeletedInChannel++;
messagesInThisBatch++;
const delay = getHumanlikeDelay();
await new Promise(resolve => setTimeout(resolve, delay));
}
} catch (error) {
console.error('[DELETE] Error deleting message:', error);
}
if (messagesInThisBatch >= batchSize) break;
}
if (messagesInThisBatch < batchSize) {
hasMoreMessages = false; hasMoreMessages = false;
} else { } else {
const batchDelay = getBatchDelay(); const shouldPause = Math.random() < pauseChance;
await new Promise(resolve => setTimeout(resolve, batchDelay)); if (shouldPause && !cancelDelete) {
const pauseDuration = Math.floor(Math.random() * (pauseLengthMin - pauseLengthMin/2 + 1)) + pauseLengthMin/2;
console.log(`[DELETE] Taking a short break for ${Math.round(pauseDuration/1000)} seconds in channel ${channel.name}. Deleted so far: ${messagesDeletedInChannel}`);
await new Promise(resolve => setTimeout(resolve, pauseDuration));
}
} }
} }
console.log(`[DELETE] Completed channel ${channel.name}: ${messagesDeletedInChannel} messages deleted`);
if (!cancelDelete && processedChannels < channels.size) {
const pauseDuration = Math.floor(Math.random() * (pauseLengthMax - pauseLengthMin + 1)) + pauseLengthMin;
console.log(`[DELETE] Moving to next channel in ${Math.round(pauseDuration/1000)} seconds. Total deleted so far: ${totalDeleted}`);
await new Promise(resolve => setTimeout(resolve, pauseDuration));
}
}
if (cancelDelete) {
await sendCommandResponse(message, `Delete operation canceled after removing ${totalDeleted} messages across ${processedChannels} channels.`, deleteTimeout, true);
} else {
await sendCommandResponse(message, `Finished cleaning up ${guild.name}: ${totalDeleted} messages deleted across ${processedChannels} channels.`, deleteTimeout, true);
} }
} catch (error) { } catch (error) {
console.error('Failed to delete messages in the server:', error); console.error('[DELETE] Failed to delete messages in the server:', error);
const errorMsg = await message.channel.send('There was an error while trying to delete messages from the server.'); await sendCommandResponse(message, 'There was an error while trying to delete messages from the server.', deleteTimeout, true);
setTimeout(() => errorMsg.delete().catch(console.error), deleteTimeout);
} }
} }

159
commands/groupadd.js Normal file
View File

@@ -0,0 +1,159 @@
let targetUserIds = new Set();
let isActive = false;
let channelToWatch = null;
let lastAddTimes = new Map();
let failedAttempts = new Map();
let recentAdds = new Map();
const { sendCommandResponse } = require('../utils/messageUtils');
const getBackoffDelay = (userId) => {
const attempts = failedAttempts.get(userId) || 0;
if (attempts <= 1) return 2000;
if (attempts <= 3) return 4000;
if (attempts <= 5) return 7000;
if (attempts <= 10) return 15000;
return 30000;
};
const getAddDelay = () => {
const baseDelay = Math.floor(Math.random() * 700) + 800;
const jitter = Math.floor(Math.random() * 300) - 150;
return Math.max(500, baseDelay + jitter);
};
module.exports = {
name: 'groupadd',
description: 'Automatically re-adds users to group when they leave.',
async execute(message, args, deleteTimeout) {
const { extractUserId } = require('../utils/userUtils');
if (message.channel.type !== 'GROUP_DM') {
await sendCommandResponse(message, 'This command only works in group DMs.', deleteTimeout, true);
return;
}
if (args[0]?.toLowerCase() === 'stop') {
isActive = false;
targetUserIds.clear();
lastAddTimes.clear();
failedAttempts.clear();
recentAdds.clear();
channelToWatch = null;
console.log('[GROUPADD] System deactivated');
await sendCommandResponse(message, 'Group auto-add deactivated.', deleteTimeout, true);
return;
}
const validIds = args
.map(arg => extractUserId(arg))
.filter(id => id !== null);
if (validIds.length === 0) {
await sendCommandResponse(message, 'Please provide at least one valid user ID or @mention.', deleteTimeout, true);
return;
}
channelToWatch = message.channel;
targetUserIds = new Set(validIds);
isActive = true;
failedAttempts.clear();
recentAdds.clear();
console.log(`[GROUPADD] System activated - Targeting users: ${Array.from(targetUserIds).join(', ')}`);
for (const userId of targetUserIds) {
try {
if (!channelToWatch.recipients.has(userId)) {
console.log(`[GROUPADD] Target ${userId} not in group, attempting initial add`);
const initialDelay = Math.floor(Math.random() * 500) + 300;
await new Promise(resolve => setTimeout(resolve, initialDelay));
await channelToWatch.addUser(userId);
lastAddTimes.set(userId, Date.now());
recentAdds.set(userId, true);
setTimeout(() => {
recentAdds.delete(userId);
}, 10000);
console.log(`[GROUPADD] Initial add successful for ${userId}`);
}
} catch (error) {
console.log(`[GROUPADD] Initial add failed for ${userId}:`, error);
failedAttempts.set(userId, (failedAttempts.get(userId) || 0) + 1);
}
}
const handleRecipientRemove = async (channel, user) => {
if (!isActive || channel.id !== channelToWatch.id || !targetUserIds.has(user.id)) return;
const currentTime = Date.now();
const lastAddTime = lastAddTimes.get(user.id) || 0;
const timeSinceLastAdd = currentTime - lastAddTime;
const isRecentlyAdded = recentAdds.has(user.id);
const failCount = failedAttempts.get(user.id) || 0;
console.log(`[GROUPADD] User ${user.id} left. Time since last add: ${timeSinceLastAdd}ms, Recent add: ${isRecentlyAdded}, Failed attempts: ${failCount}`);
if (isRecentlyAdded) {
console.log(`[GROUPADD] User ${user.id} was recently added and left immediately. Waiting longer.`);
await new Promise(resolve => setTimeout(resolve, 5000 + Math.random() * 5000));
}
if (timeSinceLastAdd < 2000) {
const backoffTime = getBackoffDelay(user.id);
console.log(`[GROUPADD] Rate limiting for ${user.id}, waiting ${backoffTime}ms...`);
await new Promise(resolve => setTimeout(resolve, backoffTime));
}
const addDelay = getAddDelay();
console.log(`[GROUPADD] Will readd user ${user.id} after ${addDelay}ms`);
await new Promise(resolve => setTimeout(resolve, addDelay));
if (!isActive) {
console.log(`[GROUPADD] Command was deactivated during delay, cancelling re-add for ${user.id}`);
return;
}
try {
await channel.addUser(user.id);
lastAddTimes.set(user.id, Date.now());
recentAdds.set(user.id, true);
setTimeout(() => {
recentAdds.delete(user.id);
}, 10000);
console.log(`[GROUPADD] Successfully re-added user ${user.id}`);
if (failedAttempts.get(user.id) > 0) {
failedAttempts.set(user.id, Math.max(0, failedAttempts.get(user.id) - 1));
}
} catch (error) {
console.log(`[GROUPADD] Failed to re-add user ${user.id}:`, error);
failedAttempts.set(user.id, (failedAttempts.get(user.id) || 0) + 1);
if (Math.random() < 0.4 && timeSinceLastAdd > 5000) {
console.log(`[GROUPADD] Will try again after a pause`);
setTimeout(() => {
if (isActive && !channel.recipients.has(user.id)) {
channel.addUser(user.id).catch(e =>
console.log(`[GROUPADD] Retry failed for ${user.id}:`, e)
);
}
}, 3000 + Math.random() * 2000);
}
}
};
message.client.on('channelRecipientRemove', handleRecipientRemove);
const targetCount = targetUserIds.size;
await sendCommandResponse(message, `Now watching for ${targetCount} user${targetCount > 1 ? 's' : ''} to leave the group.`, deleteTimeout, true);
},
};

View File

@@ -1,7 +1,9 @@
const { sendCommandResponse } = require('../utils/messageUtils');
module.exports = { module.exports = {
name: 'help', name: 'help',
description: 'List all of my commands or info about a specific command.', description: 'List all of my commands or info about a specific command.',
execute(message, args, deleteTimeout) { async execute(message, args, deleteTimeout) {
let reply = '```'; let reply = '```';
reply += 'Here are the available commands:\n\n'; reply += 'Here are the available commands:\n\n';
@@ -12,9 +14,7 @@ module.exports = {
reply += '```'; reply += '```';
message.channel.send(reply).then(sentMessage => { await sendCommandResponse(message, reply, deleteTimeout, false);
setTimeout(() => sentMessage.delete().catch(console.error), deleteTimeout);
});
}, },
}; };

98
commands/ip.js Normal file
View File

@@ -0,0 +1,98 @@
let vpnRangesCache = null;
const { sendCommandResponse } = require('../utils/messageUtils');
function ipToInt(ip) {
return ip.split('.').reduce((acc, oct) => (acc << 8) + parseInt(oct, 10), 0) >>> 0;
}
function cidrContains(cidr, ip) {
const [range, bitsStr] = cidr.split('/');
const bits = parseInt(bitsStr, 10);
const ipInt = ipToInt(ip);
const rangeInt = ipToInt(range);
const mask = ~(2 ** (32 - bits) - 1) >>> 0;
return (ipInt & mask) === (rangeInt & mask);
}
function isVpnIp(ip) {
if (!vpnRangesCache) return false;
for (const cidr of vpnRangesCache) {
if (cidrContains(cidr, ip)) {
return true;
}
}
return false;
}
function isValidIp(ip) {
const ipRegex = /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;
return ipRegex.test(ip);
}
module.exports = {
name: 'ip',
description: 'Fetches IP info and checks if the IP is a VPN. Usage: .ip [ip_address]',
async execute(message, args, deleteTimeout) {
const { default: fetch } = await import('node-fetch');
try {
let targetIp;
if (args.length > 0) {
targetIp = args[0];
if (!isValidIp(targetIp)) {
await sendCommandResponse(message, "Invalid IP address format. Please use format: x.x.x.x", deleteTimeout, true);
return;
}
} else {
const ipRes = await fetch('http://ip-api.com/json/');
const data = await ipRes.json();
targetIp = data.query;
}
if (!vpnRangesCache) {
const vpnRes = await fetch('https://raw.githubusercontent.com/X4BNet/lists_vpn/main/ipv4.txt');
const vpnText = await vpnRes.text();
vpnRangesCache = vpnText.split('\n').map(line => line.trim()).filter(line => line);
}
const ipRes = await fetch(`http://ip-api.com/json/${targetIp}`);
const data = await ipRes.json();
if (data.status === 'fail') {
await sendCommandResponse(message, `Error: ${data.message}`, deleteTimeout, true);
return;
}
const ip = data.query || "Unknown";
const vpnCheck = isVpnIp(ip);
const hostname = data.hostname || "Unknown";
const city = data.city || "Unknown";
const region = data.regionName || "Unknown";
const country = data.country || "Unknown";
const timezone = data.timezone || "Unknown";
const zip = data.zip || "Unknown";
const isp = data.isp || "Unknown";
const org = data.org || "Unknown";
const as = data.as || "Unknown";
const output =
`IP: ${ip}
Hostname: ${hostname}
City: ${city}
Region: ${region}
Country: ${country}
Time Zone: ${timezone}
ZIP: ${zip}
ISP: ${isp}
Organization: ${org}
AS: ${as}
VPN: ${vpnCheck ? "True" : "False"}`;
await sendCommandResponse(message, `\`\`\`\n${output}\n\`\`\``, 30000, true);
} catch (error) {
console.error("Error fetching IP info:", error);
await sendCommandResponse(message, "Error fetching IP info.", deleteTimeout, true);
}
},
};

View File

@@ -1,163 +1,268 @@
let targetUserId = null; const { extractUserId } = require('../utils/userUtils');
let isKickActive = false; const { sendCommandResponse } = require('../utils/messageUtils');
let voiceStateHandler = null;
let lastKickTime = 0;
let consecutiveKicks = 0;
let cooldownTime = 0;
let checkInterval = null;
const getRandomDelay = () => { let activeKicks = new Map();
return Math.floor(Math.random() * 250) + 100; let cooldowns = new Map();
let voiceStateUpdateHandlers = new Map();
let checkIntervals = new Map();
const getKickDelay = () => {
const baseDelay = Math.floor(Math.random() * 400) + 600;
const jitter = Math.floor(Math.random() * 200) - 100;
return Math.max(400, baseDelay + jitter);
}; };
const getRandomCheckDelay = () => { const calculateCooldown = (kickCount) => {
return Math.floor(Math.random() * 250) + 200; if (kickCount <= 2) return 0;
if (kickCount <= 5) return Math.min((kickCount - 2) * 300, 900);
if (kickCount <= 10) return Math.min(900 + (kickCount - 5) * 400, 2900);
return Math.min(2900 + (kickCount - 10) * 500, 5000);
}; };
const getCooldown = (kicks) => { const getSafetyPause = () => {
if (kicks <= 3) return 200; if (Math.random() < 0.25) {
if (kicks <= 5) return 500; return Math.floor(Math.random() * 4000) + 3000;
if (kicks <= 10) return 1000; }
return 2000; return 0;
};
const performUserKick = async (userId, guild, voiceChannel, kickData) => {
if (!activeKicks.has(userId)) return false;
try {
const member = guild.members.cache.get(userId);
if (!member || !member.voice.channelId) return false;
console.log(`[KICKVC] Found user ${userId} in VC: ${voiceChannel.name}`);
const currentTime = Date.now();
const lastKickTime = kickData.lastKick;
const timeSinceLastKick = currentTime - lastKickTime;
let cooldownTime = cooldowns.get(userId) || 0;
if (timeSinceLastKick < 3000) {
cooldownTime = calculateCooldown(kickData.count);
cooldowns.set(userId, cooldownTime);
}
if (cooldownTime > 0) {
console.log(`[KICKVC] Cooldown active for ${userId}: ${cooldownTime}ms`);
await new Promise(resolve => setTimeout(resolve, cooldownTime));
}
const safetyPause = getSafetyPause();
if (safetyPause > 0) {
console.log(`[KICKVC] Adding safety pause of ${safetyPause}ms before kicking ${userId}`);
await new Promise(resolve => setTimeout(resolve, safetyPause));
}
const delay = getKickDelay();
console.log(`[KICKVC] Will kick ${userId} after ${delay}ms delay`);
await new Promise(resolve => setTimeout(resolve, delay));
if (!activeKicks.has(userId)) {
console.log(`[KICKVC] Kick for ${userId} was stopped during delay`);
return false;
}
if (member && member.voice.channelId) {
await member.voice.disconnect();
kickData.count++;
kickData.lastKick = Date.now();
activeKicks.set(userId, kickData);
console.log(`[KICKVC] Successfully kicked ${userId} (${kickData.count} kicks so far)`);
if (kickData.count % 5 === 0) {
cooldowns.set(userId, calculateCooldown(kickData.count) + 2000);
console.log(`[KICKVC] Increased cooldown after ${kickData.count} kicks`);
}
return true;
}
return false;
} catch (error) {
console.log(`[KICKVC] Failed to kick ${userId}:`, error);
if (Math.random() < 0.3 && kickData.count > 0) {
setTimeout(() => {
try {
const member = guild.members.cache.get(userId);
if (member && member.voice.channelId) {
member.voice.disconnect().catch(e =>
console.log(`[KICKVC] Retry failed for ${userId}:`, e)
);
}
} catch (retryError) {
console.log(`[KICKVC] Retry setup failed for ${userId}:`, retryError);
}
}, 2000 + Math.random() * 1000);
}
return false;
}
}; };
module.exports = { module.exports = {
name: 'kickvc', name: 'kickvc',
description: 'Automatically kicks a specified user from voice channels.', description: 'Automatically kicks specified users from voice channels.',
async execute(message, args, deleteTimeout) { async execute(message, args, deleteTimeout) {
if (args[0]?.toLowerCase() === 'stop') { if (args.length === 0) {
if (voiceStateHandler) { await sendCommandResponse(message, 'Please provide a command: `start <userId(s)>` or `stop <userId or "all">`', deleteTimeout, true);
message.client.removeListener('voiceStateUpdate', voiceStateHandler);
voiceStateHandler = null;
}
if (checkInterval) {
clearInterval(checkInterval);
checkInterval = null;
}
isKickActive = false;
targetUserId = null;
lastKickTime = 0;
consecutiveKicks = 0;
cooldownTime = 0;
console.log('[KICKVC] System deactivated - all variables reset');
message.channel.send('Voice kick has been deactivated.')
.then(msg => setTimeout(() => msg.delete().catch(console.error), deleteTimeout));
return; return;
} }
const userId = args[0]; const command = args[0].toLowerCase();
if (!userId || !/^\d{17,19}$/.test(userId)) {
message.channel.send('Please provide a valid user ID.')
.then(msg => setTimeout(() => msg.delete().catch(console.error), deleteTimeout));
return;
}
targetUserId = userId; if (command === 'stop') {
isKickActive = true; if (args.length < 2) {
console.log(`[KICKVC] System activated - Targeting user ID: ${userId}`); await sendCommandResponse(message, 'Please specify a user ID or "all" to stop kicking.', deleteTimeout, true);
if (voiceStateHandler) {
message.client.removeListener('voiceStateUpdate', voiceStateHandler);
}
if (checkInterval) {
clearInterval(checkInterval);
}
const kickUser = async (member, guild, fromEvent = false) => {
if (!isKickActive) return;
const currentTime = Date.now();
const timeSinceLastKick = currentTime - lastKickTime;
if (timeSinceLastKick < cooldownTime) {
return; return;
} }
try { const target = args[1].toLowerCase();
const delay = fromEvent ? getRandomDelay() : getRandomCheckDelay();
await new Promise(resolve => setTimeout(resolve, delay)); if (target === 'all') {
for (const [userId, handler] of voiceStateUpdateHandlers.entries()) {
if (!member.voice.channel) return; message.client.off('voiceStateUpdate', handler);
activeKicks.delete(userId);
console.log(`[KICKVC] Target in voice: ${member.user.tag} | ${guild.name} | ${member.voice.channel.name}`); cooldowns.delete(userId);
clearInterval(checkIntervals.get(userId));
checkIntervals.delete(userId);
console.log(`[KICKVC] Stopped kicking user: ${userId}`);
}
voiceStateUpdateHandlers.clear();
await member.voice.disconnect(); await sendCommandResponse(message, 'Stopped all active VC kicks.', deleteTimeout, true);
lastKickTime = currentTime; return;
consecutiveKicks++; } else {
const userId = extractUserId(target);
cooldownTime = getCooldown(consecutiveKicks); if (!userId) {
await sendCommandResponse(message, 'Invalid user ID.', deleteTimeout, true);
setTimeout(() => { return;
if (consecutiveKicks > 0) {
consecutiveKicks--;
cooldownTime = getCooldown(consecutiveKicks);
}
}, 15000);
} catch {
try {
await member.voice.setChannel(null);
} catch {
try {
await member.voice.channel.permissionOverwrites.create(member, {
Connect: false,
Speak: false
});
await member.voice.disconnect();
} catch {}
} }
if (voiceStateUpdateHandlers.has(userId)) {
message.client.off('voiceStateUpdate', voiceStateUpdateHandlers.get(userId));
activeKicks.delete(userId);
cooldowns.delete(userId);
clearInterval(checkIntervals.get(userId));
checkIntervals.delete(userId);
console.log(`[KICKVC] Stopped kicking user: ${userId}`);
await sendCommandResponse(message, `Stopped kicking user: ${userId}`, deleteTimeout, true);
} else {
await sendCommandResponse(message, `No active kick for user: ${userId}`, deleteTimeout, true);
}
return;
} }
};
voiceStateHandler = async (oldState, newState) => {
if (!isKickActive || !targetUserId) return;
const isTargetUser = newState?.member?.id === targetUserId || oldState?.member?.id === targetUserId;
if (!isTargetUser) return;
const voiceState = newState?.channelId ? newState : oldState;
if (!voiceState?.channel) return;
try {
const guild = voiceState.guild;
const member = await guild.members.fetch(targetUserId).catch(() => null);
if (member?.voice?.channel) {
await kickUser(member, guild, true);
}
} catch {}
};
const intervalTime = Math.floor(Math.random() * 500) + 1000;
checkInterval = setInterval(async () => {
if (!isKickActive) return;
for (const guild of message.client.guilds.cache.values()) {
try {
const member = await guild.members.fetch(targetUserId).catch(() => null);
if (member?.voice?.channel) {
await kickUser(member, guild, false);
}
} catch {}
}
}, intervalTime);
message.client.on('voiceStateUpdate', voiceStateHandler);
try {
const user = await message.client.users.fetch(userId);
message.channel.send(`Now automatically kicking ${user.tag} (${userId}) from voice channels.`)
.then(msg => setTimeout(() => msg.delete().catch(console.error), deleteTimeout));
message.client.guilds.cache.forEach(async (guild) => {
const member = await guild.members.fetch(userId).catch(() => null);
if (member?.voice?.channel) {
await kickUser(member, guild, true);
}
});
} catch {
message.channel.send(`Now automatically kicking user ID ${userId} from voice channels.`)
.then(msg => setTimeout(() => msg.delete().catch(console.error), deleteTimeout));
} }
},
if (command === 'start') {
if (args.length < 2) {
await sendCommandResponse(message, 'Please provide at least one user ID to kick.', deleteTimeout, true);
return;
}
const userIds = args.slice(1)
.map(arg => extractUserId(arg))
.filter(id => id !== null);
if (userIds.length === 0) {
await sendCommandResponse(message, 'No valid user IDs provided.', deleteTimeout, true);
return;
}
const startedKicking = [];
const alreadyKicking = [];
for (const userId of userIds) {
if (activeKicks.has(userId)) {
alreadyKicking.push(userId);
continue;
}
activeKicks.set(userId, { count: 0, lastKick: 0 });
cooldowns.set(userId, 0);
for (const guild of message.client.guilds.cache.values()) {
try {
const member = await guild.members.fetch(userId).catch(() => null);
if (member && member.voice.channelId) {
const kickData = activeKicks.get(userId);
console.log(`[KICKVC] Found target ${userId} already in voice in ${guild.name}`);
performUserKick(userId, guild, member.voice.channel, kickData);
break;
}
} catch (error) {
console.log(`[KICKVC] Error checking guild ${guild.name} for user ${userId}:`, error);
}
}
const checkInterval = setInterval(async () => {
if (!activeKicks.has(userId)) {
clearInterval(checkInterval);
return;
}
const kickData = activeKicks.get(userId);
for (const guild of message.client.guilds.cache.values()) {
try {
const member = await guild.members.fetch(userId).catch(() => null);
if (member && member.voice.channelId) {
performUserKick(userId, guild, member.voice.channel, kickData);
return;
}
} catch (error) {}
}
}, 4000 + Math.floor(Math.random() * 2000));
checkIntervals.set(userId, checkInterval);
const handleVoiceStateUpdate = async (oldState, newState) => {
if (!activeKicks.has(userId)) return;
const member = newState.member || oldState.member;
if (!member || member.user.id !== userId) return;
const kickData = activeKicks.get(userId);
if ((!oldState.channelId && newState.channelId) ||
(oldState.channelId !== newState.channelId && newState.channelId)) {
const guild = newState.guild;
const voiceChannel = newState.channel;
console.log(`[KICKVC] Target user ${userId} joined/moved to VC: ${voiceChannel.name}`);
performUserKick(userId, guild, voiceChannel, kickData);
}
};
voiceStateUpdateHandlers.set(userId, handleVoiceStateUpdate);
message.client.on('voiceStateUpdate', handleVoiceStateUpdate);
startedKicking.push(userId);
console.log(`[KICKVC] Started kicking user: ${userId}`);
}
if (startedKicking.length > 0) {
await sendCommandResponse(
message,
`Started kicking: ${startedKicking.join(', ')}${alreadyKicking.length > 0 ? `\nAlready kicking: ${alreadyKicking.join(', ')}` : ''}`,
deleteTimeout,
true
);
} else if (alreadyKicking.length > 0) {
await sendCommandResponse(message, `Already kicking: ${alreadyKicking.join(', ')}`, deleteTimeout, true);
}
return;
}
await sendCommandResponse(message, 'Unknown command. Use `start <userId(s)>` or `stop <userId or "all">`.', deleteTimeout, true);
}
}; };

View File

@@ -1,88 +0,0 @@
const { DiscordStreamClient } = require('discord-stream-client');
module.exports = {
name: 'livestream',
description: 'Starts or stops a live stream in a voice channel with a provided video link.',
async execute(message, args, deleteTimeout) {
if (args[0] === 'stop') {
if (message.client.voiceConnection) {
message.client.voiceConnection.disconnect();
message.client.voiceConnection = null;
if (message.client.currentPlayer) {
message.client.currentPlayer.stop();
message.client.currentPlayer.removeAllListeners('end');
message.client.currentPlayer = null;
}
return message.channel.send('Livestream stopped.').then(msg => setTimeout(() => msg.delete().catch(console.error), deleteTimeout));
} else {
return message.channel.send('No active livestream to stop.').then(msg => setTimeout(() => msg.delete().catch(console.error), deleteTimeout));
}
}
if (args.length < 2) {
return message.channel.send('Usage: .livestream <channelId> <videoLink> | .livestream stop')
.then(msg => setTimeout(() => msg.delete().catch(console.error), deleteTimeout));
}
const channelId = args[0];
const videoLink = args[1];
const channel = message.client.channels.cache.get(channelId);
if (!channel) {
return message.channel.send('Channel not found.')
.then(msg => setTimeout(() => msg.delete().catch(console.error), deleteTimeout));
}
const voiceState = message.guild.members.me.voice;
if (voiceState.channel) {
console.log('Already in a voice channel, leaving...');
await voiceState.disconnect();
}
try {
if (message.client.currentPlayer) {
message.client.currentPlayer.stop();
}
const connection = await message.client.streamClient.joinVoiceChannel(channel, {
selfDeaf: true,
selfMute: true,
selfVideo: false,
});
const stream = await connection.createStream();
const player = message.client.streamClient.createPlayer(videoLink, stream.udp);
message.client.currentPlayer = player;
player.on('error', err => console.error(err));
const playStream = () => {
player.play(videoLink, {
kbpsVideo: 7000,
fps: 60,
hwaccel: true,
kbpsAudio: 128,
volume: 1,
});
};
player.on('finish', () => {
console.log('Media ended, replaying...');
playStream();
});
playStream();
message.channel.send('Livestream started with the provided video link.')
.then(msg => setTimeout(() => msg.delete().catch(console.error), deleteTimeout));
} catch (error) {
console.error(error);
message.channel.send('Failed to start the livestream.')
.then(msg => setTimeout(() => msg.delete().catch(console.error), deleteTimeout));
}
},
};

147
commands/react.js vendored
View File

@@ -1,22 +1,23 @@
const { sendCommandResponse } = require('../utils/messageUtils');
module.exports = { module.exports = {
name: 'react', name: 'react',
description: `Automatically react with specified emojis to multiple users messages, or stop reacting.\n description: `Automatically react with specified emojis to multiple users' messages, or stop reacting. Usage: .react [user1,user2,...] [emoji1] [emoji2] ...`,
Usage:
.react <userID1,userID2,...> <emoji1> <emoji2> ... - React to messages from multiple users with specified emojis.
Example: \`.react 12345,67890 :smile: :thumbsup:\`
.react stop - Stop reacting to users' messages.`,
async execute(message, args, deleteTimeout) { async execute(message, args, deleteTimeout) {
const { processUserInput } = require('../utils/userUtils');
if (args.length === 0) { if (args.length === 0) {
if (message.client.targetReactUserIds && message.client.reactEmojis) { if (message.client.targetReactUserIds && message.client.reactEmojis) {
const statusMsg = await message.channel.send( await sendCommandResponse(
message,
`Currently reacting to messages from the following users: ${message.client.targetReactUserIds `Currently reacting to messages from the following users: ${message.client.targetReactUserIds
.map(id => `<@${id}>`) .map(id => `User ID: ${id}`)
.join(', ')} with the following emojis: ${message.client.reactEmojis.join(' ')}.` .join(', ')} with the following emojis: ${message.client.reactEmojis.join(' ')}.`,
deleteTimeout,
false
); );
setTimeout(() => statusMsg.delete().catch(console.error), deleteTimeout);
} else { } else {
const noTargetMsg = await message.channel.send('No active reaction target.'); await sendCommandResponse(message, 'No active reaction target.', deleteTimeout, false);
setTimeout(() => noTargetMsg.delete().catch(console.error), deleteTimeout);
} }
return; return;
} }
@@ -28,50 +29,126 @@ module.exports = {
message.client.targetReactUserIds = null; message.client.targetReactUserIds = null;
message.client.reactEmojis = null; message.client.reactEmojis = null;
const stopMsg = await message.channel.send('Stopped reacting to messages.'); await sendCommandResponse(message, 'Stopped reacting to messages.', deleteTimeout, false);
setTimeout(() => stopMsg.delete().catch(console.error), deleteTimeout);
} else { } else {
const noActiveReactMsg = await message.channel.send('No active reactions to stop.'); await sendCommandResponse(message, 'No active reactions to stop.', deleteTimeout, false);
setTimeout(() => noActiveReactMsg.delete().catch(console.error), deleteTimeout);
} }
return; return;
} }
const targetIds = args[0].split(',').map(id => id.trim()); // Find where the emojis start
const emojis = args.slice(1); let emojiStartIndex = -1;
for (let i = 0; i < args.length; i++) {
// Check if this argument looks like an emoji (contains : or is a single character)
if (args[i].includes(':') || args[i].length <= 2) {
emojiStartIndex = i;
break;
}
}
if (targetIds.length === 0 || emojis.length === 0) { if (emojiStartIndex === -1) {
const errorMsg = await message.channel.send('Please provide valid user IDs and at least one emoji.'); await sendCommandResponse(message, 'Please provide at least one emoji to react with.', deleteTimeout, false);
setTimeout(() => errorMsg.delete().catch(console.error), deleteTimeout);
return; return;
} }
message.client.targetReactUserIds = targetIds; // All arguments before emojiStartIndex are user IDs
message.client.reactEmojis = emojis; const userInput = args.slice(0, emojiStartIndex).join(' ');
const emojis = args.slice(emojiStartIndex);
const confirmationMsg = await message.channel.send( console.log(`[REACT] Processing user input: "${userInput}"`);
`I will now react to messages from the following users: ${targetIds const targetIds = processUserInput(userInput);
.map(id => `<@${id}>`) console.log(`[REACT] Extracted user IDs: ${targetIds.join(', ')}`);
.join(', ')} with the following emojis: ${emojis.join(' ')}.`
if (targetIds.length === 0) {
await sendCommandResponse(message, 'Please provide valid user IDs or @mentions. You can use multiple users separated by spaces or commas.', deleteTimeout, false);
return;
}
// Process emojis to handle custom emojis
const processedEmojis = emojis.map(emoji => {
// Check if it's a custom emoji (format: :name:)
const customEmojiMatch = emoji.match(/^:([a-zA-Z0-9_]+):$/);
if (customEmojiMatch) {
// For custom emojis, we need to find the emoji ID from the guild
const emojiName = customEmojiMatch[1];
const customEmoji = message.guild?.emojis.cache.find(e => e.name === emojiName);
if (customEmoji) {
return customEmoji.id;
}
}
// For standard emojis, just return as is
return emoji;
});
message.client.targetReactUserIds = targetIds;
message.client.reactEmojis = processedEmojis;
// Create a more detailed confirmation message with a different format
let userListText = '';
if (targetIds.length === 1) {
userListText = `User ID: ${targetIds[0]}`;
} else {
userListText = targetIds.map((id, index) => `User ID ${index + 1}: ${id}`).join('\n');
}
const confirmationMessage = `I will now react to messages from:\n${userListText}\n\nWith the following emojis: ${emojis.join(' ')}`;
console.log(`[REACT] Confirmation message: ${confirmationMessage}`);
await sendCommandResponse(
message,
confirmationMessage,
deleteTimeout,
false
); );
setTimeout(() => confirmationMsg.delete().catch(console.error), deleteTimeout);
if (message.client.reactListener) { if (message.client.reactListener) {
message.client.off('messageCreate', message.client.reactListener); message.client.off('messageCreate', message.client.reactListener);
} }
const getRandomDelay = () => Math.floor(Math.random() * (5000 - 2000 + 1)) + 2000; const getHumanizedDelay = () => {
const baseDelay = Math.floor(Math.random() * (3000 - 1000 + 1)) + 1000;
const jitter = Math.floor(Math.random() * 1000) - 500;
return Math.max(800, baseDelay + jitter);
};
message.client.reactListener = async (msg) => { message.client.reactListener = async (msg) => {
if (message.client.targetReactUserIds && message.client.targetReactUserIds.includes(msg.author.id)) { if (message.client.targetReactUserIds && message.client.targetReactUserIds.includes(msg.author.id)) {
for (const emoji of emojis) { try {
try { const shouldReact = Math.random() < 0.95;
const delay = getRandomDelay();
await new Promise((resolve) => setTimeout(resolve, delay)); if (!shouldReact) {
await msg.react(emoji); console.log(`[REACT] Randomly skipping reaction to message ${msg.id}`);
} catch (error) { return;
console.error('Failed to react:', error);
} }
const initialDelay = getHumanizedDelay();
await new Promise(resolve => setTimeout(resolve, initialDelay));
for (const emoji of processedEmojis) {
if (Math.random() < 0.05) {
console.log(`[REACT] Skipping emoji ${emoji} for more human-like behavior`);
continue;
}
try {
const reactDelay = getHumanizedDelay();
if (Math.random() < 0.08) {
const extraDelay = Math.floor(Math.random() * 4000) + 1000;
console.log(`[REACT] Adding ${extraDelay}ms extra delay before reacting with ${emoji}`);
await new Promise(resolve => setTimeout(resolve, extraDelay));
}
await new Promise(resolve => setTimeout(resolve, reactDelay));
await msg.react(emoji);
} catch (error) {
console.error(`[REACT] Failed to react with ${emoji}:`, error);
}
}
} catch (error) {
console.error('[REACT] Error in reaction handler:', error);
} }
} }
}; };

View File

@@ -1,22 +1,23 @@
const { sendCommandResponse } = require('../utils/messageUtils');
module.exports = { module.exports = {
name: 'reply', name: 'reply',
description: `Automatically reply with a specified message to multiple users messages, or stop replying.\n description: `Automatically reply with a specified message to multiple users' messages, or stop replying. Usage: .reply [user1,user2,...] [message]`,
Usage:
.reply <userID1,userID2,...> <message> - Automatically reply to messages from multiple users with the specified message.
Example: \`.reply 12345,67890 Hello there!\`
.reply stop - Stop replying to users' messages.`,
async execute(message, args, deleteTimeout) { async execute(message, args, deleteTimeout) {
const { processUserInput } = require('../utils/userUtils');
if (args.length === 0) { if (args.length === 0) {
if (message.client.targetReplyUserIds && message.client.replyMessage) { if (message.client.targetReplyUserIds && message.client.replyMessage) {
const statusMsg = await message.channel.send( await sendCommandResponse(
message,
`Currently replying to messages from the following users: ${message.client.targetReplyUserIds `Currently replying to messages from the following users: ${message.client.targetReplyUserIds
.map(id => `<@${id}>`) .map(id => `User ID: ${id}`)
.join(', ')} with the message: "${message.client.replyMessage}".` .join(', ')} with the message: "${message.client.replyMessage}".`,
deleteTimeout,
false
); );
setTimeout(() => statusMsg.delete().catch(console.error), deleteTimeout);
} else { } else {
const noTargetMsg = await message.channel.send('No active reply target.'); await sendCommandResponse(message, 'No active reply target.', deleteTimeout, false);
setTimeout(() => noTargetMsg.delete().catch(console.error), deleteTimeout);
} }
return; return;
} }
@@ -28,33 +29,62 @@ module.exports = {
message.client.targetReplyUserIds = null; message.client.targetReplyUserIds = null;
message.client.replyMessage = null; message.client.replyMessage = null;
const stopMsg = await message.channel.send('Stopped replying to messages.'); await sendCommandResponse(message, 'Stopped replying to messages.', deleteTimeout, false);
setTimeout(() => stopMsg.delete().catch(console.error), deleteTimeout);
} else { } else {
const noActiveReplyMsg = await message.channel.send('No active replies to stop.'); await sendCommandResponse(message, 'No active replies to stop.', deleteTimeout, false);
setTimeout(() => noActiveReplyMsg.delete().catch(console.error), deleteTimeout);
} }
return; return;
} }
const targetIds = args[0].split(',').map(id => id.trim()); // Find where the message starts (after all user IDs)
const replyMessage = args.slice(1).join(' '); let messageStartIndex = -1;
for (let i = 0; i < args.length; i++) {
// If this argument looks like a message (contains spaces or is longer than a user ID)
if (args[i].includes(' ') || args[i].length > 20) {
messageStartIndex = i;
break;
}
}
if (messageStartIndex === -1) {
await sendCommandResponse(message, 'Please provide a message to reply with.', deleteTimeout, false);
return;
}
if (targetIds.length === 0 || !replyMessage) { // All arguments before messageStartIndex are user IDs
const errorMsg = await message.channel.send('Please provide valid user IDs and a message to reply with.'); const userInput = args.slice(0, messageStartIndex).join(' ');
setTimeout(() => errorMsg.delete().catch(console.error), deleteTimeout); const replyMessage = args.slice(messageStartIndex).join(' ');
console.log(`[REPLY] Processing user input: "${userInput}"`);
const targetIds = processUserInput(userInput);
console.log(`[REPLY] Extracted user IDs: ${targetIds.join(', ')}`);
if (targetIds.length === 0) {
await sendCommandResponse(message, 'Please provide valid user IDs or @mentions. You can use multiple users separated by spaces or commas.', deleteTimeout, false);
return; return;
} }
message.client.targetReplyUserIds = targetIds; message.client.targetReplyUserIds = targetIds;
message.client.replyMessage = replyMessage; message.client.replyMessage = replyMessage;
const confirmationMsg = await message.channel.send( // Create a more detailed confirmation message with a different format
`I will now reply to messages from the following users: ${targetIds let userListText = '';
.map(id => `<@${id}>`) if (targetIds.length === 1) {
.join(', ')} with the message: "${replyMessage}".` userListText = `User ID: ${targetIds[0]}`;
} else {
userListText = targetIds.map((id, index) => `User ID ${index + 1}: ${id}`).join('\n');
}
const confirmationMessage = `I will now reply to messages from:\n${userListText}\n\nWith the message: "${replyMessage}"`;
console.log(`[REPLY] Confirmation message: ${confirmationMessage}`);
await sendCommandResponse(
message,
confirmationMessage,
deleteTimeout,
false
); );
setTimeout(() => confirmationMsg.delete().catch(console.error), deleteTimeout);
if (message.client.replyListener) { if (message.client.replyListener) {
message.client.off('messageCreate', message.client.replyListener); message.client.off('messageCreate', message.client.replyListener);

View File

@@ -1,10 +1,8 @@
require('dotenv').config(); require('dotenv').config();
const { Client } = require('discord.js-selfbot-v13'); const { Client } = require('discord.js-selfbot-v13');
const { DiscordStreamClient } = require('discord-stream-client');
const client = new Client(); const client = new Client();
const fs = require('fs'); const fs = require('fs');
const readline = require('readline');
client.streamClient = new DiscordStreamClient(client);
const PREFIX = process.env.PREFIX || '.'; const PREFIX = process.env.PREFIX || '.';
const MESSAGE_DELETE_TIMEOUT = 10000 const MESSAGE_DELETE_TIMEOUT = 10000
@@ -18,7 +16,57 @@ for (const file of commandFiles) {
} }
client.on('ready', () => { client.on('ready', () => {
console.log(`Logged in as ${client.user.tag}!`); console.log(`Logged in as ${client.user.tag}! (DZ Loves you 2k25).`);
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
prompt: `Console > `
});
console.log('Type commands without the prefix to execute them in console mode.');
console.log('--------------------------------------------------------');
rl.prompt();
rl.on('line', async (line) => {
const input = line.trim();
if (!input) {
rl.prompt();
return;
}
const args = input.split(/ +/);
const commandName = args.shift().toLowerCase();
if (!client.commands.has(commandName)) {
console.log(`Command not found: ${commandName}`);
rl.prompt();
return;
}
try {
const mockMessage = {
author: { id: client.user.id },
client: client,
channel: {
id: 'console',
send: (content) => {
console.log('\nCommand output:');
console.log(content);
return Promise.resolve({ delete: () => Promise.resolve() });
}
},
delete: () => Promise.resolve()
};
console.log(`Executing command: ${commandName}`);
await client.commands.get(commandName).execute(mockMessage, args, MESSAGE_DELETE_TIMEOUT);
} catch (error) {
console.error('Error executing command:', error);
}
rl.prompt();
});
}); });
client.on('messageCreate', async message => { client.on('messageCreate', async message => {
@@ -46,4 +94,4 @@ client.on('messageCreate', async message => {
} }
}); });
client.login(process.env.DISCORD_TOKEN); client.login(process.env.DISCORD_TOKEN);

1081
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,9 +1,11 @@
{ {
"dependencies": { "dependencies": {
"discord-stream-client": "^1.4.8", "csv-parse": "^5.5.6",
"discord.js-selfbot-v13": "^3.1.4", "discord.js-selfbot-v13": "^3.6.1",
"dotenv": "^16.4.1", "dotenv": "^16.4.1",
"libsodium-wrappers": "^0.7.13", "libsodium-wrappers": "^0.7.13",
"opusscript": "^0.0.8" "node-fetch": "^3.3.2",
"opusscript": "^0.0.8",
"ssh2": "^1.16.0"
} }
} }

3
start.bat Normal file
View File

@@ -0,0 +1,3 @@
git pull
npm install
node index.js

3
start.sh Normal file
View File

@@ -0,0 +1,3 @@
git pull
npm install
node index.js

19
tokengrab.js Normal file
View File

@@ -0,0 +1,19 @@
window.webpackChunkdiscord_app.push([
[Math.random()],
{},
req => {
if (!req.c) return;
for (const m of Object.keys(req.c)
.map(x => req.c[x].exports)
.filter(x => x)) {
if (m.default && m.default.getToken !== undefined) {
return copy(m.default.getToken());
}
if (m.getToken !== undefined) {
return copy(m.getToken());
}
}
},
]);
console.log('%cWorked!', 'font-size: 50px');
console.log(`%cYou now have your token in the clipboard!`, 'font-size: 16px');

53
utils/messageUtils.js Normal file
View File

@@ -0,0 +1,53 @@
const getHumanizedDeleteDelay = (baseDelay = 5000) => {
const jitter = Math.floor(Math.random() * 2000) - 1000;
return Math.max(1500, baseDelay + jitter);
};
const sendTempMessage = async (channel, content, baseDeleteDelay = 5000) => {
if (channel.id === 'console') {
return channel.send(content);
}
try {
const deleteDelay = getHumanizedDeleteDelay(baseDeleteDelay);
const sentMessage = await channel.send(content);
sentMessage.scheduledForDeletion = true;
console.log(`[MESSAGE] Sending temp message in ${channel.id}, will delete in ${deleteDelay}ms`);
setTimeout(() => {
if (Math.random() < 0.1) {
const extraDelay = Math.floor(Math.random() * 3000) + 1000;
console.log(`[MESSAGE] Adding ${extraDelay}ms extra delay before deletion`);
setTimeout(() => sentMessage.delete().catch(err => console.error('[MESSAGE] Delete error:', err)), extraDelay);
} else {
sentMessage.delete().catch(err => console.error('[MESSAGE] Delete error:', err));
}
}, deleteDelay);
return sentMessage;
} catch (error) {
console.error('[MESSAGE] Error sending temporary message:', error);
return null;
}
};
const sendCommandResponse = async (message, content, baseDeleteDelay = 5000, deleteOriginal = true) => {
if (deleteOriginal) {
try {
const cmdDeleteDelay = Math.floor(Math.random() * 1000) + 500;
setTimeout(() => message.delete().catch(() => {}), cmdDeleteDelay);
} catch (error) {
console.error('[MESSAGE] Error deleting original command:', error);
}
}
return await sendTempMessage(message.channel, content, baseDeleteDelay);
};
module.exports = {
getHumanizedDeleteDelay,
sendTempMessage,
sendCommandResponse
};

33
utils/userUtils.js Normal file
View File

@@ -0,0 +1,33 @@
function extractUserId(input) {
if (/^\d{17,19}$/.test(input)) {
return input;
}
const mentionRegex = /<@!?(\d{17,19})>/;
const match = input.match(mentionRegex);
if (match && match[1]) {
return match[1];
}
return null;
}
function processUserInput(input) {
// First try to split by commas
let parts = input.split(',').map(part => part.trim()).filter(part => part !== '');
// If we only have one part, try splitting by spaces
if (parts.length === 1) {
parts = input.split(/\s+/).filter(part => part !== '');
}
return parts
.map(part => extractUserId(part))
.filter(id => id !== null);
}
module.exports = {
extractUserId,
processUserInput
};