· 3 months ago · Jun 17, 2025, 06:10 AM
1function startBot(token) {
2 const client = new Client({
3 intents: [
4 GatewayIntentBits.Guilds,
5 GatewayIntentBits.GuildMessages,
6 GatewayIntentBits.GuildVoiceStates,
7 GatewayIntentBits.MessageContent
8 ],
9 partials: [Partials.Channel]
10 });
11
12 client.botData = { token };
13 bots.push(client);
14
15 client.distube = new DisTube(client, {
16 emitNewSongOnly: true,
17 plugins: [
18
19 new YtDlpPlugin({ update: true })
20 ]
21 });
22
23 client.once(Events.ClientReady, async () => {
24 const setup = getSetupData(client.user.username);
25 if (!setup?.roomId) return;
26
27 for (const [, guild] of client.guilds.cache) {
28 const channel = guild.channels.cache.get(setup.roomId);
29 if (channel) await joinVoiceChannel(client, channel);
30 }
31 console.log(`✅ Bot started: ${client.user.tag}`);
32 });
33
34 client.on(Events.VoiceStateUpdate, async (oldState, newState) => {
35 const setup = getSetupData(client.user.username);
36 if (!setup?.roomId) return;
37
38 const botId = client.user.id;
39 const leftVC = oldState.channelId && !newState.channelId && oldState.id === botId;
40 if (leftVC) {
41 const key = `${botId}-${oldState.guild.id}`;
42 if (rejoinLocks.has(key)) return;
43 rejoinLocks.add(key);
44 setTimeout(() => rejoinLocks.delete(key), 150);
45
46 const channel = oldState.guild.channels.cache.get(setup.roomId);
47 if (channel?.joinable) {
48 try {
49 await joinVoiceChannel(client, channel);
50 console.log(`🔁 ${client.user.username} rejoined`);
51 } catch (e) {
52 console.error(e);
53 }
54 }
55 }
56 });
57 client.login(token).catch(err => {
58 console.error(`❌ Failed to login with token: ${token.slice(0, 10)}...`, err.message);
59 });
60}
61
62function loadTokens() {
63 if (!fs.existsSync(token_file_)) return [];
64 try {
65 const data = fs.readFileSync(token_file_, 'utf-8');
66 return JSON.parse(data);
67 } catch (err) {
68 console.error("خطأ أثناء قراءة tokens.json:", err);
69 return [];
70 }
71}
72
73function saveTokens(tokens) {
74 try {
75 fs.writeFileSync(token_file_, JSON.stringify(tokens, null, 2));
76 } catch (err) {
77 console.error("خطأ أثناء حفظ tokens.json:", err);
78 }
79}
80function saveSetupData(botName, channelId, newName) {
81 const data = fs.existsSync(setupDataPath) ? JSON.parse(fs.readFileSync(setupDataPath)) : {};
82 data[botName] = { roomId: channelId, name: newName };
83 fs.writeFileSync(setupDataPath, JSON.stringify(data, null, 2));
84}
85
86function getSetupData(botName) {
87 if (!fs.existsSync(setupDataPath)) return null;
88 const data = JSON.parse(fs.readFileSync(setupDataPath));
89 return data[botName];
90}
91
92async function searchYouTube(query) {
93 if (cache.has(query)) return cache.get(query);
94 try {
95 const { data } = await axios.get("https://www.googleapis.com/youtube/v3/search", {
96 params: {
97 part: "snippet",
98 type: "video",
99 q: query,
100 key: yt_api,
101 maxResults: 1
102 }
103 });
104 const video = data.items?.[0];
105 const url = video ? `https://www.youtube.com/watch?v=${video.id.videoId}` : null;
106 if (url) cache.set(query, url);
107 return url;
108 } catch (err) {
109 console.error("YouTube Search API Error:", err.response?.data || err);
110 return null;
111 }
112}
113
114async function joinVoiceChannel(client, channel) {
115 if (!channel?.joinable) return;
116 if (client.distube.voices.get(channel.guild.id)) return;
117
118 try {
119 await client.distube.voices.join(channel);
120 console.log(`✅ ${client.user.username} joined ${channel.id}`);
121 } catch (err) {
122 console.warn(`❌ ${client.user.username} failed to join ${channel.id}:`, err.message);
123 }
124}
125
126config.bots.forEach((botData, index) => {
127 setTimeout(() => {
128 const client = new Client({
129 intents: [
130 GatewayIntentBits.Guilds,
131 GatewayIntentBits.GuildMessages,
132 GatewayIntentBits.GuildVoiceStates,
133 GatewayIntentBits.MessageContent
134 ],
135 partials: [Partials.Channel]
136 });
137
138 client.botData = botData;
139
140 client.distube = new DisTube(client, {
141 emitNewSongOnly: true,
142 plugins: [
143
144 new YtDlpPlugin({ update: true })
145 ]
146 });
147
148 client.once(Events.ClientReady, async () => {
149 const setup = getSetupData(client.user.username);
150 if (!setup?.roomId) return;
151
152 for (const [, guild] of client.guilds.cache) {
153 const channel = guild.channels.cache.get(setup.roomId);
154 if (channel) await joinVoiceChannel(client, channel);
155 }
156 });
157
158 client.on(Events.VoiceStateUpdate, async (oldState, newState) => {
159 const setup = getSetupData(client.user.username);
160 if (!setup?.roomId) return;
161
162 const botId = client.user.id;
163 const leftVC = oldState.channelId && !newState.channelId && oldState.id === botId;
164 if (leftVC) {
165 const key = `${botId}-${oldState.guild.id}`;
166 if (rejoinLocks.has(key)) return;
167 rejoinLocks.add(key);
168 setTimeout(() => rejoinLocks.delete(key), 150);
169
170 const channel = oldState.guild.channels.cache.get(setup.roomId);
171 if (channel?.joinable) {
172 try {
173 await joinVoiceChannel(client, channel);
174 console.log(`🔁 ${client.user.username} rejoined`);
175 } catch (e) {
176 console.error(e);
177 }
178 }
179 }
180 });
181
182
183 client.distube.on("playSong", async (queue, song) => {
184 const embed = new EmbedBuilder()
185 .setTitle("Now playing")
186 .setDescription(`**[${song.name}](${song.url})**`)
187 .setThumbnail(song.thumbnail)
188 .addFields(
189 { name: "Author", value: song.uploader?.name || "Unknown", inline: true },
190 { name: "Duration", value: song.formattedDuration || "--:--", inline: true }
191 )
192 .setColor("Red");
193 const controls = new ActionRowBuilder().addComponents(
194 new ButtonBuilder().setCustomId("loop").setStyle(ButtonStyle.Secondary).setEmoji("<:loop_arqet:1382208868352004218>"),
195 new ButtonBuilder().setCustomId("music_down").setStyle(ButtonStyle.Secondary).setEmoji("<:down_arqet:1382208866246332526>"),
196 new ButtonBuilder().setCustomId("stop").setStyle(ButtonStyle.Secondary).setEmoji("<:stop_arqet:1382208861162831994>"),
197 new ButtonBuilder().setCustomId("music_up").setStyle(ButtonStyle.Secondary).setEmoji("<:up_arqet:1382208863893327942>"),
198 new ButtonBuilder().setCustomId("skip").setStyle(ButtonStyle.Secondary).setEmoji("<:skip_arqet:1382213952196575282>"));
199 const msg = await queue.textChannel.send({ content:"**↯ Playing**: \`"+song.name+"\` - (\`"+song.formattedDuration+"\`)", components: [controls] });
200 });
201
202 client.on(Events.InteractionCreate, async (interaction) => {
203 if (!interaction.isButton()) return;
204 const queue = client.distube.getQueue(interaction);
205 const memberVC = interaction.member.voice?.channelId;
206 const botVC = interaction.guild.members.me.voice?.channelId;
207
208 if (!queue || memberVC !== botVC) {
209 return interaction.reply({ content: "يجب أن تكون في نفس روم البوت للتحكم.", ephemeral: true });
210 }
211
212 try {
213 switch (interaction.customId) {
214 case "play":if (!args[0]) return message.reply("❗ You need to provide a song name or URL.");
215 distube.play(voiceChannel, args.join(" "), { textChannel: message.channel, member: message.member });break;
216 case "pause":if (!queue.paused) queue.pause();break;
217 case "resume":if (queue.paused) queue.resume();break;
218 case "skip":if (queue.songs.length > 1) queue.skip();break;
219 case "stop":queue.stop(); break;
220 case "loop":queue.setRepeatMode(queue.repeatMode === 0 ? 1 : 0);break;
221 case "loopqueue":queue.setRepeatMode(queue.repeatMode === 2 ? 0 : 2);break;
222 //case "volume":const vol = parseInt(args[0]);if (isNaN(vol) || vol < 0 || vol > 150) return message.reply("📢 Volume must be between 0 and 150.");queue.setVolume(vol);break;
223 case "music_down": {if (!queue) return interaction.reply({ content: "❌ No music playing.", ephemeral: true });
224 const vol = Math.max(0, queue.volume - 20);queue.setVolume(vol);await interaction.reply({ content: `🔉 Volume decreased to **${vol}%**`, ephemeral: true });break;}
225 case "music_up": {if (!queue) return interaction.reply({ content: "❌ No music playing.", ephemeral: true });
226 const vol = Math.min(100, queue.volume + 20);queue.setVolume(vol);await interaction.reply({ content: `🔊 Volume increased to **${vol}%**`, ephemeral: true });break;}
227 case "seek":const time = parseInt(args[0]);if (isNaN(time)) return message.reply("⏩ Provide time in seconds to seek.");queue.seek(time);break;
228 case "shuffle":queue.shuffle();break;
229 case "autoplay":queue.toggleAutoplay();break;
230 case "nowplaying":const song = queue.songs[0];message.reply(`🎶 Now Playing: **${song.name}** - \`${song.formattedDuration}\``);break;
231 case "queue":if (!queue || !queue.songs.length) return message.reply("📭 The queue is empty.");const q = queue.songs
232 .map((song, i) => `${i === 0 ? "**▶️" : `${i + 1}.`} ${song.name}** - \`${song.formattedDuration}\``).join("\n");message.reply(`🎧 **Queue List:**\n${q}`);break;
233 case "remove":const index = parseInt(args[0]);if (isNaN(index) || index < 1 || index >= queue.songs.length)return message.reply("❌ Invalid song number.");
234 const removed = queue.songs.splice(index, 1);message.reply(`🗑️ Removed: **${removed[0].name}**`);break;default:message.reply("Unknown");break;
235 }
236 await interaction.deferUpdate();
237 } catch (e) {
238 console.error("Interaction error:", e);
239 interaction.reply({ content: "حدث خطأ.", ephemeral: true });
240 }
241 });
242
243const client_1 = new Client({
244 intents: [
245 GatewayIntentBits.Guilds,
246 GatewayIntentBits.GuildMessages,
247 GatewayIntentBits.MessageContent,
248 ],
249});
250
251const owners = new Set();
252owners.add(["159824469899214848"]);
253client_1.on(Events.MessageCreate, async (message) => {
254 if (!message.guild || message.author.bot) return;
255
256 const args = message.content.trim().split(/ +/);
257 const commandText = args[0]?.toLowerCase();
258 if (["restart", "add", "addown"].includes(commandText)) {
259 if (!owners.has(message.author.id)) {
260 return message.react("❌");
261 }
262 }
263
264
265 if (commandText === "add") {
266 if (args.length < 2) return message.react("❌");
267
268 let config = {};
269 let tokens = [];
270
271 try {
272 const data = fs.readFileSync('./config.json', 'utf8');
273 config = JSON.parse(data);
274 tokens = Array.isArray(config.tokens) ? config.tokens : [];
275 } catch (error) {
276 console.log("خطأ في قراءة config.json:", error);
277 }
278
279 const newTokens = args.slice(1);
280 const existingTokens = tokens.map(t => t.token);
281 const duplicateTokens = newTokens.filter(t => existingTokens.includes(t));
282
283 if (duplicateTokens.length > 0) {
284 return message.reply(`**❌ بعض التوكنات موجودة بالفعل**\n\`${duplicateTokens.join('\n')}\``)
285 .then(msg => setTimeout(() => { msg.delete(); message.delete(); }, 5000));
286 }
287
288 newTokens.forEach(t => tokens.push({ token: t }));
289 config.tokens = tokens;
290
291 try {
292 fs.writeFileSync('./config.json', JSON.stringify(config, null, 2));
293 message.reply(`✅ تم إضافة التوكنات:\n\`${newTokens.join('\n')}\``)
294 .then(msg => setTimeout(() => { msg.delete(); message.delete(); }, 5000));
295 } catch (e) {
296 console.error("خطأ في حفظ التوكنات:", e);
297 message.react("❌");
298 }
299
300 return;
301 }
302
303
304 if (commandText === "addown") {
305 const userId = args[1]?.replace(/<@!?(\d+)>/, "$1");
306 if (!userId) return message.reply("❌ الرجاء كتابة معرف المستخدم أو منشنه.");
307 if (userId === "159824469899214848") return message.react("❌");
308 if (owners.has(userId)) return message.react("❌");
309
310 owners.add(userId);
311 message.react("✅");
312 return;
313 }
314});
315 client_1.login(config.main_bot);
316
317 client.on(Events.MessageCreate, async (message) => {
318 if (!message.guild || message.author.bot) return;
319 const args = message.content.trim().split(/ +/);
320 const commandText = args[0]?.toLowerCase();
321 const query = args.slice(1).join(" ");
322 const vc = message.member.voice.channel;
323 const setup = getSetupData(client.user.username);
324 const allowedRoom = setup?.roomId;
325 const queue = client.distube.getQueue(message);
326
327 if (message.mentions.has(client.user)) {
328 const cmd = args[1]?.toLowerCase();
329 const imgURL = message.attachments.first()?.url || args[2];
330
331 if (cmd === "setup") {
332 if (!vc) return message.react("❌");
333 try {
334 await client.user.setUsername(vc.name);
335 saveSetupData(client.user.username, vc.id, vc.name);
336 await client.distube.voices.join(vc);
337 await message.react("✅");
338 setTimeout(() => {
339 client.user.setUsername(client.botData.name).catch(() => {});
340 }, 86400000);
341 } catch (e) {
342 console.error("Setup error:", e);
343 message.react("❌");
344 }
345 }
346
347 if (cmd === "sa" && imgURL) {
348 try {
349 await client.user.setAvatar(imgURL);
350 message.react("✅");
351 } catch (e) {
352 console.error("Avatar error:", e);
353 message.react("❌");
354 }
355 }
356
357 if (cmd === "sb" && imgURL) {
358 try {
359 await client.user.setBanner(imgURL);
360 message.react("✅");
361 } catch (e) {
362 console.error("Banner error:", e);
363 message.react("❌");
364 }
365 }
366 if (cmd === "sn" && args.length) {
367 try {
368 await client.user.setUsername(args.join(" "));
369 message.react("✅");
370 } catch (e) {
371 console.error("Username error:", e);
372 message.react("❌");
373 }
374 }
375 }
376 if (!vc || vc.id !== allowedRoom) return;
377
378 if (["ش", "شغل"].includes(commandText) && query) {
379 let url = query;
380 try {
381 await client.distube.play(vc, query, { textChannel: message.channel, member: message.member });
382 } catch (err) {
383 console.warn("DisTube play failed, trying YouTube API fallback");
384 url = await searchYouTube(query);
385 if (!url) return message.react("❌");
386 try {
387 await client.distube.play(vc, url, { textChannel: message.channel, member: message.member });
388 } catch (e) {
389 console.error("Play error after fallback:", e);
390 message.react("❌");
391 }
392 }
393 }
394
395 if (["وقف", "ايقاف"].includes(commandText)) {
396 if (queue) queue.stop(), message.react("<:stop_arqet:1382208861162831994>");
397 else message.react("❌");
398 }
399
400 if (["سكب", "تخطي"].includes(commandText)) {
401 if (queue?.songs.length > 1) queue.skip(), message.react("<:skip_arqet:1382213952196575282>");
402 else message.react("❌");
403 }
404
405 if (["قائمة", "list", "queue"].includes(commandText)) {
406 if (!queue?.songs.length) return message.react("❌");const list = queue.songs.map((s, i) => `${i === 0 ? "🔊" : `${i + 1}.`} ${s.name} - \`${s.formattedDuration}\``).join("\n");message.reply(`🎶 **قائمة التشغيل:**\n${list}`);}
407 if (["وقّف", "بوز", "توقيف", "ايقاف مؤقت", "pause"].includes(commandText)) {if (queue && !queue.paused) queue.pause(), message.react("<:stop_arqet:1382208861162831994>");else message.react("❌");}
408 if (["كمل", "استئناف", "resume"].includes(commandText)) {if (queue?.paused) queue.resume(), message.react("<:start_arqet:1382208858692255854>");else message.react("❌");}
409 if (["صوت", "vol", "volume"].includes(commandText)) {
410 const vol = parseInt(args[1]);
411 if (isNaN(vol) || vol < 0 || vol > 100) return message.reply("❌ اكتب رقم بين 0 و 100");
412 queue.setVolume(vol);
413 return message.reply(`🔊 تم ضبط الصوت على ${vol}%`);
414 }
415
416 if (["تكرار", "loop"].includes(commandText)) {
417 if (queue) {const mode = queue.repeatMode === 0 ? 1 : queue.repeatMode === 1 ? 2 : 0;queue.setRepeatMode(mode); message.react(["<:loop_arqet:1382208868352004218>", "<:loop_arqet:1382208868352004218>", "<:loop_arqet:1382208868352004218>"][mode]);} else message.react("❌");
418 }
419
420 if (["عشوائي", "shuffle"].includes(commandText)) {
421 if (queue) queue.shuffle(), message.react("🔀");
422 else message.react("❌");
423 }
424
425 if (["ازالة", "remove"].includes(commandText)) {
426 const index = parseInt(args[1]);
427 if (!queue || isNaN(index) || index <= 0 || index >= queue.songs.length) {
428 return message.reply("❌ رقم غير صحيح أو لا توجد قائمة");
429 }
430 queue.songs.splice(index, 1);
431 message.reply(`🗑️ تم حذف الأغنية رقم ${index}`);
432 }
433
434 if (["الان", "now", "np", "nowplaying"].includes(commandText)) {
435 if (!queue?.songs.length) return message.react("❌");
436 const song = queue.songs[0];
437 const nowPlaying = `🎵 **الآن:** [${song.name}](${song.url}) - \`${song.formattedDuration}\``;
438 message.reply(nowPlaying);
439 }
440
441 if (["اوامر", "help", "commands"].includes(commandText)) {
442 const helpText = `**أوامر الميوزك:**\n` +
443 `• تشغيل: ش, شغل <كلمة أو رابط>\n` +
444 `• إيقاف: وقف, ايقاف\n` +
445 `• تخطي: سكب, تخطي\n` +
446 `• إيقاف مؤقت: وقّف, بوز\n` +
447 `• استئناف: كمل\n` +
448 `• قائمة التشغيل: قائمة, list\n` +
449 `• تكرار: تكرار\n` +
450 `• الصوت: صوت <0-100>\n` +
451 `• عشوائي: عشوائي\n` +
452 `• الآن: الان, now\n` +
453 `• ازالة: ازالة <رقم>`;
454 message.reply(helpText);
455 }
456
457 });
458
459
460 client.on("error", error => {
461 if (error.message?.includes("Cannot connect to the voice channel after 30 seconds")) return;
462 const name = client?.user?.username || "Unknown";
463 console.error(`[${name}] Uncaught Error:`, error);
464 });
465 const name_1 = client?.user?.username || "Unknown";
466 process.on("unhandledRejection", () => console.error());
467 process.on("uncaughtException", (err) => console.error(`[${name_1}] Uncaught Exception:`, err));
468 process.on("uncaughtExceptionMonitor", (err) => console.warn(`[${name_1}] Exception Monitor:`, err));
469
470 client.login(botData.token);
471 bots.push(client);
472 }, index * 50);
473});
474const admin = new Client({
475 intents: [
476 GatewayIntentBits.Guilds,
477 GatewayIntentBits.GuildMessages,
478 GatewayIntentBits.MessageContent
479 ]
480});
481
482admin.on(Events.MessageCreate, async (message) => {
483 if (!message.guild || message.author.bot) return;
484 const args = message.content.trim().split(/ +/);
485 const command = args[0]?.toLowerCase();
486
487 if (!owners.has(message.author.id)) return;
488
489 if (command === "addtoken") {
490 const newToken = args[1];
491 if (!newToken) return message.reply("ex: addtoken [token_bot]");
492 const tokens = loadTokens();
493 if (tokens.includes(newToken)) return message.react("❌");
494 tokens.push(newToken);
495 saveTokens(tokens);
496 startBot(newToken);
497 message.react("✅");
498 }
499
500 const failedTokens =[];
501 if (command === "info-tokens") {
502 const descriptionLines = [];
503
504 bots.forEach(bot => {
505 const nameTag = bot.user?.tag || "Unknown#0000";
506 const _1 = bot.user?.id || "1";
507 const tokenPreview = bot.token?.slice(0, 10) || "??????????";
508 descriptionLines.push(
509 `[${nameTag}](https://discord.com/oauth2/authorize?client_id=${_1}&permissions=0&integration_type=0&scope=bot) [token: ${tokenPreview}...]`
510 );
511 });
512
513 if (failedTokens.length > 0) {
514 failedTokens.forEach(t => {
515 descriptionLines.push(`[FAILED] [token: ${t.slice(0, 10)}...] ❌`);
516 });
517 }
518
519
520 const MAX_LENGTH = 4000;
521 const embeds = [];
522 let lines = [];
523 let length = 0;
524
525 for (const line of descriptionLines) {
526 const lineLength = line.length + 1;
527 if (length + lineLength > MAX_LENGTH) {
528 embeds.push(
529 new EmbedBuilder()
530 .setTitle("حالة التوكنات")
531 .setDescription(lines.join("\n"))
532 .setColor("Blue")
533 );
534 lines = [];
535 length = 0;
536 }
537
538 lines.push(line);
539 length += lineLength;
540 }
541
542 if (lines.length > 0) {
543 embeds.push(
544 new EmbedBuilder()
545 .setTitle("حالة التوكنات")
546 .setDescription(lines.join("\n"))
547 .setColor("Blue")
548 );
549 }
550
551
552 for (const embed of embeds) {
553 await message.channel.send({ embeds: [embed] });
554 }
555 }
556
557
558
559});