Merge branch 'dev' into immediate-finds
This commit is contained in:
commit
8045d65e99
73
src/plugins/automodContext/index.tsx
Normal file
73
src/plugins/automodContext/index.tsx
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
/*
|
||||||
|
* Vencord, a Discord client mod
|
||||||
|
* Copyright (c) 2024 Vendicated and contributors
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
import ErrorBoundary from "@components/ErrorBoundary";
|
||||||
|
import { Devs } from "@utils/constants";
|
||||||
|
import definePlugin from "@utils/types";
|
||||||
|
import { findByProps } from "@webpack";
|
||||||
|
import { Button, ChannelStore, Text } from "@webpack/common";
|
||||||
|
|
||||||
|
const { selectChannel } = findByProps("selectChannel", "selectVoiceChannel");
|
||||||
|
|
||||||
|
function jumpToMessage(channelId: string, messageId: string) {
|
||||||
|
const guildId = ChannelStore.getChannel(channelId)?.guild_id;
|
||||||
|
|
||||||
|
selectChannel({
|
||||||
|
guildId,
|
||||||
|
channelId,
|
||||||
|
messageId,
|
||||||
|
jumpType: "INSTANT"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function findChannelId(message: any): string | null {
|
||||||
|
const { embeds: [embed] } = message;
|
||||||
|
const channelField = embed.fields.find(({ rawName }) => rawName === "channel_id");
|
||||||
|
|
||||||
|
if (!channelField) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return channelField.rawValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default definePlugin({
|
||||||
|
name: "AutomodContext",
|
||||||
|
description: "Allows you to jump to the messages surrounding an automod hit.",
|
||||||
|
authors: [Devs.JohnyTheCarrot],
|
||||||
|
|
||||||
|
patches: [
|
||||||
|
{
|
||||||
|
find: ".Messages.GUILD_AUTOMOD_REPORT_ISSUES",
|
||||||
|
replacement: {
|
||||||
|
match: /\.Messages\.ACTIONS.+?}\)(?=,(\(0.{0,40}\.dot.*?}\)),)/,
|
||||||
|
replace: (m, dot) => `${m},${dot},$self.renderJumpButton({message:arguments[0].message})`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
|
||||||
|
renderJumpButton: ErrorBoundary.wrap(({ message }: { message: any; }) => {
|
||||||
|
const channelId = findChannelId(message);
|
||||||
|
|
||||||
|
if (!channelId) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Button
|
||||||
|
style={{ padding: "2px 8px" }}
|
||||||
|
look={Button.Looks.LINK}
|
||||||
|
size={Button.Sizes.SMALL}
|
||||||
|
color={Button.Colors.LINK}
|
||||||
|
onClick={() => jumpToMessage(channelId, message.id)}
|
||||||
|
>
|
||||||
|
<Text color="text-link" variant="text-xs/normal">
|
||||||
|
Jump to Surrounding
|
||||||
|
</Text>
|
||||||
|
</Button>
|
||||||
|
);
|
||||||
|
}, { noop: true })
|
||||||
|
});
|
|
@ -25,7 +25,7 @@ import { Logger } from "@utils/Logger";
|
||||||
import definePlugin, { OptionType } from "@utils/types";
|
import definePlugin, { OptionType } from "@utils/types";
|
||||||
import { findByProps, findStore, webpackDependantLazy } from "@webpack";
|
import { findByProps, findStore, webpackDependantLazy } from "@webpack";
|
||||||
import { Alerts, ChannelStore, DraftType, EmojiStore, FluxDispatcher, Forms, IconUtils, lodash, Parser, PermissionsBits, PermissionStore, UploadHandler, UserSettingsActionCreators, UserStore } from "@webpack/common";
|
import { Alerts, ChannelStore, DraftType, EmojiStore, FluxDispatcher, Forms, IconUtils, lodash, Parser, PermissionsBits, PermissionStore, UploadHandler, UserSettingsActionCreators, UserStore } from "@webpack/common";
|
||||||
import type { CustomEmoji } from "@webpack/types";
|
import type { Emoji } from "@webpack/types";
|
||||||
import type { Message } from "discord-types/general";
|
import type { Message } from "discord-types/general";
|
||||||
import { applyPalette, GIFEncoder, quantize } from "gifenc";
|
import { applyPalette, GIFEncoder, quantize } from "gifenc";
|
||||||
import type { ReactElement, ReactNode } from "react";
|
import type { ReactElement, ReactNode } from "react";
|
||||||
|
@ -53,16 +53,22 @@ const AppearanceSettingsActionCreators = webpackDependantLazy(() => searchProtoC
|
||||||
const ClientThemeSettingsActionsCreators = webpackDependantLazy(() => searchProtoClassField("clientThemeSettings", AppearanceSettingsActionCreators));
|
const ClientThemeSettingsActionsCreators = webpackDependantLazy(() => searchProtoClassField("clientThemeSettings", AppearanceSettingsActionCreators));
|
||||||
|
|
||||||
const enum EmojiIntentions {
|
const enum EmojiIntentions {
|
||||||
REACTION = 0,
|
REACTION,
|
||||||
STATUS = 1,
|
STATUS,
|
||||||
COMMUNITY_CONTENT = 2,
|
COMMUNITY_CONTENT,
|
||||||
CHAT = 3,
|
CHAT,
|
||||||
GUILD_STICKER_RELATED_EMOJI = 4,
|
GUILD_STICKER_RELATED_EMOJI,
|
||||||
GUILD_ROLE_BENEFIT_EMOJI = 5,
|
GUILD_ROLE_BENEFIT_EMOJI,
|
||||||
COMMUNITY_CONTENT_ONLY = 6,
|
COMMUNITY_CONTENT_ONLY,
|
||||||
SOUNDBOARD = 7
|
SOUNDBOARD,
|
||||||
|
VOICE_CHANNEL_TOPIC,
|
||||||
|
GIFT,
|
||||||
|
AUTO_SUGGESTION,
|
||||||
|
POLLS
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const IS_BYPASSEABLE_INTENTION = `[${EmojiIntentions.CHAT},${EmojiIntentions.GUILD_STICKER_RELATED_EMOJI}].includes(fakeNitroIntention)`;
|
||||||
|
|
||||||
const enum StickerType {
|
const enum StickerType {
|
||||||
PNG = 1,
|
PNG = 1,
|
||||||
APNG = 2,
|
APNG = 2,
|
||||||
|
@ -197,37 +203,43 @@ export default definePlugin({
|
||||||
patches: [
|
patches: [
|
||||||
{
|
{
|
||||||
find: ".PREMIUM_LOCKED;",
|
find: ".PREMIUM_LOCKED;",
|
||||||
|
group: true,
|
||||||
predicate: () => settings.store.enableEmojiBypass,
|
predicate: () => settings.store.enableEmojiBypass,
|
||||||
replacement: [
|
replacement: [
|
||||||
{
|
{
|
||||||
// Create a variable for the intention of listing the emoji
|
// Create a variable for the intention of using the emoji
|
||||||
match: /(?<=,intention:(\i).+?;)/,
|
match: /(?<=\.USE_EXTERNAL_EMOJIS.+?;)(?<=intention:(\i).+?)/,
|
||||||
replace: (_, intention) => `let fakeNitroIntention=${intention};`
|
replace: (_, intention) => `const fakeNitroIntention=${intention};`
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// Send the intention of listing the emoji to the nitro permission check functions
|
// Disallow the emoji for external if the intention doesn't allow it
|
||||||
match: /\.(?:canUseEmojisEverywhere|canUseAnimatedEmojis)\(\i(?=\))/g,
|
match: /&&!\i&&!\i(?=\)return \i\.\i\.DISALLOW_EXTERNAL;)/,
|
||||||
replace: '$&,typeof fakeNitroIntention!=="undefined"?fakeNitroIntention:void 0'
|
replace: m => `${m}&&!${IS_BYPASSEABLE_INTENTION}`
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// Disallow the emoji if the intention doesn't allow it
|
// Disallow the emoji for unavailable if the intention doesn't allow it
|
||||||
match: /(&&!\i&&)!(\i)(?=\)return \i\.\i\.DISALLOW_EXTERNAL;)/,
|
match: /!\i\.available(?=\)return \i\.\i\.GUILD_SUBSCRIPTION_UNAVAILABLE;)/,
|
||||||
replace: (_, rest, canUseExternal) => `${rest}(!${canUseExternal}&&(typeof fakeNitroIntention==="undefined"||![${EmojiIntentions.CHAT},${EmojiIntentions.GUILD_STICKER_RELATED_EMOJI}].includes(fakeNitroIntention)))`
|
replace: m => `${m}&&!${IS_BYPASSEABLE_INTENTION}`
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// Make the emoji always available if the intention allows it
|
// Disallow the emoji for premium locked if the intention doesn't allow it
|
||||||
match: /if\(!\i\.available/,
|
match: /!\i\.\i\.canUseEmojisEverywhere\(\i\)/,
|
||||||
replace: m => `${m}&&(typeof fakeNitroIntention==="undefined"||![${EmojiIntentions.CHAT},${EmojiIntentions.GUILD_STICKER_RELATED_EMOJI}].includes(fakeNitroIntention))`
|
replace: m => `(${m}&&!${IS_BYPASSEABLE_INTENTION})`
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// Allow animated emojis to be used if the intention allows it
|
||||||
|
match: /(?<=\|\|)\i\.\i\.canUseAnimatedEmojis\(\i\)/,
|
||||||
|
replace: m => `(${m}||${IS_BYPASSEABLE_INTENTION})`
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
// Allow emojis and animated emojis to be sent everywhere
|
// Allows the usage of subscription-locked emojis
|
||||||
{
|
{
|
||||||
find: "canUseAnimatedEmojis:function",
|
find: "isUnusableRoleSubscriptionEmoji:function",
|
||||||
predicate: () => settings.store.enableEmojiBypass,
|
|
||||||
replacement: {
|
replacement: {
|
||||||
match: /((?:canUseEmojisEverywhere|canUseAnimatedEmojis):function\(\i)\){(.+?\))(?=})/g,
|
match: /isUnusableRoleSubscriptionEmoji:function/,
|
||||||
replace: (_, rest, premiumCheck) => `${rest},fakeNitroIntention){${premiumCheck}||fakeNitroIntention==null||[${EmojiIntentions.CHAT},${EmojiIntentions.GUILD_STICKER_RELATED_EMOJI}].includes(fakeNitroIntention)`
|
// Replace the original export with a func that always returns false and alias the original
|
||||||
|
replace: "isUnusableRoleSubscriptionEmoji:()=>()=>false,isUnusableRoleSubscriptionEmojiOriginal:function"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// Allow stickers to be sent everywhere
|
// Allow stickers to be sent everywhere
|
||||||
|
@ -241,10 +253,10 @@ export default definePlugin({
|
||||||
},
|
},
|
||||||
// Make stickers always available
|
// Make stickers always available
|
||||||
{
|
{
|
||||||
find: "\"SENDABLE\"",
|
find: '"SENDABLE"',
|
||||||
predicate: () => settings.store.enableStickerBypass,
|
predicate: () => settings.store.enableStickerBypass,
|
||||||
replacement: {
|
replacement: {
|
||||||
match: /(\w+)\.available\?/,
|
match: /\i\.available\?/,
|
||||||
replace: "true?"
|
replace: "true?"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -407,15 +419,6 @@ export default definePlugin({
|
||||||
match: /canUseCustomNotificationSounds:function\(\i\){/,
|
match: /canUseCustomNotificationSounds:function\(\i\){/,
|
||||||
replace: "$&return true;"
|
replace: "$&return true;"
|
||||||
}
|
}
|
||||||
},
|
|
||||||
// Allows the usage of subscription-locked emojis
|
|
||||||
{
|
|
||||||
find: "isUnusableRoleSubscriptionEmoji:function",
|
|
||||||
replacement: {
|
|
||||||
match: /isUnusableRoleSubscriptionEmoji:function/,
|
|
||||||
// replace the original export with a func that always returns false and alias the original
|
|
||||||
replace: "isUnusableRoleSubscriptionEmoji:()=>()=>false,isUnusableRoleSubscriptionEmojiOriginal:function"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
||||||
|
@ -808,8 +811,8 @@ export default definePlugin({
|
||||||
UploadHandler.promptToUpload([file], ChannelStore.getChannel(channelId), DraftType.ChannelMessage);
|
UploadHandler.promptToUpload([file], ChannelStore.getChannel(channelId), DraftType.ChannelMessage);
|
||||||
},
|
},
|
||||||
|
|
||||||
canUseEmote(e: CustomEmoji, channelId: string) {
|
canUseEmote(e: Emoji, channelId: string) {
|
||||||
if (e.require_colons === false) return true;
|
if (e.type === "UNICODE") return true;
|
||||||
if (e.available === false) return false;
|
if (e.available === false) return false;
|
||||||
|
|
||||||
const isUnusableRoleSubEmoji = RoleSubscriptionEmojiUtils.isUnusableRoleSubscriptionEmojiOriginal ?? RoleSubscriptionEmojiUtils.isUnusableRoleSubscriptionEmoji;
|
const isUnusableRoleSubEmoji = RoleSubscriptionEmojiUtils.isUnusableRoleSubscriptionEmojiOriginal ?? RoleSubscriptionEmojiUtils.isUnusableRoleSubscriptionEmoji;
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { definePluginSettings } from "@api/Settings";
|
import { definePluginSettings, migratePluginSettings } from "@api/Settings";
|
||||||
import { Devs } from "@utils/constants";
|
import { Devs } from "@utils/constants";
|
||||||
import definePlugin, { OptionType } from "@utils/types";
|
import definePlugin, { OptionType } from "@utils/types";
|
||||||
import { FluxDispatcher } from "@webpack/common";
|
import { FluxDispatcher } from "@webpack/common";
|
||||||
|
@ -41,8 +41,9 @@ const settings = definePluginSettings({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
migratePluginSettings("PartyMode", "Party mode 🎉");
|
||||||
export default definePlugin({
|
export default definePlugin({
|
||||||
name: "Party mode 🎉",
|
name: "PartyMode",
|
||||||
description: "Allows you to use party mode cause the party never ends ✨",
|
description: "Allows you to use party mode cause the party never ends ✨",
|
||||||
authors: [Devs.UwUDev],
|
authors: [Devs.UwUDev],
|
||||||
settings,
|
settings,
|
||||||
|
|
107
src/plugins/replaceGoogleSearch/index.tsx
Normal file
107
src/plugins/replaceGoogleSearch/index.tsx
Normal file
|
@ -0,0 +1,107 @@
|
||||||
|
/*
|
||||||
|
* Vencord, a Discord client mod
|
||||||
|
* Copyright (c) 2024 Vendicated and contributors
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { findGroupChildrenByChildId, NavContextMenuPatchCallback } from "@api/ContextMenu";
|
||||||
|
import { definePluginSettings } from "@api/Settings";
|
||||||
|
import { Devs } from "@utils/constants";
|
||||||
|
import definePlugin, { OptionType } from "@utils/types";
|
||||||
|
import { Flex, Menu } from "@webpack/common";
|
||||||
|
|
||||||
|
const DefaultEngines = {
|
||||||
|
Google: "https://www.google.com/search?q=",
|
||||||
|
DuckDuckGo: "https://duckduckgo.com/",
|
||||||
|
Bing: "https://www.bing.com/search?q=",
|
||||||
|
Yahoo: "https://search.yahoo.com/search?p=",
|
||||||
|
Github: "https://github.com/search?q=",
|
||||||
|
Kagi: "https://kagi.com/search?q=",
|
||||||
|
Yandex: "https://yandex.com/search/?text=",
|
||||||
|
AOL: "https://search.aol.com/aol/search?q=",
|
||||||
|
Baidu: "https://www.baidu.com/s?wd=",
|
||||||
|
Wikipedia: "https://wikipedia.org/w/index.php?search=",
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
const settings = definePluginSettings({
|
||||||
|
customEngineName: {
|
||||||
|
description: "Name of the custom search engine",
|
||||||
|
type: OptionType.STRING,
|
||||||
|
placeholder: "Google"
|
||||||
|
},
|
||||||
|
customEngineURL: {
|
||||||
|
description: "The URL of your Engine",
|
||||||
|
type: OptionType.STRING,
|
||||||
|
placeholder: "https://google.com/search?q="
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function search(src: string, engine: string) {
|
||||||
|
open(engine + encodeURIComponent(src), "_blank");
|
||||||
|
}
|
||||||
|
|
||||||
|
function makeSearchItem(src: string) {
|
||||||
|
let Engines = {};
|
||||||
|
|
||||||
|
if (settings.store.customEngineName && settings.store.customEngineURL) {
|
||||||
|
Engines[settings.store.customEngineName] = settings.store.customEngineURL;
|
||||||
|
}
|
||||||
|
|
||||||
|
Engines = { ...Engines, ...DefaultEngines };
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Menu.MenuItem
|
||||||
|
label="Search Text"
|
||||||
|
key="search-text"
|
||||||
|
id="vc-search-text"
|
||||||
|
>
|
||||||
|
{Object.keys(Engines).map((engine, i) => {
|
||||||
|
const key = "vc-search-content-" + engine;
|
||||||
|
return (
|
||||||
|
<Menu.MenuItem
|
||||||
|
key={key}
|
||||||
|
id={key}
|
||||||
|
label={
|
||||||
|
<Flex style={{ alignItems: "center", gap: "0.5em" }}>
|
||||||
|
<img
|
||||||
|
style={{
|
||||||
|
borderRadius: "50%"
|
||||||
|
}}
|
||||||
|
aria-hidden="true"
|
||||||
|
height={16}
|
||||||
|
width={16}
|
||||||
|
src={`https://www.google.com/s2/favicons?domain=${Engines[engine]}`}
|
||||||
|
/>
|
||||||
|
{engine}
|
||||||
|
</Flex>
|
||||||
|
}
|
||||||
|
action={() => search(src, Engines[engine])}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</Menu.MenuItem>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const messageContextMenuPatch: NavContextMenuPatchCallback = (children, _props) => {
|
||||||
|
const selection = document.getSelection()?.toString();
|
||||||
|
if (!selection) return;
|
||||||
|
|
||||||
|
const group = findGroupChildrenByChildId("search-google", children);
|
||||||
|
if (group) {
|
||||||
|
const idx = group.findIndex(c => c?.props?.id === "search-google");
|
||||||
|
if (idx !== -1) group[idx] = makeSearchItem(selection);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default definePlugin({
|
||||||
|
name: "ReplaceGoogleSearch",
|
||||||
|
description: "Replaces the Google search with different Engines",
|
||||||
|
authors: [Devs.Moxxie, Devs.Ethan],
|
||||||
|
|
||||||
|
settings,
|
||||||
|
|
||||||
|
contextMenus: {
|
||||||
|
"message": messageContextMenuPatch
|
||||||
|
}
|
||||||
|
});
|
|
@ -442,6 +442,10 @@ export const Devs = /* #__PURE__*/ Object.freeze({
|
||||||
name: "newwares",
|
name: "newwares",
|
||||||
id: 421405303951851520n
|
id: 421405303951851520n
|
||||||
},
|
},
|
||||||
|
JohnyTheCarrot: {
|
||||||
|
name: "JohnyTheCarrot",
|
||||||
|
id: 132819036282159104n
|
||||||
|
},
|
||||||
puv: {
|
puv: {
|
||||||
name: "puv",
|
name: "puv",
|
||||||
id: 469441552251355137n
|
id: 469441552251355137n
|
||||||
|
@ -490,6 +494,14 @@ export const Devs = /* #__PURE__*/ Object.freeze({
|
||||||
name: "ScattrdBlade",
|
name: "ScattrdBlade",
|
||||||
id: 678007540608532491n
|
id: 678007540608532491n
|
||||||
},
|
},
|
||||||
|
Moxxie: {
|
||||||
|
name: "Moxxie",
|
||||||
|
id: 712653921692155965n,
|
||||||
|
},
|
||||||
|
Ethan: {
|
||||||
|
name: "Ethan",
|
||||||
|
id: 721717126523781240n,
|
||||||
|
},
|
||||||
nyx: {
|
nyx: {
|
||||||
name: "verticalsync",
|
name: "verticalsync",
|
||||||
id: 328165170536775680n
|
id: 328165170536775680n
|
||||||
|
|
3
src/webpack/common/types/stores.d.ts
vendored
3
src/webpack/common/types/stores.d.ts
vendored
|
@ -63,7 +63,7 @@ export interface CustomEmoji {
|
||||||
originalName?: string;
|
originalName?: string;
|
||||||
require_colons: boolean;
|
require_colons: boolean;
|
||||||
roles: string[];
|
roles: string[];
|
||||||
url: string;
|
type: "GUILD_EMOJI";
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface UnicodeEmoji {
|
export interface UnicodeEmoji {
|
||||||
|
@ -75,6 +75,7 @@ export interface UnicodeEmoji {
|
||||||
};
|
};
|
||||||
index: number;
|
index: number;
|
||||||
surrogates: string;
|
surrogates: string;
|
||||||
|
type: "UNICODE";
|
||||||
uniqueName: string;
|
uniqueName: string;
|
||||||
useSpriteSheet: boolean;
|
useSpriteSheet: boolean;
|
||||||
get allNamesString(): string;
|
get allNamesString(): string;
|
||||||
|
|
Loading…
Reference in a new issue