discord / Commands /mass-dm.ts
Twan07's picture
Upload 8 files
67bf4ee verified
import { Colors, EmbedBuilder, Guild, Message } from "discord.js";
import type { Command } from "../types";
import { clients } from "..";
import { getJsonFromURL } from "../utils/discohook";
export default <Command>{
data: {
name: "mass-dm",
description: "Gửi tin nhắn đến toàn bộ thành viên trong server.",
toJSON() {
return {
name: "mass-dm",
description: "Gửi tin nhắn đến toàn bộ thành viên trong server.",
};
},
},
ownersOnly: true,
execute: async (message: Message, args?: string[]) => {
if (!message.guild || !args || args.length === 0) {
return message.reply("Vui lòng cung cấp nội dung tin nhắn.");
}
const contentInput = args.join(" ").trim();
const guild = message.guild as Guild;
const clientsInGuild = clients.filter((client) =>
client.guilds.cache.has(guild.id)
);
if (clientsInGuild.length === 0) {
return message.reply("❌ Không có client nào trong server.");
}
const DISCOHOOK_URL_REGEX =
/^(https?:\/\/)?(www\.)?(discohook\.app|discohook\.org)\/\?data=/;
let content = contentInput;
const embeds: any[] = [];
if (DISCOHOOK_URL_REGEX.test(contentInput)) {
const discohook = getJsonFromURL(contentInput);
if (discohook) {
if (discohook.embeds && discohook.embeds.length > 0) {
embeds.push(...discohook.embeds);
}
if (discohook.content) {
content = discohook.content;
}
}
}
const variables: Map<string, string> = new Map();
variables.set("guild.name", guild.name);
variables.set("guild.id", guild.id);
variables.set("guild.memberCount", guild.memberCount.toString());
const allMembers = guild.members.cache.filter((m) => !m.user.bot);
const done: { clientId: string; done: number; failed: number }[] =
clientsInGuild.map((client) => ({
clientId: client.user?.id as string,
done: 0,
failed: 0,
}));
const getTotallDone = () => done.reduce((acc, cur) => acc + cur.done, 0);
const getTotallFailed = () =>
done.reduce((acc, cur) => acc + cur.failed, 0);
const isDone = () => getTotallDone() + getTotallFailed() === allMembers.size;
const getEmbed = () =>
new EmbedBuilder()
.setTitle("📬 Mass DM Status")
.setDescription(
`Total: ${allMembers.size}\nDone: ${getTotallDone()}\nFailed: ${getTotallFailed()}\nStatus: ${isDone() ? "✅ Done" : "⏳ In Progress"}`
)
.setColor(isDone() ? Colors.Green : Colors.Yellow)
.setTimestamp();
const statusMessage = await message.reply({
embeds: [getEmbed()],
});
let clientIndex = 0;
for (const member of allMembers.values()) {
if (!clientsInGuild[clientIndex]) clientIndex = 0;
const client = clientsInGuild[clientIndex];
const clientDone = done.find((d) => d.clientId === client.user?.id)!;
clientIndex = (clientIndex + 1) % clientsInGuild.length;
// Tạo nội dung riêng biệt mỗi user
const personalizedVariables = new Map(variables);
personalizedVariables.set("user.username", member.user.username);
personalizedVariables.set("user.id", member.user.id);
personalizedVariables.set("user.tag", member.user.tag);
personalizedVariables.set("user.avatar", member.user.displayAvatarURL());
personalizedVariables.set("user.mention", member.user.toString());
personalizedVariables.set("user.nickname", member.nickname ?? member.user.username);
let personalizedContent = content;
for (const [key, value] of personalizedVariables.entries()) {
personalizedContent = personalizedContent.replace(new RegExp(`{${key}}`, "g"), value);
}
try {
await client.users.send(member.user.id, {
content: personalizedContent,
embeds: embeds,
});
clientDone.done++;
} catch (error) {
console.error(`❌ Không gửi được đến ${member.user.tag}:`, error);
clientDone.failed++;
}
try {
await statusMessage.edit({
embeds: [getEmbed()],
});
} catch (err) {
console.error("Không thể cập nhật tiến độ:", err);
}
await new Promise((res) => setTimeout(res, 400)); // delay nhẹ tránh bị rate limit
}
},
};