/[sudobot]/branches/8.x/src/services/ChannelLockManager.ts
ViewVC logotype

Contents of /branches/8.x/src/services/ChannelLockManager.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: 12747 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-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 {
21 ChannelType,
22 Guild,
23 GuildBasedChannel,
24 PermissionFlags,
25 PermissionFlagsBits,
26 PermissionOverwriteOptions,
27 Snowflake,
28 TextChannel,
29 User
30 } from "discord.js";
31 import Service from "../core/Service";
32 import { log, logError } from "../utils/Logger";
33 import { getChannelPermissionOverride } from "../utils/utils";
34
35 export const name = "channelLockManager";
36
37 type ChannelLockOptions = {
38 channels?: Snowflake[];
39 channelMode?: "exclude" | "include";
40 ignorePrivateChannels?: boolean;
41 moderator: User;
42 reason?: string;
43 };
44
45 export default class ChannelLockManager extends Service {
46 async shouldLock(channels: Snowflake[], channel: GuildBasedChannel, channelMode: "exclude" | "include") {
47 return (
48 channels.length === 0 ||
49 (channelMode === "include" && channels.includes(channel.id)) ||
50 (channelMode === "exclude" && !channels.includes(channel.id))
51 );
52 }
53
54 async lockGuild(
55 guild: Guild,
56 { reason, moderator, channels = [], channelMode = "include", ignorePrivateChannels = true }: ChannelLockOptions
57 ) {
58 let countSuccess = 0,
59 countFailed = 0,
60 countSkipped = 0,
61 countInvalidChannel = 0;
62
63 const originalPermissions = [];
64
65 for (const [, channel] of guild.channels.cache) {
66 log(channel.name);
67
68 if (
69 !this.shouldLock(channels, channel, channelMode) ||
70 ![
71 ChannelType.GuildAnnouncement,
72 ChannelType.GuildCategory,
73 ChannelType.GuildText,
74 ChannelType.GuildVoice,
75 ChannelType.GuildStageVoice,
76 ChannelType.GuildForum
77 ].includes(channel.type)
78 ) {
79 countInvalidChannel++;
80 continue;
81 }
82
83 try {
84 const permissionOverwrites = (channel as TextChannel).permissionOverwrites?.cache.get(guild.id);
85
86 if (ignorePrivateChannels) {
87 if (permissionOverwrites?.deny.has(PermissionFlagsBits.ViewChannel, true)) {
88 log("Private channel, skipping lock");
89 countSkipped++;
90 continue;
91 }
92 }
93
94 if (permissionOverwrites?.deny.has(PermissionFlagsBits.SendMessages, true)) {
95 log("Already locked channel, skipping lock");
96 countSkipped++;
97 continue;
98 }
99
100 const permissionJson = {
101 Connect: permissionOverwrites
102 ? getChannelPermissionOverride(PermissionFlagsBits.Connect, permissionOverwrites)
103 : null,
104 SendMessages: permissionOverwrites
105 ? getChannelPermissionOverride(PermissionFlagsBits.SendMessages, permissionOverwrites)
106 : null,
107 SendMessagesInThreads: permissionOverwrites
108 ? getChannelPermissionOverride(PermissionFlagsBits.SendMessagesInThreads, permissionOverwrites)
109 : null,
110 AddReactions: permissionOverwrites
111 ? getChannelPermissionOverride(PermissionFlagsBits.AddReactions, permissionOverwrites)
112 : null
113 };
114
115 originalPermissions.push({
116 channel_id: channel.id,
117 guild_id: guild.id,
118 permissions: permissionJson
119 });
120
121 await (channel as TextChannel).permissionOverwrites?.edit(guild.id, {
122 Connect: false,
123 SendMessages: false,
124 SendMessagesInThreads: false,
125 AddReactions: false
126 });
127
128 countSuccess++;
129 } catch (e) {
130 logError(e);
131 countFailed++;
132 }
133 }
134
135 await this.client.prisma.channelLock.createMany({
136 data: originalPermissions
137 });
138
139 await this.client.loggerService.logServerLockOrUnlock({
140 guild,
141 action: "Locked",
142 moderator,
143 countSuccess,
144 countFailed,
145 countInvalidChannel,
146 countSkipped,
147 reason
148 });
149
150 return {
151 countSuccess,
152 countFailed,
153 countInvalidChannel,
154 countSkipped
155 };
156 }
157
158 async unlockGuild(
159 guild: Guild,
160 {
161 channels = [],
162 channelMode = "include",
163 ignorePrivateChannels = true,
164 force,
165 moderator,
166 reason
167 }: ChannelLockOptions & { force?: boolean }
168 ) {
169 let countSuccess = 0,
170 countFailed = 0,
171 countSkipped = 0,
172 countInvalidChannel = 0;
173
174 const originalPermissions = force
175 ? guild.channels.cache.map(c => ({ channel_id: c.id, permissions: {}, id: 0 }))
176 : await this.client.prisma.channelLock.findMany({
177 where: {
178 guild_id: guild.id
179 }
180 });
181
182 for (const originalPermission of originalPermissions) {
183 const channel = guild.channels.cache.get(originalPermission.channel_id);
184
185 if (!channel) continue;
186
187 if (
188 !this.shouldLock(channels, channel, channelMode) ||
189 ![
190 ChannelType.GuildAnnouncement,
191 ChannelType.GuildCategory,
192 ChannelType.GuildText,
193 ChannelType.GuildVoice,
194 ChannelType.GuildStageVoice,
195 ChannelType.GuildForum
196 ].includes(channel.type)
197 ) {
198 countInvalidChannel++;
199 continue;
200 }
201
202 try {
203 const options = {
204 Connect: force ? true : (originalPermission.permissions! as PermissionFlags).Connect,
205 SendMessages: force ? true : (originalPermission.permissions! as PermissionFlags).SendMessages,
206 SendMessagesInThreads: force
207 ? true
208 : (originalPermission.permissions! as PermissionFlags).SendMessagesInThreads,
209 AddReactions: force ? true : (originalPermission.permissions! as PermissionFlags).AddReactions
210 };
211
212 const permissionOverwrites = (channel as TextChannel).permissionOverwrites?.cache.get(guild.id);
213
214 if (ignorePrivateChannels && !force) {
215 if (permissionOverwrites?.deny.has(PermissionFlagsBits.ViewChannel, true)) {
216 log("Private channel, skipping lock");
217 countSkipped++;
218 continue;
219 }
220 }
221
222 if (permissionOverwrites)
223 await (channel as TextChannel).permissionOverwrites?.edit(guild.id, options as PermissionOverwriteOptions);
224 else await (channel as TextChannel).permissionOverwrites?.create(guild.id, options as PermissionOverwriteOptions);
225
226 countSuccess++;
227 } catch (e) {
228 logError(e);
229 countFailed++;
230 }
231 }
232
233 log(originalPermissions);
234
235 if (!force)
236 await this.client.prisma.channelLock.deleteMany({
237 where: {
238 id: {
239 in: originalPermissions.map(permission => permission.id)
240 }
241 }
242 });
243
244 await this.client.loggerService.logServerLockOrUnlock({
245 guild,
246 action: "Unlocked",
247 moderator,
248 countSuccess,
249 countFailed,
250 countInvalidChannel,
251 countSkipped,
252 reason
253 });
254
255 return {
256 countSuccess,
257 countFailed,
258 countInvalidChannel,
259 countSkipped
260 };
261 }
262
263 async lock(channel: TextChannel, moderator: User, reason?: string) {
264 try {
265 const options = {
266 Connect: false,
267 SendMessages: false,
268 SendMessagesInThreads: false,
269 AddReactions: false
270 };
271
272 const permissionOverwrites = channel.permissionOverwrites?.cache.get(channel.guild.id);
273
274 const permissionJson = {
275 Connect: permissionOverwrites
276 ? getChannelPermissionOverride(PermissionFlagsBits.Connect, permissionOverwrites)
277 : null,
278 SendMessages: permissionOverwrites
279 ? getChannelPermissionOverride(PermissionFlagsBits.SendMessages, permissionOverwrites)
280 : null,
281 SendMessagesInThreads: permissionOverwrites
282 ? getChannelPermissionOverride(PermissionFlagsBits.SendMessagesInThreads, permissionOverwrites)
283 : null,
284 AddReactions: permissionOverwrites
285 ? getChannelPermissionOverride(PermissionFlagsBits.AddReactions, permissionOverwrites)
286 : null
287 };
288
289 if (permissionOverwrites) await channel.permissionOverwrites?.edit(channel.guild.id, options);
290 else await channel.permissionOverwrites?.create(channel.guild.id, options);
291
292 this.client.loggerService
293 .logChannelLockOrUnlock({
294 guild: channel.guild,
295 action: "Locked",
296 channel,
297 moderator,
298 reason
299 })
300 .catch(logError);
301
302 return await this.client.prisma.channelLock.create({
303 data: {
304 channel_id: channel.id,
305 guild_id: channel.guild.id,
306 permissions: permissionJson
307 }
308 });
309 } catch (e) {
310 logError(e);
311 return null;
312 }
313 }
314
315 async unlock(channel: TextChannel, moderator: User, reason?: string, force?: boolean) {
316 try {
317 const channelLock = await this.client.prisma.channelLock.findFirst({
318 where: {
319 channel_id: channel.id,
320 guild_id: channel.guild.id
321 }
322 });
323
324 if (!channelLock) return null;
325
326 const options = {
327 Connect: force ? true : (channelLock.permissions as unknown as PermissionFlags).Connect,
328 SendMessages: force ? true : (channelLock.permissions as unknown as PermissionFlags).SendMessages,
329 SendMessagesInThreads: force
330 ? true
331 : (channelLock.permissions as unknown as PermissionFlags).SendMessagesInThreads,
332 AddReactions: force ? true : (channelLock.permissions as unknown as PermissionFlags).AddReactions
333 };
334
335 const permissionOverwrites = channel.permissionOverwrites?.cache.get(channel.guild.id);
336
337 if (permissionOverwrites)
338 await channel.permissionOverwrites?.edit(channel.guild.id, options as PermissionOverwriteOptions);
339 else await channel.permissionOverwrites?.create(channel.guild.id, options as PermissionOverwriteOptions);
340
341 this.client.loggerService
342 .logChannelLockOrUnlock({
343 guild: channel.guild,
344 action: "Unlocked",
345 channel,
346 moderator,
347 reason
348 })
349 .catch(logError);
350
351 return true;
352 } catch (e) {
353 logError(e);
354 return false;
355 }
356 }
357 }

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26