mirror of
https://github.com/Equicord/Equicord.git
synced 2025-06-13 08:33:01 -04:00
wip
This commit is contained in:
parent
e7e298d2e7
commit
a3952b35a4
20 changed files with 168 additions and 94 deletions
|
@ -31,7 +31,7 @@ export default definePlugin({
|
|||
match: /let\{[^}]*lostPermissionTooltipText:\i[^}]*\}=(\i),/,
|
||||
replace: "$&vencordProps=$1,"
|
||||
}, {
|
||||
match: /\.Messages\.GUILD_OWNER(?=.+?decorators:(\i)\(\)).+?\1=?\(\)=>.+?children:\[/,
|
||||
match: /#intl<GUILD_OWNER>(?=.+?decorators:(\i)\(\)).+?\1=?\(\)=>.+?children:\[/,
|
||||
replace: "$&...(typeof vencordProps=='undefined'?[]:Vencord.Api.MemberListDecorators.__getDecorators(vencordProps)),"
|
||||
}
|
||||
]
|
||||
|
|
|
@ -25,7 +25,7 @@ export default definePlugin({
|
|||
authors: [Devs.Cyn],
|
||||
patches: [
|
||||
{
|
||||
find: ".Messages.REMOVE_ATTACHMENT_BODY",
|
||||
find: "#intl<REMOVE_ATTACHMENT_BODY>",
|
||||
replacement: {
|
||||
match: /(?<=.container\)?,children:)(\[.+?\])/,
|
||||
replace: "Vencord.Api.MessageAccessories._modifyAccessories($1,this.props)",
|
||||
|
|
|
@ -27,7 +27,7 @@ export default definePlugin({
|
|||
{
|
||||
find: '"Message Username"',
|
||||
replacement: {
|
||||
match: /\.Messages\.GUILD_COMMUNICATION_DISABLED_BOTTOM_SHEET_TITLE.+?}\),\i(?=\])/,
|
||||
match: /#intl<GUILD_COMMUNICATION_DISABLED_BOTTOM_SHEET_TITLE>.+?}\),\i(?=\])/,
|
||||
replace: "$&,...Vencord.Api.MessageDecorations.__addDecorationsToMessage(arguments[0])"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ export default definePlugin({
|
|||
authors: [Devs.Arjix, Devs.hunt, Devs.Ven],
|
||||
patches: [
|
||||
{
|
||||
find: ".Messages.EDIT_TEXTAREA_HELP",
|
||||
find: "#intl<EDIT_TEXTAREA_HELP>",
|
||||
replacement: {
|
||||
match: /(?<=,channel:\i\}\)\.then\().+?(?=return \i\.content!==this\.props\.message\.content&&\i\((.+?)\))/,
|
||||
replace: (match, args) => "" +
|
||||
|
|
|
@ -24,9 +24,9 @@ export default definePlugin({
|
|||
description: "API to add buttons to message popovers.",
|
||||
authors: [Devs.KingFish, Devs.Ven, Devs.Nuckyz],
|
||||
patches: [{
|
||||
find: "Messages.MESSAGE_UTILITIES_A11Y_LABEL",
|
||||
find: "#intl<MESSAGE_UTILITIES_A11Y_LABEL>",
|
||||
replacement: {
|
||||
match: /\.jsx\)\((\i\.\i),\{label:\i\.\i\.Messages\.MESSAGE_ACTION_REPLY.{0,200}?"reply-self".{0,50}?\}\):null(?=,.+?message:(\i))/,
|
||||
match: /\.jsx\)\((\i\.\i),\{label:\i\.\i\.string\(\i\.\i#intl<MESSAGE_ACTION_REPLY>.{0,200}?"reply-self".{0,50}?\}\):null(?=,.+?message:(\i))/,
|
||||
replace: "$&,Vencord.Api.MessagePopover._buildPopoverElements($1,$2)"
|
||||
}
|
||||
}],
|
||||
|
|
|
@ -25,16 +25,16 @@ export default definePlugin({
|
|||
description: "Api required for plugins that modify the server list",
|
||||
patches: [
|
||||
{
|
||||
find: "Messages.DISCODO_DISABLED",
|
||||
find: "#intl<DISCODO_DISABLED>",
|
||||
replacement: {
|
||||
match: /(?<=Messages\.DISCODO_DISABLED.+?return)(\(.{0,75}?tutorialContainer.+?}\))(?=}function)/,
|
||||
match: /(?<=#intl<DISCODO_DISABLED>.+?return)(\(.{0,75}?tutorialContainer.+?}\))(?=}function)/,
|
||||
replace: "[$1].concat(Vencord.Api.ServerList.renderAll(Vencord.Api.ServerList.ServerListRenderPosition.Above))"
|
||||
}
|
||||
},
|
||||
{
|
||||
find: "Messages.SERVERS,children",
|
||||
replacement: {
|
||||
match: /(?<=Messages\.SERVERS,children:)\i\.map\(\i\)/,
|
||||
match: /(?<=#intl<SERVERS>\),children:)\i\.map\(\i\)/,
|
||||
replace: "Vencord.Api.ServerList.renderAll(Vencord.Api.ServerList.ServerListRenderPosition.In).concat($&)"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -57,7 +57,7 @@ export default definePlugin({
|
|||
]
|
||||
},
|
||||
{
|
||||
find: "Messages.ACTIVITY_SETTINGS",
|
||||
find: "#intl<ACTIVITY_SETTINGS>",
|
||||
replacement: [
|
||||
{
|
||||
match: /(?<=section:(.{0,50})\.DIVIDER\}\))([,;])(?=.{0,200}(\i)\.push.{0,100}label:(\i)\.header)/,
|
||||
|
@ -70,7 +70,7 @@ export default definePlugin({
|
|||
]
|
||||
},
|
||||
{
|
||||
find: "Messages.USER_SETTINGS_ACTIONS_MENU_LABEL",
|
||||
find: "#intl<USER_SETTINGS_ACTIONS_MENU_LABEL>",
|
||||
replacement: {
|
||||
match: /(?<=function\((\i),\i\)\{)(?=let \i=Object.values\(\i.\i\).*?(\i\.\i)\.open\()/,
|
||||
replace: "$2.open($1);return;"
|
||||
|
|
|
@ -147,7 +147,7 @@ export default definePlugin({
|
|||
settings,
|
||||
|
||||
patches: [{
|
||||
find: ".BEGINNING_DM.format",
|
||||
find: "#intl<BEGINNING_DM>",
|
||||
replacement: {
|
||||
match: /BEGINNING_DM\.format\(\{.+?\}\),(?=.{0,300}(\i)\.isMultiUserDM)/,
|
||||
replace: "$& $self.renderContributorDmWarningCard({ channel: $1 }),"
|
||||
|
|
|
@ -69,7 +69,7 @@ export default definePlugin({
|
|||
|
||||
patches: [
|
||||
{
|
||||
find: ".Messages.ACCOUNT_SPEAKING_WHILE_MUTED",
|
||||
find: "#intl<ACCOUNT_SPEAKING_WHILE_MUTED>",
|
||||
group: true,
|
||||
replacement: [
|
||||
{
|
||||
|
|
|
@ -172,7 +172,7 @@ export default definePlugin({
|
|||
// Disable expanding and collapsing folders transition in the normal GuildsBar sidebar
|
||||
{
|
||||
predicate: () => !settings.store.keepIcons,
|
||||
match: /(?<=\.Messages\.SERVER_FOLDER_PLACEHOLDER.+?useTransition\)\()/,
|
||||
match: /(?<=#intl<SERVER_FOLDER_PLACEHOLDER>.+?useTransition\)\()/,
|
||||
replace: "$self.shouldShowTransition(arguments[0])&&"
|
||||
},
|
||||
// If we are rendering the normal GuildsBar sidebar, we avoid rendering guilds from folders that are expanded
|
||||
|
@ -205,7 +205,7 @@ export default definePlugin({
|
|||
}
|
||||
},
|
||||
{
|
||||
find: ".Messages.DISCODO_DISABLED",
|
||||
find: "#intl<DISCODO_DISABLED>",
|
||||
predicate: () => settings.store.closeAllHomeButton,
|
||||
replacement: {
|
||||
// Close all folders when clicking the home button
|
||||
|
|
|
@ -41,7 +41,7 @@ export default definePlugin({
|
|||
{
|
||||
find: "DefaultCustomizationSections",
|
||||
replacement: {
|
||||
match: /(?<=USER_SETTINGS_AVATAR_DECORATION},"decoration"\),)/,
|
||||
match: /(?<=#intl<USER_SETTINGS_AVATAR_DECORATION>\)},"decoration"\),)/,
|
||||
replace: "$self.DecorSection(),"
|
||||
}
|
||||
},
|
||||
|
|
|
@ -26,7 +26,7 @@ export default definePlugin({
|
|||
{
|
||||
find: ".PANEL}),nicknameIcons",
|
||||
replacement: {
|
||||
match: /USER_PROFILE_MEMBER_SINCE,.{0,100}userId:(\i\.id)}\)}\)/,
|
||||
match: /#intl<USER_PROFILE_MEMBER_SINCE>,.{0,100}userId:(\i\.id)}\)}\)/,
|
||||
replace: "$&,$self.FriendsSinceComponent({userId:$1,isSidebar:true})"
|
||||
}
|
||||
},
|
||||
|
@ -34,7 +34,7 @@ export default definePlugin({
|
|||
{
|
||||
find: "action:\"PRESS_APP_CONNECTION\"",
|
||||
replacement: {
|
||||
match: /USER_PROFILE_MEMBER_SINCE,.{0,100}userId:(\i\.id),.{0,100}}\)}\),/,
|
||||
match: /#intl<USER_PROFILE_MEMBER_SINCE>,.{0,100}userId:(\i\.id),.{0,100}}\)}\),/,
|
||||
replace: "$&,$self.FriendsSinceComponent({userId:$1,isSidebar:false}),"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -74,7 +74,7 @@ export default definePlugin({
|
|||
{
|
||||
find: ".invitesDisabledTooltip",
|
||||
replacement: {
|
||||
match: /\.VIEW_AS_ROLES_MENTIONS_WARNING.{0,100}(?=])/,
|
||||
match: /#intl<VIEW_AS_ROLES_MENTIONS_WARNING>.{0,100}(?=])/,
|
||||
replace: "$&,$self.renderTooltip(arguments[0].guild)"
|
||||
},
|
||||
predicate: () => settings.store.toolTip
|
||||
|
|
|
@ -28,21 +28,21 @@ export default definePlugin({
|
|||
{
|
||||
find: '.id,"Search Results"',
|
||||
replacement: {
|
||||
match: /if\(.{1,10}\)(.{1,10}\.show\({.{1,50}UNBLOCK_TO_JUMP_TITLE)/,
|
||||
match: /if\(.{1,10}\)(.{1,10}\.show\({.{1,50}#intl<UNBLOCK_TO_JUMP_TITLE>)/,
|
||||
replace: "if(false)$1"
|
||||
}
|
||||
},
|
||||
{
|
||||
find: "renderJumpButton()",
|
||||
replacement: {
|
||||
match: /if\(.{1,10}\)(.{1,10}\.show\({.{1,50}UNBLOCK_TO_JUMP_TITLE)/,
|
||||
match: /if\(.{1,10}\)(.{1,10}\.show\({.{1,50}#intl<UNBLOCK_TO_JUMP_TITLE>)/,
|
||||
replace: "if(false)$1"
|
||||
}
|
||||
},
|
||||
{
|
||||
find: "flash:!0,returnMessageId",
|
||||
replacement: {
|
||||
match: /.\?(.{1,10}\.show\({.{1,50}UNBLOCK_TO_JUMP_TITLE)/,
|
||||
match: /.\?(.{1,10}\.show\({.{1,50}#intl<UNBLOCK_TO_JUMP_TITLE>)/,
|
||||
replace: "false?$1"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -57,7 +57,7 @@ export default definePlugin({
|
|||
patches: [
|
||||
// Change the max volume for sliders to allow for values above 200
|
||||
...[
|
||||
".Messages.USER_VOLUME",
|
||||
"#intl<USER_VOLUME>",
|
||||
"currentVolume:"
|
||||
].map(find => ({
|
||||
find,
|
||||
|
|
|
@ -127,11 +127,11 @@ export default definePlugin({
|
|||
replace: "return [true"
|
||||
},
|
||||
{
|
||||
match: /(?<=COPY_IMAGE_MENU_ITEM,)action:/,
|
||||
match: /(?<=#intl<COPY_IMAGE_MENU_ITEM>,)action:/,
|
||||
replace: "action:()=>$self.copyImage(arguments[0]),oldAction:"
|
||||
},
|
||||
{
|
||||
match: /(?<=SAVE_IMAGE_MENU_ITEM,)action:/,
|
||||
match: /(?<=#intl<SAVE_IMAGE_MENU_ITEM>,)action:/,
|
||||
replace: "action:()=>$self.saveImage(arguments[0]),oldAction:"
|
||||
},
|
||||
]
|
||||
|
@ -224,10 +224,10 @@ export default definePlugin({
|
|||
{
|
||||
find: '("interactionUsernameProfile',
|
||||
replacement:
|
||||
{
|
||||
match: /\i\.isPlatformEmbedded(?=.{0,50}\.tagName)/,
|
||||
replace: "true"
|
||||
},
|
||||
{
|
||||
match: /\i\.isPlatformEmbedded(?=.{0,50}\.tagName)/,
|
||||
replace: "true"
|
||||
},
|
||||
}
|
||||
],
|
||||
|
||||
|
|
53
src/utils/intlHash.ts
Normal file
53
src/utils/intlHash.ts
Normal file
|
@ -0,0 +1,53 @@
|
|||
/* eslint-disable simple-header/header */
|
||||
|
||||
/**
|
||||
* discord-intl
|
||||
*
|
||||
* @copyright 2024 Discord, Inc.
|
||||
* @link https://github.com/discord/discord-intl
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
|
||||
import { hash as h64 } from "@intrnl/xxhash64";
|
||||
|
||||
const BASE64_TABLE = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".split("");
|
||||
const IS_BIG_ENDIAN = (() => {
|
||||
const array = new Uint8Array(4);
|
||||
const view = new Uint32Array(array.buffer);
|
||||
return !((view[0] = 1) & array[0]);
|
||||
})();
|
||||
|
||||
function numberToBytes(number: number | bigint) {
|
||||
number = BigInt(number);
|
||||
const array: number[] = [];
|
||||
const byteCount = Math.ceil(Math.floor(Math.log2(Number(number)) + 1) / 8);
|
||||
for (let i = 0; i < byteCount; i++) {
|
||||
array.unshift(Number((number >> BigInt(8 * i)) & BigInt(255)));
|
||||
}
|
||||
|
||||
const bytes = new Uint8Array(array);
|
||||
// The native `hashToMessageKey` always works in Big/Network Endian bytes, so this array
|
||||
// needs to be converted to the same endianness to get the same base64 result.
|
||||
return IS_BIG_ENDIAN ? bytes : bytes.reverse();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a consistent, short hash of the given key by first processing it through a hash digest,
|
||||
* then encoding the first few bytes to base64.
|
||||
*
|
||||
* This function is specifically written to mirror the native backend hashing function used by
|
||||
* `@discord/intl-loader-core`, to be able to hash names at runtime.
|
||||
*/
|
||||
export function runtimeHashMessageKey(key: string): string {
|
||||
const hash = h64(key, 0);
|
||||
const bytes = numberToBytes(hash);
|
||||
return [
|
||||
BASE64_TABLE[bytes[0] >> 2],
|
||||
BASE64_TABLE[((bytes[0] & 0x03) << 4) | (bytes[1] >> 4)],
|
||||
BASE64_TABLE[((bytes[1] & 0x0f) << 2) | (bytes[2] >> 6)],
|
||||
BASE64_TABLE[bytes[2] & 0x3f],
|
||||
BASE64_TABLE[bytes[3] >> 2],
|
||||
BASE64_TABLE[((bytes[3] & 0x03) << 4) | (bytes[3] >> 4)],
|
||||
].join("");
|
||||
}
|
|
@ -16,12 +16,24 @@
|
|||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { runtimeHashMessageKey } from "./intlHash";
|
||||
import { Patch, PatchReplacement, ReplaceFn } from "./types";
|
||||
|
||||
export function canonicalizeMatch<T extends RegExp | string>(match: T): T {
|
||||
if (typeof match === "string") return match;
|
||||
const canonSource = match.source
|
||||
.replaceAll("\\i", "[A-Za-z_$][\\w$]*");
|
||||
let partialCanon = typeof match === "string" ? match : match.source;
|
||||
partialCanon = partialCanon.replaceAll(/#intl?<([A-Za-z_$][\w$]*)>/g, (_, key) => {
|
||||
const hashed = runtimeHashMessageKey(key);
|
||||
const isStr = typeof match === "string";
|
||||
|
||||
return /^[\d]/.test(hashed) || !/^[\w$]+$/.test(hashed)
|
||||
? isStr ? `["${hashed}` : `(?:\\["${hashed}"\\])`
|
||||
: isStr ? `.${hashed}` : `(?:\\.${hashed})`;
|
||||
});
|
||||
|
||||
if (typeof match === "string") return partialCanon as T;
|
||||
|
||||
const canonSource = partialCanon
|
||||
.replaceAll(String.raw`\i`, String.raw`(?:[A-Za-z_$][\w$]*)`);
|
||||
return new RegExp(canonSource, match.flags) as T;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue