From 3325a8de4060d3837f1480d2aec3bdbe8208f90c Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Tue, 6 Feb 2024 21:30:07 -0300 Subject: [PATCH 01/20] Fix FakeNitro patch --- src/plugins/fakeNitro/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/fakeNitro/index.ts b/src/plugins/fakeNitro/index.ts index 6107df00e..0b96412fd 100644 --- a/src/plugins/fakeNitro/index.ts +++ b/src/plugins/fakeNitro/index.ts @@ -345,7 +345,7 @@ export default definePlugin({ predicate: () => settings.store.transformEmojis, replacement: { // Add the fake nitro emoji notice - match: /(?<=isDiscoverable:\i,emojiComesFromCurrentGuild:\i,.+?}=(\i).+?;)(.+?return )(.{0,1000}\.Messages\.EMOJI_POPOUT_UNJOINED_DISCOVERABLE_GUILD_DESCRIPTION.+?)(?=},)/, + match: /(?<=isDiscoverable:\i,emojiComesFromCurrentGuild:\i,.+?}=(\i).+?;)(.*?return )(.{0,1000}\.Messages\.EMOJI_POPOUT_UNJOINED_DISCOVERABLE_GUILD_DESCRIPTION.+?)(?=},)/, replace: (_, props, rest, reactNode) => `let{fakeNitroNode}=${props};${rest}$self.addFakeNotice(${FakeNoticeType.Emoji},${reactNode},!!fakeNitroNode?.fake)` } }, From a108448255261c9bffa0911386a35d6e2ba93117 Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Wed, 7 Feb 2024 20:39:02 -0300 Subject: [PATCH 02/20] Improve DisableDMCallIdle --- src/plugins/disableDMCallIdle/index.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plugins/disableDMCallIdle/index.ts b/src/plugins/disableDMCallIdle/index.ts index bce119d01..5738dc238 100644 --- a/src/plugins/disableDMCallIdle/index.ts +++ b/src/plugins/disableDMCallIdle/index.ts @@ -27,8 +27,8 @@ export default definePlugin({ { find: ".Messages.BOT_CALL_IDLE_DISCONNECT", replacement: { - match: /(?<=function \i\(\){)(?=.{1,120}\.Messages\.BOT_CALL_IDLE_DISCONNECT)/, - replace: "return;" + match: /,?(?=this\.idleTimeout=new \i\.Timeout)/, + replace: ";return;" } } ] From 935d0a0a03a7e713014fc1019b1b36d5f1989980 Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Thu, 8 Feb 2024 15:33:49 -0300 Subject: [PATCH 03/20] Fix broken patches and finds --- src/plugins/showHiddenChannels/index.tsx | 4 ++-- src/plugins/typingIndicator/index.tsx | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/plugins/showHiddenChannels/index.tsx b/src/plugins/showHiddenChannels/index.tsx index 906bed504..919f3f3c5 100644 --- a/src/plugins/showHiddenChannels/index.tsx +++ b/src/plugins/showHiddenChannels/index.tsx @@ -29,7 +29,7 @@ import type { Channel, Role } from "discord-types/general"; import HiddenChannelLockScreen from "./components/HiddenChannelLockScreen"; -const ChannelListClasses = findByPropsLazy("channelEmoji", "unread", "icon"); +const ChannelListClasses = findByPropsLazy("modeMuted", "modeSelected", "unread", "icon"); const enum ShowMode { LockIcon, @@ -162,7 +162,7 @@ export default definePlugin({ }, // Add the hidden eye icon if the channel is hidden { - match: /\i\.children.+?:null(?<=,channel:(\i).+?)/, + match: /\.name\),.{0,120}\.children.+?:null(?<=,channel:(\i).+?)/, replace: (m, channel) => `${m},$self.isHiddenChannel(${channel})?$self.HiddenChannelIcon():null` }, // Make voice channels also appear as muted if they are muted diff --git a/src/plugins/typingIndicator/index.tsx b/src/plugins/typingIndicator/index.tsx index 171c560d8..280301480 100644 --- a/src/plugins/typingIndicator/index.tsx +++ b/src/plugins/typingIndicator/index.tsx @@ -133,7 +133,7 @@ export default definePlugin({ { find: "UNREAD_IMPORTANT:", replacement: { - match: /channel:(\i).{0,100}?channelEmoji,.{0,250}?\.children.{0,50}?:null/, + match: /\.name\),.{0,120}\.children.+?:null(?<=,channel:(\i).+?)/, replace: "$&,$self.TypingIndicator($1.id)" } }, From f1f0da4a9db09625a50a812285c4479d5e692036 Mon Sep 17 00:00:00 2001 From: Klen_list <49125075+klen-list@users.noreply.github.com> Date: Thu, 8 Feb 2024 21:55:48 +0300 Subject: [PATCH 04/20] fixYoutubeEmbeds: fix when youtube decides to use http without s (#2155) Co-authored-by: V --- src/plugins/fixYoutubeEmbeds.desktop/native.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/fixYoutubeEmbeds.desktop/native.ts b/src/plugins/fixYoutubeEmbeds.desktop/native.ts index 5419d4ad8..d5c2df363 100644 --- a/src/plugins/fixYoutubeEmbeds.desktop/native.ts +++ b/src/plugins/fixYoutubeEmbeds.desktop/native.ts @@ -17,7 +17,7 @@ app.on("browser-window-created", (_, win) => { frame.executeJavaScript(` new MutationObserver(() => { if( - document.querySelector('div.ytp-error-content-wrap-subreason a[href^="https://www.youtube.com/watch?v="]') + document.querySelector('div.ytp-error-content-wrap-subreason a[href*="www.youtube.com/watch?v="]') ) location.reload() }).observe(document.body, { childList: true, subtree:true }); `); From b2c047390e1e383758aa6e996b5c255a1e31d003 Mon Sep 17 00:00:00 2001 From: sappho Date: Fri, 9 Feb 2024 17:31:02 -0500 Subject: [PATCH 05/20] FakeNitro: Send fake links using Discord hyperlink markdown feature (#2158) --- src/plugins/fakeNitro/index.ts | 53 ++++++++++++++++++++++------------ 1 file changed, 34 insertions(+), 19 deletions(-) diff --git a/src/plugins/fakeNitro/index.ts b/src/plugins/fakeNitro/index.ts index 0b96412fd..2caecc45b 100644 --- a/src/plugins/fakeNitro/index.ts +++ b/src/plugins/fakeNitro/index.ts @@ -108,6 +108,7 @@ const enum FakeNoticeType { const fakeNitroEmojiRegex = /\/emojis\/(\d+?)\.(png|webp|gif)/; const fakeNitroStickerRegex = /\/stickers\/(\d+?)\./; const fakeNitroGifStickerRegex = /\/attachments\/\d+?\/\d+?\/(\d+?)\.gif/; +const hyperLinkRegex = /\[.+?\]\((https?:\/\/.+?)\)/; const settings = definePluginSettings({ enableEmojiBypass: { @@ -447,13 +448,23 @@ export default definePlugin({ trimContent(content: Array) { const firstContent = content[0]; - if (typeof firstContent === "string") content[0] = firstContent.trimStart(); - if (content[0] === "") content.shift(); + if (typeof firstContent === "string") { + content[0] = firstContent.trimStart(); + content[0] || content.shift(); + } else if (firstContent?.type === "span") { + firstContent.props.children = firstContent.props.children.trimStart(); + firstContent.props.children || content.shift(); + } const lastIndex = content.length - 1; const lastContent = content[lastIndex]; - if (typeof lastContent === "string") content[lastIndex] = lastContent.trimEnd(); - if (content[lastIndex] === "") content.pop(); + if (typeof lastContent === "string") { + content[lastIndex] = lastContent.trimEnd(); + content[lastIndex] || content.pop(); + } else if (lastContent?.type === "span") { + lastContent.props.children = lastContent.props.children.trimEnd(); + lastContent.props.children || content.pop(); + } }, clearEmptyArrayItems(array: Array) { @@ -465,7 +476,7 @@ export default definePlugin({ }, patchFakeNitroEmojisOrRemoveStickersLinks(content: Array, inline: boolean) { - // If content has more than one child or it's a single ReactElement like a header or list + // If content has more than one child or it's a single ReactElement like a header, list or span if ((content.length > 1 || typeof content[0]?.type === "string") && !settings.store.transformCompoundSentence) return content; let nextIndex = content.length; @@ -574,7 +585,7 @@ export default definePlugin({ itemsToMaybePush.push(...message.attachments.filter(attachment => attachment.content_type === "image/gif").map(attachment => attachment.url)); for (const item of itemsToMaybePush) { - if (!settings.store.transformCompoundSentence && !item.startsWith("http")) continue; + if (!settings.store.transformCompoundSentence && !item.startsWith("http") && !hyperLinkRegex.test(item)) continue; const imgMatch = item.match(fakeNitroStickerRegex); if (imgMatch) { @@ -619,8 +630,7 @@ export default definePlugin({ case "image": { if ( !settings.store.transformCompoundSentence - && !contentItems.includes(embed.url!) - && !contentItems.includes(embed.image?.proxyURL!) + && !contentItems.some(item => item === embed.url! || item.match(hyperLinkRegex)?.[1] === embed.url!) ) return false; if (settings.store.transformEmojis) { @@ -795,12 +805,16 @@ export default definePlugin({ 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 }; } else { + const url = new URL(link); + url.searchParams.set("name", sticker.name); + + messageObj.content += `${getWordBoundary(messageObj.content, messageObj.content.length - 1)}[${sticker.name}](${url})`; extra.stickers!.length = 0; - messageObj.content += ` ${link}&name=${encodeURIComponent(sticker.name)}`; } } @@ -813,12 +827,13 @@ export default definePlugin({ if (emoji.guildId === guildId && !emoji.animated) continue; const emojiString = `<${emoji.animated ? "a" : ""}:${emoji.originalName || emoji.name}:${emoji.id}>`; - const url = emoji.url.replace(/\?size=\d+/, "?" + new URLSearchParams({ - size: Settings.plugins.FakeNitro.emojiSize, - name: encodeURIComponent(emoji.name) - })); + + const url = new URL(emoji.url); + url.searchParams.set("size", settings.store.emojiSize.toString()); + url.searchParams.set("name", emoji.name); + messageObj.content = messageObj.content.replace(emojiString, (match, offset, origStr) => { - return `${getWordBoundary(origStr, offset - 1)}${url}${getWordBoundary(origStr, offset + match.length)}`; + return `${getWordBoundary(origStr, offset - 1)}[:${emoji.name}:](${url})${getWordBoundary(origStr, offset + match.length)}`; }); } } @@ -840,11 +855,11 @@ export default definePlugin({ if (emoji.available !== false && canUseEmotes) return emojiStr; if (emoji.guildId === guildId && !emoji.animated) return emojiStr; - const url = emoji.url.replace(/\?size=\d+/, "?" + new URLSearchParams({ - size: Settings.plugins.FakeNitro.emojiSize, - name: encodeURIComponent(emoji.name) - })); - return `${getWordBoundary(origStr, offset - 1)}${url}${getWordBoundary(origStr, offset + emojiStr.length)}`; + const url = new URL(emoji.url); + url.searchParams.set("size", settings.store.emojiSize.toString()); + url.searchParams.set("name", emoji.name); + + return `${getWordBoundary(origStr, offset - 1)}[:${emoji.name}:](${url})${getWordBoundary(origStr, offset + emojiStr.length)}`; }); }); }, From 237f0804717d0fe9bef1f33c0eea9f7682dba884 Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Fri, 9 Feb 2024 17:59:40 -0300 Subject: [PATCH 06/20] DisableDMCallIdle -> DisableCallIdle; add more functionality --- .../{disableDMCallIdle => disableCallIdle}/index.ts | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) rename src/plugins/{disableDMCallIdle => disableCallIdle}/index.ts (74%) diff --git a/src/plugins/disableDMCallIdle/index.ts b/src/plugins/disableCallIdle/index.ts similarity index 74% rename from src/plugins/disableDMCallIdle/index.ts rename to src/plugins/disableCallIdle/index.ts index 5738dc238..904d53b03 100644 --- a/src/plugins/disableDMCallIdle/index.ts +++ b/src/plugins/disableCallIdle/index.ts @@ -16,12 +16,14 @@ * along with this program. If not, see . */ +import { migratePluginSettings } from "@api/Settings"; import { Devs } from "@utils/constants"; import definePlugin from "@utils/types"; +migratePluginSettings("DisableCallIdle", "DisableDMCallIdle"); export default definePlugin({ - name: "DisableDMCallIdle", - description: "Disables automatically getting kicked from a DM voice call after 3 minutes.", + name: "DisableCallIdle", + description: "Disables automatically getting kicked from a DM voice call after 3 minutes and being moved to an AFK voice channel.", authors: [Devs.Nuckyz], patches: [ { @@ -30,6 +32,13 @@ export default definePlugin({ match: /,?(?=this\.idleTimeout=new \i\.Timeout)/, replace: ";return;" } + }, + { + find: "handleIdleUpdate(){", + replacement: { + match: /(?<=_initialize\(\){)/, + replace: "return;" + } } ] }); From 558c2a0b2ef46cb19ecabef64e11f0b11ca9bd32 Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Fri, 9 Feb 2024 19:46:10 -0300 Subject: [PATCH 07/20] Make PermissionsViewer and ShowHiddenChannels default dropdown change when clicked --- .../permissionsViewer/components/UserPermissions.tsx | 1 + .../components/HiddenChannelLockScreen.tsx | 10 +++++----- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/plugins/permissionsViewer/components/UserPermissions.tsx b/src/plugins/permissionsViewer/components/UserPermissions.tsx index 3c6767713..bcd6bdf07 100644 --- a/src/plugins/permissionsViewer/components/UserPermissions.tsx +++ b/src/plugins/permissionsViewer/components/UserPermissions.tsx @@ -104,6 +104,7 @@ function UserPermissionsComponent({ guild, guildMember, showBorder }: { guild: G guildMember.nick || UserStore.getUser(guildMember.userId).username ) } + onDropDownClick={state => settings.store.defaultPermissionsDropdownState = !state} defaultState={settings.store.defaultPermissionsDropdownState} buttons={[ ( diff --git a/src/plugins/showHiddenChannels/components/HiddenChannelLockScreen.tsx b/src/plugins/showHiddenChannels/components/HiddenChannelLockScreen.tsx index 87946110d..7904cd10b 100644 --- a/src/plugins/showHiddenChannels/components/HiddenChannelLockScreen.tsx +++ b/src/plugins/showHiddenChannels/components/HiddenChannelLockScreen.tsx @@ -120,7 +120,7 @@ const VideoQualityModesToNames = { const HiddenChannelLogo = "/assets/433e3ec4319a9d11b0cbe39342614982.svg"; function HiddenChannelLockScreen({ channel }: { channel: ExtendedChannel; }) { - const [viewAllowedUsersAndRoles, setViewAllowedUsersAndRoles] = useState(settings.store.defaultAllowedUsersAndRolesDropdownState); + const { defaultAllowedUsersAndRolesDropdownState } = settings.use(["defaultAllowedUsersAndRolesDropdownState"]); const [permissions, setPermissions] = useState([]); const { @@ -301,19 +301,19 @@ function HiddenChannelLockScreen({ channel }: { channel: ExtendedChannel; }) { )} Allowed users and roles: - + {({ onMouseLeave, onMouseEnter }) => (