From 26912f9f7a9757c57e87bc14bd7eea7ab11cb0ef Mon Sep 17 00:00:00 2001 From: vencordplus-a <151923520+vencordplus-a@users.noreply.github.com> Date: Thu, 14 Dec 2023 07:34:42 +0300 Subject: [PATCH 1/2] Fork Sync: Update from parent repository (#38) * ci: test all branches * oneko: allow oneko in reduced motion (#2018) * Fix broken patches * fixAll.eslint: `true` -> `"explicit"` * GameActivityToggle: Icon cleanup (#2041) * FakeNitro: fix non apng gif stickers being sent as images (#2050) * AlwaysAnimate: Add guild banner (#2036) * TypingIndicator: setting to disable for current channel (#2043) * fix(notrack): murder sentry * Fix reporter and AlwaysAnimate patch * reporter: fix icon * Move commons from discord utils; Make ThemesTab use invite modal util --------- Co-authored-by: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Co-authored-by: AutumnVN Co-authored-by: ruukulada <126130342+ruukulada@users.noreply.github.com> Co-authored-by: sappho Co-authored-by: zImPatrick <23613354+zImPatrick@users.noreply.github.com> Co-authored-by: Andrew Grant Co-authored-by: V --- .github/workflows/test.yml | 3 --- .vscode/settings.json | 2 +- scripts/generateReport.ts | 10 +++++--- src/api/Commands/commandHelpers.ts | 3 +-- src/components/VencordSettings/ThemesTab.tsx | 13 +++------- src/plugins/alwaysAnimate/index.ts | 8 ++++++ src/plugins/fakeNitro/index.ts | 11 ++++++-- src/plugins/gameActivityToggle/index.tsx | 27 ++++++++++---------- src/plugins/greetStickerPicker/index.tsx | 3 +-- src/plugins/oneko/index.ts | 3 ++- src/plugins/showHiddenChannels/index.tsx | 6 ++--- src/plugins/spotifyShareCommands/index.ts | 3 +-- src/plugins/typingIndicator/index.tsx | 13 ++++++++-- src/plugins/voiceMessages/index.tsx | 3 +-- src/utils/discord.tsx | 9 +------ src/webpack/common/utils.ts | 4 +++ src/webpack/patchWebpack.ts | 7 ++--- 17 files changed, 71 insertions(+), 57 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index a756681c274..d4746d6733f 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,9 +1,6 @@ name: test on: push: - branches: - - main - - dev pull_request: branches: - main diff --git a/.vscode/settings.json b/.vscode/settings.json index 426ff680155..fa543b38c9b 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,7 +1,7 @@ { "editor.formatOnSave": true, "editor.codeActionsOnSave": { - "source.fixAll.eslint": true + "source.fixAll.eslint": "explicit" }, "[typescript]": { "editor.defaultFormatter": "vscode.typescript-language-features" diff --git a/scripts/generateReport.ts b/scripts/generateReport.ts index 54db96e6626..b4033ecb329 100644 --- a/scripts/generateReport.ts +++ b/scripts/generateReport.ts @@ -137,7 +137,7 @@ async function printReport() { body: JSON.stringify({ description: "Here's the latest Vencord Report!", username: "Vencord Reporter" + (CANARY ? " (Canary)" : ""), - avatar_url: "https://cdn.discordapp.com/icons/1015060230222131221/6101cff21e241cebb60c4a01563d0c01.webp?size=512", + avatar_url: "https://cdn.discordapp.com/avatars/1017176847865352332/c312b6b44179ae6817de7e4b09e9c6af.webp?size=512", embeds: [ { title: "Bad Patches", @@ -211,9 +211,12 @@ page.on("console", async e => { switch (tag) { case "WebpackInterceptor:": + const patchFailMatch = message.match(/Patch by (.+?) (had no effect|errored|found no module) \(Module id is (.+?)\): (.+)/)!; + if (!patchFailMatch) break; + process.exitCode = 1; - const [, plugin, type, id, regex] = message.match(/Patch by (.+?) (had no effect|errored|found no module) \(Module id is (.+?)\): (.+)/)!; + const [, plugin, type, id, regex] = patchFailMatch; report.badPatches.push({ plugin, type, @@ -253,7 +256,7 @@ page.on("console", async e => { ).then(a => a.join(" ").trim()); - if (text.length && !text.startsWith("Failed to load resource: the server responded with a status of") && !text.includes("found no module Filter:")) { + if (text.length && !text.startsWith("Failed to load resource: the server responded with a status of") && !text.includes("Webpack")) { console.error("[Unexpected Error]", text); report.otherErrors.push(text); } @@ -293,6 +296,7 @@ function runTime(token: string) { p.patches?.forEach(patch => { patch.plugin = p.name; delete patch.predicate; + delete patch.group; if (!Array.isArray(patch.replacement)) patch.replacement = [patch.replacement]; diff --git a/src/api/Commands/commandHelpers.ts b/src/api/Commands/commandHelpers.ts index 8f4a88e4b22..dc5ecfd67be 100644 --- a/src/api/Commands/commandHelpers.ts +++ b/src/api/Commands/commandHelpers.ts @@ -16,10 +16,9 @@ * along with this program. If not, see . */ -import { MessageActions } from "@utils/discord"; import { mergeDefaults } from "@utils/misc"; import { findByPropsLazy } from "@webpack"; -import { SnowflakeUtils } from "@webpack/common"; +import { MessageActions, SnowflakeUtils } from "@webpack/common"; import { Message } from "discord-types/general"; import type { PartialDeep } from "type-fest"; diff --git a/src/components/VencordSettings/ThemesTab.tsx b/src/components/VencordSettings/ThemesTab.tsx index e65de21922d..2808494a147 100644 --- a/src/components/VencordSettings/ThemesTab.tsx +++ b/src/components/VencordSettings/ThemesTab.tsx @@ -21,12 +21,13 @@ import { classNameFactory } from "@api/Styles"; import { Flex } from "@components/Flex"; import { DeleteIcon } from "@components/Icons"; import { Link } from "@components/Link"; +import { openInviteModal } from "@utils/discord"; import { Margins } from "@utils/margins"; import { classes } from "@utils/misc"; import { showItemInFolder } from "@utils/native"; import { useAwaiter } from "@utils/react"; import { findByPropsLazy, findLazy } from "@webpack"; -import { Button, Card, FluxDispatcher, Forms, React, showToast, TabBar, TextArea, useEffect, useRef, useState } from "@webpack/common"; +import { Button, Card, Forms, React, showToast, TabBar, TextArea, useEffect, useRef, useState } from "@webpack/common"; import { UserThemeHeader } from "main/themes"; import type { ComponentType, Ref, SyntheticEvent } from "react"; @@ -125,15 +126,7 @@ function ThemeCard({ theme, enabled, onChange, onDelete }: ThemeCardProps) { href={`https://discord.gg/${theme.invite}`} onClick={async e => { e.preventDefault(); - const { invite } = await InviteActions.resolveInvite(theme.invite, "Desktop Modal"); - if (!invite) return showToast("Invalid or expired invite"); - - FluxDispatcher.dispatch({ - type: "INVITE_MODAL_OPEN", - invite, - code: theme.invite, - context: "APP" - }); + theme.invite != null && openInviteModal(theme.invite).catch(() => showToast("Invalid or expired invite")); }} > Discord Server diff --git a/src/plugins/alwaysAnimate/index.ts b/src/plugins/alwaysAnimate/index.ts index d53e514522c..dbec3b4e326 100644 --- a/src/plugins/alwaysAnimate/index.ts +++ b/src/plugins/alwaysAnimate/index.ts @@ -46,6 +46,14 @@ export default definePlugin({ match: /(?<=\.activityEmoji,.+?animate:)\i/, replace: "!0" } + }, + { + // Guild Banner + find: ".animatedBannerHoverLayer,onMouseEnter:", + replacement: { + match: /(?<=guildBanner:\i,animate:)\i(?=}\))/, + replace: "!0" + } } ] }); diff --git a/src/plugins/fakeNitro/index.ts b/src/plugins/fakeNitro/index.ts index 3ac75556737..6107df00e8a 100644 --- a/src/plugins/fakeNitro/index.ts +++ b/src/plugins/fakeNitro/index.ts @@ -359,7 +359,7 @@ export default definePlugin({ }, // Separate patch for allowing using custom app icons { - find: "location:\"AppIconHome\"", + find: ".FreemiumAppIconIds.DEFAULT&&(", replacement: { match: /\i\.\i\.isPremium\(\i\.\i\.getCurrentUser\(\)\)/, replace: "true" @@ -787,7 +787,14 @@ export default definePlugin({ if (sticker.available !== false && (canUseStickers || sticker.guild_id === guildId)) break stickerBypass; - const link = this.getStickerLink(sticker.id); + // [12/12/2023] + // Work around an annoying bug where getStickerLink will return StickerType.GIF, + // but will give us a normal non animated png for no reason + // TODO: Remove this workaround when it's not needed anymore + let link = this.getStickerLink(sticker.id); + if (sticker.format_type === StickerType.GIF && link.includes(".png")) { + link = link.replace(".png", ".gif"); + } if (sticker.format_type === StickerType.APNG) { this.sendAnimatedSticker(link, sticker.id, channelId); return { cancel: true }; diff --git a/src/plugins/gameActivityToggle/index.tsx b/src/plugins/gameActivityToggle/index.tsx index 2b84d26f1a0..99cee5b1c20 100644 --- a/src/plugins/gameActivityToggle/index.tsx +++ b/src/plugins/gameActivityToggle/index.tsx @@ -28,21 +28,22 @@ import style from "./style.css?managed"; const Button = findComponentByCodeLazy("Button.Sizes.NONE,disabled:"); function makeIcon(showCurrentGame?: boolean) { + const controllerIcon = "M3.06 20.4q-1.53 0-2.37-1.065T.06 16.74l1.26-9q.27-1.8 1.605-2.97T6.06 3.6h11.88q1.8 0 3.135 1.17t1.605 2.97l1.26 9q.21 1.53-.63 2.595T20.94 20.4q-.63 0-1.17-.225T18.78 19.5l-2.7-2.7H7.92l-2.7 2.7q-.45.45-.99.675t-1.17.225Zm14.94-7.2q.51 0 .855-.345T19.2 12q0-.51-.345-.855T18 10.8q-.51 0-.855.345T16.8 12q0 .51.345 .855T18 13.2Zm-2.4-3.6q.51 0 .855-.345T16.8 8.4q0-.51-.345-.855T15.6 7.2q-.51 0-.855.345T14.4 8.4q0 .51.345 .855T15.6 9.6ZM6.9 13.2h1.8v-2.1h2.1v-1.8h-2.1v-2.1h-1.8v2.1h-2.1v1.8h2.1v2.1Z"; return function () { return ( - - - {!showCurrentGame && <> - - - - - - } + + {showCurrentGame ? ( + + ) : ( + <> + + + + + + + + )} ); }; diff --git a/src/plugins/greetStickerPicker/index.tsx b/src/plugins/greetStickerPicker/index.tsx index c2104af4ed8..73bb5125eea 100644 --- a/src/plugins/greetStickerPicker/index.tsx +++ b/src/plugins/greetStickerPicker/index.tsx @@ -18,10 +18,9 @@ import { definePluginSettings } from "@api/Settings"; import { Devs } from "@utils/constants"; -import { MessageActions } from "@utils/discord"; import definePlugin, { OptionType } from "@utils/types"; import { findByPropsLazy } from "@webpack"; -import { ContextMenuApi, FluxDispatcher, Menu } from "@webpack/common"; +import { ContextMenuApi, FluxDispatcher, Menu, MessageActions } from "@webpack/common"; import { Channel, Message } from "discord-types/general"; interface Sticker { diff --git a/src/plugins/oneko/index.ts b/src/plugins/oneko/index.ts index c5de470e193..90a3901a7d0 100644 --- a/src/plugins/oneko/index.ts +++ b/src/plugins/oneko/index.ts @@ -28,7 +28,8 @@ export default definePlugin({ start() { fetch("https://raw.githubusercontent.com/adryd325/oneko.js/8fa8a1864aa71cd7a794d58bc139e755e96a236c/oneko.js") .then(x => x.text()) - .then(s => s.replace("./oneko.gif", "https://raw.githubusercontent.com/adryd325/oneko.js/14bab15a755d0e35cd4ae19c931d96d306f99f42/oneko.gif")) + .then(s => s.replace("./oneko.gif", "https://raw.githubusercontent.com/adryd325/oneko.js/14bab15a755d0e35cd4ae19c931d96d306f99f42/oneko.gif") + .replace("(isReducedMotion)", "(false)")) .then(eval); }, diff --git a/src/plugins/showHiddenChannels/index.tsx b/src/plugins/showHiddenChannels/index.tsx index f242146c980..906bed504b0 100644 --- a/src/plugins/showHiddenChannels/index.tsx +++ b/src/plugins/showHiddenChannels/index.tsx @@ -77,7 +77,7 @@ export default definePlugin({ }, // Do not check for unreads when selecting the render level if the channel is hidden { - match: /(?=!\(0,\i\.getHasImportantUnread\)\(this\.record\))/, + match: /(?<=&&)(?=!\i\.\i\.hasUnread\(this\.record\.id\))/, replace: "$self.isHiddenChannel(this.record)||" }, // Make channels we dont have access to be the same level as normal ones @@ -334,12 +334,12 @@ export default definePlugin({ replacement: [ { // Remove the divider and the open chat button for the HiddenChannelLockScreen - match: /"more-options-popout"\)\),(?<=let{channel:(\i).+?inCall:(\i).+?)/, + match: /"more-options-popout"\)\),(?<=channel:(\i).+?inCall:(\i).+?)/, replace: (m, channel, inCall) => `${m}${inCall}||!$self.isHiddenChannel(${channel},true)&&` }, { // Remove invite users button for the HiddenChannelLockScreen - match: /"popup".{0,100}?if\((?<=let{channel:(\i).+?inCall:(\i).+?)/, + match: /"popup".{0,100}?if\((?<=channel:(\i).+?inCall:(\i).+?)/, replace: (m, channel, inCall) => `${m}(${inCall}||!$self.isHiddenChannel(${channel},true))&&` }, ] diff --git a/src/plugins/spotifyShareCommands/index.ts b/src/plugins/spotifyShareCommands/index.ts index 3569dd2883a..a3b82dc20fb 100644 --- a/src/plugins/spotifyShareCommands/index.ts +++ b/src/plugins/spotifyShareCommands/index.ts @@ -18,10 +18,9 @@ import { ApplicationCommandInputType, sendBotMessage } from "@api/Commands"; import { Devs } from "@utils/constants"; -import { MessageActions } from "@utils/discord"; import definePlugin from "@utils/types"; import { findByPropsLazy } from "@webpack"; -import { FluxDispatcher } from "@webpack/common"; +import { FluxDispatcher, MessageActions } from "@webpack/common"; interface Album { id: string; diff --git a/src/plugins/typingIndicator/index.tsx b/src/plugins/typingIndicator/index.tsx index c5cf5a9d002..171c560d8ae 100644 --- a/src/plugins/typingIndicator/index.tsx +++ b/src/plugins/typingIndicator/index.tsx @@ -21,7 +21,7 @@ import ErrorBoundary from "@components/ErrorBoundary"; import { Devs } from "@utils/constants"; import definePlugin, { OptionType } from "@utils/types"; import { findExportedComponentLazy, findStoreLazy } from "@webpack"; -import { ChannelStore, GuildMemberStore, i18n, RelationshipStore, Tooltip, UserStore, useStateFromStores } from "@webpack/common"; +import { ChannelStore, GuildMemberStore, i18n, RelationshipStore, SelectedChannelStore, Tooltip, UserStore, useStateFromStores } from "@webpack/common"; import { buildSeveralUsers } from "../typingTweaks"; @@ -47,7 +47,7 @@ function TypingIndicator({ channelId }: { channelId: string; }) { return oldKeys.length === currentKeys.length && currentKeys.every(key => old[key] != null); } ); - + const currentChannelId: string = useStateFromStores([SelectedChannelStore], () => SelectedChannelStore.getChannelId()); const guildId = ChannelStore.getChannel(channelId).guild_id; if (!settings.store.includeMutedChannels) { @@ -55,6 +55,10 @@ function TypingIndicator({ channelId }: { channelId: string; }) { if (isChannelMuted) return null; } + if (!settings.store.includeCurrentChannel) { + if (currentChannelId === channelId) return null; + } + const myId = UserStore.getCurrentUser()?.id; const typingUsersArray = Object.keys(typingUsers).filter(id => id !== myId && !(RelationshipStore.isBlocked(id) && !settings.store.includeBlockedUsers)); @@ -101,6 +105,11 @@ function TypingIndicator({ channelId }: { channelId: string; }) { } const settings = definePluginSettings({ + includeCurrentChannel: { + type: OptionType.BOOLEAN, + description: "Whether to show the typing indicator for the currently selected channel", + default: true + }, includeMutedChannels: { type: OptionType.BOOLEAN, description: "Whether to show the typing indicator for muted channels.", diff --git a/src/plugins/voiceMessages/index.tsx b/src/plugins/voiceMessages/index.tsx index 17e10a4b8e4..f4898de68bf 100644 --- a/src/plugins/voiceMessages/index.tsx +++ b/src/plugins/voiceMessages/index.tsx @@ -21,13 +21,12 @@ import "./styles.css"; import { addContextMenuPatch, NavContextMenuPatchCallback, removeContextMenuPatch } from "@api/ContextMenu"; import { Microphone } from "@components/Icons"; import { Devs } from "@utils/constants"; -import { MessageActions } from "@utils/discord"; import { ModalContent, ModalFooter, ModalHeader, ModalProps, ModalRoot, openModal } from "@utils/modal"; import { useAwaiter } from "@utils/react"; import definePlugin from "@utils/types"; import { chooseFile } from "@utils/web"; import { findByPropsLazy, findStoreLazy } from "@webpack"; -import { Button, FluxDispatcher, Forms, lodash, Menu, PermissionsBits, PermissionStore, RestAPI, SelectedChannelStore, showToast, SnowflakeUtils, Toasts, useEffect, useState } from "@webpack/common"; +import { Button, FluxDispatcher, Forms, lodash, Menu, MessageActions, PermissionsBits, PermissionStore, RestAPI, SelectedChannelStore, showToast, SnowflakeUtils, Toasts, useEffect, useState } from "@webpack/common"; import { ComponentType } from "react"; import { VoiceRecorderDesktop } from "./DesktopRecorder"; diff --git a/src/utils/discord.tsx b/src/utils/discord.tsx index 788f0add73c..74e1aefe8ff 100644 --- a/src/utils/discord.tsx +++ b/src/utils/discord.tsx @@ -17,18 +17,11 @@ */ import { MessageObject } from "@api/MessageEvents"; -import { findByPropsLazy, findStoreLazy } from "@webpack"; -import { ChannelStore, ComponentDispatch, FluxDispatcher, GuildStore, MaskedLink, ModalImageClasses, PrivateChannelsStore, RestAPI, SelectedChannelStore, SelectedGuildStore, UserProfileStore, UserSettingsActionCreators, UserUtils } from "@webpack/common"; +import { ChannelStore, ComponentDispatch, FluxDispatcher, GuildStore, InviteActions, MaskedLink, MessageActions, ModalImageClasses, PrivateChannelsStore, RestAPI, SelectedChannelStore, SelectedGuildStore, UserProfileActions, UserProfileStore, UserSettingsActionCreators, UserUtils } from "@webpack/common"; import { Guild, Message, User } from "discord-types/general"; import { ImageModal, ModalRoot, ModalSize, openModal } from "./modal"; -export const MessageActions = findByPropsLazy("editMessage", "sendMessage"); -export const UserProfileActions = findByPropsLazy("openUserProfileModal", "closeUserProfileModal"); -export const InviteActions = findByPropsLazy("resolveInvite"); - -const InviteModalStore = findStoreLazy("InviteModalStore"); - /** * Open the invite modal * @param code The invite code diff --git a/src/webpack/common/utils.ts b/src/webpack/common/utils.ts index f5d2a966669..c62f745a989 100644 --- a/src/webpack/common/utils.ts +++ b/src/webpack/common/utils.ts @@ -133,3 +133,7 @@ export const zustandCreate: typeof import("zustand").default = findByCodeLazy("w const persistFilter = filters.byCode("[zustand persist middleware]"); export const { persist: zustandPersist }: typeof import("zustand/middleware") = findLazy(m => m.persist && persistFilter(m.persist)); + +export const MessageActions = findByPropsLazy("editMessage", "sendMessage"); +export const UserProfileActions = findByPropsLazy("openUserProfileModal", "closeUserProfileModal"); +export const InviteActions = findByPropsLazy("resolveInvite"); diff --git a/src/webpack/patchWebpack.ts b/src/webpack/patchWebpack.ts index f131471bfb6..db47c875a9a 100644 --- a/src/webpack/patchWebpack.ts +++ b/src/webpack/patchWebpack.ts @@ -58,6 +58,9 @@ if (window[WEBPACK_CHUNK]) { // normally, this is populated via webpackGlobal.push, which we patch below. // However, Discord has their .m prepopulated. // Thus, we use this hack to immediately access their wreq.m and patch all already existing factories + // + // Update: Discord now has TWO webpack instances. Their normal one and sentry + // Sentry does not push chunks to the global at all, so this same patch now also handles their sentry modules Object.defineProperty(Function.prototype, "m", { set(v: any) { // When using react devtools or other extensions, we may also catch their webpack here. @@ -65,8 +68,6 @@ if (window[WEBPACK_CHUNK]) { if (new Error().stack?.includes("discord.com")) { logger.info("Found webpack module factory"); patchFactories(v); - - delete (Function.prototype as any).m; } Object.defineProperty(this, "m", { @@ -142,7 +143,7 @@ function patchFactories(factories: Record Date: Sun, 31 Dec 2023 21:22:01 +0300 Subject: [PATCH 2/2] try to ignore README in pull requests --- .gitattributes | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitattributes b/.gitattributes index 6313b56c578..e410a5314ef 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1 +1,2 @@ * text=auto eol=lf +README.md merge=ours