/**
 * @name VoiceChatUtilities
 * @author Ahlawat
 * @authorId 1025214794766221384
 * @version 1.3.0
 * @invite SgKSKyh9gY
 * @description Useful voice chat utilities for server administrators.
 * @website https://tharki-god.github.io/
 * @source https://github.com/Tharki-God/BetterDiscordPlugins
 * @updateUrl https://tharki-god.github.io/BetterDiscordPlugins/VoiceChatUtilities.plugin.js
 */
/*@cc_on
@if (@_jscript)
var shell = WScript.CreateObject("WScript.Shell");
var fs = new ActiveXObject("Scripting.FileSystemObject");
var pathPlugins = shell.ExpandEnvironmentStrings("%APPDATA%\\BetterDiscord\\plugins");
var pathSelf = WScript.ScriptFullName;
shell.Popup("It looks like you've mistakenly tried to run me directly. \n(Don't do that!)", 0, "I'm a plugin for BetterDiscord", 0x30);
if (fs.GetParentFolderName(pathSelf) === fs.GetAbsolutePathName(pathPlugins)) {
shell.Popup("I'm in the correct folder already.", 0, "I'm already installed", 0x40);
} else if (!fs.FolderExists(pathPlugins)) {
shell.Popup("I can't find the BetterDiscord plugins folder.\nAre you sure it's even installed?", 0, "Can't install myself", 0x10);
} else if (shell.Popup("Should I move myself to BetterDiscord's plugins folder for you?", 0, "Do you need some help?", 0x34) === 6) {
fs.MoveFile(pathSelf, fs.BuildPath(pathPlugins, fs.GetFileName(pathSelf)));
shell.Exec("explorer " + pathPlugins);
shell.Popup("I'm installed!", 0, "Successfully installed", 0x40);
}
WScript.Quit();
@else@*/
module.exports = (() => {
  const config = {
    info: {
      name: "VoiceChatUtilities",
      authors: [
        {
          name: "Ahlawat",
          discord_id: "1025214794766221384",
          github_username: "Tharki-God",
        }
      ],
      version: "1.3.0",
      description: "Useful voice chat utilities for server administrators.",
      github: "https://github.com/Tharki-God/BetterDiscordPlugins",
      github_raw:
        "https://tharki-god.github.io/BetterDiscordPlugins/VoiceChatUtilities.plugin.js",
    },
    changelog: [
      {
        title: "v0.0.1",
        items: ["Idea in mind"],
      },
      {
        title: "v0.0.5",
        items: ["Base Model"],
      },
      {
        title: "Initial Release v1.0.0",
        items: [
          "This is the initial release of the plugin :)",
          "Fuck me, This took time but was worth it.",
          "Well Now Do it in mass (●ˇ∀ˇ●)",
        ],
      },
      {
        title: "v1.0.1",
        items: ["Bug Fixes"],
      },
      {
        title: "v1.0.2",
        items: ["Added Icons", "Refractor", "Beautify"],
      },
      {
        title: "v1.0.4",
        items: ["Added More Options"],
      },
      {
        title: "v1.0.5",
        items: ["Made it Toogleable"],
      },
      {
        title: "v1.2.1",
        items: ["Corrected text."],
      },
    ],
    main: "VoiceChatUtilities.plugin.js",
  };
  const RequiredLibs = [{
    window: "ZeresPluginLibrary",
    filename: "0PluginLibrary.plugin.js",
    external: "https://rauenzi.github.io/BDPluginLibrary/release/0PluginLibrary.plugin.js",
    downloadUrl: "https://rauenzi.github.io/BDPluginLibrary/release/0PluginLibrary.plugin.js"
  },
  {
    window: "BunnyLib",
    filename: "1BunnyLib.plugin.js",
    external: "https://github.com/Tharki-God/BetterDiscordPlugins",
    downloadUrl: "https://tharki-god.github.io/BetterDiscordPlugins/1BunnyLib.plugin.js"
  },
  ];
  class handleMissingLibrarys {
    load() {
      for (const Lib of RequiredLibs.filter(lib => !window.hasOwnProperty(lib.window)))
        BdApi.showConfirmationModal(
          "Library Missing",
          `The library plugin (${Lib.window}) needed for ${config.info.name} is missing. Please click Download Now to install it.`,
          {
            confirmText: "Download Now",
            cancelText: "Cancel",
            onConfirm: () => this.downloadLib(Lib),
          }
        );
    }
    async downloadLib(Lib) {
      const fs = require("fs");
      const path = require("path");
      const { Plugins } = BdApi;
      const LibFetch = await fetch(
        Lib.downloadUrl
      );
      if (!LibFetch.ok) return this.errorDownloadLib(Lib);
      const LibContent = await LibFetch.text();
      try {
        await fs.writeFile(
          path.join(Plugins.folder, Lib.filename),
          LibContent,
          (err) => {
            if (err) return this.errorDownloadLib(Lib);
          }
        );
      } catch (err) {
        return this.errorDownloadLib(Lib);
      }
    }
    errorDownloadZLib(Lib) {
      const { shell } = require("electron");
      BdApi.showConfirmationModal(
        "Error Downloading",
        [
          `${Lib.window} download failed. Manually install plugin library from the link below.`,
        ],
        {
          confirmText: "Download",
          cancelText: "Cancel",
          onConfirm: () => {
            shell.openExternal(
              Lib.external
            );
          },
        }
      );
    }
    start() { }
    stop() { }
  }
  return RequiredLibs.some(m => !window.hasOwnProperty(m.window))
    ? handleMissingLibrarys
    : (([Plugin, ZLibrary]) => {
      const {
        PluginUpdater,
        Logger,
        Utilities,
        Settings: { SettingPanel, Slider, Switch },
        DiscordModules: {
          UserStore,
          GuildChannelsStore,
          ChannelStore,
          SelectedChannelStore,
        },
      } = ZLibrary;
      const { ContextMenu } = BdApi;
      const {
        LibraryIcons,
        LibraryUtils,
        LibraryModules: {
          DiscordNative: { clipboard },
          RequestsUtils,
          SortedVoiceStateStore,
          DiscordConstants,
          ChannelPermissionStore
        } } = BunnyLib.build(config);
      const defaultSettings = {
        BulkActionsdelay: 0.25,
        voicechatcopyids: true,
        exceptSelf: false,
        fastMove: true,
      };
      return class VoiceChatUtilities extends Plugin {
        constructor() {
          super();
          this.settings = Utilities.loadData(
            config.info.name,
            "settings",
            defaultSettings
          );
          this.addVCUtils = this.addVCUtils.bind(this);
        }
        checkForUpdates() {
          try {
            PluginUpdater.checkForUpdate(
              config.info.name,
              config.info.version,
              config.info.github_raw
            );
          } catch (err) {
            Logger.err("Plugin Updater could not be reached.", err);
          }
        }
        onStart() {
          this.checkForUpdates();
          ContextMenu.patch("channel-context", this.addVCUtils)
        }

        addVCUtils(menu, { channel }) {
          menu.props.children = [...menu.props.children, this.moveAll(channel), this.massUtils(channel)];

        }
        moveAll(channel) {
          const currentChannel = this.getVoiceChannel();
          const ChannelMembers = currentChannel?.members;
          if (
            !currentChannel ||
            !this.settings["fastMove"] ||
            channel.type !== 2 ||
            currentChannel.channel.guild_id !== channel.guild_id ||
            ChannelMembers < 1 ||
            ChannelMembers.length == 1 ||
            currentChannel.channel.id == channel.id ||
            !ChannelPermissionStore.can(
              DiscordConstants.Plq.MOVE_MEMBERS,
              channel
            ) ||
            !ChannelPermissionStore.can(
              DiscordConstants.Plq.CONNECT,
              channel
            )
          ) return;
          return ContextMenu.buildItem({
            label: "Fast Move",
            id: "fast-move",
            action: async () => {
              for (const member of ChannelMembers) {
                RequestsUtils.patch({
                  url: DiscordConstants.ANM.GUILD_MEMBER(channel.guild_id, member),
                  body: {
                    channel_id: channel.id,
                  },
                });
                if (this.settings["BulkActionsdelay"] != 0)
                  await LibraryUtils.Sleep(this.settings["BulkActionsdelay"]);
              }
            },
          });
        }
        massUtils(channel) {
          if (channel.type !== 2) return;
          const children = [];
          const User = UserStore.getCurrentUser();
          const currentChannel = this.getVoiceChannel();
          const ChannelMembers =
            currentChannel?.channel.id === channel.id
              ? currentChannel?.members
              : this.getVoiceChannelMembers(channel?.guild_id, channel.id);
          const voiceChannels = GuildChannelsStore.getChannels(
            channel?.guild_id
          ).VOCAL.map(({ channel }) => channel);
          if (ChannelMembers < 1 || ChannelMembers.length == 1) return;
          let exceptSelf =
            this.settings["exceptSelf"] &&
            SelectedChannelStore.getVoiceChannelId() == channel.id;
          if (this.settings["voicechatcopyids"]) {
            children.push({
              id: "copy-all-vc-members",
              label: "Copy All User IDs",
              icon: () => LibraryIcons.MassCopy("18", "18"),
              action: async () => {
                clipboard.copy(ChannelMembers.join(",\n"));
              },
            });
          }
          if (
            ChannelPermissionStore.can(
              DiscordConstants.Plq.MOVE_MEMBERS,
              channel
            )
          ) {
            children.push({
              id: "disconnect-all-vc",
              label: "Disconnect All",
              icon: () => LibraryIcons.Disconnect("18", "18"),
              action: async () => {
                for (const member of ChannelMembers) {
                  RequestsUtils.patch({
                    url: DiscordConstants.ANM.GUILD_MEMBER(channel.guild_id, member),
                    body: {
                      channel_id: null,
                    },
                  });
                  if (this.settings["BulkActionsdelay"] != 0)
                    await LibraryUtils.Sleep(this.settings["BulkActionsdelay"]);
                }
              },
            });
            if (exceptSelf)
              children.push({
                id: "disconnect-all-vc-except-self",
                label: "Disconnect All Except Self",
                icon: () => LibraryIcons.Disconnect("18", "18"),
                action: async () => {
                  for (const member of ChannelMembers) {
                    if (member == User.id) continue;
                    RequestsUtils.patch({
                      url: DiscordConstants.ANM.GUILD_MEMBER(channel.guild_id, member),
                      body: {
                        channel_id: null,
                      },
                    });
                    if (this.settings["BulkActionsdelay"] != 0)
                      await LibraryUtils.Sleep(this.settings["BulkActionsdelay"]);
                  }
                },
              });
            children.push({
              type: "submenu",
              id: "move-all-vc",
              label: "Move All",
              items: this.getMoveableChannels(
                channel,
                voiceChannels,
                ChannelMembers,
                false
              ),
            });
            if (exceptSelf)
              children.push({
                type: "submenu",
                id: "move-all-vc-except-self",
                label: "Move All Except Self",
                items: this.getMoveableChannels(
                  channel,
                  voiceChannels,
                  ChannelMembers,
                  User
                ),
              });
          }
          if (
            ChannelPermissionStore.can(
              DiscordConstants.Plq.MUTE_MEMBERS,
              channel
            )
          ) {
            children.push({
              id: "mute-all-vc",
              label: "Mute All",
              icon: () => LibraryIcons.Mute("18", "18"),
              action: async () => {
                for (const member of ChannelMembers) {
                  RequestsUtils.patch({
                    url: DiscordConstants.ANM.GUILD_MEMBER(channel.guild_id, member),
                    body: {
                      mute: true,
                    },
                  });
                  if (this.settings["BulkActionsdelay"] != 0)
                    await LibraryUtils.Sleep(this.settings["BulkActionsdelay"]);
                }
              },
            });
            if (exceptSelf)
              children.push({
                id: "mute-all-vc-except-self",
                label: "Mute All Except Self",
                icon: () => LibraryIcons.Mute("18", "18"),
                action: async () => {
                  for (const member of ChannelMembers) {
                    if (member == User.id) continue;
                    RequestsUtils.patch({
                      url: DiscordConstants.ANM.GUILD_MEMBER(channel.guild_id, member),
                      body: {
                        mute: true,
                      },
                    });
                    if (this.settings["BulkActionsdelay"] != 0)
                      await LibraryUtils.Sleep(this.settings["BulkActionsdelay"]);
                  }
                },
              });
            children.push({
              id: "unmute-all-vc",
              label: "Unmute All",
              icon: () => LibraryIcons.Unmute("18", "18"),
              action: async () => {
                for (const member of ChannelMembers) {
                  RequestsUtils.patch({
                    url: DiscordConstants.ANM.GUILD_MEMBER(channel.guild_id, member),
                    body: {
                      mute: false,
                    },
                  });
                  if (this.settings["BulkActionsdelay"] != 0)
                    await LibraryUtils.Sleep(this.settings["BulkActionsdelay"]);
                }
              },
            });
            if (exceptSelf)
              children.push({
                id: "unmute-all-vc-except-self",
                label: "Unmute All Except Self",
                icon: () => LibraryIcons.Unmute("18", "18"),
                action: async () => {
                  for (const member of ChannelMembers) {
                    if (member == User.id) continue;
                    RequestsUtils.patch({
                      url: DiscordConstants.ANM.GUILD_MEMBER(channel.guild_id, member),
                      body: {
                        mute: false,
                      },
                    });
                    if (this.settings["BulkActionsdelay"] != 0)
                      await LibraryUtils.Sleep(this.settings["BulkActionsdelay"]);
                  }
                },
              });
          }
          if (
            ChannelPermissionStore.can(
              DiscordConstants.Plq.DEAFEN_MEMBERS,
              channel
            )
          ) {
            children.push({
              id: "defen-all-vc",
              label: "Deafen All",
              icon: () => LibraryIcons.Deaf("18", "18"),
              action: async () => {
                for (const member of ChannelMembers) {
                  RequestsUtils.patch({
                    url: DiscordConstants.ANM.GUILD_MEMBER(channel.guild_id, member),
                    body: {
                      deaf: true,
                    },
                  });
                  if (this.settings["BulkActionsdelay"] != 0)
                    await LibraryUtils.Sleep(this.settings["BulkActionsdelay"]);
                }
              },
            });

            if (exceptSelf)
              children.push({
                id: "deafen-all-vc-except-self",
                label: "Deafen All Except Self",
                icon: () => LibraryIcons.Deaf("18", "18"),
                action: async () => {
                  for (const member of ChannelMembers) {
                    if (member == User.id) continue;
                    RequestsUtils.patch({
                      url: DiscordConstants.ANM.GUILD_MEMBER(channel.guild_id, member),
                      body: {
                        deaf: true,
                      },
                    });
                    if (this.settings["BulkActionsdelay"] != 0)
                      await LibraryUtils.Sleep(this.settings["BulkActionsdelay"]);
                  }
                },
              });
            children.push({
              id: "undeafen-all-vc",
              label: "Undeafen All",
              icon: () => LibraryIcons.Undeaf("18", "18"),
              action: async () => {
                for (const member of ChannelMembers) {
                  RequestsUtils.patch({
                    url: DiscordConstants.ANM.GUILD_MEMBER(channel.guild_id, member),
                    body: {
                      deaf: false,
                    },
                  });
                  if (this.settings["BulkActionsdelay"] != 0)
                    await LibraryUtils.Sleep(this.settings["BulkActionsdelay"]);
                }
              },
            });
            if (exceptSelf)
              children.push({
                id: "undeafen-all-vc-except-self",
                label: "Undeafen All Except Self",
                icon: () => LibraryIcons.Undeaf("18", "18"),
                action: async () => {
                  for (const member of ChannelMembers) {
                    if (member == User.id) continue;
                    RequestsUtils.patch({
                      url: DiscordConstants.ANM.GUILD_MEMBER(channel.guild_id, member),
                      body: {
                        deaf: false,
                      },
                    });
                    if (this.settings["BulkActionsdelay"] != 0)
                      await LibraryUtils.Sleep(this.settings["BulkActionsdelay"]);
                  }
                },
              });
          }
          if (!children?.length) return;
          return ContextMenu.buildItem(
            {
              type: "submenu",
              label: "Mass VC Utilities",
              id: "mass-vc-utilities",
              action: () => {
                Logger.info(`Teri Mummy Meri Hoja ${User.username}`); //what
              },
              items: children,
            },
          );
        }
        getMoveableChannels(channel, voiceChannels, ChannelMembers, User) {
          voiceChannels = voiceChannels.filter(
            (vc) =>
              vc.id !== channel.id &&
              ChannelPermissionStore.can(
                DiscordConstants.Plq.CONNECT,
                vc
              )
          );
          if (!voiceChannels.length)
            return [{
              label: "No VC Available",
              id: "no-vc",
              icon: () => LibraryIcons.NoVC("18", "18"),
              action: () => {
                Logger.info(`Teri Mummy Meri Hoja ${User.username}`); //what
              },
            }];
          return voiceChannels.map((channel) => {
            return {
              label: channel.name,
              id: channel.id,
              icon: () => LibraryIcons.VC("18", "18"),
              action: async () => {
                for (const member of ChannelMembers) {
                  if (member == User?.id) continue;
                  RequestsUtils.patch({
                    url: DiscordConstants.ANM.GUILD_MEMBER(channel.guild_id, member),
                    body: {
                      channel_id: channel.id,
                    },
                  });
                  if (this.settings["BulkActionsdelay"] != 0)
                    await LibraryUtils.Sleep(this.settings["BulkActionsdelay"]);
                }
              },
            };
          });

        }
        getVoiceUserIds(guildId, channelId) {
          return Object.values(SortedVoiceStateStore.getVoiceStatesForChannel({ getGuildId: () => guildId, id: channelId })).map(m => m.user.id);
        }
        getVoiceChannelMembers(channel) {
          return this.getVoiceUserIds(channel?.guild_id, channel?.id);
        }
        getVoiceChannel() {
          let channel = ChannelStore.getChannel(
            SelectedChannelStore.getVoiceChannelId()
          );
          if (!channel) return;
          return {
            channel: channel,
            members: this.getVoiceChannelMembers(channel),
          };
        }
        stop() {
          ContextMenu.unpatch("channel-context", this.addVCUtils)
        }
        getSettingsPanel() {
          return SettingPanel.build(
            this.saveSettings.bind(this),
            new Slider(
              "Bulk actions delay, in seconds",
              "Making it 0 makes all of the actions happen simultaneously. It might be cool, but can get you banned due to selfbotting. Higher value means lower risk of getting banned.",
              0,
              1,
              this.settings["BulkActionsdelay"],
              (e) => {
                this.settings["BulkActionsdelay"] = e;
              },
              {
                onValueRender: (value) => {
                  const seconds = value / 1000;
                  const minutes = value / 1000 / 60;
                  return value < 60000
                    ? `${seconds.toFixed(0)} secs`
                    : `${minutes.toFixed(0)} min`;
                },
              }
            ),
            new Switch(
              "Show option to copy all user IDs",
              "Whether or not to show the button to copy the user IDs of all participants.",
              this.settings["voicechatcopyids"],
              (e) => {
                this.settings["voicechatcopyids"] = e;
              }
            ),
            new Switch(
              "Except Self",
              "Whether or not to show an array of options that allow you to execute a task on everyone in the voice channel except yourself.",
              this.settings["exceptSelf"],
              (e) => {
                this.settings["exceptSelf"] = e;
              }
            ),
            new Switch(
              "Fast Move",
              "Whether or not to show an option to move to the selected voice channel from your current voice channel.",
              this.settings["fastMove"],
              (e) => {
                this.settings["fastMove"] = e;
              }
            )
          );
        }
        saveSettings() {
          Utilities.saveData(config.info.name, "settings", this.settings);
        }
      };
    })(ZLibrary.buildPlugin(config));
})();
/*@end@*/