import { ProfileBadge } from "../api/Badges";
import { ChatBarButtonData } from "../api/ChatButtons";
import { NavContextMenuPatchCallback } from "../api/ContextMenu";
import { MemberListDecoratorFactory } from "../api/MemberListDecorators";
import { MessageAccessoryFactory } from "../api/MessageAccessories";
import { MessageDecorationFactory } from "../api/MessageDecorations";
import { MessageClickListener, MessageEditListener, MessageSendListener } from "../api/MessageEvents";
import { MessagePopoverButtonData } from "../api/MessagePopover";
import { Command, FluxEvents } from "@vencord/discord-types";
import { ReactNode } from "react";
import { LiteralUnion } from "type-fest";
export default function definePlugin
(p: P & Record): typeof p & Plugin;
export declare function makeRange(start: number, end: number, step?: number): number[];
export type ReplaceFn = (match: string, ...groups: string[]) => string;
export interface PatchReplacement {
/** The match for the patch replacement. If you use a string it will be implicitly converted to a RegExp */
match: string | RegExp;
/** The replacement string or function which returns the string for the patch replacement */
replace: string | ReplaceFn;
/** Do not warn if this replacement did no changes */
noWarn?: boolean;
/**
* A function which returns whether this patch replacement should be applied.
* This is ran before patches are registered, so if this returns false, the patch will never be registered.
*/
predicate?(): boolean;
/** The minimum build number for this patch to be applied */
fromBuild?: number;
/** The maximum build number for this patch to be applied */
toBuild?: number;
}
export interface Patch {
plugin: string;
/** A string or RegExp which is only include/matched in the module code you wish to patch. Prefer only using a RegExp if a simple string test is not enough */
find: string | RegExp;
/** The replacement(s) for the module being patched */
replacement: PatchReplacement | PatchReplacement[];
/** Whether this patch should apply to multiple modules */
all?: boolean;
/** Do not warn if this patch did no changes */
noWarn?: boolean;
/** Only apply this set of replacements if all of them succeed. Use this if your replacements depend on each other */
group?: boolean;
/**
* A function which returns whether this patch replacement should be applied.
* This is ran before patches are registered, so if this returns false, the patch will never be registered.
*/
predicate?(): boolean;
/** The minimum build number for this patch to be applied */
fromBuild?: number;
/** The maximum build number for this patch to be applied */
toBuild?: number;
}
export interface PluginAuthor {
name: string;
id: BigInt;
}
export interface Plugin extends PluginDef {
patches?: Patch[];
started: boolean;
isDependency?: boolean;
}
export type IconComponent = (props: IconProps & Record) => ReactNode;
export type IconProps = {
height?: number | string;
width?: number | string;
className?: string;
};
export interface PluginDef {
name: string;
description: string;
authors: PluginAuthor[];
start?(): void;
stop?(): void;
patches?: Omit[];
/**
* List of commands that your plugin wants to register
*/
commands?: Command[];
/**
* A list of other plugins that your plugin depends on.
* These will automatically be enabled and loaded before your plugin
* Generally these will be API plugins
*/
dependencies?: string[];
/**
* Whether this plugin is required and forcefully enabled
*/
required?: boolean;
/**
* Whether this plugin should be hidden from the user
*/
hidden?: boolean;
/**
* Whether this plugin should be enabled by default, but can be disabled
*/
enabledByDefault?: boolean;
/**
* Whether enabling or disabling this plugin requires a restart. Defaults to true if the plugin has patches.
*/
requiresRestart?: boolean;
/**
* When to call the start() method
* @default StartAt.WebpackReady
*/
startAt?: StartAt;
/**
* Which parts of the plugin can be tested by the reporter. Defaults to all parts
*/
reporterTestable?: number;
/**
* Optionally provide settings that the user can configure in the Plugins tab of settings.
* @deprecated Use `settings` instead
*/
options?: Record;
/**
* Optionally provide settings that the user can configure in the Plugins tab of settings.
*/
settings?: DefinedSettings;
/**
* Allows you to specify a custom Component that will be rendered in your
* plugin's settings page
*/
settingsAboutComponent?: React.ComponentType<{}>;
/**
* Allows you to subscribe to Flux events
*/
flux?: Partial<{
[E in LiteralUnion]: (event: any) => void | Promise;
}>;
/**
* Allows you to manipulate context menus
*/
contextMenus?: Record;
/**
* Allows you to add custom actions to the Vencord Toolbox.
*
* Can either be an object mapping labels to action functions or a Function returning Menu components.
* Please note that you can only use Menu components.
*
* @example
* toolboxActions: {
* "Click Me": () => alert("Hi")
* }
*/
toolboxActions?: Record void> | (() => ReactNode);
tags?: string[];
/**
* Managed style to automatically enable and disable when the plugin is enabled or disabled
*/
managedStyle?: string;
userProfileBadge?: ProfileBadge;
messagePopoverButton?: MessagePopoverButtonData;
chatBarButton?: ChatBarButtonData;
onMessageClick?: MessageClickListener;
onBeforeMessageSend?: MessageSendListener;
onBeforeMessageEdit?: MessageEditListener;
renderMessageAccessory?: MessageAccessoryFactory;
renderMessageDecoration?: MessageDecorationFactory;
renderMemberListDecorator?: MemberListDecoratorFactory;
/**
* @deprecated Use {@link chatBarButton} instead
*/
renderChatBarButton?: never;
/**
* @deprecated Use {@link messagePopoverButton} instead
*/
renderMessagePopoverButton?: never;
}
export declare const enum StartAt {
/** Right away, as soon as Vencord initialised */
Init = "Init",
/** On the DOMContentLoaded event, so once the document is ready */
DOMContentLoaded = "DOMContentLoaded",
/** Once Discord's core webpack modules have finished loading, so as soon as things like react and flux are available */
WebpackReady = "WebpackReady"
}
export declare const enum ReporterTestable {
None = 2,
Start = 4,
Patches = 8,
FluxEvents = 16
}
export declare function defineDefault(value: T): T;
export declare const enum OptionType {
STRING = 0,
NUMBER = 1,
BIGINT = 2,
BOOLEAN = 3,
SELECT = 4,
SLIDER = 5,
COMPONENT = 6,
CUSTOM = 7
}
export type SettingsDefinition = Record;
export type SettingsChecks = {
[K in keyof D]?: D[K] extends PluginSettingComponentDef ? IsDisabled> : (IsDisabled> & IsValid, DefinedSettings>);
};
export type PluginSettingDef = (PluginSettingCustomDef & Pick) | (PluginSettingComponentDef & Omit) | ((PluginSettingStringDef | PluginSettingNumberDef | PluginSettingBooleanDef | PluginSettingSelectDef | PluginSettingSliderDef | PluginSettingBigIntDef) & PluginSettingCommon);
export interface PluginSettingCommon {
description: string;
placeholder?: string;
onChange?(newValue: any): void;
/**
* Whether changing this setting requires a restart
*/
restartNeeded?: boolean;
componentProps?: Record;
/**
* Hide this setting from the settings UI
*/
hidden?: boolean;
/**
* Set this if the setting only works on Browser or Desktop, not both
*/
target?: "WEB" | "DESKTOP" | "BOTH";
}
interface IsDisabled {
/**
* Checks if this setting should be disabled
*/
disabled?(this: D): boolean;
}
interface IsValid {
/**
* Prevents the user from saving settings if this is false or a string
*/
isValid?(this: D, value: T): boolean | string;
}
export interface PluginSettingStringDef {
type: OptionType.STRING;
default?: string;
}
export interface PluginSettingNumberDef {
type: OptionType.NUMBER;
default?: number;
}
export interface PluginSettingBigIntDef {
type: OptionType.BIGINT;
default?: BigInt;
}
export interface PluginSettingBooleanDef {
type: OptionType.BOOLEAN;
default?: boolean;
}
export interface PluginSettingSelectDef {
type: OptionType.SELECT;
options: readonly PluginSettingSelectOption[];
}
export interface PluginSettingSelectOption {
label: string;
value: string | number | boolean;
default?: boolean;
}
export interface PluginSettingCustomDef {
type: OptionType.CUSTOM;
default?: any;
}
export interface PluginSettingSliderDef {
type: OptionType.SLIDER;
/**
* All the possible values in the slider. Needs at least two values.
*/
markers: number[];
/**
* Default value to use
*/
default: number;
/**
* If false, allow users to select values in-between your markers.
*/
stickToMarkers?: boolean;
}
export interface IPluginOptionComponentProps {
/**
* Run this when the value changes.
*
* NOTE: The user will still need to click save to apply these changes.
*/
setValue(newValue: any): void;
/**
* The options object
*/
option: PluginSettingComponentDef;
}
export interface PluginSettingComponentDef {
type: OptionType.COMPONENT;
component: (props: IPluginOptionComponentProps) => ReactNode | Promise;
default?: any;
}
/** Maps a `PluginSettingDef` to its value type */
type PluginSettingType = O extends PluginSettingStringDef ? string : O extends PluginSettingNumberDef ? number : O extends PluginSettingBigIntDef ? BigInt : O extends PluginSettingBooleanDef ? boolean : O extends PluginSettingSelectDef ? O["options"][number]["value"] : O extends PluginSettingSliderDef ? number : O extends PluginSettingComponentDef ? O extends {
default: infer Default;
} ? Default : any : O extends PluginSettingCustomDef ? O extends {
default: infer Default;
} ? Default : any : never;
type PluginSettingDefaultType = O extends PluginSettingSelectDef ? (O["options"] extends {
default?: boolean;
}[] ? O["options"][number]["value"] : undefined) : O extends {
default: infer T;
} ? T : undefined;
type SettingsStore = {
[K in keyof D]: PluginSettingType | PluginSettingDefaultType;
};
/** An instance of defined plugin settings */
export interface DefinedSettings = {}, PrivateSettings extends object = {}> {
/** Shorthand for `Vencord.Settings.plugins.PluginName`, but with typings */
store: SettingsStore & PrivateSettings;
/** Shorthand for `Vencord.PlainSettings.plugins.PluginName`, but with typings */
plain: SettingsStore & PrivateSettings;
/**
* React hook for getting the settings for this plugin
* @param filter optional filter to avoid rerenders for irrelevent settings
*/
use>(filter?: F[]): Pick & PrivateSettings, F>;
/** Definitions of each setting */
def: Def;
/** Setting methods with return values that could rely on other settings */
checks: Checks;
/**
* Name of the plugin these settings belong to,
* will be an empty string until plugin is initialized
*/
pluginName: string;
withPrivateSettings(): DefinedSettings;
}
export type PartialExcept = Partial & Required>;
export type IpcRes = {
ok: true;
value: V;
} | {
ok: false;
error: any;
};
export type PluginOptionBase = PluginSettingCommon & IsDisabled;
export type PluginOptionsItem = PluginOptionString | PluginOptionNumber | PluginOptionBoolean | PluginOptionSelect | PluginOptionSlider | PluginOptionComponent | PluginOptionCustom;
export type PluginOptionString = PluginSettingStringDef & PluginSettingCommon & IsDisabled & IsValid;
export type PluginOptionNumber = (PluginSettingNumberDef | PluginSettingBigIntDef) & PluginSettingCommon & IsDisabled & IsValid;
export type PluginOptionBoolean = PluginSettingBooleanDef & PluginSettingCommon & IsDisabled & IsValid;
export type PluginOptionSelect = PluginSettingSelectDef & PluginSettingCommon & IsDisabled & IsValid;
export type PluginOptionSlider = PluginSettingSliderDef & PluginSettingCommon & IsDisabled & IsValid;
export type PluginOptionComponent = PluginSettingComponentDef & Omit;
export type PluginOptionCustom = PluginSettingCustomDef & Pick;
export type PluginNative any>> = {
[key in keyof PluginExports]: PluginExports[key] extends (event: Electron.IpcMainInvokeEvent, ...args: infer Args) => infer Return ? (...args: Args) => Return extends Promise ? Return : Promise : never;
};
export type AllOrNothing = T | {
[K in keyof T]?: never;
};
export {};