Merge branch 'Vendicated:main' into listenbrainz

This commit is contained in:
ConfiG 2025-01-24 03:10:11 +03:00 committed by GitHub
commit 351d3eb387
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
13 changed files with 65 additions and 43 deletions

View file

@ -1,7 +1,7 @@
{ {
"name": "vencord", "name": "vencord",
"private": "true", "private": "true",
"version": "1.11.0", "version": "1.11.2",
"description": "The cutest Discord client mod", "description": "The cutest Discord client mod",
"homepage": "https://github.com/Vendicated/Vencord#readme", "homepage": "https://github.com/Vendicated/Vencord#readme",
"bugs": { "bugs": {

View file

@ -16,7 +16,7 @@ import { User } from "discord-types/general";
interface UserProfileProps { interface UserProfileProps {
popoutProps: Record<string, any>; popoutProps: Record<string, any>;
currentUser: User; currentUser: User;
OriginalPopout: () => React.ReactNode; originalRenderPopout: () => React.ReactNode;
} }
const UserProfile = findComponentByCodeLazy("UserProfilePopoutWrapper: user cannot be undefined"); const UserProfile = findComponentByCodeLazy("UserProfilePopoutWrapper: user cannot be undefined");
@ -78,7 +78,7 @@ export default definePlugin({
}, },
{ {
match: /(\.AVATAR,children:.+?renderPopout:(\i)=>){(.+?)}(?=,position)(?<=currentUser:(\i).+?)/, match: /(\.AVATAR,children:.+?renderPopout:(\i)=>){(.+?)}(?=,position)(?<=currentUser:(\i).+?)/,
replace: (_, rest, popoutProps, originalPopout, currentUser) => `${rest}$self.UserProfile({popoutProps:${popoutProps},currentUser:${currentUser},OriginalPopout:()=>{${originalPopout}}})` replace: (_, rest, popoutProps, originalPopout, currentUser) => `${rest}$self.UserProfile({popoutProps:${popoutProps},currentUser:${currentUser},originalRenderPopout:()=>{${originalPopout}}})`
}, },
{ {
match: /\.AVATAR,children:.+?(?=renderPopout:)/, match: /\.AVATAR,children:.+?(?=renderPopout:)/,
@ -112,17 +112,17 @@ export default definePlugin({
openAlternatePopout = false; openAlternatePopout = false;
}, },
UserProfile: ErrorBoundary.wrap(({ popoutProps, currentUser, OriginalPopout }: UserProfileProps) => { UserProfile: ErrorBoundary.wrap(({ popoutProps, currentUser, originalRenderPopout }: UserProfileProps) => {
if ( if (
(settings.store.prioritizeServerProfile && openAlternatePopout) || (settings.store.prioritizeServerProfile && openAlternatePopout) ||
(!settings.store.prioritizeServerProfile && !openAlternatePopout) (!settings.store.prioritizeServerProfile && !openAlternatePopout)
) { ) {
return <OriginalPopout />; return originalRenderPopout();
} }
const currentChannel = getCurrentChannel(); const currentChannel = getCurrentChannel();
if (currentChannel?.getGuildId() == null) { if (currentChannel?.getGuildId() == null) {
return <OriginalPopout />; return originalRenderPopout();
} }
return ( return (

View file

@ -41,7 +41,7 @@ export default definePlugin({
}, },
{ {
// Status emojis // Status emojis
find: "#{intl::GUILD_OWNER}", find: "#{intl::GUILD_OWNER}),children:",
replacement: { replacement: {
match: /(?<=\.activityEmoji,.+?animate:)\i/, match: /(?<=\.activityEmoji,.+?animate:)\i/,
replace: "!0" replace: "!0"

View file

@ -27,7 +27,7 @@ export default definePlugin({
{ {
find: '"ChannelAttachButton"', find: '"ChannelAttachButton"',
replacement: { replacement: {
match: /\.attachButtonInner,"aria-label":.{0,50},onDoubleClick:(.+?:void 0),\.\.\.(\i),/, match: /\.attachButtonInner,"aria-label":.{0,50},onDoubleClick:(.+?:void 0),.{0,30}?\.\.\.(\i),/,
replace: "$&onClick:$1,onContextMenu:$2.onClick,", replace: "$&onClick:$1,onContextMenu:$2.onClick,",
}, },
}, },

View file

@ -19,6 +19,7 @@
import { definePluginSettings, Settings } from "@api/Settings"; import { definePluginSettings, Settings } from "@api/Settings";
import { getUserSettingLazy } from "@api/UserSettings"; import { getUserSettingLazy } from "@api/UserSettings";
import { ErrorCard } from "@components/ErrorCard"; import { ErrorCard } from "@components/ErrorCard";
import { Flex } from "@components/Flex";
import { Link } from "@components/Link"; import { Link } from "@components/Link";
import { Devs } from "@utils/constants"; import { Devs } from "@utils/constants";
import { isTruthy } from "@utils/guards"; import { isTruthy } from "@utils/guards";
@ -27,15 +28,14 @@ import { classes } from "@utils/misc";
import { useAwaiter } from "@utils/react"; import { useAwaiter } from "@utils/react";
import definePlugin, { OptionType } from "@utils/types"; import definePlugin, { OptionType } from "@utils/types";
import { findByCodeLazy, findComponentByCodeLazy } from "@webpack"; import { findByCodeLazy, findComponentByCodeLazy } from "@webpack";
import { ApplicationAssetUtils, Button, FluxDispatcher, Forms, GuildStore, React, SelectedChannelStore, SelectedGuildStore, UserStore } from "@webpack/common"; import { ApplicationAssetUtils, Button, FluxDispatcher, Forms, React, UserStore } from "@webpack/common";
const useProfileThemeStyle = findByCodeLazy("profileThemeStyle:", "--profile-gradient-primary-color"); const useProfileThemeStyle = findByCodeLazy("profileThemeStyle:", "--profile-gradient-primary-color");
const ActivityComponent = findComponentByCodeLazy("onOpenGameProfile"); const ActivityView = findComponentByCodeLazy(".party?(0", ".card");
const ShowCurrentGame = getUserSettingLazy<boolean>("status", "showCurrentGame")!; const ShowCurrentGame = getUserSettingLazy<boolean>("status", "showCurrentGame")!;
async function getApplicationAsset(key: string): Promise<string> { async function getApplicationAsset(key: string): Promise<string> {
if (/https?:\/\/(cdn|media)\.discordapp\.(com|net)\/attachments\//.test(key)) return "mp:" + key.replace(/https?:\/\/(cdn|media)\.discordapp\.(com|net)\//, "");
return (await ApplicationAssetUtils.fetchAssetIds(settings.store.appID!, [key]))[0]; return (await ApplicationAssetUtils.fetchAssetIds(settings.store.appID!, [key]))[0];
} }
@ -169,7 +169,7 @@ const settings = definePluginSettings({
value: TimestampMode.NOW value: TimestampMode.NOW
}, },
{ {
label: "Same as your current time", label: "Same as your current time (not reset after 24h)",
value: TimestampMode.TIME value: TimestampMode.TIME
}, },
{ {
@ -269,6 +269,7 @@ function isStreamLinkDisabled() {
function isStreamLinkValid(value: string) { function isStreamLinkValid(value: string) {
if (!isStreamLinkDisabled() && !/https?:\/\/(www\.)?(twitch\.tv|youtube\.com)\/\w+/.test(value)) return "Streaming link must be a valid URL."; if (!isStreamLinkDisabled() && !/https?:\/\/(www\.)?(twitch\.tv|youtube\.com)\/\w+/.test(value)) return "Streaming link must be a valid URL.";
if (value && value.length > 512) return "Streaming link must be not longer than 512 characters.";
return true; return true;
} }
@ -277,8 +278,9 @@ function isTimestampDisabled() {
} }
function isImageKeyValid(value: string) { function isImageKeyValid(value: string) {
if (/https?:\/\/(?!i\.)?imgur\.com\//.test(value)) return "Imgur link must be a direct link to the image. (e.g. https://i.imgur.com/...)"; if (/https?:\/\/(cdn|media)\.discordapp\.(com|net)\//.test(value)) return "Don't use a Discord link. Use an Imgur image link instead.";
if (/https?:\/\/(?!media\.)?tenor\.com\//.test(value)) return "Tenor link must be a direct link to the image. (e.g. https://media.tenor.com/...)"; if (/https?:\/\/(?!i\.)?imgur\.com\//.test(value)) return "Imgur link must be a direct link to the image (e.g. https://i.imgur.com/...). Right click the image and click 'Copy image address'";
if (/https?:\/\/(?!media\.)?tenor\.com\//.test(value)) return "Tenor link must be a direct link to the image (e.g. https://media.tenor.com/...). Right click the GIF and click 'Copy image address'";
return true; return true;
} }
@ -390,13 +392,24 @@ async function setRpc(disable?: boolean) {
export default definePlugin({ export default definePlugin({
name: "CustomRPC", name: "CustomRPC",
description: "Allows you to set a custom rich presence.", description: "Add a fully customisable Rich Presence (Game status) to your Discord profile",
authors: [Devs.captain, Devs.AutumnVN, Devs.nin0dev], authors: [Devs.captain, Devs.AutumnVN, Devs.nin0dev],
dependencies: ["UserSettingsAPI"], dependencies: ["UserSettingsAPI"],
start: setRpc, start: setRpc,
stop: () => setRpc(true), stop: () => setRpc(true),
settings, settings,
patches: [
{
find: ".party?(0",
all: true,
replacement: {
match: /\i\.id===\i\.id\?null:/,
replace: ""
}
}
],
settingsAboutComponent: () => { settingsAboutComponent: () => {
const activity = useAwaiter(createActivity); const activity = useAwaiter(createActivity);
const gameActivityEnabled = ShowCurrentGame.useSetting(); const gameActivityEnabled = ShowCurrentGame.useSetting();
@ -410,7 +423,7 @@ export default definePlugin({
style={{ padding: "1em" }} style={{ padding: "1em" }}
> >
<Forms.FormTitle>Notice</Forms.FormTitle> <Forms.FormTitle>Notice</Forms.FormTitle>
<Forms.FormText>Game activity isn't enabled, people won't be able to see your custom rich presence!</Forms.FormText> <Forms.FormText>Activity Sharing isn't enabled, people won't be able to see your custom rich presence!</Forms.FormText>
<Button <Button
color={Button.Colors.TRANSPARENT} color={Button.Colors.TRANSPARENT}
@ -422,24 +435,33 @@ export default definePlugin({
</ErrorCard> </ErrorCard>
)} )}
<Forms.FormText> <Flex flexDirection="column" style={{ gap: ".5em" }} className={Margins.top16}>
Go to <Link href="https://discord.com/developers/applications">Discord Developer Portal</Link> to create an application and <Forms.FormText>
get the application ID. Go to the <Link href="https://discord.com/developers/applications">Discord Developer Portal</Link> to create an application and
</Forms.FormText> get the application ID.
<Forms.FormText> </Forms.FormText>
Upload images in the Rich Presence tab to get the image keys. <Forms.FormText>
</Forms.FormText> Upload images in the Rich Presence tab to get the image keys.
<Forms.FormText> </Forms.FormText>
If you want to use image link, download your image and reupload the image to <Link href="https://imgur.com">Imgur</Link> and get the image link by right-clicking the image and select "Copy image address". <Forms.FormText>
</Forms.FormText> If you want to use an image link, download your image and reupload the image to <Link href="https://imgur.com">Imgur</Link> and get the image link by right-clicking the image and selecting "Copy image address".
</Forms.FormText>
<Forms.FormText>
You can't see your own buttons on your profile, but everyone else can see it fine.
</Forms.FormText>
<Forms.FormText>
Some weird unicode text ("fonts" 𝖑𝖎𝖐𝖊 𝖙𝖍𝖎𝖘) may cause the rich presence to not show up, try using normal letters instead.
</Forms.FormText>
</Flex>
<Forms.FormDivider className={Margins.top8} /> <Forms.FormDivider className={Margins.top8} />
<div style={{ width: "284px", ...profileThemeStyle, padding: 8, marginTop: 8, borderRadius: 8, background: "var(--bg-mod-faint)" }}> <div style={{ width: "284px", ...profileThemeStyle, marginTop: 8, borderRadius: 8, background: "var(--bg-mod-faint)" }}>
{activity[0] && <ActivityComponent activity={activity[0]} channelId={SelectedChannelStore.getChannelId()} {activity[0] && <ActivityView
guild={GuildStore.getGuild(SelectedGuildStore.getLastSelectedGuildId())} activity={activity[0]}
application={{ id: settings.store.appID }} user={UserStore.getCurrentUser()}
user={UserStore.getCurrentUser()} />} currentUser={UserStore.getCurrentUser()}
/>}
</div> </div>
</> </>
); );

View file

@ -391,7 +391,7 @@ export default definePlugin({
}, },
// Separate patch for allowing using custom app icons // Separate patch for allowing using custom app icons
{ {
find: /\.getCurrentDesktopIcon.{0,25}\.isPremium/, find: "?24:30,",
replacement: { replacement: {
match: /\i\.\i\.isPremium\(\i\.\i\.getCurrentUser\(\)\)/, match: /\i\.\i\.isPremium\(\i\.\i\.getCurrentUser\(\)\)/,
replace: "true" replace: "true"

View file

@ -13,7 +13,7 @@ export default definePlugin({
authors: [Devs.Nuckyz], authors: [Devs.Nuckyz],
patches: [ patches: [
{ {
find: "getFormatQuality(){", find: ".handleImageLoad)",
replacement: { replacement: {
match: /(?<=null;return )\i\.\i&&\(\i\|\|!\i\.isAnimated.+?:(?=\i&&\(\i="png"\))/, match: /(?<=null;return )\i\.\i&&\(\i\|\|!\i\.isAnimated.+?:(?=\i&&\(\i="png"\))/,
replace: "" replace: ""

View file

@ -27,7 +27,7 @@ export default definePlugin({
authors: [Devs.D3SOX, Devs.Nickyux], authors: [Devs.D3SOX, Devs.Nickyux],
patches: [ patches: [
{ {
find: "#{intl::GUILD_OWNER}", find: "#{intl::GUILD_OWNER}),children:",
replacement: { replacement: {
match: /,isOwner:(\i),/, match: /,isOwner:(\i),/,
replace: ",_isOwner:$1=$self.isGuildOwner(e)," replace: ",_isOwner:$1=$self.isGuildOwner(e),"

View file

@ -16,7 +16,7 @@ interface UserMentionComponentProps {
id: string; id: string;
channelId: string; channelId: string;
guildId: string; guildId: string;
OriginalComponent: () => ReactNode; originalComponent: () => ReactNode;
} }
export default definePlugin({ export default definePlugin({
@ -29,7 +29,7 @@ export default definePlugin({
find: ':"text":', find: ':"text":',
replacement: { replacement: {
match: /(hidePersonalInformation\).+?)(if\(null!=\i\){.+?return \i)(?=})/, match: /(hidePersonalInformation\).+?)(if\(null!=\i\){.+?return \i)(?=})/,
replace: "$1return $self.UserMentionComponent({...arguments[0],OriginalComponent:()=>{$2}});" replace: "$1return $self.UserMentionComponent({...arguments[0],originalComponent:()=>{$2}});"
} }
} }
], ],
@ -42,6 +42,6 @@ export default definePlugin({
channelId={props.channelId} channelId={props.channelId}
/> />
), { ), {
fallback: ({ wrappedProps: { OriginalComponent } }) => <OriginalComponent /> fallback: ({ wrappedProps: { originalComponent } }) => originalComponent()
}) })
}); });

View file

@ -218,7 +218,7 @@ export default definePlugin({
}, },
// in the member list // in the member list
{ {
find: "#{intl::GUILD_OWNER}", find: "#{intl::GUILD_OWNER}),children:",
replacement: { replacement: {
match: /(?<type>\i)=\(null==.{0,100}\.BOT;return null!=(?<user>\i)&&\i\.bot/, match: /(?<type>\i)=\(null==.{0,100}\.BOT;return null!=(?<user>\i)&&\i\.bot/,
replace: "$<type> = $self.getTag({user: $<user>, channel: arguments[0].channel, origType: $<user>.bot ? 0 : null, location: 'not-chat' }); return typeof $<type> === 'number'" replace: "$<type> = $self.getTag({user: $<user>, channel: arguments[0].channel, origType: $<user>.bot ? 0 : null, location: 'not-chat' }); return typeof $<type> === 'number'"

View file

@ -55,7 +55,7 @@ export default definePlugin({
}, },
{ {
// Clicking on replied messages to jump // Clicking on replied messages to jump
find: "flash:!0,returnMessageId", find: '("interactionUsernameProfile',
replacement: [ replacement: [
{ {
match: /.\?(.{1,10}\.show\({.{1,50}#{intl::UNBLOCK_TO_JUMP_TITLE})/, match: /.\?(.{1,10}\.show\({.{1,50}#{intl::UNBLOCK_TO_JUMP_TITLE})/,

View file

@ -108,7 +108,7 @@ export default definePlugin({
patches: [ patches: [
{ {
find: "#{intl::MESSAGE_ACTIONS_MENU_LABEL}", find: "#{intl::MESSAGE_ACTIONS_MENU_LABEL}),shouldHideMediaOptions:",
replacement: { replacement: {
match: /favoriteableType:\i,(?<=(\i)\.getAttribute\("data-type"\).+?)/, match: /favoriteableType:\i,(?<=(\i)\.getAttribute\("data-type"\).+?)/,
replace: (m, target) => `${m}reverseImageSearchType:${target}.getAttribute("data-role"),` replace: (m, target) => `${m}reverseImageSearchType:${target}.getAttribute("data-role"),`

View file

@ -58,7 +58,7 @@ export default definePlugin({
}, },
}, },
{ {
find: /context:\i,checkElevated:!1\}\),\i\.\i.{0,200}autoTrackExposure/, find: /,checkElevated:!1}\),\i\.\i\)}(?<=getCurrentUser\(\);return.+?)/,
predicate: () => settings.store.showModView, predicate: () => settings.store.showModView,
replacement: { replacement: {
match: /return \i\.\i\(\i\.\i\(\{user:\i,context:\i,checkElevated:!1\}\),\i\.\i\)/, match: /return \i\.\i\(\i\.\i\(\{user:\i,context:\i,checkElevated:!1\}\),\i\.\i\)/,
@ -67,7 +67,7 @@ export default definePlugin({
}, },
// fixes a bug where Members page must be loaded to see highest role, why is Discord depending on MemberSafetyStore.getEnhancedMember for something that can be obtained here? // fixes a bug where Members page must be loaded to see highest role, why is Discord depending on MemberSafetyStore.getEnhancedMember for something that can be obtained here?
{ {
find: "#{intl::GUILD_MEMBER_MOD_VIEW_PERMISSION_GRANTED_BY_ARIA_LABEL}", find: "#{intl::GUILD_MEMBER_MOD_VIEW_PERMISSION_GRANTED_BY_ARIA_LABEL}),allowOverflow:",
predicate: () => settings.store.showModView, predicate: () => settings.store.showModView,
replacement: { replacement: {
match: /(role:)\i(?=,guildId.{0,100}role:(\i\[))/, match: /(role:)\i(?=,guildId.{0,100}role:(\i\[))/,
@ -76,7 +76,7 @@ export default definePlugin({
}, },
// allows you to open mod view on yourself // allows you to open mod view on yourself
{ {
find: ".MEMBER_SAFETY,{modViewPanel:", find: 'action:"PRESS_MOD_VIEW",icon:',
predicate: () => settings.store.showModView, predicate: () => settings.store.showModView,
replacement: { replacement: {
match: /\i(?=\?null)/, match: /\i(?=\?null)/,