@spatulox/simplediscordbot 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +2 -0
- package/LICENSE.md +21 -0
- package/README.md +1 -0
- package/dist/bot/Bot.js +107 -0
- package/dist/bot/BotEnv.js +29 -0
- package/dist/bot/BotLog.js +90 -0
- package/dist/bot/BotMessage.js +79 -0
- package/dist/cli/BaseCLI.js +165 -0
- package/dist/cli/GenerationCLI/ContextMenuGeneratorCLI.js +109 -0
- package/dist/cli/GenerationCLI/GenerationCLI.js +25 -0
- package/dist/cli/GenerationCLI/InteractionGeneratorCLI.js +20 -0
- package/dist/cli/GenerationCLI/ModalGeneratorCLI.js +166 -0
- package/dist/cli/GenerationCLI/SlashCommandsGeneratorCLI.js +221 -0
- package/dist/cli/GenerationCLI.js +36 -0
- package/dist/cli/GuildListManager.js +61 -0
- package/dist/cli/InputCLI.js +25 -0
- package/dist/cli/InteractionCLI/InteractionCLI.js +30 -0
- package/dist/cli/InteractionCLI/InteractionCLIManager.js +80 -0
- package/dist/cli/InteractionCLI.js +109 -0
- package/dist/cli/MainCLI.js +32 -0
- package/dist/cli/type/ContextMenuConfig.js +2 -0
- package/dist/cli/type/InteractionType.js +14 -0
- package/dist/cli/type/SlashCommandConfig.js +2 -0
- package/dist/index.js +31 -0
- package/dist/manager/FileManager.js +136 -0
- package/dist/manager/direct/UserManager.js +76 -0
- package/dist/manager/discord/ChannelManager.js +48 -0
- package/dist/manager/discord/DiscordRegex.js +114 -0
- package/dist/manager/discord/GuildManager.js +67 -0
- package/dist/manager/discord/InviteManager.js +89 -0
- package/dist/manager/discord/RoleManager.js +83 -0
- package/dist/manager/discord/UserManager.js +69 -0
- package/dist/manager/guild/ChannelManager/ForumChannelManager.js +33 -0
- package/dist/manager/guild/ChannelManager/GuildChannelList.js +20 -0
- package/dist/manager/guild/ChannelManager/GuildChannelManager.js +91 -0
- package/dist/manager/guild/ChannelManager/GuildMessageManager.js +85 -0
- package/dist/manager/guild/ChannelManager/GuildTextChannelManager.js +33 -0
- package/dist/manager/guild/ChannelManager/GuildVoiceChannelManager.js +33 -0
- package/dist/manager/guild/ChannelManager/NewsChannelManager.js +33 -0
- package/dist/manager/guild/ChannelManager/StageChannelManager.js +33 -0
- package/dist/manager/guild/ChannelManager/ThreadChannelManager.js +34 -0
- package/dist/manager/guild/GuildManager.js +134 -0
- package/dist/manager/guild/GuildUserManager.js +212 -0
- package/dist/manager/guild/InviteManager.js +68 -0
- package/dist/manager/guild/InviteManager_old.js +89 -0
- package/dist/manager/guild/RoleManager.js +83 -0
- package/dist/manager/hadlers_old/builder/ModalManager.js +111 -0
- package/dist/manager/hadlers_old/builder/delete.js +49 -0
- package/dist/manager/hadlers_old/builder/deploy.js +225 -0
- package/dist/manager/hadlers_old/builder/interactions/CommandManager.js +14 -0
- package/dist/manager/hadlers_old/builder/interactions/ContextMenuManager.js +14 -0
- package/dist/manager/hadlers_old/builder/interactions/InteractionBase.js +341 -0
- package/dist/manager/hadlers_old/builder/interactions/InteractionManager.js +65 -0
- package/dist/manager/hadlers_old/builder/list.js +166 -0
- package/dist/manager/messages/EmbedManager.js +131 -0
- package/dist/manager/messages/ReactionManager.js +99 -0
- package/dist/manager/messages/WebhookManager.js +105 -0
- package/dist/type/FolderName.js +9 -0
- package/dist/utils/DiscordRegex.js +116 -0
- package/dist/utils/Log.js +28 -0
- package/dist/utils/SimpleMutex.js +39 -0
- package/dist/utils/network/InternetChecker.js +54 -0
- package/dist/utils/times/UnitTime.js +85 -0
- package/package.json +40 -0
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
// src/discord/InteractionManager.ts
|
|
7
|
+
const readline_1 = __importDefault(require("readline"));
|
|
8
|
+
const CommandManager_1 = require("./CommandManager");
|
|
9
|
+
const ContextMenuManager_1 = require("./ContextMenuManager");
|
|
10
|
+
const Log_1 = require("../../../../utils/Log");
|
|
11
|
+
class InteractionManager {
|
|
12
|
+
static async start() {
|
|
13
|
+
console.clear();
|
|
14
|
+
Log_1.Log.info('🎛️ INTERACTION MANAGER');
|
|
15
|
+
Log_1.Log.info('=====================');
|
|
16
|
+
const rl = readline_1.default.createInterface({
|
|
17
|
+
input: process.stdin,
|
|
18
|
+
output: process.stdout
|
|
19
|
+
});
|
|
20
|
+
await this.showMainMenu(rl);
|
|
21
|
+
rl.on('line', async (input) => {
|
|
22
|
+
await this.handleMainMenu(input.trim().toLowerCase(), rl);
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
static async showMainMenu(rl) {
|
|
26
|
+
console.log('\n🎯 QUE VOULEZ-VOUS FAIRE ?');
|
|
27
|
+
console.log(' 1. Slash Commands → npm run deploy:slash');
|
|
28
|
+
console.log(' 2. Context Menus → npm run deploy:context');
|
|
29
|
+
console.log(' 3. Tout déployer → npm run deploy:all');
|
|
30
|
+
console.log(' help → Aide');
|
|
31
|
+
console.log(' exit → Quitter\n');
|
|
32
|
+
rl.prompt();
|
|
33
|
+
}
|
|
34
|
+
static async handleMainMenu(input, rl) {
|
|
35
|
+
switch (input) {
|
|
36
|
+
case '1':
|
|
37
|
+
case 'slash':
|
|
38
|
+
await new CommandManager_1.CommandManager().startInteractive();
|
|
39
|
+
break;
|
|
40
|
+
case '2':
|
|
41
|
+
case 'context':
|
|
42
|
+
await new ContextMenuManager_1.ContextMenuManager().startInteractive();
|
|
43
|
+
break;
|
|
44
|
+
case '3':
|
|
45
|
+
case 'all':
|
|
46
|
+
Log_1.Log.info('🚀 Déploiement complet...');
|
|
47
|
+
await Promise.all([
|
|
48
|
+
//new CommandManager().deployAll(),
|
|
49
|
+
//new ContextMenuManager().deployAll()
|
|
50
|
+
]);
|
|
51
|
+
break;
|
|
52
|
+
case 'help':
|
|
53
|
+
await this.showMainMenu(rl);
|
|
54
|
+
break;
|
|
55
|
+
case 'exit':
|
|
56
|
+
Log_1.Log.info('👋 Au revoir !');
|
|
57
|
+
rl.close();
|
|
58
|
+
process.exit(0);
|
|
59
|
+
default:
|
|
60
|
+
Log_1.Log.error('❌ Choix invalide');
|
|
61
|
+
rl.prompt();
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
InteractionManager.start();
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
/*import { Routes } from 'discord-api-types/v10';
|
|
4
|
+
import {Events} from "discord.js";
|
|
5
|
+
import {Log} from "../../../utils/Log";
|
|
6
|
+
import {client} from "../../../../src_example/client";
|
|
7
|
+
|
|
8
|
+
export interface Command {
|
|
9
|
+
name: string;
|
|
10
|
+
description: string;
|
|
11
|
+
options?: any[];
|
|
12
|
+
default_member_permissions?: string | bigint | number;
|
|
13
|
+
guildID?: string[];
|
|
14
|
+
type: 1 | 2 | 3; // 1 = slash, 2 = user context, 3 = message context
|
|
15
|
+
id?: string; // Discord API Command ID
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface DiscordCommand extends Command {
|
|
19
|
+
discordData?: any; // Données complètes depuis Discord API
|
|
20
|
+
deployedGuilds: string[]; // Serveurs où la commande est déployée
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export async function analyzeRegisteredCommands(): Promise<DiscordCommand[]> {
|
|
24
|
+
if (!(await loginBot(client))) {
|
|
25
|
+
Log.error("Impossible de connecter le bot");
|
|
26
|
+
process.exit();
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const allRegisteredCommands: DiscordCommand[] = [];
|
|
30
|
+
|
|
31
|
+
client.once(Events.ClientReady, async () => {
|
|
32
|
+
Log.info('Analyse des commandes enregistrées sur Discord');
|
|
33
|
+
|
|
34
|
+
// 1. Récupérer TOUTES les commandes Discord du bot
|
|
35
|
+
const globalDiscordCmds: any[] = await client.rest.get(
|
|
36
|
+
Routes.applicationCommands(client.user!.id)
|
|
37
|
+
) as any[];
|
|
38
|
+
|
|
39
|
+
// 2. Récupérer les commandes de TOUS les serveurs où le bot est présent
|
|
40
|
+
const botGuilds = client.guilds.cache.map(guild => guild.id);
|
|
41
|
+
const guildDiscordCmds: Record<string, any[]> = {};
|
|
42
|
+
|
|
43
|
+
Log.info(`Analyse des ${botGuilds.length} serveurs où le bot est présent...`);
|
|
44
|
+
|
|
45
|
+
for (const guildId of botGuilds) {
|
|
46
|
+
try {
|
|
47
|
+
const guildCmds = await client.rest.get(
|
|
48
|
+
Routes.applicationGuildCommands(config.clientId, guildId)
|
|
49
|
+
) as any[];
|
|
50
|
+
guildDiscordCmds[guildId] = guildCmds;
|
|
51
|
+
Log.info((`Serveur ${guildId}: ${guildCmds.length} commandes guild`);
|
|
52
|
+
} catch (error) {
|
|
53
|
+
// Le bot n'a peut-être pas les permissions ou n'est pas dans ce serveur
|
|
54
|
+
guildDiscordCmds[guildId] = [];
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// 3. Classer les commandes par nom et type
|
|
59
|
+
const commandMap = new Map<string, DiscordCommand>();
|
|
60
|
+
|
|
61
|
+
// Commandes globales
|
|
62
|
+
for (const cmd of globalDiscordCmds) {
|
|
63
|
+
const key = `${cmd.name}_${cmd.type}`;
|
|
64
|
+
if (!commandMap.has(key)) {
|
|
65
|
+
commandMap.set(key, {
|
|
66
|
+
name: cmd.name,
|
|
67
|
+
description: cmd.description || '',
|
|
68
|
+
type: cmd.type,
|
|
69
|
+
id: cmd.id,
|
|
70
|
+
deployedGuilds: ['GLOBAL'],
|
|
71
|
+
discordData: cmd
|
|
72
|
+
});
|
|
73
|
+
} else {
|
|
74
|
+
const existing = commandMap.get(key)!;
|
|
75
|
+
existing.deployedGuilds.push('GLOBAL');
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Commandes par serveur
|
|
80
|
+
for (const [guildId, guildCmds] of Object.entries(guildDiscordCmds)) {
|
|
81
|
+
for (const cmd of guildCmds) {
|
|
82
|
+
const key = `${cmd.name}_${cmd.type}`;
|
|
83
|
+
if (!commandMap.has(key)) {
|
|
84
|
+
commandMap.set(key, {
|
|
85
|
+
name: cmd.name,
|
|
86
|
+
description: cmd.description || '',
|
|
87
|
+
type: cmd.type,
|
|
88
|
+
id: cmd.id,
|
|
89
|
+
deployedGuilds: [guildId],
|
|
90
|
+
discordData: cmd
|
|
91
|
+
});
|
|
92
|
+
} else {
|
|
93
|
+
const existing = commandMap.get(key)!;
|
|
94
|
+
if (!existing.deployedGuilds.includes(guildId)) {
|
|
95
|
+
existing.deployedGuilds.push(guildId);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
} // ← Fermeture de la boucle for guildId
|
|
100
|
+
|
|
101
|
+
// 4. Conversion en tableau et tri ← ✅ DÉPLACÉ ICI (CORRIGÉ)
|
|
102
|
+
for (const [_key, cmd] of commandMap) {
|
|
103
|
+
allRegisteredCommands.push(cmd);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
allRegisteredCommands.sort((a, b) => {
|
|
107
|
+
if (a.deployedGuilds.includes('GLOBAL') && !b.deployedGuilds.includes('GLOBAL')) return -1;
|
|
108
|
+
if (!a.deployedGuilds.includes('GLOBAL') && b.deployedGuilds.includes('GLOBAL')) return 1;
|
|
109
|
+
return a.name.localeCompare(b.name);
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
// 5. Affichage du classement
|
|
113
|
+
console.log('\n' + '='.repeat(80));
|
|
114
|
+
console.log('📋 CLASSEMENT DES COMMANDES ENREGISTRÉES SUR DISCORD');
|
|
115
|
+
console.log('='.repeat(80));
|
|
116
|
+
|
|
117
|
+
const globalCmds = allRegisteredCommands.filter(cmd => cmd.deployedGuilds.includes('GLOBAL'));
|
|
118
|
+
const guildOnlyCmds = allRegisteredCommands.filter(cmd => !cmd.deployedGuilds.includes('GLOBAL'));
|
|
119
|
+
|
|
120
|
+
console.log(`🌍 ${globalCmds.length} commandes GLOBALES`);
|
|
121
|
+
console.log(`🏛️ ${guildOnlyCmds.length} commandes SERVEUR-SEUL`);
|
|
122
|
+
|
|
123
|
+
// Tableau récapitulatif
|
|
124
|
+
console.table(
|
|
125
|
+
allRegisteredCommands.map(cmd => ({
|
|
126
|
+
Nom: cmd.name,
|
|
127
|
+
Type: cmd.type === 1 ? 'Slash' : cmd.type === 2 ? 'User Context' : 'Message Context',
|
|
128
|
+
Serveurs: cmd.deployedGuilds.length > 3
|
|
129
|
+
? `${cmd.deployedGuilds.slice(0, 3).join(', ')}... (+${cmd.deployedGuilds.length - 3})`
|
|
130
|
+
: cmd.deployedGuilds.join(', '),
|
|
131
|
+
ID: cmd.id?.slice(-8) || 'N/A'
|
|
132
|
+
}))
|
|
133
|
+
);
|
|
134
|
+
|
|
135
|
+
// Détails par catégorie
|
|
136
|
+
if (globalCmds.length > 0) {
|
|
137
|
+
console.log('\n🌍 COMMANDES GLOBALES:');
|
|
138
|
+
globalCmds.forEach(cmd => {
|
|
139
|
+
console.log(` • ${cmd.name} (ID: ${cmd.id?.slice(-8)}) - ${cmd.description}`);
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
if (guildOnlyCmds.length > 0) {
|
|
144
|
+
console.log('\n🏛️ COMMANDES SERVEUR-SEULEMENT:');
|
|
145
|
+
const groupedByGuild = guildOnlyCmds.reduce((acc, cmd) => {
|
|
146
|
+
for (const guildId of cmd.deployedGuilds) {
|
|
147
|
+
if (!acc[guildId]) acc[guildId] = [];
|
|
148
|
+
acc[guildId].push(cmd.name);
|
|
149
|
+
}
|
|
150
|
+
return acc;
|
|
151
|
+
}, {} as Record<string, string[]>);
|
|
152
|
+
|
|
153
|
+
for (const [guildId, cmds] of Object.entries(groupedByGuild)) {
|
|
154
|
+
console.log(` 📂 Serveur ${guildId.slice(-8)}: ${cmds.join(', ')}`);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
console.log('\n✅ Analyse terminée!');
|
|
159
|
+
process.exit();
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
return allRegisteredCommands;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// Utilisation
|
|
166
|
+
analyzeRegisteredCommands();*/
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.EmbedManager = exports.EmbedColor = void 0;
|
|
4
|
+
const discord_js_1 = require("discord.js");
|
|
5
|
+
const Bot_1 = require("../../bot/Bot");
|
|
6
|
+
var EmbedColor;
|
|
7
|
+
(function (EmbedColor) {
|
|
8
|
+
EmbedColor[EmbedColor["error"] = 8912917] = "error";
|
|
9
|
+
EmbedColor[EmbedColor["success"] = 65280] = "success";
|
|
10
|
+
EmbedColor[EmbedColor["black"] = 0] = "black";
|
|
11
|
+
EmbedColor[EmbedColor["white"] = 16777215] = "white";
|
|
12
|
+
EmbedColor[EmbedColor["red"] = 16711680] = "red";
|
|
13
|
+
EmbedColor[EmbedColor["green"] = 65280] = "green";
|
|
14
|
+
EmbedColor[EmbedColor["blue"] = 255] = "blue";
|
|
15
|
+
EmbedColor[EmbedColor["yellow"] = 16776960] = "yellow";
|
|
16
|
+
EmbedColor[EmbedColor["cyan"] = 65535] = "cyan";
|
|
17
|
+
EmbedColor[EmbedColor["magenta"] = 16711935] = "magenta";
|
|
18
|
+
EmbedColor[EmbedColor["gray"] = 8421504] = "gray";
|
|
19
|
+
EmbedColor[EmbedColor["lightgray"] = 13882323] = "lightgray";
|
|
20
|
+
EmbedColor[EmbedColor["darkgray"] = 11119017] = "darkgray";
|
|
21
|
+
EmbedColor[EmbedColor["orange"] = 16753920] = "orange";
|
|
22
|
+
EmbedColor[EmbedColor["purple"] = 8388736] = "purple";
|
|
23
|
+
EmbedColor[EmbedColor["pink"] = 16761035] = "pink";
|
|
24
|
+
EmbedColor[EmbedColor["brown"] = 10824234] = "brown";
|
|
25
|
+
EmbedColor[EmbedColor["lime"] = 65280] = "lime";
|
|
26
|
+
EmbedColor[EmbedColor["navy"] = 128] = "navy";
|
|
27
|
+
EmbedColor[EmbedColor["teal"] = 32896] = "teal";
|
|
28
|
+
EmbedColor[EmbedColor["olive"] = 8421376] = "olive";
|
|
29
|
+
EmbedColor[EmbedColor["gold"] = 16766720] = "gold";
|
|
30
|
+
EmbedColor[EmbedColor["silver"] = 12632256] = "silver";
|
|
31
|
+
EmbedColor[EmbedColor["coral"] = 16744272] = "coral";
|
|
32
|
+
EmbedColor[EmbedColor["salmon"] = 16416882] = "salmon";
|
|
33
|
+
EmbedColor[EmbedColor["khaki"] = 15787660] = "khaki";
|
|
34
|
+
EmbedColor[EmbedColor["plum"] = 14524637] = "plum";
|
|
35
|
+
EmbedColor[EmbedColor["lavender"] = 15132410] = "lavender";
|
|
36
|
+
EmbedColor[EmbedColor["beige"] = 16119260] = "beige";
|
|
37
|
+
EmbedColor[EmbedColor["mint"] = 10026904] = "mint";
|
|
38
|
+
EmbedColor[EmbedColor["peach"] = 16767673] = "peach";
|
|
39
|
+
EmbedColor[EmbedColor["chocolate"] = 13789470] = "chocolate";
|
|
40
|
+
EmbedColor[EmbedColor["crimson"] = 14423100] = "crimson";
|
|
41
|
+
EmbedColor[EmbedColor["youtube"] = 16718362] = "youtube";
|
|
42
|
+
EmbedColor[EmbedColor["default"] = 6064856] = "default";
|
|
43
|
+
EmbedColor[EmbedColor["minecraft"] = 25600] = "minecraft";
|
|
44
|
+
})(EmbedColor || (exports.EmbedColor = EmbedColor = {}));
|
|
45
|
+
class EmbedManager {
|
|
46
|
+
static get BOT_ICON() {
|
|
47
|
+
return Bot_1.Bot.config.botIconUrl || "";
|
|
48
|
+
}
|
|
49
|
+
static get DEFAULT_COLOR() {
|
|
50
|
+
return Bot_1.Bot.config.defaultEmbedColor || EmbedColor.default;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Creates base embed - SAME SIMPLE API !
|
|
54
|
+
*/
|
|
55
|
+
static create(color = null) {
|
|
56
|
+
return new discord_js_1.EmbedBuilder()
|
|
57
|
+
.setColor(color ?? this.DEFAULT_COLOR)
|
|
58
|
+
.setTitle('Title')
|
|
59
|
+
.setDescription('')
|
|
60
|
+
.setThumbnail('')
|
|
61
|
+
.setFooter({
|
|
62
|
+
text: Bot_1.Bot.config.botName || "",
|
|
63
|
+
iconURL: this.BOT_ICON
|
|
64
|
+
})
|
|
65
|
+
.setTimestamp(new Date());
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Creates simple embed with just description
|
|
69
|
+
*/
|
|
70
|
+
static simple(description, color = null) {
|
|
71
|
+
return this.create(color)
|
|
72
|
+
.setTitle('')
|
|
73
|
+
.setDescription(description)
|
|
74
|
+
.setTimestamp(null);
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Creates error embed
|
|
78
|
+
*/
|
|
79
|
+
static error(description) {
|
|
80
|
+
return this.create(EmbedColor.error)
|
|
81
|
+
.setTitle('Something went Wrong')
|
|
82
|
+
.setDescription(description);
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Creates success embed
|
|
86
|
+
*/
|
|
87
|
+
static success(description) {
|
|
88
|
+
return this.create(EmbedColor.minecraft)
|
|
89
|
+
.setTitle('Success')
|
|
90
|
+
.setDescription(description);
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Creates debug embed
|
|
94
|
+
*/
|
|
95
|
+
static debug(description) {
|
|
96
|
+
return this.create(EmbedColor.green)
|
|
97
|
+
.setTitle('Debug')
|
|
98
|
+
.setDescription(description);
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Defer ephemeral reply
|
|
102
|
+
*/
|
|
103
|
+
static deferEphemeral() {
|
|
104
|
+
return { flags: discord_js_1.MessageFlags.Ephemeral };
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Quick field adder
|
|
108
|
+
*/
|
|
109
|
+
static field(embed, name, value, inline = false) {
|
|
110
|
+
return embed.addFields({ name, value, inline });
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Fluent API shortcuts
|
|
114
|
+
*/
|
|
115
|
+
static title(embed, title) {
|
|
116
|
+
return embed.setTitle(title);
|
|
117
|
+
}
|
|
118
|
+
static desc(embed, description) {
|
|
119
|
+
return embed.setDescription(description);
|
|
120
|
+
}
|
|
121
|
+
static thumb(embed, url) {
|
|
122
|
+
return embed.setThumbnail(url);
|
|
123
|
+
}
|
|
124
|
+
static image(embed, url) {
|
|
125
|
+
return embed.setImage(url);
|
|
126
|
+
}
|
|
127
|
+
static footer(embed, text) {
|
|
128
|
+
return embed.setFooter({ text, iconURL: this.BOT_ICON });
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
exports.EmbedManager = EmbedManager;
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ReactionManager = void 0;
|
|
4
|
+
const Log_1 = require("../../utils/Log");
|
|
5
|
+
const Bot_1 = require("../../bot/Bot");
|
|
6
|
+
const GuildTextChannelManager_1 = require("../guild/ChannelManager/GuildTextChannelManager");
|
|
7
|
+
class ReactionManager {
|
|
8
|
+
/**
|
|
9
|
+
* Add a reaction to a message
|
|
10
|
+
*/
|
|
11
|
+
static async add(channelId, messageId, emoji) {
|
|
12
|
+
try {
|
|
13
|
+
const channel = await GuildTextChannelManager_1.GuildTextChannelManager.find(channelId);
|
|
14
|
+
if (!channel) {
|
|
15
|
+
throw new Error(`Channel ${channelId} not found`);
|
|
16
|
+
}
|
|
17
|
+
if (!channel.isTextBased()) {
|
|
18
|
+
throw new Error(`Channel ${channelId} is not text based`);
|
|
19
|
+
}
|
|
20
|
+
const message = await channel.messages.fetch(messageId);
|
|
21
|
+
await message.react(emoji);
|
|
22
|
+
Log_1.Log.info(`Added reaction ${emoji} to message ${messageId}`);
|
|
23
|
+
}
|
|
24
|
+
catch (error) {
|
|
25
|
+
Log_1.Log.error(`Failed to add reaction to ${messageId}: ${error}`);
|
|
26
|
+
throw error;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Delete a reaction from a user
|
|
31
|
+
*/
|
|
32
|
+
static async remove(channelId, messageId, emoji, userId) {
|
|
33
|
+
try {
|
|
34
|
+
const channel = await GuildTextChannelManager_1.GuildTextChannelManager.find(channelId);
|
|
35
|
+
if (!channel) {
|
|
36
|
+
throw new Error(`Channel ${channelId} not found`);
|
|
37
|
+
}
|
|
38
|
+
const message = await channel.messages.fetch(messageId);
|
|
39
|
+
const reaction = message.reactions.resolve(emoji);
|
|
40
|
+
if (!reaction) {
|
|
41
|
+
throw new Error(`Reaction ${emoji} not found on message ${messageId}`);
|
|
42
|
+
}
|
|
43
|
+
const user = await Bot_1.Bot.client.users.fetch(userId);
|
|
44
|
+
await reaction.users.remove(user);
|
|
45
|
+
Log_1.Log.info(`Removed reaction ${emoji} from user ${userId} on message ${messageId}`);
|
|
46
|
+
}
|
|
47
|
+
catch (error) {
|
|
48
|
+
Log_1.Log.error(`Failed to remove reaction from ${messageId}: ${error}`);
|
|
49
|
+
throw error;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Get all reaction of a message
|
|
54
|
+
*/
|
|
55
|
+
static async getAll(channelId, messageId) {
|
|
56
|
+
try {
|
|
57
|
+
const channel = await GuildTextChannelManager_1.GuildTextChannelManager.find(channelId);
|
|
58
|
+
if (!channel) {
|
|
59
|
+
throw new Error(`Channel ${channelId} not found`);
|
|
60
|
+
}
|
|
61
|
+
const message = await channel.messages.fetch(messageId);
|
|
62
|
+
const reactions = message.reactions.cache;
|
|
63
|
+
const reactionList = [];
|
|
64
|
+
for (const reaction of reactions.values()) {
|
|
65
|
+
const users = await reaction.users.fetch();
|
|
66
|
+
reactionList.push({
|
|
67
|
+
emoji: reaction.emoji,
|
|
68
|
+
count: reaction.count,
|
|
69
|
+
users: Array.from(users.values())
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
Log_1.Log.info(`Fetched ${reactionList.length} reactions for message ${messageId}`);
|
|
73
|
+
return reactionList;
|
|
74
|
+
}
|
|
75
|
+
catch (error) {
|
|
76
|
+
Log_1.Log.error(`Failed to fetch reactions for ${messageId}: ${error}`);
|
|
77
|
+
throw error;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Delete all reaction
|
|
82
|
+
*/
|
|
83
|
+
static async clear(channelId, messageId) {
|
|
84
|
+
try {
|
|
85
|
+
const channel = await GuildTextChannelManager_1.GuildTextChannelManager.find(channelId);
|
|
86
|
+
if (!channel) {
|
|
87
|
+
throw new Error(`Channel ${channelId} not found`);
|
|
88
|
+
}
|
|
89
|
+
const message = await channel.messages.fetch(messageId);
|
|
90
|
+
await message.reactions.removeAll();
|
|
91
|
+
Log_1.Log.info(`Cleared all reactions from message ${messageId}`);
|
|
92
|
+
}
|
|
93
|
+
catch (error) {
|
|
94
|
+
Log_1.Log.error(`Failed to clear reactions from ${messageId}: ${error}`);
|
|
95
|
+
throw error;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
exports.ReactionManager = ReactionManager;
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.WebhookManager = void 0;
|
|
4
|
+
const discord_js_1 = require("discord.js");
|
|
5
|
+
const EmbedManager_1 = require("./EmbedManager");
|
|
6
|
+
const Log_1 = require("../../utils/Log");
|
|
7
|
+
const Bot_1 = require("../../bot/Bot");
|
|
8
|
+
class WebhookManager {
|
|
9
|
+
constructor(channel, name = Bot_1.Bot.config.botName || "", avatarURL) {
|
|
10
|
+
this.channel = channel;
|
|
11
|
+
this.name = name;
|
|
12
|
+
this.avatarURL = avatarURL;
|
|
13
|
+
this.webhook = null;
|
|
14
|
+
}
|
|
15
|
+
get textChannel() {
|
|
16
|
+
return this.channel instanceof discord_js_1.ThreadChannel
|
|
17
|
+
? this.channel.parent
|
|
18
|
+
: this.channel;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Get or create webhook (lazy initialization)
|
|
22
|
+
*/
|
|
23
|
+
async getWebhook() {
|
|
24
|
+
if (this.webhook)
|
|
25
|
+
return this.webhook;
|
|
26
|
+
try {
|
|
27
|
+
const webhooks = await this.textChannel.fetchWebhooks();
|
|
28
|
+
this.webhook = webhooks.find(h => h.name === this.name) ??
|
|
29
|
+
await this.textChannel.createWebhook({
|
|
30
|
+
name: this.name,
|
|
31
|
+
avatar: this.avatarURL,
|
|
32
|
+
reason: 'Auto-created by WebhookManager'
|
|
33
|
+
});
|
|
34
|
+
Log_1.Log.info(`Webhook ${this.webhook.id} ready for ${this.textChannel.id}`);
|
|
35
|
+
return this.webhook;
|
|
36
|
+
}
|
|
37
|
+
catch (error) {
|
|
38
|
+
Log_1.Log.error(`Failed to setup webhook: ${error}`);
|
|
39
|
+
throw error;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Send message/text/embed - EmbedBuilder NATIVE !
|
|
44
|
+
*/
|
|
45
|
+
async send(content) {
|
|
46
|
+
const webhook = await this.getWebhook();
|
|
47
|
+
const options = {};
|
|
48
|
+
if (content instanceof discord_js_1.EmbedBuilder) {
|
|
49
|
+
options.embeds = [content];
|
|
50
|
+
}
|
|
51
|
+
else if (typeof content === 'object') {
|
|
52
|
+
Object.assign(options, content);
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
options.content = content;
|
|
56
|
+
}
|
|
57
|
+
if (this.channel instanceof discord_js_1.ThreadChannel) {
|
|
58
|
+
options.threadId = this.channel.id;
|
|
59
|
+
}
|
|
60
|
+
try {
|
|
61
|
+
const message = await webhook.send(options);
|
|
62
|
+
Log_1.Log.info(`Webhook sent to ${this.channel.id}: ${content}`);
|
|
63
|
+
return message;
|
|
64
|
+
}
|
|
65
|
+
catch (error) {
|
|
66
|
+
Log_1.Log.error(`Webhook send failed ${this.channel.id}: ${error}`);
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Quick success embed
|
|
72
|
+
*/
|
|
73
|
+
async success(message) {
|
|
74
|
+
return await this.send(EmbedManager_1.EmbedManager.success(message));
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Quick error embed
|
|
78
|
+
*/
|
|
79
|
+
async error(message) {
|
|
80
|
+
return await this.send(EmbedManager_1.EmbedManager.error(message));
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Delete webhook
|
|
84
|
+
*/
|
|
85
|
+
async delete(reason) {
|
|
86
|
+
if (!this.webhook)
|
|
87
|
+
return;
|
|
88
|
+
try {
|
|
89
|
+
await this.webhook.delete(reason ?? 'Deleted by WebhookManager');
|
|
90
|
+
Log_1.Log.info(`Webhook ${this.webhook.id} deleted`);
|
|
91
|
+
}
|
|
92
|
+
catch (error) {
|
|
93
|
+
if (error.message.includes('Unknown Webhook')) {
|
|
94
|
+
Log_1.Log.warn('Webhook already deleted');
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
Log_1.Log.error(`Failed to delete webhook: ${error}`);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
finally {
|
|
101
|
+
this.webhook = null;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
exports.WebhookManager = WebhookManager;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.FolderName = void 0;
|
|
4
|
+
var FolderName;
|
|
5
|
+
(function (FolderName) {
|
|
6
|
+
FolderName["SLASH_COMMANDS"] = "commands";
|
|
7
|
+
FolderName["CONTEXT_MENU"] = "context_menu";
|
|
8
|
+
FolderName["MODAL"] = "modals";
|
|
9
|
+
})(FolderName || (exports.FolderName = FolderName = {}));
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var _a;
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.DiscordRegex = void 0;
|
|
5
|
+
/**
|
|
6
|
+
* Classe utilitaire pour valider tous les formats Discord avec regex
|
|
7
|
+
*/
|
|
8
|
+
class DiscordRegex {
|
|
9
|
+
/**
|
|
10
|
+
* Validate Discord ID Discord (18)
|
|
11
|
+
*/
|
|
12
|
+
static isDiscordId(id) {
|
|
13
|
+
return this.USER_ID.test(id) || this.GUILD_ID.test(id) || this.CHANNEL_ID.test(id);
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Validate a bot ID (19)
|
|
17
|
+
*/
|
|
18
|
+
static isBotMention(mention) {
|
|
19
|
+
return this.BOT_REGEX.test(mention);
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Validate a User ping
|
|
23
|
+
*/
|
|
24
|
+
static isUserMention(mention) {
|
|
25
|
+
return this.USER_REGEX.test(mention);
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Validate a Discord username
|
|
29
|
+
*/
|
|
30
|
+
static isUsername(username) {
|
|
31
|
+
return this.USERNAME.test(username);
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Type guard for Discord ID
|
|
35
|
+
*/
|
|
36
|
+
static isDiscordIdType(id) {
|
|
37
|
+
return this.isDiscordId(id);
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Any Discord URL
|
|
41
|
+
*/
|
|
42
|
+
static isDiscordUrl(url) {
|
|
43
|
+
return this.URL_REGEX.test(url) || this.INVITE.test(url);
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Any discord mention
|
|
47
|
+
*/
|
|
48
|
+
static isAnyMention(text) {
|
|
49
|
+
return this.DISCORD_MENTION_REGEX.test(text);
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* List all regex
|
|
53
|
+
*/
|
|
54
|
+
static listAll() {
|
|
55
|
+
return {
|
|
56
|
+
SPACE: this.SPACE,
|
|
57
|
+
URL_REGEX: this.URL_REGEX,
|
|
58
|
+
USER_REGEX: this.USER_REGEX,
|
|
59
|
+
BOT_REGEX: this.BOT_REGEX,
|
|
60
|
+
CHANNEL_REGEX: this.CHANNEL_REGEX,
|
|
61
|
+
ROLE_REGEX: this.ROLE_REGEX,
|
|
62
|
+
DISCORD_PING_REGEX: this.DISCORD_PING_REGEX,
|
|
63
|
+
DISCORD_MENTION_REGEX: this.DISCORD_MENTION_REGEX,
|
|
64
|
+
USER_ID: this.USER_ID,
|
|
65
|
+
CHANNEL_ID: this.CHANNEL_ID,
|
|
66
|
+
GUILD_ID: this.GUILD_ID,
|
|
67
|
+
USERNAME: this.USERNAME,
|
|
68
|
+
USERNAME_DISCRIM: this.USERNAME_DISCRIM,
|
|
69
|
+
CHANNEL_MENTION: this.CHANNEL_MENTION,
|
|
70
|
+
USER_MENTION: this.USER_MENTION,
|
|
71
|
+
ROLE_MENTION: this.ROLE_MENTION,
|
|
72
|
+
INVITE: this.INVITE,
|
|
73
|
+
EMOJI: this.EMOJI
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
exports.DiscordRegex = DiscordRegex;
|
|
78
|
+
_a = DiscordRegex;
|
|
79
|
+
// Caractères spéciaux
|
|
80
|
+
DiscordRegex.SPACE = "\u200B";
|
|
81
|
+
// URLs basiques
|
|
82
|
+
DiscordRegex.URL_REGEX = /(https?:\/\/[^s]+)/;
|
|
83
|
+
/* DISCORD REGEX */
|
|
84
|
+
DiscordRegex.USER_REGEX = /<@\d{18}>/;
|
|
85
|
+
DiscordRegex.BOT_REGEX = /<@\d{19}>/;
|
|
86
|
+
DiscordRegex.CHANNEL_REGEX = /(<#\d{19}>)|(<id:(browse|customize|guide)>)/;
|
|
87
|
+
DiscordRegex.ROLE_REGEX = /<@&\d{19}>/;
|
|
88
|
+
/**
|
|
89
|
+
* Mention a User
|
|
90
|
+
* Mention a Role
|
|
91
|
+
*/
|
|
92
|
+
DiscordRegex.DISCORD_PING_REGEX = new RegExp(`(${_a.USER_REGEX.source})|(${_a.BOT_REGEX.source})|(${_a.ROLE_REGEX.source})`);
|
|
93
|
+
/**
|
|
94
|
+
* Mention a User
|
|
95
|
+
* Mention a Role
|
|
96
|
+
* Mention a Channel
|
|
97
|
+
*/
|
|
98
|
+
DiscordRegex.DISCORD_MENTION_REGEX = new RegExp(`(${_a.DISCORD_PING_REGEX.source})|(${_a.CHANNEL_REGEX.source})`);
|
|
99
|
+
// ID Discord (user, channel guild)
|
|
100
|
+
DiscordRegex.USER_ID = /^[0-9]{18}$/;
|
|
101
|
+
DiscordRegex.CHANNEL_ID = /^[0-9]{18}$/;
|
|
102
|
+
DiscordRegex.GUILD_ID = /^[0-9]{19}$/;
|
|
103
|
+
// Username Discord (2-32 caractères alphanumériques + _ .)
|
|
104
|
+
DiscordRegex.USERNAME = /^[a-zA-Z0-9_]{2,32}$/;
|
|
105
|
+
// Username + discrim (ancien format)
|
|
106
|
+
DiscordRegex.USERNAME_DISCRIM = /^[a-zA-Z0-9_]{2,32}#\d{4}$/;
|
|
107
|
+
// Channel mention <#123456789012345678>
|
|
108
|
+
DiscordRegex.CHANNEL_MENTION = /^<#([0-9]{18})>$/;
|
|
109
|
+
// User mention <@123456789012345678> ou <@!123456789012345678>
|
|
110
|
+
DiscordRegex.USER_MENTION = /^<@!?([0-9]{18})>$/;
|
|
111
|
+
// Role mention <@&123456789012345678>
|
|
112
|
+
DiscordRegex.ROLE_MENTION = /^<@&([0-9]{18})>$/;
|
|
113
|
+
// URL Invite Discord
|
|
114
|
+
DiscordRegex.INVITE = /^discord(?:app\.com\/invite|gg)\/[a-zA-Z0-9]+$/;
|
|
115
|
+
// Emoji Discord (custom or unicode)
|
|
116
|
+
DiscordRegex.EMOJI = /^<a?:[a-zA-Z0-9_]{2,32}:[0-9]{18}>$|^[\u{1F300}-\u{1F5FF}\u{1F600}-\u{1F64F}\u{1F680}-\u{1F6FF}\u{2600}-\u{26FF}\u{2700}-\u{27BF}]+$/u;
|