Skip to content

Commit 9b18235

Browse files
committed
Re-add automatic dynamic permission overwrite when mod joins voice channel
1 parent fe49045 commit 9b18235

1 file changed

Lines changed: 94 additions & 0 deletions

File tree

src/modules/tccpp/components/permissions-manager.ts

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import SkillRoles from "./skill-roles.js";
1515
import { named_id } from "../../../channel-map.js";
1616
import { unwrap } from "../../../utils/misc.js";
1717
import { CommandSetBuilder } from "../../../command-abstractions/command-set-builder.js";
18+
import { channel_has_member_with_role } from "../../../utils/discord.js";
1819
import { set_timeout } from "../../../utils/node.js";
1920

2021
const categories_map = {
@@ -104,6 +105,7 @@ export default class PermissionManager extends BotComponent {
104105

105106
category_permissions: Partial<Record<string, permission_overwrites>> = {};
106107
channel_overwrites: Partial<Record<string, permission_overwrites>> = {};
108+
dynamic_channel_overwrites: Partial<Record<string, permission_overwrites>> = {};
107109

108110
override async setup(commands: CommandSetBuilder) {
109111
await this.channels.resolve();
@@ -471,6 +473,11 @@ export default class PermissionManager extends BotComponent {
471473
}
472474

473475
async sync_channel_permissions(channel: Discord.CategoryChildChannel) {
476+
if (channel.id in this.dynamic_channel_overwrites) {
477+
M.log(`Setting dynamic permissions for channel ${channel.id} ${channel.name}`);
478+
await this.set_channel_permissions(channel, unwrap(this.dynamic_channel_overwrites[channel.id]));
479+
return;
480+
}
474481
if (channel.id in this.channel_overwrites) {
475482
M.log(`Setting permissions for channel ${channel.id} ${channel.name}`);
476483
await this.set_channel_permissions(channel, unwrap(this.channel_overwrites[channel.id]));
@@ -487,6 +494,14 @@ export default class PermissionManager extends BotComponent {
487494
);
488495
for (const channel of category.children.cache.values()) {
489496
await this.sync_channel_permissions(channel);
497+
if (channel.isVoiceBased()) {
498+
for (const [id, member] of channel.members) {
499+
if (await this.wheatley.check_permissions(member, Discord.PermissionFlagsBits.MuteMembers)) {
500+
await this.mod_has_entered_the_building(channel, member.id);
501+
break;
502+
}
503+
}
504+
}
490505
}
491506
}
492507

@@ -506,4 +521,83 @@ export default class PermissionManager extends BotComponent {
506521
this.sync_permissions().catch(this.wheatley.critical_error.bind(this.wheatley));
507522
}, HOUR);
508523
}
524+
525+
private get_base_permissions(
526+
channel: Discord.VoiceChannel | Discord.StageChannel,
527+
): permission_overwrites | undefined {
528+
if (this.channel_overwrites[channel.id] != null) {
529+
return this.channel_overwrites[channel.id];
530+
}
531+
if (channel.parent != null) {
532+
return this.category_permissions[channel.parent.id];
533+
}
534+
return undefined;
535+
}
536+
537+
private has_moderator_in_channel(channel: Discord.VoiceChannel | Discord.StageChannel): boolean {
538+
return channel.members.some(member => member.permissions.has(Discord.PermissionFlagsBits.MuteMembers));
539+
}
540+
541+
private async mod_has_entered_the_building(
542+
channel: Discord.VoiceChannel | Discord.StageChannel,
543+
entering_moderator_id: string,
544+
) {
545+
if (channel.id in this.dynamic_channel_overwrites || channel.id == this.wheatley.guild.afkChannelId) {
546+
return;
547+
}
548+
const everyone = this.wheatley.guild.roles.everyone.id;
549+
const base_perms = this.get_base_permissions(channel);
550+
if (
551+
!base_perms ||
552+
!base_perms[everyone] ||
553+
!base_perms[everyone].deny ||
554+
!base_perms[everyone].deny.includes(Discord.PermissionsBitField.Flags.Speak) ||
555+
!base_perms[everyone].deny.includes(Discord.PermissionsBitField.Flags.Stream)
556+
) {
557+
return;
558+
}
559+
if (channel_has_member_with_role(channel, this.roles.voice_moderator.id, entering_moderator_id)) {
560+
return;
561+
}
562+
const perms = Object.assign({}, base_perms);
563+
perms[everyone] = {
564+
allow: [
565+
Discord.PermissionsBitField.Flags.Speak,
566+
Discord.PermissionsBitField.Flags.Stream,
567+
...(perms[everyone]?.allow ?? []),
568+
],
569+
deny: perms[everyone]?.deny,
570+
};
571+
this.dynamic_channel_overwrites[channel.id] = perms;
572+
await this.sync_channel_permissions(channel);
573+
}
574+
575+
private async mod_has_left_the_building(channel: Discord.VoiceChannel | Discord.StageChannel) {
576+
if (!(channel.id in this.dynamic_channel_overwrites)) {
577+
return;
578+
}
579+
if (this.has_moderator_in_channel(channel)) {
580+
return;
581+
}
582+
delete this.dynamic_channel_overwrites[channel.id];
583+
await this.sync_channel_permissions(channel);
584+
}
585+
586+
override async on_voice_state_update(old_state: Discord.VoiceState, new_state: Discord.VoiceState) {
587+
if (new_state.guild.id !== this.wheatley.guild.id) {
588+
return;
589+
}
590+
if (
591+
new_state.member &&
592+
new_state.member.permissions.has(Discord.PermissionFlagsBits.MuteMembers) &&
593+
new_state.channelId != old_state.channelId
594+
) {
595+
if (old_state.channel) {
596+
await this.mod_has_left_the_building(old_state.channel);
597+
}
598+
if (new_state.channel) {
599+
await this.mod_has_entered_the_building(new_state.channel, new_state.member.id);
600+
}
601+
}
602+
}
509603
}

0 commit comments

Comments
 (0)