/[sudobot]/trunk/src/commands/moderation/HistoryCommand.ts
ViewVC logotype

Diff of /trunk/src/commands/moderation/HistoryCommand.ts

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 51 by rakin, Mon Jul 29 17:28:23 2024 UTC revision 393 by rakin, Mon Jul 29 17:29:59 2024 UTC
# Line 1  Line 1 
1  import { BanOptions, CommandInteraction, EmojiIdentifierResolvable, GuildMember, Interaction, Message, TextChannel, User } from 'discord.js';  /**
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';  import BaseCommand from '../../utils/structures/BaseCommand';
22  import DiscordClient from '../../client/Client';  import DiscordClient from '../../client/Client';
23  import CommandOptions from '../../types/CommandOptions';  import CommandOptions from '../../types/CommandOptions';
24  import InteractionOptions from '../../types/InteractionOptions';  import InteractionOptions from '../../types/InteractionOptions';
25  import MessageEmbed from '../../client/MessageEmbed';  import MessageEmbed from '../../client/MessageEmbed';
26  import getUser from '../../utils/getUser';  import getUser from '../../utils/getUser';
27  import getMember from '../../utils/getMember';  import Punishment from '../../models/Punishment';
28  import History from '../../automod/History';  import PunishmentType from '../../types/PunishmentType';
 import { fetchEmoji } from '../../utils/Emoji';  
29    
30  export default class HistoryCommand extends BaseCommand {  export default class HistoryCommand extends BaseCommand {
31      supportsInteractions: boolean = true;      supportsInteractions: boolean = true;
32        supportsContextMenu = true;
33    
34      constructor() {      constructor() {
35          super('history', 'moderation', []);          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) {      async run(client: DiscordClient, msg: Message | CommandInteraction, options: CommandOptions | InteractionOptions) {
# Line 56  export default class HistoryCommand exte Line 247  export default class HistoryCommand exte
247              }              }
248          }          }
249    
250          History.get(user.id, msg.guild!, async (data) => {          (global as any).user = user;
             let str = '';  
251    
252              for await (const row of data) {          let message = <Message> await msg.reply(await this.genEmbed(client, msg, user));
                 let mod: User | string | undefined;  
253    
254                  try {          if (msg instanceof CommandInteraction)
255                      mod = await client.users.fetch(row.mod_id);              message = <Message> await msg.fetchReply();
256    
257                      if (!mod) {          const collector = new InteractionCollector(client, {
258                          throw new Error();              guild: msg.guild!,
259                      }              channel: msg.channel!,
260                  }              max: 20,
261                  catch (e) {              componentType: 'BUTTON',
262                      console.log(e);              interactionType: 'MESSAGE_COMPONENT',
263                                    message,
264                      user = row.user_id;              time: 30000,
265                      mod = row.mod_id;              filter(i) {
266                  }                  return i.isButton() && i.member?.user.id === msg.member!.user.id;
267                }
268                  str += `\`[${new Date(row.date).toLocaleString()}]\` \`[${typeof mod === 'string' ? mod : mod?.tag}]\` `;          });
269    
270                  let type: string;          collector.on('collect', async i => {
271                await this.update(client, i, message);
272            });
273    
274                  if (row.type === 'ban') {          collector.on('end', async () => {
275                      type = 'Banned';              try {
276                  }                  if (msg instanceof ContextMenuInteraction) {
277                  else if (row.type === 'unban') {                      await msg.editReply({
278                      type = 'Unbanned';                          components: []
279                  }                      });
                 else if (row.type === 'kick') {  
                     type = 'Kicked';  
                 }  
                 else if (row.type === 'mute') {  
                     type = 'Muted';  
                 }  
                 else if (row.type === 'unmute') {  
                     type = 'Unmuted';  
                 }  
                 else if (row.type === 'bean') {  
                     type = 'Beaned';  
                 }  
                 else if (row.type === 'warn') {  
                     type = 'Warned';  
280                  }                  }
281                  else {                  else {
282                      type = 'Deleted warning for';                      await message.edit({
283                            components: []
284                        });
285                  }                  }
   
                 str += `\`${type}\` \`${typeof user === 'string' ? user : user?.tag}\` \`[Reason: ${row.reason ? row.reason : "No reason provided"}]\`\n`;  
286              }              }
287                catch (e) {
288              await msg.reply({                  console.log(e);                
289                  embeds: [              }
                     new MessageEmbed()  
                     .setAuthor({  
                         name: user!.tag,  
                         iconURL: user?.displayAvatarURL()!  
                     })  
                     .setTitle('Moderation history')  
                     .setDescription(str == '' ? 'No history' : str)  
                 ]  
             });  
290          });          });
291      }      }
 }  
292    }

Legend:
Removed from v.51  
changed lines
  Added in v.393

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26