-
Notifications
You must be signed in to change notification settings - Fork 2
/
index.tsx
171 lines (145 loc) · 5.43 KB
/
index.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
/*
* Vencord, a Discord client mod
* Copyright (c) 2024 Vendicated and contributors
* SPDX-License-Identifier: GPL-3.0-or-later
*/
import { NavContextMenuPatchCallback } from "@api/ContextMenu";
import { definePluginSettings } from "@api/Settings";
import { makeRange } from "@components/PluginSettings/components";
import { Devs } from "@utils/constants";
import definePlugin, { OptionType } from "@utils/types";
import { findStoreLazy } from "@webpack";
import { GuildChannelStore, Menu, React, RestAPI, UserStore } from "@webpack/common";
import type { Channel } from "discord-types/general";
const VoiceStateStore = findStoreLazy("VoiceStateStore");
async function runSequential<T>(promises: Promise<T>[]): Promise<T[]> {
const results: T[] = [];
for (let i = 0; i < promises.length; i++) {
const promise = promises[i];
const result = await promise;
results.push(result);
if (i % settings.store.waitAfter === 0) {
await new Promise(resolve => setTimeout(resolve, settings.store.waitSeconds * 1000));
}
}
return results;
}
function sendPatch(channel: Channel, body: Record<string, any>, bypass = false) {
const usersVoice = VoiceStateStore.getVoiceStatesForChannel(channel.id); // Get voice states by channel id
const myId = UserStore.getCurrentUser().id; // Get my user id
const promises: Promise<any>[] = [];
Object.keys(usersVoice).forEach((key, index) => {
const userVoice = usersVoice[key];
if (bypass || userVoice.userId !== myId) {
promises.push(RestAPI.patch({
url: `/guilds/${channel.guild_id}/members/${userVoice.userId}`,
body: body
}));
}
});
runSequential(promises).catch(error => {
console.error("VoiceChatUtilities failed to run", error);
});
}
interface VoiceChannelContextProps {
channel: Channel;
}
const VoiceChannelContext: NavContextMenuPatchCallback = (children, { channel }: VoiceChannelContextProps) => {
// only for voice and stage channels
if (!channel || (channel.type !== 2 && channel.type !== 13)) return;
const userCount = Object.keys(VoiceStateStore.getVoiceStatesForChannel(channel.id)).length;
if (userCount === 0) return;
const guildChannels: { VOCAL: { channel: Channel, comparator: number }[] } = GuildChannelStore.getChannels(channel.guild_id);
const voiceChannels = guildChannels.VOCAL.map(({ channel }) => channel).filter(({ id }) => id !== channel.id);
children.splice(
-1,
0,
<Menu.MenuItem
label="Voice Tools"
key="voice-tools"
id="voice-tools"
>
<Menu.MenuItem
key="voice-tools-disconnect-all"
id="voice-tools-disconnect-all"
label="Disconnect all"
action={() => sendPatch(channel, {
channel_id: null,
})}
/>
<Menu.MenuItem
key="voice-tools-mute-all"
id="voice-tools-mute-all"
label="Mute all"
action={() => sendPatch(channel, {
mute: true,
})}
/>
<Menu.MenuItem
key="voice-tools-unmute-all"
id="voice-tools-unmute-all"
label="Unmute all"
action={() => sendPatch(channel, {
mute: false,
})}
/>
<Menu.MenuItem
key="voice-tools-deafen-all"
id="voice-tools-deafen-all"
label="Deafen all"
action={() => sendPatch(channel, {
deaf: true,
})}
/>
<Menu.MenuItem
key="voice-tools-undeafen-all"
id="voice-tools-undeafen-all"
label="Undeafen all"
action={() => sendPatch(channel, {
deaf: false,
})}
/>
<Menu.MenuItem
label="Move all"
key="voice-tools-move-all"
id="voice-tools-move-all"
>
{voiceChannels.map(voiceChannel => {
return (
<Menu.MenuItem
key={voiceChannel.id}
id={voiceChannel.id}
label={voiceChannel.name}
action={() => sendPatch(channel, {
channel_id: voiceChannel.id,
}, true)}
/>
);
})}
</Menu.MenuItem>
</Menu.MenuItem>
);
};
const settings = definePluginSettings({
waitAfter: {
type: OptionType.SLIDER,
description: "Amount of API actions to perform before waiting (to avoid rate limits)",
default: 5,
markers: makeRange(1, 20),
},
waitSeconds: {
type: OptionType.SLIDER,
description: "Time to wait between each action (in seconds)",
default: 2,
markers: makeRange(1, 10, .5),
}
});
export default definePlugin({
name: "VoiceChatUtilities",
description: "This plugin allows you to perform multiple actions on an entire channel (move, mute, disconnect, etc.) (originally by dutake)",
authors: [Devs.D3SOX],
settings,
contextMenus: {
"channel-context": VoiceChannelContext
},
});