diff --git a/package.json b/package.json index 6a3f58794..8723705fb 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "equicord", "private": "true", - "version": "1.13.6.4", + "version": "1.13.7", "description": "The other cutest Discord client mod", "homepage": "https://github.com/Equicord/Equicord#readme", "bugs": { @@ -121,4 +121,4 @@ "engines": { "node": ">=18" } -} \ No newline at end of file +} diff --git a/packages/discord-types/src/common/messages/Message.d.ts b/packages/discord-types/src/common/messages/Message.d.ts index c2af24962..4a6f3e8b5 100644 --- a/packages/discord-types/src/common/messages/Message.d.ts +++ b/packages/discord-types/src/common/messages/Message.d.ts @@ -2,7 +2,7 @@ import { CommandOption } from './Commands'; import { User, UserJSON } from '../User'; import { Embed, EmbedJSON } from './Embed'; import { DiscordRecord } from "../Record"; -import { MessageFlags, MessageType, StickerFormatType } from "../../../enums"; +import { ApplicationIntegrationType, MessageFlags, MessageType, StickerFormatType } from "../../../enums"; /* * TODO: looks like discord has moved over to Date instead of Moment; @@ -71,6 +71,19 @@ export class Message extends DiscordRecord { type: number; version: string; }[]; + interactionMetadata?: { + id: string; + type: number; + name?: string; + command_type?: number; + ephemerality_reason?: number; + user: User; + authorizing_integration_owners: Record; + original_response_message_id?: string; + interacted_message_id?: string; + target_user?: User; + target_message_id?: string; + }; interactionError: unknown[]; isSearchHit: boolean; loggingName: unknown; diff --git a/packages/vencord-types/package.json b/packages/vencord-types/package.json index d5eb7776f..8df469b04 100644 --- a/packages/vencord-types/package.json +++ b/packages/vencord-types/package.json @@ -1,7 +1,7 @@ { "name": "@equicord/types", "private": false, - "version": "1.13.6", + "version": "1.13.7", "description": "", "types": "index.d.ts", "scripts": { @@ -29,4 +29,4 @@ "@types/react": "18.3.1", "@types/react-dom": "18.3.1" } -} \ No newline at end of file +} diff --git a/src/api/SettingsSync/offline.ts b/src/api/SettingsSync/offline.ts index 711dcf697..e28786fac 100644 --- a/src/api/SettingsSync/offline.ts +++ b/src/api/SettingsSync/offline.ts @@ -26,6 +26,21 @@ const toastFailure = (err: any) => const logger = new Logger("SettingsSync:Offline", "#39b7e0"); +function isSafeObject(obj: any) { + if (obj == null || typeof obj !== "object") return true; + + for (const key in obj) { + if (["__proto__", "constructor", "prototype"].includes(key)) { + return false; + } + if (!isSafeObject(obj[key])) { + return false; + } + } + + return true; +} + export async function importSettings(data: string) { try { var parsed = JSON.parse(data); @@ -34,6 +49,9 @@ export async function importSettings(data: string) { throw new Error("Failed to parse JSON: " + String(err)); } + if (!isSafeObject(parsed)) + throw new Error("Unsafe Settings"); + if ("settings" in parsed && "quickCss" in parsed) { Object.assign(PlainSettings, parsed.settings); await VencordNative.settings.set(parsed.settings); diff --git a/src/plugins/lastfmRichPresence/index.tsx b/src/plugins/lastfmRichPresence/index.tsx index b7d448a68..98acdc2e3 100644 --- a/src/plugins/lastfmRichPresence/index.tsx +++ b/src/plugins/lastfmRichPresence/index.tsx @@ -17,6 +17,11 @@ */ import { definePluginSettings } from "@api/Settings"; +import { LinkButton } from "@components/Button"; +import { Card } from "@components/Card"; +import { Heading } from "@components/Heading"; +import { Margins } from "@components/margins"; +import { Paragraph } from "@components/Paragraph"; import { Devs } from "@utils/constants"; import { Logger } from "@utils/Logger"; import definePlugin, { OptionType } from "@utils/types"; @@ -63,6 +68,10 @@ function setActivity(activity: Activity | null) { } const settings = definePluginSettings({ + apiKey: { + description: "Custom Last.fm API key. Not required but highly recommended to avoid rate limiting with our shared key", + type: OptionType.STRING, + }, username: { description: "Last.fm username", type: OptionType.STRING, @@ -172,10 +181,6 @@ const settings = definePluginSettings({ type: OptionType.BOOLEAN, default: false, }, - apiKey: { - description: "Custom Last.fm API key. You shouldn't need to set this", - type: OptionType.STRING, - }, }); export default definePlugin({ @@ -185,6 +190,16 @@ export default definePlugin({ settings, + settingsAboutComponent() { + return ( + + How to create an API key + Set Application name and Application description to anything and leave the rest blank. + Create API Key + + ); + }, + start() { this.updatePresence(); updateInterval = setInterval(() => { this.updatePresence(); }, 16000); diff --git a/src/plugins/messageClickActions/index.ts b/src/plugins/messageClickActions/index.ts index 6404bd6f3..b9eb718d1 100644 --- a/src/plugins/messageClickActions/index.ts +++ b/src/plugins/messageClickActions/index.ts @@ -21,9 +21,9 @@ import { definePluginSettings } from "@api/Settings"; import NoReplyMentionPlugin from "@plugins/noReplyMention"; import { Devs } from "@utils/constants"; import definePlugin, { OptionType } from "@utils/types"; -import { MessageFlags } from "@vencord/discord-types/enums"; +import { ApplicationIntegrationType, MessageFlags } from "@vencord/discord-types/enums"; import { findByPropsLazy } from "@webpack"; -import { FluxDispatcher, MessageTypeSets, PermissionsBits, PermissionStore, UserStore, WindowStore } from "@webpack/common"; +import { AuthenticationStore, FluxDispatcher, MessageTypeSets, PermissionsBits, PermissionStore, WindowStore } from "@webpack/common"; const MessageActions = findByPropsLazy("deleteMessage", "startEditMessage"); const EditStore = findByPropsLazy("isEditing", "isEditingAny"); @@ -76,7 +76,9 @@ export default definePlugin({ }, onMessageClick(msg, channel, event) { - const isMe = msg.author.id === UserStore.getCurrentUser().id; + const myId = AuthenticationStore.getId(); + const isMe = msg.author.id === myId; + const isSelfInvokedUserApp = msg.interactionMetadata?.authorizing_integration_owners[ApplicationIntegrationType.USER_INSTALL] === myId; if (!isDeletePressed) { if (event.detail < 2) return; if (settings.store.requireModifier && !event.ctrlKey && !event.shiftKey) return; @@ -106,7 +108,7 @@ export default definePlugin({ showMentionToggle: channel.guild_id !== null }); } - } else if (settings.store.enableDeleteOnClick && (isMe || PermissionStore.can(PermissionsBits.MANAGE_MESSAGES, channel))) { + } else if (settings.store.enableDeleteOnClick && (isMe || PermissionStore.can(PermissionsBits.MANAGE_MESSAGES, channel) || isSelfInvokedUserApp)) { if (msg.deleted) { FluxDispatcher.dispatch({ type: "MESSAGE_DELETE", diff --git a/src/plugins/showHiddenChannels/index.tsx b/src/plugins/showHiddenChannels/index.tsx index 73cd0e509..397556872 100644 --- a/src/plugins/showHiddenChannels/index.tsx +++ b/src/plugins/showHiddenChannels/index.tsx @@ -483,11 +483,11 @@ export default definePlugin({ // Filter hidden channels from GuildChannelStore.getChannels unless told otherwise match: /(?<=getChannels\(\i)(\){.*?)return (.+?)}/, replace: (_, rest, channels) => `,shouldIncludeHidden${rest}return $self.resolveGuildChannels(${channels},shouldIncludeHidden??arguments[0]==="@favorites");}` - } + }, ] }, { - find: "#{intl::FORM_LABEL_MUTED}", + find: ".invitesDisabledTooltip", replacement: { // Make GuildChannelStore.getChannels return hidden channels match: /(?<=getChannels\(\i)(?=\))/, diff --git a/src/webpack/common/utils.ts b/src/webpack/common/utils.ts index 5d527ca6f..0c7473133 100644 --- a/src/webpack/common/utils.ts +++ b/src/webpack/common/utils.ts @@ -52,7 +52,7 @@ export const useDrag = findByCodeLazy("useDrag::spec.begin was deprecated"); // you cant make a better finder i love that they remove display names sm export const useDrop = findByCodeLazy(".options);return", ".collect,"); -export const { match, P }: Pick = mapMangledModuleLazy("@ts-pattern/matcher", { +export const { match, P }: { match: typeof TSPattern["match"], P: typeof TSPattern["P"]; } = mapMangledModuleLazy("@ts-pattern/matcher", { match: filters.byCode("return new"), P: filters.byProps("when") }); @@ -175,6 +175,11 @@ export const { zustandPersist } = mapMangledModuleLazy(".onRehydrateStorage)?", zustandPersist: filters.byCode(/(\(\i,\i\))=>.+?\i\1/) }); +export const { openUserSettings } = findByPropsLazy("openUserSettings"); +export function openUserSettingsPanel(panel: string) { + openUserSettings(panel + "_panel"); +} + export const MessageActions = findByPropsLazy("editMessage", "sendMessage"); export const MessageCache = findByPropsLazy("clearCache", "_channelMessages"); export const UserProfileActions = findByPropsLazy("openUserProfileModal", "closeUserProfileModal");