/[sudobot]/branches/8.x/src/commands/moderation/InfractionEditCommand.ts
ViewVC logotype

Annotation of /branches/8.x/src/commands/moderation/InfractionEditCommand.ts

Parent Directory Parent Directory | Revision Log Revision Log


Revision 577 - (hide annotations)
Mon Jul 29 18:52:37 2024 UTC (8 months ago) by rakinar2
File MIME type: application/typescript
File size: 8896 byte(s)
chore: add old version archive branches (2.x to 9.x-dev)
1 rakinar2 577 /**
2     * This file is part of SudoBot.
3     *
4     * Copyright (C) 2021-2023 OSN Developers.
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 { formatDistanceToNowStrict } from "date-fns";
21     import { ChatInputCommandInteraction, EmbedBuilder, PermissionsBitField } from "discord.js";
22     import Command, { CommandReturn, ValidationRule } from "../../core/Command";
23     import { stringToTimeInterval } from "../../utils/datetime";
24     import { safeUserFetch } from "../../utils/fetch";
25    
26     export default class InfractionEditCommand extends Command {
27     public readonly name = "infraction__edit";
28     public readonly validationRules: ValidationRule[] = [];
29     public readonly permissions = [
30     PermissionsBitField.Flags.ModerateMembers,
31     PermissionsBitField.Flags.ViewAuditLog
32     ];
33     public readonly permissionMode = "or";
34     public readonly supportsLegacy: boolean = false;
35    
36     public readonly description = "Edit infractions.";
37     public readonly detailedDescription =
38     "Update an infraction with a new reason or duration or both.";
39     public readonly argumentSyntaxes = ["<infraction_id> [new_reason] [new_duration]"];
40    
41     async execute(interaction: ChatInputCommandInteraction): Promise<CommandReturn> {
42     const id = interaction.options.getInteger("id", true);
43     let newReason = interaction.options.getString("new_reason");
44     const newDuration = interaction.options.getString("new_duration");
45    
46     if (!newReason && !newDuration) {
47     await interaction.editReply(
48     `${this.emoji(
49     "error"
50     )} Either provide a reason or duration or both to update this infraction, if it exists!`
51     );
52     return;
53     }
54    
55     const newDurationSeconds = newDuration ? stringToTimeInterval(newDuration) : undefined;
56     const silent = interaction.options.getBoolean("silent") ?? true;
57    
58     if (newDurationSeconds && newDurationSeconds.error) {
59     await interaction.editReply(
60     `${this.emoji("error")} ${
61     newDurationSeconds.error
62     } provided in the \`new_duration\` field`
63     );
64     return;
65     }
66    
67     const infraction = await this.client.prisma.infraction.findFirst({
68     where: { id, guildId: interaction.guildId! }
69     });
70    
71     if (!infraction) {
72     await interaction.editReply(
73     `${this.emoji("error")} Could not find an infraction with that ID!`
74     );
75     return;
76     }
77    
78     if (
79     newDurationSeconds?.result &&
80     infraction.expiresAt &&
81     infraction.expiresAt.getTime() <= Date.now()
82     ) {
83     await interaction.editReply(
84     `${this.emoji(
85     "error"
86     )} That infraction is expired, so you can't change it's duration!`
87     );
88     return;
89     }
90    
91     if (
92     newDurationSeconds?.result &&
93     infraction.createdAt.getTime() + newDurationSeconds?.result * 1000 <= Date.now()
94     ) {
95     await interaction.editReply(
96     `${this.emoji(
97     "error"
98     )} That duration makes the infraction expire in the past, which is not possible! Please make sure the time of infraction creation plus the new duration is greater than the current time!`
99     );
100     return;
101     }
102    
103     if (newDurationSeconds?.result && infraction.expiresAt === null) {
104     await interaction.editReply(
105     `${this.emoji(
106     "error"
107     )} This infraction did not have a duration in the first place, so you can't set one now.`
108     );
109    
110     return;
111     }
112    
113     const user = await safeUserFetch(this.client, infraction.userId);
114    
115     if (newDurationSeconds && infraction.queueId) {
116     const queue = this.client.queueManager.queues.get(`${infraction.queueId}`);
117    
118     if (queue) {
119     await queue.updateTime(
120     new Date(infraction.createdAt.getTime() + newDurationSeconds.result * 1000)
121     );
122     }
123     }
124    
125     if (!silent) {
126     await user?.send({
127     embeds: [
128     new EmbedBuilder({
129     author: {
130     icon_url: interaction.guild?.iconURL() ?? undefined,
131     name: "Your infraction has been updated in " + interaction.guild!.name
132     },
133     color: 0xf14a60,
134     fields: [
135     ...(newReason
136     ? [
137     {
138     name: "Reason",
139     value: newReason
140     }
141     ]
142     : []),
143     ...(newDurationSeconds?.result
144     ? [
145     {
146     name: "Duration",
147     value: formatDistanceToNowStrict(
148     new Date(
149     infraction.createdAt.getTime() +
150     newDurationSeconds.result * 1000
151     )
152     )
153     }
154     ]
155     : []),
156     {
157     name: "Infraction ID",
158     value: id.toString()
159     }
160     ]
161     }).setTimestamp()
162     ]
163     });
164     }
165    
166     if (newReason) {
167     newReason = this.client.infractionManager.processInfractionReason(
168     interaction.guildId!,
169     newReason,
170     true
171     );
172     }
173    
174     await this.client.prisma.infraction.update({
175     data: {
176     reason: newReason ?? undefined,
177     expiresAt: newDurationSeconds
178     ? new Date(infraction.createdAt.getTime() + newDurationSeconds.result * 1000)
179     : undefined
180     },
181     where: { id }
182     });
183    
184     await interaction.editReply({
185     embeds: [
186     new EmbedBuilder({
187     title: "Infraction update",
188     description: "Updated successfully!",
189     color: 0x007bff,
190     fields: [
191     ...(newReason
192     ? [
193     {
194     name: "New Reason",
195     value: newReason
196     }
197     ]
198     : []),
199     ...(newDurationSeconds?.result
200     ? [
201     {
202     name: "New Duration",
203     value: formatDistanceToNowStrict(
204     new Date(
205     infraction.createdAt.getTime() +
206     newDurationSeconds.result * 1000
207     )
208     )
209     }
210     ]
211     : []),
212     {
213     name: "ID",
214     value: id.toString()
215     },
216     {
217     name: "Notifying User?",
218     value: silent ? "No" : "Yes",
219     inline: true
220     }
221     ],
222     footer: {
223     text: "Updated"
224     }
225     }).setTimestamp()
226     ]
227     });
228     }
229     }

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26