/[sudobot]/branches/3.x/src/commands/moderation/HistoryCommand.ts
ViewVC logotype

Contents of /branches/3.x/src/commands/moderation/HistoryCommand.ts

Parent Directory Parent Directory | Revision Log Revision Log


Revision 577 - (show annotations)
Mon Jul 29 18:52:37 2024 UTC (8 months ago) by rakinar2
File MIME type: application/typescript
File size: 9396 byte(s)
chore: add old version archive branches (2.x to 9.x-dev)
1 /**
2 * This file is part of SudoBot.
3 *
4 * Copyright (C) 2021-2022 OSN Inc.
5 *
6 * SudoBot is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU Affero General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * SudoBot is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Affero General Public License for more details.
15 *
16 * You should have received a copy of the GNU Affero General Public License
17 * along with SudoBot. If not, see <https://www.gnu.org/licenses/>.
18 */
19
20 import { CommandInteraction, ContextMenuInteraction, Interaction, InteractionCollector, Message, MessageActionRow, MessageButton, User } from 'discord.js';
21 import BaseCommand from '../../utils/structures/BaseCommand';
22 import DiscordClient from '../../client/Client';
23 import CommandOptions from '../../types/CommandOptions';
24 import InteractionOptions from '../../types/InteractionOptions';
25 import MessageEmbed from '../../client/MessageEmbed';
26 import getUser from '../../utils/getUser';
27 import Punishment from '../../models/Punishment';
28 import PunishmentType from '../../types/PunishmentType';
29
30 export default class HistoryCommand extends BaseCommand {
31 supportsInteractions: boolean = true;
32 supportsContextMenu = true;
33
34 constructor() {
35 super('history', 'moderation', ['Moderation History']);
36 }
37
38 async genEmbed(client: DiscordClient, msg: Message | Interaction, user: User, page: number = 1) {
39 const limit = 3;
40 const offset = ((page < 1 ? 1 : page) - 1) * limit;
41
42 const logs = await Punishment.find({
43 guild_id: msg.guild!.id,
44 user_id: user.id,
45 }).skip(offset).limit(limit).sort({ createdAt: -1 });
46
47 let str = '';
48
49 const maxPage = Math.ceil((await Punishment.count({
50 guild_id: msg.guild!.id,
51 user_id: user.id,
52 })) / limit);
53
54 const convert = (type: PunishmentType) => {
55 switch (type) {
56 case PunishmentType.BAN:
57 return 'Ban';
58 case PunishmentType.SOFTBAN:
59 return 'Soft Ban';
60 case PunishmentType.TEMPBAN:
61 return 'Temporary Ban';
62 case PunishmentType.SHOT:
63 return 'Shot';
64 case PunishmentType.MUTE:
65 return 'Mute';
66 case PunishmentType.HARDMUTE:
67 return 'Hardmute';
68 case PunishmentType.KICK:
69 return 'Kick';
70 case PunishmentType.WARNING:
71 return 'Warning';
72 case PunishmentType.UNBAN:
73 return 'Unban';
74 case PunishmentType.UNMUTE:
75 return 'Unmute';
76 default:
77 return "Unknown";
78 }
79 };
80
81 for await (const log of logs) {
82 str += `**Case ID**: ${log.id}\n`;
83 str += `Type: ${convert(log.type as PunishmentType)}\n`;
84 str += `Reason: ${log.reason ? (log.reason.trim() === '' ? '*No reason provided*' : log.reason) : '*No reason provided*'}\n`;
85
86 // let mod_tag;
87
88 // try {
89 // const mod = await client.users.fetch(log.get().mod_id);
90
91 // if (!mod)
92 // throw new Error();
93
94 // mod_tag = mod.tag;
95 // }
96 // catch (e) {
97 // mod_tag = log.get().mod_id;
98 // }
99
100 str += `Action Executor: ${log.mod_tag}\n`;
101 str += `Date: ${log.createdAt.toLocaleString('en-US')}\n`;
102
103 // if (log.get().type === PunishmentType.MUTE) {
104 // str += `Duration: ${(log.get().meta ? JSON.parse(log.get().meta) : {})?.time ?? '*No duration set*'}\n`;
105 // }
106
107 if (log.meta) {
108 const json = typeof log.meta === 'string' ? JSON.parse(log.meta) : log.meta;
109
110 if (Object.keys(json).length > 0) {
111 str += "Additional Attributes:\n```\n";
112
113 for (const key in json) {
114 str += `${key}: ${json[key]}\n`;
115 }
116
117 str += '\n```\n';
118 }
119 }
120
121 str += '\n';
122 }
123
124 return {
125 embeds: [
126 new MessageEmbed({
127 author: {
128 name: user.tag,
129 iconURL: user.displayAvatarURL()
130 },
131 title: 'Moderation History',
132 description: str === '' ? 'No history.' : str,
133 timestamp: new Date(),
134 })
135 ],
136 components: [
137 this.createActionRow(page, maxPage)
138 ]
139 };
140 }
141
142 createActionRow(page: number, max: number) {
143 console.log(max);
144
145 const back = new MessageButton({
146 customId: 'history-back-',
147 label: '<<',
148 style: 'PRIMARY'
149 });
150
151 const next = new MessageButton({
152 customId: 'history-next-',
153 label: '>>',
154 style: 'PRIMARY'
155 });
156
157 let nextPage = page + 1;
158 console.log(nextPage);
159
160 if (nextPage > max) {
161 nextPage = max;
162 next.setDisabled(true);
163 }
164 else {
165 next.setDisabled(false);
166 }
167
168 let prevPage = page - 1;
169 console.log(prevPage);
170
171 if (prevPage <= 0) {
172 prevPage = 1;
173 back.setDisabled(true);
174 }
175 else {
176 back.setDisabled(false);
177 }
178
179 next.setCustomId('history-next-' + nextPage);
180 back.setCustomId('history-back-' + prevPage);
181
182 return new MessageActionRow()
183 .addComponents(
184 back,
185 next
186 );
187 }
188
189 async update(client: DiscordClient, interaction: Interaction, message: Message) {
190 console.log('here');
191
192 if (interaction.isButton() && interaction.customId.startsWith('history-')) {
193 const splitted = interaction.customId.split('-');
194
195 if (splitted[2] === undefined || parseInt(splitted[2]) === NaN)
196 return;
197
198 if (splitted[1] === 'next' || splitted[1] === 'back') {
199 const options = await this.genEmbed(client, interaction, (global as any).user, parseInt(splitted[2]));
200 try {
201 await interaction.update(options);
202 }
203 catch (e) {
204 console.log(e);
205 }
206 }
207 }
208 }
209
210 async run(client: DiscordClient, msg: Message | CommandInteraction, options: CommandOptions | InteractionOptions) {
211 if (!options.isInteraction && typeof options.args[0] === 'undefined') {
212 await msg.reply({
213 embeds: [
214 new MessageEmbed()
215 .setColor('#f14a60')
216 .setDescription(`This command requires at least one argument.`)
217 ]
218 });
219
220 return;
221 }
222
223 let user: User | null | undefined;
224
225 if (options.isInteraction) {
226 user = await <User> options.options.getUser('user');
227 }
228 else {
229 try {
230 user = await getUser(client, msg as Message, options);
231
232 if (!user)
233 throw new Error();
234 }
235 catch (e) {
236 console.log(e);
237
238 await msg.reply({
239 embeds: [
240 new MessageEmbed()
241 .setColor('#f14a60')
242 .setDescription(`Invalid user given.`)
243 ]
244 });
245
246 return;
247 }
248 }
249
250 (global as any).user = user;
251
252 let message = <Message> await msg.reply(await this.genEmbed(client, msg, user));
253
254 if (msg instanceof CommandInteraction)
255 message = <Message> await msg.fetchReply();
256
257 const collector = new InteractionCollector(client, {
258 guild: msg.guild!,
259 channel: msg.channel!,
260 max: 20,
261 componentType: 'BUTTON',
262 interactionType: 'MESSAGE_COMPONENT',
263 message,
264 time: 30000,
265 filter(i) {
266 return i.isButton() && i.member?.user.id === msg.member!.user.id;
267 }
268 });
269
270 collector.on('collect', async i => {
271 await this.update(client, i, message);
272 });
273
274 collector.on('end', async () => {
275 try {
276 if (msg instanceof ContextMenuInteraction) {
277 await msg.editReply({
278 components: []
279 });
280 }
281 else {
282 await message.edit({
283 components: []
284 });
285 }
286 }
287 catch (e) {
288 console.log(e);
289 }
290 });
291 }
292 }

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26