Merge branch 'dev'

This commit is contained in:
thororen1234 2026-04-16 12:05:11 -04:00
commit f4a22f5e05
No known key found for this signature in database
403 changed files with 3414 additions and 1006 deletions

View file

@ -1,7 +1,7 @@
{
"name": "equicord",
"private": "true",
"version": "1.14.6.2",
"version": "1.14.7.0",
"description": "The other cutest Discord client mod",
"homepage": "https://github.com/Equicord/Equicord#readme",
"bugs": {
@ -54,47 +54,47 @@
"gifenc": "github:mattdesl/gifenc#64842fca317b112a8590f8fef2bf3825da8f6fe3",
"idb": "8.0.3",
"jsqr": "1.4.0",
"monaco-editor": "^0.54.0",
"monaco-editor": "^0.55.1",
"nanoid": "^5.1.6",
"native-file-system-adapter": "^3.0.1",
"usercss-meta": "^0.12.0",
"virtual-merge": "^1.0.1"
"virtual-merge": "^1.0.1",
"yaml-js": "^0.3.1"
},
"devDependencies": {
"@electron/asar": "^4.0.1",
"@stylistic/eslint-plugin": "^5.6.0",
"@types/adm-zip": "^0.5.7",
"@types/chrome": "^0.1.30",
"@types/diff": "^7.0.2",
"@types/lodash": "^4.17.20",
"@types/node": "^24.10.1",
"@electron/asar": "^4.2.0",
"@stylistic/eslint-plugin": "^5.10.0",
"@types/chrome": "^0.1.40",
"@types/lodash": "^4.17.24",
"@types/node": "^25.6.0",
"@types/react": "^19.0.10",
"@types/react-dom": "^19.0.4",
"@types/yazl": "^3.3.0",
"@types/yazl": "^3.3.1",
"@vencord/discord-types": "link:packages/discord-types",
"diff": "^8.0.2",
"esbuild": "^0.27.0",
"eslint": "9.39.1",
"diff": "^9.0.0",
"esbuild": "^0.28.0",
"eslint": "10.2.0",
"eslint-import-resolver-alias": "^1.1.2",
"eslint-plugin-react": "^7.37.5",
"eslint-plugin-simple-header": "^1.2.1",
"eslint-plugin-simple-import-sort": "^12.1.1",
"eslint-plugin-unused-imports": "^4.3.0",
"eslint-plugin-simple-import-sort": "^13.0.0",
"eslint-plugin-unused-imports": "^4.4.1",
"highlight.js": "11.11.1",
"html-minifier-terser": "^7.2.0",
"moment": "^2.22.2",
"p-limit": "^7.3.0",
"puppeteer-core": "^24.30.0",
"standalone-electron-types": "^34.2.0",
"stylelint": "^16.25.0",
"stylelint-config-standard": "^39.0.1",
"puppeteer-core": "^24.41.0",
"standalone-electron-types": "^41.2.1",
"stylelint": "^17.8.0",
"stylelint-config-standard": "^40.0.0",
"svgo": "^4.0.1",
"ts-patch": "^3.3.0",
"ts-pattern": "^5.6.0",
"tsx": "^4.20.6",
"type-fest": "^5.2.0",
"typescript": "^5.9.3",
"typescript-eslint": "^8.47.0",
"typescript-transform-paths": "^3.5.5",
"ts-pattern": "^5.9.0",
"tsx": "^4.21.0",
"type-fest": "^5.5.0",
"typescript": "^6.0.2",
"typescript-eslint": "^8.58.2",
"typescript-transform-paths": "^3.5.6",
"zip-local": "^0.3.5"
},
"packageManager": "pnpm@10.33.0",
@ -125,4 +125,4 @@
"engines": {
"node": ">=18"
}
}
}

1857
pnpm-lock.yaml generated

File diff suppressed because it is too large Load diff

View file

@ -38,6 +38,7 @@ export interface PluginData {
name: string;
description: string;
tags: string[];
searchTerms: string[];
authors: Dev[];
dependencies: string[];
hasPatches: boolean;
@ -152,7 +153,8 @@ export async function parseFile(fileName: string) {
enabledByDefault: false,
required: false,
isModified: false,
tags: [] as string[]
tags: [] as string[],
searchTerms: [] as string[],
} as PluginData;
for (const prop of pluginObj.properties) {
@ -208,9 +210,10 @@ export async function parseFile(fileName: string) {
});
break;
case "tags":
if (!isArrayLiteralExpression(value)) throw fail("tags is not an array literal");
data.tags = value.elements.map(e => {
if (!isStringLiteral(e)) throw fail("tags array contains non-string literals");
case "searchTerms":
if (!isArrayLiteralExpression(value)) throw fail(`${key} is not an array literal`);
data[key] = value.elements.map(e => {
if (!isStringLiteral(e)) throw fail(`${key} array contains non-string literals`);
return e.text;
});
break;

View file

@ -4,7 +4,7 @@
* SPDX-License-Identifier: GPL-3.0-or-later
*/
import { findByCodeLazy, findLazy } from "webpack";
import { findByCodeLazy, findLazy } from "@webpack";
let defaultSounds: null | string[] = null;
const findDefaultSounds = findLazy(module => module.resolve && module.id && module.keys().some(key => key.endsWith(".mp3")), false);

View file

@ -28,6 +28,7 @@ import { addMessagePopoverButton, removeMessagePopoverButton } from "@api/Messag
import { addNicknameIcon, removeNicknameIcon } from "@api/NicknameIcons";
import { Settings, SettingsStore } from "@api/Settings";
import { disableStyle, enableStyle } from "@api/Styles";
import { traceFunction } from "@debug/Tracer";
import { Logger } from "@utils/Logger";
import { onlyOnce } from "@utils/onlyOnce";
import { canonicalizeFind, canonicalizeReplacement } from "@utils/patches";
@ -39,7 +40,6 @@ import { patches } from "@webpack/patcher";
import Plugins from "~plugins";
export { Plugins as plugins };
import { traceFunction } from "../debug/Tracer";
import { addAudioProcessor, removeAudioProcessor } from "./AudioPlayer";
import { addChannelToolbarButton, addHeaderBarButton, removeChannelToolbarButton, removeHeaderBarButton } from "./HeaderBar";
import { addProfileCollection, removeProfileCollection } from "./ProfileCollections";

View file

@ -16,13 +16,13 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import { React, TextInput } from "@webpack/common";
import { React, TextInput, useState } from "@webpack/common";
interface TextInputProps {
/**
* WARNING: Changing this between renders will have no effect!
*/
value: string;
initialValue: string;
/**
* This will only be called if the new value passed validate()
*/
@ -41,13 +41,15 @@ interface TextInputProps {
* A very simple wrapper around Discord's TextInput that validates input and shows
* the user an error message and only calls your onChange when the input is valid
*/
export function CheckedTextInput({ value: initialValue, onChange, validate, placeholder }: TextInputProps) {
const [value, setValue] = React.useState(initialValue);
const [error, setError] = React.useState<string>();
export function CheckedTextInput({ initialValue, onChange, validate, placeholder }: TextInputProps) {
const [value, setValue] = useState(initialValue);
const [error, setError] = useState<string>();
function handleChange(v: string) {
setValue(v);
const res = validate(v);
if (res === true) {
setError(void 0);
onChange(v);

View file

@ -9,6 +9,7 @@ import "./colorStyles.css";
import { classNameFactory } from "@utils/css";
import { findByCodeLazy } from "@webpack";
import { ColorPicker, useMemo } from "@webpack/common";
import type tinycolor from "tinycolor2";
// TinyColor is completely unmangled and it's duplicated in two modules! Fun!
const TinyColor: tinycolor.Constructor = findByCodeLazy("this._gradientType=");

View file

@ -6,13 +6,13 @@
import { showNotice } from "@api/Notices";
import { isPluginEnabled, pluginRequiresRestart, startDependenciesRecursive, startPlugin, stopPlugin } from "@api/PluginManager";
import { Settings } from "@api/Settings";
import { CogWheel, InfoIcon } from "@components/Icons";
import { AddonCard } from "@components/settings/AddonCard";
import { classNameFactory } from "@utils/css";
import { Logger } from "@utils/Logger";
import { OptionType, Plugin } from "@utils/types";
import { React, showToast, Toasts } from "@webpack/common";
import { Settings } from "Vencord";
import { PluginMeta } from "~plugins";

View file

@ -60,5 +60,25 @@
}
.vc-plugin-modal-info {
display: flex;
gap: 1em;
justify-content: space-between;
align-items: start;
}
.vc-plugin-modal-tags {
display: flex;
flex-wrap: wrap;
gap: 4px;
margin-block: 8px 16px;
}
.vc-plugin-modal-tag {
align-items: center;
}
border: 1px solid var(--border-normal);
border-radius: 9999px;
display: flex;
justify-content: center;
padding: 6px 12px;
color: var(--text-default);
}

View file

@ -32,7 +32,7 @@ import { proxyLazy } from "@utils/lazy";
import { Margins } from "@utils/margins";
import { classes, isObjectEmpty } from "@utils/misc";
import { ModalContent, ModalFooter, ModalHeader, ModalProps, ModalRoot, ModalSize, openModal } from "@utils/modal";
import { OptionType, Plugin } from "@utils/types";
import { OptionType, Plugin, PluginTag } from "@utils/types";
import { User } from "@vencord/discord-types";
import { findComponentByCodeLazy, findCssClassesLazy } from "@webpack";
import { Clickable, FluxDispatcher, React, Toasts, Tooltip, useEffect, useMemo, UserStore, UserSummaryItem, UserUtils, useState } from "@webpack/common";
@ -74,6 +74,16 @@ export function makeDummyUser(user: { username: string; id?: string; avatar?: st
return newUser;
}
function PluginTags({ tags }: { tags: PluginTag[]; }) {
return (
<div className={cl("tags")}>
{tags.map(tag => (
<div key={tag} className={cl("tag")}>{tag}</div>
))}
</div>
);
}
export default function PluginModal({ plugin, onRestartNeeded, onClose, transitionState }: PluginModalProps) {
const pluginSettings = useSettings([`plugins.${plugin.name}.*`]).plugins[plugin.name];
const hasSettings = Boolean(pluginSettings && plugin.options && !isObjectEmpty(plugin.options));
@ -167,6 +177,7 @@ export default function PluginModal({ plugin, onRestartNeeded, onClose, transiti
<div className={cl("header-content")}>
<BaseText size="lg" weight="semibold" className={cl("title")}>{plugin.name}</BaseText>
<BaseText size="sm" className={cl("description")}>{plugin.description}</BaseText>
{!!plugin.tags?.length && <PluginTags tags={plugin.tags} />}
{!!plugin.settingsAboutComponent && (
<div className={Margins.top8}>
<ErrorBoundary message="An error occurred while rendering this plugin's custom Info Component">

View file

@ -36,7 +36,8 @@ import { Logger } from "@utils/Logger";
import { Margins } from "@utils/margins";
import { classes } from "@utils/misc";
import { useAwaiter, useIntersection } from "@utils/react";
import { Alerts, lodash, Parser, React, Select, TextInput, Toasts, Tooltip, useCallback, useMemo, useState } from "@webpack/common";
import { PluginTag, PluginTags } from "@utils/types";
import { Alerts, lodash, Parser, React, SearchableSelect, Select, TextInput, Toasts, Tooltip, useCallback, useMemo, useRef, useState } from "@webpack/common";
import { JSX } from "react";
import Plugins, { ExcludedPlugins, PluginMeta } from "~plugins";
@ -143,7 +144,8 @@ function ExcludedPluginsList({ search }: { search: string; }) {
export default function PluginSettings() {
const settings = useSettings();
const changes = React.useMemo(() => new ChangeList<string>(), []);
const changeRef = useRef<ChangeList<string>>(null);
const changes = changeRef.current ??= new ChangeList<string>();
React.useEffect(() => {
return () => {
@ -194,25 +196,13 @@ export default function PluginSettings() {
const hasUserPlugins = useMemo(() => !IS_STANDALONE && Object.values(PluginMeta).some(m => m.userPlugin), []);
const [searchValue, setSearchValue] = useState({ value: "", status: SearchStatus.ALL });
const [searchInput, setSearchInput] = useState("");
const debouncedSetSearch = useMemo(
() => debounce((query: string) => setSearchValue(prev => ({ ...prev, value: query })), 150),
[]
);
const [searchValue, setSearchValue] = useState({ value: "", tags: [] as PluginTag[], status: SearchStatus.ALL });
const search = searchValue.value.toLowerCase();
const onSearch = useCallback((query: string) => {
setSearchInput(query);
debouncedSetSearch(query);
}, [debouncedSetSearch]);
const onStatusChange = useCallback((status: SearchStatus) => {
setSearchValue(prev => ({ ...prev, status }));
}, []);
const onSearch = (query: string) => setSearchValue(prev => ({ ...prev, value: query }));
const pluginFilter = useCallback((plugin: typeof Plugins[keyof typeof Plugins], newPluginsSet: Set<string> | null) => {
const { status } = searchValue;
const { status, tags } = searchValue;
const enabled = isPluginEnabled(plugin.name);
switch (status) {
@ -239,12 +229,14 @@ export default function PluginSettings() {
break;
}
if (tags.length && tags.some(t => !plugin.tags?.includes(t))) return false;
if (!search.length) return true;
return (
plugin.name.toLowerCase().includes(search.replace(/\s+/g, "")) ||
plugin.description.toLowerCase().includes(search) ||
plugin.tags?.some(t => t.toLowerCase().includes(search))
plugin.searchTerms?.some(t => t.toLowerCase().includes(search))
);
}, [searchValue, search]);
@ -406,31 +398,45 @@ export default function PluginSettings() {
Filters
</HeadingTertiary>
<div className={classes(Margins.bottom20, cl("filter-controls"))}>
<ErrorBoundary noop>
<TextInput autoFocus value={searchInput} placeholder="Search for a plugin..." onChange={onSearch} />
</ErrorBoundary>
<div>
<ErrorBoundary noop>
<Select
options={[
{ label: "Show All", value: SearchStatus.ALL, default: true },
{ label: "Show Enabled", value: SearchStatus.ENABLED },
{ label: "Show Disabled", value: SearchStatus.DISABLED },
{ label: "Show Equicord", value: SearchStatus.EQUICORD },
{ label: "Show Vencord", value: SearchStatus.VENCORD },
{ label: "Show New", value: SearchStatus.NEW },
hasUserPlugins && { label: "Show UserPlugins", value: SearchStatus.USER_PLUGINS },
{ label: "Show API Plugins", value: SearchStatus.API_PLUGINS },
].filter(isTruthy)}
serialize={String}
select={onStatusChange}
isSelected={v => v === searchValue.status}
closeOnSelect={true}
/>
</ErrorBoundary>
<ErrorBoundary noop>
<TextInput
inputClassName={cl("filter-control")}
placeholder="Search for a plugin..."
value={searchValue.value}
onChange={onSearch}
autoFocus
/>
</ErrorBoundary>
<ErrorBoundary noop>
<div className={classes(Margins.bottom20, Margins.top8, cl("filter-controls"))}>
<Select
options={[
{ label: "Show All", value: SearchStatus.ALL, default: true },
{ label: "Show Enabled", value: SearchStatus.ENABLED },
{ label: "Show Disabled", value: SearchStatus.DISABLED },
{ label: "Show Equicord", value: SearchStatus.EQUICORD },
{ label: "Show Vencord", value: SearchStatus.VENCORD },
{ label: "Show New", value: SearchStatus.NEW },
hasUserPlugins && { label: "Show UserPlugins", value: SearchStatus.USER_PLUGINS },
{ label: "Show API Plugins", value: SearchStatus.API_PLUGINS },
].filter(isTruthy)}
serialize={String}
select={status => setSearchValue(prev => ({ ...prev, status }))}
isSelected={v => v === searchValue.status}
closeOnSelect={true}
placeholder="Filter by Type"
/>
<SearchableSelect
options={PluginTags.map(tag => ({ label: tag, value: tag }))}
value={searchValue.tags}
onChange={tags => setSearchValue(prev => ({ ...prev, tags }))}
closeOnSelect={false}
placeholder="Filter by Tags"
multi
/>
</div>
</div>
</ErrorBoundary>
<HeadingTertiary className={Margins.top20}>Plugins</HeadingTertiary>
@ -456,6 +462,7 @@ export default function PluginSettings() {
<HeadingTertiary className={classes(Margins.top20, Margins.bottom8)}>
Required Plugins
</HeadingTertiary>
<div className={cl("grid")}>
{requiredPlugins.length
? requiredPlugins

View file

@ -45,7 +45,12 @@
display: grid;
height: 40px;
gap: 10px;
grid-template-columns: 1fr 150px;
grid-template-columns: 1fr 1fr;
align-items: center;
}
.vc-plugins-filter-control {
height: 40px;
}
.vc-plugins-dep-name {

View file

@ -137,7 +137,7 @@ function CloudTab() {
<div style={{ flex: 1 }}>
<CheckedTextInput
key={`backendUrl-${inputKey}`}
value={cloud.url}
initialValue={cloud.url}
onChange={async v => {
cloud.url = v;
cloud.authenticated = false;

View file

@ -20,6 +20,7 @@ import { Paragraph } from "@components/Paragraph";
import { openContributorModal, openPluginModal, SettingsTab, wrapTab } from "@components/settings";
import { QuickAction, QuickActionCard } from "@components/settings/QuickAction";
import { SpecialCard } from "@components/settings/SpecialCard";
import BadgeAPI from "@plugins/_api/badges";
import { gitRemote } from "@shared/vencordUserAgent";
import { DONOR_ROLE_ID, GUILD_ID, IS_MAC, IS_WINDOWS, VC_DONOR_ROLE_ID, VC_GUILD_ID } from "@utils/constants";
import { classNameFactory } from "@utils/css";
@ -27,7 +28,6 @@ import { Margins } from "@utils/margins";
import { identity, isAnyPluginDev } from "@utils/misc";
import { relaunch } from "@utils/native";
import { GuildMemberStore, React, Select, UserStore } from "@webpack/common";
import BadgeAPI from "plugins/_api/badges";
import { DonateButtonComponent } from "./DonateButton";
import { openNotificationSettingsModal } from "./NotificationSettings";

View file

@ -9,8 +9,8 @@ import { canonicalizeMatch } from "@utils/patches";
import { ModuleFactory } from "@vencord/discord-types/webpack";
import * as Webpack from "@webpack";
import { wreq } from "@webpack";
import { AnyModuleFactory } from "@webpack/types";
import pLimit from "p-limit";
import { AnyModuleFactory } from "webpack";
function getWebpackChunkMap() {
const sym = Symbol();

View file

@ -26,6 +26,7 @@ export interface ReporterData {
};
failedWebpack: Record<TypeWebpackSearchHistory, string[][]>;
}
export const reporterData: ReporterData = {
failedPatches: {
foundNoModule: [],

View file

@ -10,6 +10,7 @@ import definePlugin from "@utils/types";
export default definePlugin({
name: "AltKrispSwitch",
description: "Makes the Noise Suppression Popout switch between None and Krisp instead of Krisp and Standard",
tags: ["Customisation", "Voice"],
authors: [Devs.newwares],
patches: [
{

View file

@ -11,6 +11,7 @@ import definePlugin from "@utils/types";
export default definePlugin({
name: "AlwaysExpandProfiles",
description: "Always expands profile popouts to the full modal",
tags: ["Appearance", "Utility"],
authors: [Devs.thororen],
patches: [
{

View file

@ -193,6 +193,7 @@ async function playSound(buffer: AudioBuffer, volume: number) {
export default definePlugin({
name: "Animalese",
description: "Plays animal crossing animalese for every message sent (they yap a lot)",
tags: ["Customisation", "Fun"],
authors: [EquicordDevs.ryanamay, EquicordDevs.Mocha],
settings,

View file

@ -13,6 +13,7 @@ export default definePlugin({
name: "AtSomeone",
authors: [Devs.Joona],
description: "Mention someone randomly",
tags: ["Chat", "Fun"],
patches: [
{
find: ".LAUNCHABLE_APPLICATIONS;",

View file

@ -209,6 +209,7 @@ function handlePaste(event: ClipboardEvent) {
export default definePlugin({
name: "AutoZipper",
description: "Automatically zips specified file types and folders before uploading to Discord",
tags: ["Chat", "Organisation"],
authors: [EquicordDevs.SSnowly],
settings,

View file

@ -44,6 +44,7 @@ const DATASTORE_KEY = "bannersEverywhere";
export default definePlugin({
name: "BannersEverywhere",
description: "Displays banners in the member list ",
tags: ["Appearance", "Customisation"],
authors: [Devs.ImLvna, Devs.AutumnVN],
settings,
patches: [

View file

@ -107,6 +107,8 @@ const settings = definePluginSettings({
export default definePlugin({
name: "DecodeBase64",
description: "Decode base64 content of any message and copy the decoded content.",
dependencies: ["MessagePopoverAPI"],
tags: ["Appearance", "Customisation", "Chat"],
authors: [EquicordDevs.ThePirateStoner],
settings,
messagePopoverButton: {

View file

@ -20,7 +20,7 @@ export default definePlugin({
name: "BetterActivities",
description: "Shows activity icons in the member list and allows showing all activities",
authors: [Devs.D3SOX, Devs.Arjix, Devs.AutumnVN, Devs.thororen],
tags: ["activity"],
tags: ["Activity"],
settings,
patchActivityList,
showAllActivitiesComponent,

View file

@ -274,6 +274,7 @@ const settings = definePluginSettings({
export default definePlugin({
name: "BetterAudioPlayer",
description: "Adds a spectrograph and oscilloscope visualizer to audio attachment players.",
tags: ["Appearance", "Media", "Voice"],
authors: [EquicordDevs.creations],
settings,

View file

@ -74,6 +74,7 @@ const settings = definePluginSettings({
export default definePlugin({
name: "BetterBanReasons",
description: "Create custom reasons to use in the Discord ban modal, and/or show a text input by default instead of the options.",
tags: ["Appearance", "Customisation"],
authors: [Devs.Inbestigator],
patches: [
{

View file

@ -17,6 +17,7 @@ let updateFunc = (v: any) => { };
export default definePlugin({
name: "BetterBlockedUsers",
description: "Allows you to search in blocked users list and makes names selectable in settings.",
tags: ["Appearance", "Shortcuts"],
authors: [EquicordDevs.TheArmagan],
patches: [
{

View file

@ -33,6 +33,8 @@ function fetchIndex(target: object) {
export default definePlugin({
name: "BetterCommands",
description: "Enhances the command system with miscellaneous improvements.",
dependencies: ["CommandsAPI"],
tags: ["Appearance", "Commands", "Shortcuts"],
authors: [Devs.thororen],
settings,
patches: [

View file

@ -34,6 +34,7 @@ function lurk(id: string) {
export default definePlugin({
name: "BetterInvites",
description: "See invites expiration date, view inviter profile and preview servers before joining by clicking the name",
tags: ["Appearance", "Customisation", "Chat", "Servers"],
authors: [EquicordDevs.iamme, Devs.thororen],
patches: [
{

View file

@ -12,6 +12,7 @@ export default definePlugin({
name: "BetterPlusReacts",
authors: [Devs.Joona],
description: "The amount of plus before :emoji: is the message to add it to",
tags: ["Chat", "Emotes"],
patches: [
{
find: ".SLASH_COMMAND_USED,",

View file

@ -70,6 +70,7 @@ export function containsBlockedKeywords(message: Message) {
export default definePlugin({
name: "BlockKeywords",
description: "Blocks messages containing specific user-defined keywords, as if the user sending them was blocked.",
tags: ["Appearance", "Customisation", "Privacy"],
authors: [EquicordDevs.catcraft],
patches: [
{

View file

@ -10,6 +10,7 @@ import definePlugin from "@utils/types";
export default definePlugin({
name: "BlockKrisp",
description: "Prevent Krisp from loading",
tags: ["Privacy", "Utility", "Voice"],
authors: [Devs.D3SOX],
patches: [
// Block loading modules on Desktop

View file

@ -10,6 +10,7 @@ import definePlugin from "@utils/types";
export default definePlugin({
name: "BypassPinPrompt",
description: "Bypass the pin prompt when using the pin functions",
tags: ["Shortcuts"],
authors: [Devs.thororen],
patches: [
...[

View file

@ -157,6 +157,7 @@ const settings = definePluginSettings({
export default definePlugin({
name: "BypassStatus",
description: "Still get notifications from specific sources when in do not disturb mode. Right-click on users/channels/guilds to set them to bypass do not disturb mode.",
tags: ["Activity", "Customisation", "Notifications", "Servers"],
authors: [Devs.Inbestigator],
dependencies: ["AudioPlayerAPI"],
flux: {

View file

@ -32,6 +32,7 @@ function renderBadge(id: number, title: string) {
export default definePlugin({
name: "ChannelBadges",
description: "Adds badges to channels based on their type",
tags: ["Appearance", "Customisation", "Servers"],
authors: [EquicordDevs.creations, Devs.thororen],
settings,
patches: [

View file

@ -15,8 +15,8 @@ import { ChannelStore, Menu } from "@webpack/common";
import { JSX } from "react";
import ChannelsTabsContainer from "./components/ChannelTabsContainer";
import { BasicChannelTabsProps, createTab, handleChannelSwitch, settings } from "./util";
import * as ChannelTabsUtils from "./util";
import { BasicChannelTabsProps, createTab, handleChannelSwitch, settings } from "./util";
const contextMenuPatch: NavContextMenuPatchCallback = (children, props: { channel: Channel, messageId?: string; }) => {
const { channel, messageId } = props;
@ -47,6 +47,7 @@ const contextMenuPatch: NavContextMenuPatchCallback = (children, props: { channe
export default definePlugin({
name: "ChannelTabs",
description: "Group your commonly visited channels in tabs, like a browser",
tags: ["Appearance", "Customisation", "Organisation", "Servers"],
authors: [Devs.TheSun, Devs.TheKodeToad, EquicordDevs.keifufu, Devs.Nickyux, EquicordDevs.DiabeloDEV, EquicordDevs.justjxke],
dependencies: ["ContextMenuAPI"],
contextMenus: {

View file

@ -12,6 +12,7 @@ export default definePlugin({
name: "CleanChannelName",
authors: [Devs.AutumnVN],
description: "remove all emoji and decor shit from channel names",
tags: ["Appearance", "Customisation", "Chat", "Emotes", "Servers"],
patches: [
{
find: "loadAllGuildAndPrivateChannelsFromDisk(){",

View file

@ -10,6 +10,7 @@ import definePlugin from "@utils/types";
export default definePlugin({
name: "CleanerChannelGroups",
description: "Hides all channels in collapsed categories, even if they have unread messages.",
tags: ["Appearance", "Customisation", "Chat", "Organisation", "Servers"],
authors: [EquicordDevs.justjxke],
patches: [
{

View file

@ -146,6 +146,7 @@ const WrappedClickableRole = ErrorBoundary.wrap(ClickableRole, { noop: true });
export default definePlugin({
name: "ClickableRoles",
description: "Click on roles in user profiles and the member list to see which members have them.",
tags: ["Appearance", "Roles"],
authors: [Devs.prism],
patches: [

View file

@ -142,7 +142,8 @@ function activeNowView(cards) {
export default definePlugin({
name: "ClientSideBlock",
description: "Allows you to locally hide almost all content from any user",
tags: ["blocked", "block", "hide", "hidden", "noblockedmessages"],
tags: ["Utility"],
searchTerms: ["blocked", "block", "hide", "hidden", "noblockedmessages"],
authors: [Devs.Samwich, EquicordDevs.KamiRu],
settings,
activeNowView,

View file

@ -72,6 +72,7 @@ migratePluginSettings("ClipsEnhancements", "TimelessClips");
export default definePlugin({
name: "ClipsEnhancements",
description: "Add more Clip FPS and duration options, custom clip length, RPC tagging and more",
tags: ["Activity", "Media", "Utility"],
authors: [Devs.niko, Devs.Joona, EquicordDevs.keircn],
settings,
patches: [

View file

@ -108,8 +108,10 @@ const ChatButtonsRow = ErrorBoundary.wrap(({ buttons }: { buttons: ReactNode[];
export default definePlugin({
name: "CollapsibleUI",
description: "Native collapsible channel, member, chat button, and user area surfaces.",
tags: ["Appearance", "Customisation", "Chat", "Servers"],
dependencies: ["HeaderBarAPI"],
authors: [EquicordDevs.benjii],
tags: ["ui", "sidebar", "layout"],
searchTerms: ["ui", "sidebar", "layout"],
managedStyle,
settings,

View file

@ -201,6 +201,7 @@ function hotkeyUsesModifiers() {
export default definePlugin({
name: "CommandPalette",
description: "Quickly run actions through a searchable command palette",
tags: ["Appearance", "Customisation", "Commands", "Shortcuts"],
authors: [EquicordDevs.justjxke],
settings,
patches: [

View file

@ -6,7 +6,7 @@
import { DataStore } from "@api/index";
import { isPluginEnabled, plugins, startPlugin, stopPlugin } from "@api/PluginManager";
import { SettingsStore } from "@api/Settings";
import { Settings, SettingsStore } from "@api/Settings";
import { getUserSettingLazy } from "@api/UserSettings";
import { openPluginModal } from "@components/settings/tabs";
import { toggleEnabled } from "@equicordplugins/equicordHelper/utils";
@ -18,7 +18,6 @@ import { Guild } from "@vencord/discord-types";
import { findByPropsLazy, findExportedComponentLazy, findStoreLazy } from "@webpack";
import { Alerts, ChannelActionCreators, ChannelRouter, ChannelStore, ComponentDispatch, FluxDispatcher, GuildStore, IconUtils, MediaEngineStore, MessageStore, NavigationRouter, React, ReadStateStore, ReadStateUtils, SelectedChannelStore, SelectedGuildStore, SettingsRouter, StreamerModeStore, Toasts, useEffect, UserStore, VoiceActions } from "@webpack/common";
import type { FC, ReactElement, ReactNode } from "react";
import { Settings } from "Vencord";
import commandPalette from ".";
import {

View file

@ -18,6 +18,7 @@ import ComponentsTab from "./components/ComponentsTab";
export default definePlugin({
name: "Components",
description: "Adds a new tab to settings to browse Discord components.",
tags: ["Appearance", "Customisation", "Console", "Developers", "Organisation"],
authors: [Devs.prism],
dependencies: ["Settings"],
startAt: StartAt.WebpackReady,

View file

@ -152,6 +152,7 @@ export default definePlugin({
name: "ContentWarning",
authors: [EquicordDevs.camila314],
description: "Allows you to specify certain trigger words that will be blurred by default. Hovering/Clicking on the blurred content will reveal it.",
tags: ["Appearance", "Utility"],
settings,
patches: [
{

View file

@ -90,6 +90,7 @@ const userContextMenuPatch: NavContextMenuPatchCallback = (children, { user }) =
export default definePlugin({
name: "CopyProfileColors",
description: "A plugin to copy people's profile gradient colors to clipboard.",
tags: ["Appearance", "Customisation"],
authors: [EquicordDevs.Crxa, EquicordDevs.Cortex],
contextMenus: {
"user-context": userContextMenuPatch,

View file

@ -23,6 +23,7 @@ const getMetadataFromApi: (activity: any, userId: string) => Promise<any> = find
export default definePlugin({
name: "CopyStatusUrls",
description: "Copy the users status url when you right-click it",
tags: ["Activity", "Utility"],
authors: [Devs.sadan],
patches: [

View file

@ -48,6 +48,7 @@ export default definePlugin({
name: "CopyUserMention",
authors: [EquicordDevs.Cortex, Devs.castdrian],
description: "Adds a button to copy user's mention on the user context menu, works best with ValidUser.",
tags: ["Chat", "Utility"],
contextMenus: {
"user-context": UserContextMenuPatch
}

View file

@ -235,8 +235,9 @@ migratePluginSettings("CursorBuddy", "Oneko", "oneko");
export default definePlugin({
name: "CursorBuddy",
description: "Adds a sprite that follows your cursor.",
tags: ["Appearance", "Customisation", "Fun"],
authors: [Devs.Ven, Devs.adryd, EquicordDevs.nexpid, EquicordDevs.ZcraftElite],
tags: ["Oneko", "FatassHorse", "Pet"],
searchTerms: ["Oneko", "FatassHorse", "Pet"],
settings,
isModified: true,

View file

@ -14,6 +14,7 @@ import { folderProp, int2rgba } from "./util";
export default definePlugin({
name: "CustomFolderIcons",
description: "Customize folder icons with any png",
tags: ["Appearance", "Customisation", "Organisation"],
authors: [EquicordDevs.sadan],
settings,
patches: [

View file

@ -393,6 +393,8 @@ export function findOverride(id: string): SoundOverride | null {
export default definePlugin({
name: "CustomSounds",
description: "Customize Discord's sounds.",
dependencies: ["AudioPlayerAPI"],
tags: ["Customisation", "Notifications", "Voice"],
authors: [Devs.ScattrdBlade, Devs.TheKodeToad],
settings,
startAt: StartAt.Init,

View file

@ -54,6 +54,7 @@ const settings = definePluginSettings({
export default definePlugin({
name: "CustomStatusTimeouts",
description: "Adds configurable timeout presets to the status (presence) menu.",
tags: ["Activity", "Utility"],
authors: [EquicordDevs.Kiri, EquicordDevs.thororen],
settings,
patches: [

View file

@ -125,6 +125,7 @@ const settings = definePluginSettings({
export default definePlugin({
name: "CustomTimestamps",
description: "Custom timestamps on messages and tooltips",
tags: ["Appearance", "Customisation"],
authors: [Devs.Rini, EquicordDevs.nvhhr, EquicordDevs.Suffocate, Devs.Obsidian],
settings,
settingsAboutComponent: () => (

View file

@ -100,6 +100,7 @@ const settings = definePluginSettings({
export default definePlugin({
name: "CustomUserColors",
description: "Lets you add a custom color to any user, anywhere! Highly recommend to use with typingTweaks and roleColorEverywhere",
tags: ["Appearance", "Customisation", "Chat"],
authors: [EquicordDevs.mochienya],
contextMenus: {
"user-context": userContextMenuPatch,

View file

@ -141,6 +141,7 @@ function SectionSeparator(title: string) {
export default definePlugin({
name: "Declutter",
description: "Cleans up Discord by removing non-essential UI elements like profile effects, shop tabs, boosts, and more.",
tags: ["Appearance", "Customisation"],
authors: [EquicordDevs.Leon135, Devs.prism, Devs.Kyuuhachi],
settings,
patches: [

View file

@ -10,6 +10,7 @@ import definePlugin from "@utils/types";
export default definePlugin({
name: "DisableCameras",
description: "Disables cameras in a call by default",
tags: ["Appearance", "Customisation", "Media", "Privacy"],
authors: [Devs.Joona],
patches: [
{

View file

@ -4,10 +4,10 @@
* SPDX-License-Identifier: GPL-3.0-or-later
*/
import SettingsPlugin from "@plugins/_core/settings";
import { detectClient } from "@plugins/_core/supportHelper";
import { gitHashShort } from "@shared/vencordUserAgent";
import { React } from "@webpack/common";
import SettingsPlugin from "plugins/_core/settings";
import { JSX } from "react";
import { ChromiumIcon, ClientIcon, DevBannerIcon, DiscordIcon, ElectronIcon, EquicordIcon, names, settings } from ".";

View file

@ -14,6 +14,7 @@ import { makeDevBanner, settings } from "./components";
export default definePlugin({
name: "DiscordDevBanner",
description: "Enables the Discord developer banner, in which displays the build-ID",
tags: ["Appearance", "Console", "Developers"],
authors: [EquicordDevs.KrystalSkull, Devs.thororen],
settings,
patches: [

View file

@ -45,6 +45,7 @@ export default definePlugin({
name: "DragFavoriteEmotes",
authors: [EquicordDevs.PWall],
description: "Adds the ability to change the order of your favourite emotes",
tags: ["Customisation", "Chat", "Emotes"],
patches: [
{
find: "#{intl::EMOJI_FAVORITE_TOOLTIP}",

View file

@ -149,6 +149,7 @@ const settings = definePluginSettings({
export default definePlugin({
name: "Dragify",
description: "Drop users, channels, or servers into chat to insert mentions or invites.",
tags: ["Chat", "Servers", "Utility", "Voice"],
authors: [EquicordDevs.justjxke],
settings,

View file

@ -449,6 +449,7 @@ function onToggle(e: KeyboardEvent) {
export default definePlugin({
name: "ElementHighlighter",
description: "Highlight and inspect elements easily.",
tags: ["Developers"],
authors: [Devs.prism],
settings,

View file

@ -89,6 +89,7 @@ const settings = definePluginSettings({
export default definePlugin({
name: "EquibopStreamFixes",
description: "Tries to fix stream quality on Equibop by patching Discord's encoder and quality restrictions.",
tags: ["Voice"],
authors: [EquicordDevs.creations],
settings,

View file

@ -133,6 +133,8 @@ const settings = definePluginSettings({
export default definePlugin({
name: "EquicordHelper",
description: "Used to provide support, fix discord caused crashes, and other misc features.",
tags: ["Appearance", "Commands", "Utility"],
dependencies: ["CommandsAPI", "HeaderBarAPI", "MessageAccessoriesAPI"],
authors: [
Devs.thororen,
EquicordDevs.nyx,

View file

@ -77,11 +77,10 @@ migratePluginSettings("EquicordToolbox", "VencordToolbox");
export default definePlugin({
name: "EquicordToolbox",
description: "Adds a button next to the inbox button in the channel header that houses Equicord quick actions",
tags: ["Voice", "Accessibility"],
authors: [Devs.Ven, Devs.AutumnVN],
dependencies: ["HeaderBarAPI"],
settings,
headerBarButton: {
icon: Icon,
render: VencordPopoutButton,

View file

@ -33,6 +33,7 @@ const settings = definePluginSettings({
export default definePlugin({
name: "Equissant",
description: "Crossant every specified amount of clicks :trolley:",
tags: ["Fun"],
authors: [EquicordDevs.SomeAspy, Devs.thororen],
dependencies: ["AudioPlayerAPI"],
settings,

View file

@ -104,6 +104,7 @@ let original: typeof ChannelActions.selectVoiceChannel;
export default definePlugin({
name: "ExitSounds",
description: "Play soundboard sounds when you disconnect from voice.",
tags: ["Fun", "Voice"],
authors: [Devs.prism],
dependencies: ["AudioPlayerAPI"],
settings,

View file

@ -129,6 +129,7 @@ function getUsernames(contacts: ContactsList[], type: number): string[] {
export default definePlugin({
name: "ExportMessages",
description: "Allows you to export any message to a file",
tags: ["Chat", "Utility"],
authors: [EquicordDevs.veygax, EquicordDevs.dat_insanity],
settings,
contextMenus: {

View file

@ -74,6 +74,7 @@ const settings = definePluginSettings({
export default definePlugin({
name: "FastDeleteChannels",
description: "Adds a trash icon to delete channels",
tags: ["Servers", "Utility"],
authors: [Devs.thororen],
settings,
patches: [

View file

@ -25,8 +25,9 @@ export const AttachmentContext = proxyLazyWebpack(() => React.createContext<null
export default definePlugin({
name: "FavouriteAnything",
description: "Favourite any image, video, or file attachment",
tags: ["Chat", "Media"],
authors: [Devs.nin0dev, EquicordDevs.davri],
tags: ["favorite"],
searchTerms: ["favorite"],
managedStyle,
patches: [
// EMBEDS

View file

@ -44,7 +44,7 @@ interface Uint8ArrayConstructorExtended extends Uint8ArrayConstructor {
): Uint8ArrayExtended<ArrayBuffer>;
}
function supportsToBase64(array: Uint8Array<ArrayBufferLike>): array is Uint8ArrayExtended<ArrayBufferLike> {
function supportsToBase64(array: Uint8Array<ArrayBufferLike>): boolean {
return "toBase64" in array && typeof array.toBase64 === "function";
}

View file

@ -216,6 +216,7 @@ const channelAttachMenuPatch: NavContextMenuPatchCallback = (children, props) =>
export default definePlugin({
name: "FileUpload",
description: "Upload images and videos to file hosting services like Zipline and Nest",
tags: ["Media"],
authors: [EquicordDevs.creations, EquicordDevs.keircn, Devs.ScattrdBlade],
settings,
patches: [

View file

@ -89,6 +89,8 @@ const settings = definePluginSettings({
export default definePlugin({
name: "FindReply",
description: "Jumps to the earliest reply to a message in a channel (lets you follow past conversations more easily).",
dependencies: ["MessagePopoverAPI"],
tags: ["Chat", "Shortcuts"],
authors: [Devs.newwares],
settings,
messagePopoverButton: {

View file

@ -29,6 +29,7 @@ export default definePlugin({
name: "FixFileExtensions",
authors: [Devs.thororen],
description: "Fixes file extensions by renaming them to a compatible supported format if possible",
tags: ["Media", "Utility"],
reporterTestable: ReporterTestable.None,
patches: [
// Taken from AnonymiseFileNames

View file

@ -74,6 +74,7 @@ const UserContextMenuPatch: NavContextMenuPatchCallback = (children, { channel,
export default definePlugin({
name: "FollowVoiceUser",
description: "Follow a friend in voice chat.",
tags: ["Voice"],
authors: [EquicordDevs.TheArmagan],
settings,
settingsAboutComponent: () => (

View file

@ -200,6 +200,7 @@ const settings = definePluginSettings({
export default definePlugin({
name: "FontLoader",
description: "Loads any font from Google Fonts",
tags: ["Appearance", "Customisation"],
authors: [EquicordDevs.vmohammad],
settings,

View file

@ -25,6 +25,7 @@ const settings = definePluginSettings({
export default definePlugin({
name: "ForwardAnywhere",
description: "If a forward fails send it as a normal message also allows nsfw forwards",
tags: ["Chat", "Utility"],
authors: [Devs.thororen],
settings,
patches: [

View file

@ -37,6 +37,7 @@ function generateSearchResults(query) {
export default definePlugin({
name: "FrequentQuickSwitcher",
description: "Rewrites and filters the quick switcher results to be your most frequent channels",
tags: ["Shortcuts", "Servers"],
authors: [Devs.Samwich],
generateSearchResults: generateSearchResults,
patches: [

View file

@ -12,6 +12,7 @@ import FriendCodesPanel from "./FriendCodesPanel";
export default definePlugin({
name: "FriendCodes",
description: "Generate FriendCodes to easily add friends",
tags: ["Friends", "Utility"],
authors: [Devs.HypedDomi],
patches: [
{

View file

@ -209,6 +209,7 @@ const userPatch: NavContextMenuPatchCallback = (children, { user }) => {
export default definePlugin({
name: "FriendTags",
description: "Allows you to filter by custom tags in the quick switcher by starting a search with &",
tags: ["Shortcuts"],
authors: [Devs.Samwich],
settings,
contextMenus: {

View file

@ -143,6 +143,7 @@ function getBadgesToApply() {
export default definePlugin({
name: "FriendshipRanks",
description: "Adds badges showcasing how long you have been friends with a user for",
tags: ["Friends"],
authors: [Devs.Samwich],
start() {
getBadgesToApply().forEach(b => Badges.addProfileBadge(b));

View file

@ -14,6 +14,7 @@ import style from "./style.css?managed";
export default definePlugin({
name: "FullVCPFP",
description: "Makes avatars take up the entire vc tile",
tags: ["Appearance", "Voice"],
authors: [EquicordDevs.mochienya],
patches: [
{

View file

@ -147,6 +147,7 @@ function makeContextItem(props) {
export default definePlugin({
name: "Ghosted",
description: "A cute ghost will appear if you don't answer their DMs",
tags: ["Chat", "Utility"],
authors: [EquicordDevs.vei, Devs.sadan, EquicordDevs.justjxke, EquicordDevs.iamme],
settings,
dependencies: ["AudioPlayerAPI", "ServerListAPI"],

View file

@ -26,6 +26,7 @@ let oldTrendingCat: Category[] | null = null;
export default definePlugin({
name: "GifCollections",
description: "Allows you to create collections of gifs.",
tags: ["Chat", "Emotes"],
authors: [EquicordDevs.creations],
settings,
contextMenus: {

View file

@ -38,6 +38,8 @@ export const settings = definePluginSettings({
export default definePlugin({
name: "GitHubRepos",
description: "Displays a user's public GitHub repositories in their profile",
dependencies: ["ProfileCollectionsAPI"],
tags: ["Appearance"],
authors: [EquicordDevs.talhakf, EquicordDevs.Panniku, EquicordDevs.benjii],
settings,

View file

@ -25,6 +25,7 @@ migratePluginSetting("GlobalBadges", "showRaincord", "showRa1ncord");
export default definePlugin({
name: "GlobalBadges",
description: "Adds global badges from other client mods",
tags: ["Appearance"],
authors: [Devs.HypedDomi, EquicordDevs.Wolfie, Devs.thororen],
settings,
settingsAboutComponent: () => (

View file

@ -75,8 +75,10 @@ const settings = definePluginSettings({
export default definePlugin({
name: "GoogleThat",
description: "Adds a command to send a internet search link",
dependencies: ["CommandsAPI"],
tags: ["Commands", "Utility"],
authors: [Devs.Samwich, EquicordDevs.KrystalSkull],
tags: ["search", "google", "query", "duckduckgo", "command"],
searchTerms: ["search", "google", "query", "duckduckgo", "command"],
settings,
commands: [
{

View file

@ -95,6 +95,7 @@ async function zipGuildAssets(guild: Guild, type: "emojis" | "stickers") {
export default definePlugin({
name: "GuildPickerDumper",
description: "Context menu to dump and download a server's emojis and stickers.",
tags: ["Emotes", "Servers", "Utility"],
authors: [EquicordDevs.Cortex, Devs.Samwich, EquicordDevs.Synth, Devs.thororen],
contextMenus: {
"guild-context": Patch,

View file

@ -81,6 +81,7 @@ function ButtonsInnerComponent({ buttons }: { buttons: ReactNode; }) {
export default definePlugin({
name: "HideChatButtons",
description: "Able to hide the chat buttons",
tags: ["Chat", "Utility"],
settings: settings,
authors: [EquicordDevs.iamme],
patches: [

View file

@ -49,6 +49,8 @@ const settings = definePluginSettings({
export default definePlugin({
name: "HideMessages",
description: "A plugin to temporarily hide messages until you restart.",
dependencies: ["MessagePopoverAPI"],
tags: ["Chat", "Utility"],
authors: [EquicordDevs.yash],
contextMenus: {
"message": messageCtxPatch

View file

@ -76,8 +76,9 @@ export function removeIndicator() {
export default definePlugin({
name: "HideServers",
description: "Allows you to hide servers from the guild list and quick switcher by right clicking them",
tags: ["Servers", "Utility"],
authors: [EquicordDevs.bep],
tags: ["guild", "server", "hide", "folder"],
searchTerms: ["guild", "server", "hide", "folder"],
dependencies: ["ServerListAPI"],
contextMenus: {

View file

@ -72,6 +72,8 @@ function ToolBarHeader() {
export default definePlugin({
name: "HolyNotes",
description: "Save messages as notes to revisit later",
dependencies: ["MessagePopoverAPI", "HeaderBarAPI"],
tags: ["Chat", "Organisation"],
authors: [EquicordDevs.Wolfie],
toolboxActions: {

View file

@ -18,6 +18,7 @@ const PrivateChannelSortStore = findStoreLazy("PrivateChannelSortStore") as { ge
export default definePlugin({
name: "HomeTyping",
description: "Changes the home button to a typing indicator if someone in your dms is typing",
tags: ["Chat"],
authors: [Devs.Samwich],
TypingIcon() {
return <ThreeDots className={cl("dots")} dotRadius={3} themed={true} />;

View file

@ -32,6 +32,7 @@ const settings = definePluginSettings({
export default definePlugin({
name: "HopOn",
description: "Hop on! Opens a configurable URL when a message matches a custom regex in the current channel.",
tags: ["Fun"],
authors: [Devs.ImLvna],
settings,
flux: {

View file

@ -99,6 +99,8 @@ function getEmojiIdThatShouldBeUsed(guildId: string) {
export default definePlugin({
name: "Husk",
description: "Adds Husk button (check settings to change used emoji)",
dependencies: ["MessagePopoverAPI"],
tags: ["Emotes", "Fun"],
authors: [Devs.nin0dev],
settings,
messagePopoverButton: {

View file

@ -19,6 +19,7 @@ import DataUI from "./components/ui";
export default definePlugin({
name: "IRememberYou",
description: "Locally saves everyone you've been communicating with (including servers), in case of lose",
tags: ["Chat", "Servers"],
authors: [EquicordDevs.zoodogood, EquicordDevs.keircn],
dependencies: ["MessageEventsAPI"],

View file

@ -19,6 +19,7 @@ import { SettingsAbout } from "./components/Modals";
export default definePlugin({
name: "IconViewer",
description: "Adds a new tab to settings to preview all icons.",
tags: ["Developers"],
authors: [EquicordDevs.iamme],
dependencies: ["Settings"],
startAt: StartAt.WebpackReady,

View file

@ -36,6 +36,7 @@ function onActivity() {
export default definePlugin({
name: "IdleAutoRestart",
description: "Automatically restarts the client after being idle for a configurable amount of time, but avoids restarting while you are in VC.",
tags: ["Utility"],
authors: [EquicordDevs.SteelTech],
settings,

View file

@ -93,6 +93,7 @@ const settings = definePluginSettings({
export default definePlugin({
name: "IgnoreCalls",
description: "Allows you to ignore calls from specific users or dm groups.",
tags: ["Voice"],
authors: [EquicordDevs.TheArmagan, Devs.thororen],
settings,
patches: [

View file

@ -34,8 +34,9 @@ function getMembersInRole(roleId: string, guildId: string) {
export default definePlugin({
name: "InRole",
description: "Know who is in a role with the role context menu or /inrole command (read plugin info!)",
tags: ["Commands", "Roles"],
authors: [Devs.nin0dev],
dependencies: ["UserSettingsAPI"],
dependencies: ["UserSettingsAPI", "CommandsAPI"],
start() {
// DeveloperMode needs to be enabled for the context menu to be shown
DeveloperMode.updateSetting(true);

Some files were not shown because too many files have changed in this diff Show more