diff --git a/packages/discord-types/src/utils.d.ts b/packages/discord-types/src/utils.d.ts index bf20e3625..df0621606 100644 --- a/packages/discord-types/src/utils.d.ts +++ b/packages/discord-types/src/utils.d.ts @@ -25,14 +25,29 @@ export type Parser = Record< | "parse" | "parseTopic" | "parseEmbedTitle" + | "parseEmbedTitleWithoutLinks" | "parseInlineReply" | "parseGuildVerificationFormRule" | "parseGuildEventDescription" | "parseAutoModerationSystemMessage" | "parseForumPostGuidelines" - | "parseForumPostMostRecentMessage", + | "parseVoiceChannelStatus", (content: string, inline?: boolean, state?: Record) => ReactNode[] -> & Record<"defaultRules" | "guildEventRules", Record>>; +> & Record< + | "parseToAST" + | "parseTopicToAST" + | "parseEmbedTitleToAST" + | "parseEmbedTitleWithoutLinksToAST" + | "parseInlineReplyToAST" + | "parseAutoModerationSystemMessageToAST", + (content: string, inline?: boolean, state?: Record) => any[] +> & Record<"defaultRules" | "guildEventRules" | "notifCenterV2MessagePreviewRules" | "lockscreenWidgetMessageRules", Record>> & { + reactParserFor(rules: Record): (content: string, inline?: boolean, state?: Record) => ReactNode[]; + astParserFor(rules: Record): (content: string, inline?: boolean, state?: Record) => any[]; + createReactRules(options: Record): Record; + defaultReactRuleOptions: Record; + combineAndInjectMentionRule(rules: Record, mentionRule: Record): Record; +}; export interface Alerts { show(alert: { @@ -48,16 +63,39 @@ export interface Alerts { onConfirmSecondary?(): void; onCloseCallback?(): void; }): void; + confirm(alert: { + title: any; + body: React.ReactNode; + className?: string; + confirmColor?: string; + cancelText?: string; + confirmText?: string; + secondaryConfirmText?: string; + onCancel?(): void; + onConfirmSecondary?(): void; + onCloseCallback?(): void; + }): Promise; /** This is a noop, it does nothing. */ close(): void; } export interface SnowflakeUtils { fromTimestamp(timestamp: number): string; + fromTimestampWithSequence(timestamp: number, sequence: number): string; extractTimestamp(snowflake: string): number; age(snowflake: string): number; atPreviousMillisecond(snowflake: string): string; + atNextMillisecond(snowflake: string): string; compare(snowflake1?: string, snowflake2?: string): number; + isProbablyAValidSnowflake(snowflake: string): boolean; + castChannelIdAsMessageId(channelId: string): string; + castMessageIdAsChannelId(messageId: string): string; + castGuildIdAsEveryoneGuildRoleId(guildId: string): string; + cast(snowflake: string): string; + keys(obj: Record): string[]; + forEach(obj: Record, callback: (value: any, key: string) => void): void; + forEachKey(obj: Record, callback: (key: string) => void): void; + entries(obj: Record): [string, any][]; } interface RestRequestData { @@ -249,45 +287,55 @@ export interface UsernameUtils { useName(user: User): string; getUserTag(user: User, options?: UserNameUtilsTagOptions): string; useUserTag(user: User, options?: UserNameUtilsTagOptions): string; - - + isNameConcealed(user: User): boolean; + getUserIsStaff(user: User): boolean; useDirectMessageRecipient: any; humanizeStatus: any; } -// TODO: fix type export class DisplayProfile { userId: string; + guildId?: string; banner?: string; bio?: string; pronouns?: string; accentColor?: number; themeColors?: number[]; + profileEffect?: any; popoutAnimationParticleType?: any; - profileEffectId?: string; + fetchStartedAt?: Date | null; + fetchEndedAt?: Date | null; _userProfile?: any; _guildMemberProfile?: any; - canUsePremiumProfileCustomization: boolean; - canEditThemes: boolean; - premiumGuildSince: Date | null; - premiumSince: Date | null; - premiumType?: PremiumType; - primaryColor?: number; + get premiumSince(): Date | null; + get premiumGuildSince(): Date | null; + get premiumType(): PremiumType | undefined; + get private(): boolean; + get widgets(): any[] | undefined; + get gameWidgets(): any[] | undefined; + get primaryColor(): number | undefined; + get canUsePremiumProfileCustomization(): boolean; + get canEditThemes(): boolean; + get application(): any; + get isLoaded(): boolean; + + hasThemeColors(): boolean; + hasPremiumCustomization(): boolean; + isUsingGuildMemberBanner(): boolean; + isUsingGuildMemberBio(): boolean; + isUsingGuildMemberPronouns(): boolean; + getBannerURL(options: { canAnimate: boolean; size: number; }): string; + getPreviewBanner(banner: string | null, canAnimate: boolean, size?: number): string | null; + getPreviewBio(bio: string | undefined): string | undefined; + getPreviewThemeColors(themeColors: number[] | undefined): number[] | undefined; getBadges(): Array<{ id: string; description: string; icon: string; link?: string; }>; - getBannerURL(options: { canAnimate: boolean; size: number; }): string; getLegacyUsername(): string | null; - hasFullProfile(): boolean; - hasPremiumCustomization(): boolean; - hasThemeColors(): boolean; - isUsingGuildMemberBanner(): boolean; - isUsingGuildMemberBio(): boolean; - isUsingGuildMemberPronouns(): boolean; } export interface DisplayProfileUtils { @@ -317,3 +365,51 @@ export interface CommandOptions { max_value?: number; autocomplete?: boolean; } + +export interface URLUtils { + URL_REGEX: RegExp; + makeUrl(url: string): URL | null; + isDiscordUrl(url: string): boolean; + isDiscordCdnUrl(url: string): boolean; + isDiscordAssetUrl(url: string, proxyUrl?: string, originalUrl?: string): boolean; + isDiscordDirectAssetUrl(url: string): boolean; + isDiscordProxiedAssetUrl(url: string, proxyUrl?: string, originalUrl?: string): boolean; + isDiscordHostname(hostname: string): boolean; + isDiscordLocalhost(hostname: string): boolean; + isDiscordProtocol(url: string): boolean; + isDiscordUri(url: string): boolean; + isDiscordUrlOrUri(url: string): boolean; + isAllowedGifProviderUrl(url: string): boolean; + isAppRoute(url: string): boolean; + isOriginalContentTypeDifferent(url: string, proxyUrl: string): boolean; + toURLSafe(url: string): URL | null; + safeDecodeURIComponent(component: string): string; + safeParseWithQuery(url: string): URL | null; + format(url: URL): string; + formatPathWithQuery(path: string, query: Record): string; + formatSearch(query: Record): string; +} + +export interface Humanize { + filesize(bytes: number, base?: number, decimals?: number, decimalSep?: string, thousandsSep?: string, suffix?: string): string; + intword(number: number, units?: string[], base?: number, decimals?: number, decimalSep?: string, thousandsSep?: string): string; + relativeTime(timestamp?: number): string; + naturalDay(timestamp?: number, format?: string): string; + ordinal(value: number): string; + numberFormat(number: number, decimals?: number, decimalSep?: string, thousandsSep?: string): string; + truncatechars(str: string, maxLength: number): string; + truncatewords(str: string, maxWords: number): string; + pad(str: string, length: number, padChar?: string, direction?: "left" | "right"): string; + date(format: string, timestamp?: Date | number): string; + time(): number; + linebreaks(str: string): string; + nl2br(str: string): string; +} + +export interface EmojiUtils { + getEmojiColors(emoji: any): number[] | null; + getURL(emoji: any): string; + filterUnsupportedEmojis(emojis: any[]): any[]; + triggerFullscreenAnimation(emoji: any, node: HTMLElement): void; + applyPlatformToThemedEmojiColorPalette(colors: any): any; +} diff --git a/src/webpack/common/utils.ts b/src/webpack/common/utils.ts index b083abed8..914ffbe0f 100644 --- a/src/webpack/common/utils.ts +++ b/src/webpack/common/utils.ts @@ -250,3 +250,7 @@ export const MessageTypeSets: t.MessageTypeSets = findByPropsLazy("REPLYABLE", " export const fetchApplicationsRPC = findByCodeLazy('"Invalid Origin"', ".application"); export const CloudUploader = findLazy(m => m.prototype?.trackUploadFinished) as typeof t.CloudUpload; + +export const URLUtils: t.URLUtils = findByPropsLazy("URL_REGEX", "makeUrl", "isDiscordUrl"); +export const Humanize: t.Humanize = findByPropsLazy("filesize", "relativeTime", "ordinal"); +export const EmojiUtils: t.EmojiUtils = findByPropsLazy("getEmojiColors", "getURL");