chore: init
This commit is contained in:
207
antiRickroll/index.tsx
Normal file
207
antiRickroll/index.tsx
Normal file
@@ -0,0 +1,207 @@
|
||||
/*
|
||||
* Vencord, a Discord client mod
|
||||
* Copyright (c) 2024 Vendicated and contributors
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import { addMessageAccessory, removeMessageAccessory } from "@api/MessageAccessories";
|
||||
import { definePluginSettings } from "@api/Settings";
|
||||
import { getUserSettingLazy } from "@api/UserSettings";
|
||||
import ErrorBoundary from "@components/ErrorBoundary";
|
||||
import definePlugin, { OptionType } from "@utils/types";
|
||||
import { Message } from "@vencord/discord-types";
|
||||
import { React, Text } from "@webpack/common";
|
||||
|
||||
import { knownHosts } from "./knownHosts";
|
||||
import { knownVideoIds } from "./knownVideoIDs";
|
||||
const MessageDisplayCompact = getUserSettingLazy(
|
||||
"textAndImages",
|
||||
"messageDisplayCompact"
|
||||
)!;
|
||||
|
||||
const settings = definePluginSettings({
|
||||
customLinks: {
|
||||
description: "Custom links to check for (separated by commas)",
|
||||
type: OptionType.STRING,
|
||||
default: "",
|
||||
restartNeeded: true,
|
||||
},
|
||||
customVideoIds: {
|
||||
description:
|
||||
"Custom YouTube video IDs to check for (separated by commas)",
|
||||
type: OptionType.STRING,
|
||||
default: "",
|
||||
restartNeeded: true,
|
||||
},
|
||||
});
|
||||
|
||||
function isPotentialRickroll(url: string): boolean {
|
||||
try {
|
||||
const parsedUrl = new URL(url);
|
||||
const hostname = parsedUrl.hostname.replace("www.", "");
|
||||
|
||||
const customLinks = settings.store.customLinks
|
||||
.split(",")
|
||||
.map(s => s.trim())
|
||||
.filter(Boolean);
|
||||
const customVideoIDs = settings.store.customVideoIds
|
||||
.split(",")
|
||||
.map(s => s.trim())
|
||||
.filter(Boolean);
|
||||
|
||||
if (customLinks.some(link => parsedUrl.href.includes(link))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (hostname === "youtube.com" || hostname === "youtu.be") {
|
||||
let videoID = "";
|
||||
|
||||
if (hostname === "youtube.com") {
|
||||
videoID =
|
||||
parsedUrl.searchParams.get("v") ||
|
||||
parsedUrl.searchParams.get("V") ||
|
||||
"";
|
||||
} else if (hostname === "youtu.be") {
|
||||
videoID = parsedUrl.pathname.slice(1);
|
||||
}
|
||||
|
||||
const knownVideoIDs = [...knownVideoIds, ...customVideoIDs];
|
||||
|
||||
if (knownVideoIDs.includes(videoID)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (knownHosts.includes(hostname)) {
|
||||
return true;
|
||||
}
|
||||
} catch (e) {
|
||||
// Invalid URL, ignore :trolley:
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function extractUrls(content: string): string[] {
|
||||
const urls: string[] = [];
|
||||
const markdownLinkRegex = /\[.*?\]\((<)?(https?:\/\/[^\s>]+)(>)?\)/g;
|
||||
const urlRegex = /https?:\/\/[^\s<]+/g;
|
||||
const maskedUrlRegex = /<(https?:\/\/[^\s>]+)>/g;
|
||||
|
||||
let match: RegExpExecArray | null;
|
||||
|
||||
while ((match = markdownLinkRegex.exec(content)) !== null) {
|
||||
urls.push(match[2]);
|
||||
}
|
||||
|
||||
while ((match = urlRegex.exec(content)) !== null) {
|
||||
urls.push(match[0]);
|
||||
}
|
||||
|
||||
while ((match = maskedUrlRegex.exec(content)) !== null) {
|
||||
urls.push(match[1]);
|
||||
}
|
||||
|
||||
return urls;
|
||||
}
|
||||
|
||||
function RickrollWarningAccessory({ message }: { message: Message; }) {
|
||||
const urls = extractUrls(message.content);
|
||||
if (urls.length === 0) return null;
|
||||
|
||||
for (const url of urls) {
|
||||
const isCustom = isCustomRickroll(url);
|
||||
if (isPotentialRickroll(url) || isCustom) {
|
||||
return (
|
||||
<ErrorBoundary>
|
||||
<RickrollWarning message={message} isCustom={isCustom} />
|
||||
</ErrorBoundary>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function isCustomRickroll(url: string): boolean {
|
||||
try {
|
||||
const parsedUrl = new URL(url);
|
||||
const customLinks = settings.store.customLinks
|
||||
.split(",")
|
||||
.map(s => s.trim())
|
||||
.filter(Boolean);
|
||||
const customVideoIDs = settings.store.customVideoIds
|
||||
.split(",")
|
||||
.map(s => s.trim())
|
||||
.filter(Boolean);
|
||||
|
||||
if (customLinks.some(link => parsedUrl.href.includes(link))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const hostname = parsedUrl.hostname.replace("www.", "");
|
||||
if (hostname === "youtube.com" || hostname === "youtu.be") {
|
||||
let videoID = "";
|
||||
if (hostname === "youtube.com") {
|
||||
videoID = parsedUrl.searchParams.get("v") || "";
|
||||
} else if (hostname === "youtu.be") {
|
||||
videoID = parsedUrl.pathname.slice(1);
|
||||
}
|
||||
|
||||
if (customVideoIDs.includes(videoID)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
// Invalid URL, ignore :trolley: (could probably merge this)
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function RickrollWarning({
|
||||
message,
|
||||
isCustom,
|
||||
}: {
|
||||
message: Message;
|
||||
isCustom: boolean;
|
||||
}) {
|
||||
const compact = MessageDisplayCompact.useSetting();
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Text color="text-danger" variant="text-xs/semibold">
|
||||
⚠️ This link is{" "}
|
||||
{isCustom
|
||||
? "matching one of your filters for rickrolls."
|
||||
: "a known rickroll."}
|
||||
</Text>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default definePlugin({
|
||||
name: "AntiRickroll",
|
||||
description:
|
||||
"Warns you of potential Rickrolls in messages, including masked links (supports custom rules)",
|
||||
authors: [{ name: "ryanamay", id: 1262793452236570667n }],
|
||||
dependencies: ["MessageAccessoriesAPI", "UserSettingsAPI"],
|
||||
|
||||
settings,
|
||||
|
||||
start() {
|
||||
addMessageAccessory(
|
||||
"rickrollWarning",
|
||||
(props: Record<string, any>) => {
|
||||
return (
|
||||
<RickrollWarningAccessory
|
||||
message={props.message as Message}
|
||||
/>
|
||||
);
|
||||
},
|
||||
4
|
||||
);
|
||||
},
|
||||
|
||||
stop() {
|
||||
removeMessageAccessory("rickrollWarning");
|
||||
},
|
||||
});
|
||||
106
antiRickroll/knownHosts.ts
Normal file
106
antiRickroll/knownHosts.ts
Normal file
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* Vencord, a Discord client mod
|
||||
* Copyright (c) 2024 Vendicated and contributors
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
export const knownHosts = [
|
||||
"rickroll.link",
|
||||
"rickrolled.fr",
|
||||
"dub.sh/MetropolisOffline",
|
||||
"my-cool-app.com",
|
||||
"1227.com",
|
||||
"203.24.182.170",
|
||||
"74.125.95.104/search?q=cache:YLZLcPVmjrsJ:smouch.net/lol/+rick+roll&hl=en&ct=clnk&cd=5&gl=us",
|
||||
"8chan.henriwatson.com/b",
|
||||
"adurah.com/img/hp7_spoilers.jpg",
|
||||
"ali3ns.net",
|
||||
"almightypickle.deviantart.com/art/a-very-stupid-flash-movie-83440015",
|
||||
"apoke.com",
|
||||
"asongbyagayguy.ytmnd.com",
|
||||
"bit.ly/1628nB",
|
||||
"bringvictory.com",
|
||||
"choose.yudia.net",
|
||||
"classpc.nl",
|
||||
"collegehumor.com/video:1809841",
|
||||
"comicwonder.com/joke/8a46a9b4a",
|
||||
"crappypc.com",
|
||||
"ebaumsworld.com/video/watch/411687",
|
||||
"ecritters.biz/sr",
|
||||
"epicwinrar.com",
|
||||
"evanball.com",
|
||||
"finalclan.net",
|
||||
"freeppcsecrets.com",
|
||||
"fuckdreamhost.com",
|
||||
"furryartpile.com",
|
||||
"i65games.tk",
|
||||
"internetisseriousbusiness.com",
|
||||
"irc.infinitynet.info",
|
||||
"johncow.com/moo.html",
|
||||
"just-different.info/secret",
|
||||
"keiraknightley.ytmnd.com",
|
||||
"krazykustoms.co.cc/pages",
|
||||
"krazykustoms.co.cc/phpBB3/index.php",
|
||||
"liner.org",
|
||||
"members.tele2.nl/class-pc",
|
||||
"mxweas.com/docs/jailbreakservhack",
|
||||
"newroupdates.tk",
|
||||
"niya.cc/flash/rick",
|
||||
"noelurl.easyasweb.eu/u0Rx744fi",
|
||||
"palmsout.net/music/remixsunday/104/Never%20Gonna%20Give%20You%20Up%20%28Solly%20Remix%29.mp3",
|
||||
"paulsmom.prohosts.org",
|
||||
"pottermisleading.ytmnd.com",
|
||||
"prankdialer.com/rickroll.php",
|
||||
"pspemporium.webs.com/rickdance.html",
|
||||
"punahou.com",
|
||||
"rasher.dk/r",
|
||||
"rasher.dk/r/linode-dns",
|
||||
"ravenstorm.byethost15.com",
|
||||
"raygoldmodels.com",
|
||||
"reichroll.com",
|
||||
"reichrolled.com",
|
||||
"rick-rolld.com",
|
||||
"rickroll.net",
|
||||
"rickrolling.com/lol",
|
||||
"rr.rezbit.com",
|
||||
"rr.rezbit.com/blog/021107/rick-astley-speaks-about-rickroll.html",
|
||||
"rurl.org/2vq",
|
||||
"sirpnut.info/sorry.jpg",
|
||||
"smouch.net/lol",
|
||||
"sprigler.com/steven",
|
||||
"stucknut.com/locker/files/jessica.gif",
|
||||
"t1ny.us/7wp5i",
|
||||
"technocolbert.co.nr",
|
||||
"techsmartly.net",
|
||||
"thekickback.com/rickroll/rickroll.php",
|
||||
"tinyurl.com/interfont",
|
||||
"tinyurl.com/244u3n",
|
||||
"tinyurl.com/2nmscj",
|
||||
"tinyurl.com/2tcnbl",
|
||||
"tinyurl.com/2w4apm",
|
||||
"tinyurl.com/37ws8e",
|
||||
"tinyurl.com/4xur8r",
|
||||
"tinyurl.com/5a3jqf",
|
||||
"tinyurl.com/5sb29l",
|
||||
"tinyurl.com/CELEBRITY-XXX-VIDS",
|
||||
"tinyurl.com/KIM-KARDASHIAN-SEX-TAPE",
|
||||
"tinyurl.com/britneyspearsXXX",
|
||||
"tinyurl.com/rickrolll",
|
||||
"tinyurl.com/ynupj4",
|
||||
"tinyurl.com/yowxeq",
|
||||
"tobi-x.com/kate_moss_nude",
|
||||
"todaysbigthing.com/2008/04/07",
|
||||
"todo.is",
|
||||
"url.uppix.net/NFWGJ",
|
||||
"video.hexxeh.net",
|
||||
"video.yahoo.com/watch/1313289/4562193",
|
||||
"video.yahoo.com/watch/2013707/v2138974",
|
||||
"video.yahoo.com/watch/804885/3375801",
|
||||
"vids.myspace.com/index.cfm?fuseaction=vids.individual&videoid=25992858",
|
||||
"warlocksnerfed.ytmnd.com",
|
||||
"ww.rickroll.net",
|
||||
"you-host.info",
|
||||
"yougotrickrolled.com",
|
||||
"zeroboard.com/16979949#0",
|
||||
"zideo.nl/index.php?option=com_podfeed&zideo=6c4971596d513d3d&playzideo=6c344f596d31593d&Itemid=",
|
||||
];
|
||||
500
antiRickroll/knownVideoIDs.ts
Normal file
500
antiRickroll/knownVideoIDs.ts
Normal file
@@ -0,0 +1,500 @@
|
||||
/*
|
||||
* Vencord, a Discord client mod
|
||||
* Copyright (c) 2024 Vendicated and contributors
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
export const knownVideoIds = [
|
||||
"dQw4w9WgXcQ", // The original
|
||||
"oHg5SJYRHA0", // In case they know that link
|
||||
"p7YXXieghto", // But with a different link
|
||||
"E4WlUXrJgy4", // Yet another alt link
|
||||
"6_b7RDuLwcI", // Lyrics
|
||||
"G8iEMVr7GFg", // Otamatone (favorite)
|
||||
"AyOqGRjVtls", // Kermit
|
||||
"6mhmcwmgWbA", // Fortnite
|
||||
"SpZ2FsEfwP4", // Minecraft
|
||||
"H01BwSD9eyQ", // Undertale
|
||||
"nrsnN23tmUA", // Toad
|
||||
"8mkofgRW1II", // Karl Wheezer
|
||||
"rAx5LIul1N8", // 24 cartoon impressions
|
||||
"sO4wVSA9UPs", // Wii Theme
|
||||
"rrs0B_LM898", // Pufferfish
|
||||
"doEqUhFiQS4", // Rick is going to give you up
|
||||
"epyRUp0BhrA", // Sung by 169 movies (2nd favorite)
|
||||
"uK5WDo_3s7s", // Ninja
|
||||
"wzSVOcgKq04", // Barack Obama
|
||||
"7B--1KArxow", // Recorder
|
||||
"rbsPu1z3ugQ", // Brian (Family guy)
|
||||
"ptw2FLKXDQE", // Wreck Roll
|
||||
"E50L-JYWm3w", // Dead memes (this one sucks lmao)
|
||||
"8leAAwMIigI", // Karaoke
|
||||
"ByqFY-Boq5Y", // Just Dance 4
|
||||
"E4ihJMQUmUQ", // Anime style
|
||||
"cjBHXvBYw5s", // Goofy
|
||||
"xaazUgEKuVA", // 1 hr
|
||||
"TzXXHVhGXTQ", // 10 hr
|
||||
"Uj1ykZWtPYI", // R2D2's secret message
|
||||
"EE-xtCF3T94", // Who's that pokemon?
|
||||
"V-_O7nl0Ii0", // Ocean waves
|
||||
"cqF6M25kqq4", // Patrick's secret box
|
||||
"0SoNH07Slj0", // Jellyfish
|
||||
"xfr64zoBTAQ", // Breaking news
|
||||
"j5a0jTc9S10", // Cute dogs
|
||||
"dPmZqsQNzGA", // True Love by Coldplay
|
||||
"nHRbZW097Uk", // Hidden message
|
||||
"BjDebmqFRuc", // Voice cracks, among other weird stuff
|
||||
"Gc2u6AFImn8", // WTF grandayy
|
||||
"8VFzHYtOARw", // Bass boosted
|
||||
"cSAp9sBzPbc", // All notes are C
|
||||
"Dx5i1t0mN78", // ????????
|
||||
"Oo0twK2ZbLU", // Vocals get higher, instruments get lower
|
||||
"cvh0nX08nRw", // It never starts
|
||||
"lXMskKTw3Bc", // Nice singing bro
|
||||
"7z_1E8VGJOw", // Lyrics are Roblox usernames
|
||||
"VgojnNgmgVs", // Beats 2 and 4 are switched
|
||||
"5wOXc03RwVA", // Sung by a cat
|
||||
"2xx_2XNxxfA", // Lofi.
|
||||
"lpiB2wMc49g", // Made anime
|
||||
"H8ZH_mkfPUY", // Rebooted
|
||||
"Svj1bZz2mXw", // Lyrics in alphabetical order
|
||||
"iik25wqIuFo", // Different link
|
||||
"hvL1339luv0", // A cat sings it
|
||||
"N9w1lCZfaWI", // Gamecube version
|
||||
"ivV-kssG3NI", // Kasane Teto
|
||||
"0SoNH07Slj0",
|
||||
"2xx_2XNxxfA",
|
||||
"5wOXc03RwVA",
|
||||
"6_b7RDuLwcI",
|
||||
"6mhmcwmgWbA",
|
||||
"7B--1KArxow",
|
||||
"7z_1E8VGJOw",
|
||||
"8VFzHYtOARw",
|
||||
"8leAAwMIigI",
|
||||
"8mkofgRW1II",
|
||||
"AyOqGRjVtls",
|
||||
"BjDebmqFRuc",
|
||||
"ByqFY-Boq5Y",
|
||||
"Dx5i1t0mN78",
|
||||
"E4WlUXrJgy4",
|
||||
"E4ihJMQUmUQ",
|
||||
"E50L-JYWm3w",
|
||||
"EE-xtCF3T94",
|
||||
"G8iEMVr7GFg",
|
||||
"Gc2u6AFImn8",
|
||||
"H01BwSD9eyQ",
|
||||
"H8ZH_mkfPUY",
|
||||
"N9w1lCZfaWI",
|
||||
"Oo0twK2ZbLU",
|
||||
"SpZ2FsEfwP4",
|
||||
"Svj1bZz2mXw",
|
||||
"TzXXHVhGXTQ",
|
||||
"Uj1ykZWtPYI",
|
||||
"V-_O7nl0Ii0",
|
||||
"VgojnNgmgVs",
|
||||
"cSAp9sBzPbc",
|
||||
"cjBHXvBYw5s",
|
||||
"cqF6M25kqq4",
|
||||
"cvh0nX08nRw",
|
||||
"dPmZqsQNzGA",
|
||||
"dQw4w9WgXcQ",
|
||||
"doEqUhFiQS4",
|
||||
"epyRUp0BhrA",
|
||||
"hvL1339luv0",
|
||||
"iik25wqIuFo",
|
||||
"ivV-kssG3NI",
|
||||
"j5a0jTc9S10",
|
||||
"lXMskKTw3Bc",
|
||||
"lpiB2wMc49g",
|
||||
"nHRbZW097Uk",
|
||||
"nrsnN23tmUA",
|
||||
"oHg5SJYRHA0",
|
||||
"p7YXXieghto",
|
||||
"ptw2FLKXDQE",
|
||||
"rAx5LIul1N8",
|
||||
"rbsPu1z3ugQ",
|
||||
"rrs0B_LM898",
|
||||
"sO4wVSA9UPs",
|
||||
"uK5WDo_3s7s",
|
||||
"wzSVOcgKq04",
|
||||
"xaazUgEKuVA",
|
||||
"xfr64zoBTAQ",
|
||||
"AuKR2fQbMBk",
|
||||
"xvFZjo5PgG0",
|
||||
"BBJa32lCaaY",
|
||||
"QB7ACr7pUuE",
|
||||
"pKskW7wJ0v0",
|
||||
"j7gKwxRe7MQ",
|
||||
"LWErcuHm_C4",
|
||||
"a6pbjksYUHY",
|
||||
"ll-mQPDCn-U",
|
||||
"dRV6NaciZVk",
|
||||
"MCjlo7PtXMQ",
|
||||
"mrThFRR3n8A",
|
||||
"HnfkEVtetuE",
|
||||
"j8PxqgliIno",
|
||||
"AACOcpA8i-U",
|
||||
"bIwVIx5pp88",
|
||||
"OyHQlZeyEr4",
|
||||
"8ybW48rKBME",
|
||||
"ZK1pNGmNBEc",
|
||||
"cSQTZoZPJzs",
|
||||
"6lhwMJuBIEw",
|
||||
"IR_rbAer7kY",
|
||||
"5iqIug1Rox8",
|
||||
"EkfDmzprwrw",
|
||||
"EjahYsvSTts",
|
||||
"8NBdab8iors",
|
||||
"UHYLsSLSUCw",
|
||||
"QMIaYRaUC5E",
|
||||
"JDuaYGd0zUI",
|
||||
"dy4bWkj4_RA",
|
||||
"55C1L77QrGk",
|
||||
"TSi6_A74lCw",
|
||||
"w-kk-bU_QVw",
|
||||
"uPbl8o3bjY0",
|
||||
"dQw4w9WgXcQ",
|
||||
"hVzINKRbekY",
|
||||
"wzSVOcgKq04",
|
||||
"xaazUgEKuVA",
|
||||
"xfr64zoBTAQ",
|
||||
"xm3YgoEiEDc",
|
||||
"xvFZjo5PgG0",
|
||||
"zL19uMsnpSU",
|
||||
"-HRRGn6tNd4",
|
||||
"-umtVthRGJI",
|
||||
"1V_aE_Xdde8",
|
||||
"3HrSN7176XI",
|
||||
"3KANI2dpXLw",
|
||||
"4TJB9FQo45E",
|
||||
"4ynGOr9vmyc",
|
||||
"5F5nc1bAaKw",
|
||||
"5kQKh2tdisQ",
|
||||
"5uZr3JWYdy8",
|
||||
"65I0HNvTDH4",
|
||||
"67KOFEEOhkI",
|
||||
"6SYVdI7Llrg",
|
||||
"8Set3JpJJ4w",
|
||||
"8aJjMOy-Ops",
|
||||
"A1sgzEDUG-o",
|
||||
"ABUhOJxZQmg",
|
||||
"AP12uZvfvag",
|
||||
"AS35zlAdaSQ",
|
||||
"CZoJt0Sbqrs",
|
||||
"DpPhnECPe2I",
|
||||
"EEbzptEFsKk",
|
||||
"FGEUClII8x0",
|
||||
"G_vas-7a7is",
|
||||
"HiaBjpzLgQI",
|
||||
"I6_0tpqg3ZE",
|
||||
"IHKAgwIxUAY",
|
||||
"IVvl_R2jYMo",
|
||||
"IpjGmx2v6bM",
|
||||
"J3VnZMoh7sk",
|
||||
"Kmt4wrn1MTk",
|
||||
"LeSnAn-Sc0g",
|
||||
"LqXTU8YAGzo",
|
||||
"MJCH_wT9TaU",
|
||||
"MoUPdJrjkCM",
|
||||
"NZ-AAD7Ci_c",
|
||||
"PIMrL4qXtJ0",
|
||||
"PXrHCBoEj7g",
|
||||
"QumbExFAj-U",
|
||||
"R5P1_U7LZX8",
|
||||
"RSsJ19sy3JI",
|
||||
"RgIDuaxiT0w",
|
||||
"RzoZGNsJ71w",
|
||||
"SGi7qi_y0Jw",
|
||||
"UDTGvgE5eJw",
|
||||
"VBY4TV5qK-4",
|
||||
"VVjUWKSZSsc",
|
||||
"WpEVccrkYQ0",
|
||||
"X-j828DqqnY",
|
||||
"XfTUDW93z6E",
|
||||
"Xsvi9uNrDSI",
|
||||
"YWn54TjfBkk",
|
||||
"Yu_moia-oVI",
|
||||
"ZIQZHqNQODo",
|
||||
"ZOU8GIRUd_g",
|
||||
"Zc2tpMgz6MI",
|
||||
"_0719DxMOUY",
|
||||
"_FyXC-SsAPE",
|
||||
"aSzhxllE0RM",
|
||||
"atiNprQmjks",
|
||||
"b1WWpKEPdT4",
|
||||
"b43GgNbz9fg",
|
||||
"cjeogv9VUAE",
|
||||
"cxwxBheZniM",
|
||||
"dS9DO6kx-Ek",
|
||||
"eKDcl0V6o6k",
|
||||
"eLiXPfl8EPY",
|
||||
"f2b1D5w82yU",
|
||||
"f8FHqEIzSlE",
|
||||
"fMzkMpMraFY",
|
||||
"fmxGLQd3J0U",
|
||||
"gLVtavM962w",
|
||||
"gdpijMRhoT8",
|
||||
"gvUiLtwlEl8",
|
||||
"hq05IRf0dBQ",
|
||||
"hyX_krrTBZ0",
|
||||
"iJbwc4wm5Y0",
|
||||
"lAQIiNTH46I",
|
||||
"lfO4Z5WEUuE",
|
||||
"lfao5IToml4",
|
||||
"lp6nr-rD_g8",
|
||||
"lzSjyzqfegI",
|
||||
"oHg5SJYRHA0",
|
||||
"piLTpv1eKdU",
|
||||
"q6NwqFlctZY",
|
||||
"r8tXjJL3xcM",
|
||||
"rfp7FbsnsbU",
|
||||
"tazYxtJcwCc",
|
||||
"thNTPin2RBY",
|
||||
"uYMIMPVK1vU",
|
||||
"ub_VBGajh-s",
|
||||
"uwnuL5Fy5g8",
|
||||
"uxIsiTo4VJo",
|
||||
"v7cyQ-dVaAM",
|
||||
"veFrQTKQy7A",
|
||||
"vf79MCuQ8jM",
|
||||
"vp8fkB0uwd0",
|
||||
"vvs7cXmVwN8",
|
||||
"xAp3HqpE7V8",
|
||||
"xm_EMOdpDhc",
|
||||
"xpupxRzumYs",
|
||||
"y5Ja-E529sU",
|
||||
"yXGqsnkLg0A",
|
||||
"ywoqy9PBN-0",
|
||||
"yxnWl63Avo4",
|
||||
"z-HWXfRKkJU",
|
||||
"z2kThcO6ig8",
|
||||
"zGm0nGF_y2E",
|
||||
"BUykFA7FCo4",
|
||||
"0SoNH07Slj0",
|
||||
"2mun7xy12H0",
|
||||
"34Ig3X59_qA",
|
||||
"5wOXc03RwVA",
|
||||
"6-HUgzYPm9g",
|
||||
"6_b7RDuLwcI",
|
||||
"6mhmcwmgWbA",
|
||||
"7B--1KArxow",
|
||||
"7z_1E8VGJOw",
|
||||
"828hEBkvA5g",
|
||||
"8VFzHYtOARw",
|
||||
"8leAAwMIigI",
|
||||
"8mkofgRW1II",
|
||||
"AyOqGRjVtls",
|
||||
"BjDebmqFRuc",
|
||||
"ByqFY-Boq5Y",
|
||||
"DLzxrzFCyOs",
|
||||
"Dx5i1t0mN78",
|
||||
"E4ihJMQUmUQ",
|
||||
"EE-xtCF3T94",
|
||||
"G8iEMVr7GFg",
|
||||
"Gc2u6AFImn8",
|
||||
"H01BwSD9eyQ",
|
||||
"IdkCEioCp24",
|
||||
"Oo0twK2ZbLU",
|
||||
"Rtqkxkt7Hyg",
|
||||
"SpZ2FsEfwP4",
|
||||
"TOcAAaZ1HhU",
|
||||
"TzXXHVhGXTQ",
|
||||
"Uj1ykZWtPYI",
|
||||
"UmOi40tnUcM",
|
||||
"V-_O7nl0Ii0",
|
||||
"VbUuB1aN2DA",
|
||||
"VgojnNgmgVs",
|
||||
"YJWSAJjkTsI",
|
||||
"ZzUsKizhb8o",
|
||||
"a3Z7zEc7AXQ",
|
||||
"cSAp9sBzPbc",
|
||||
"cqF6M25kqq4",
|
||||
"cvh0nX08nRw",
|
||||
"dPmZqsQNzGA",
|
||||
"dQw4w9WgXcQ",
|
||||
"doEqUhFiQS4",
|
||||
"epyRUp0BhrA",
|
||||
"gvGyS5j9aFY",
|
||||
"hLZW4U86cL4",
|
||||
"iik25wqIuFo",
|
||||
"j5a0jTc9S10",
|
||||
"lXMskKTw3Bc",
|
||||
"nHRbZW097Uk",
|
||||
"nrsnN23tmUA",
|
||||
"oHg5SJYRHA0",
|
||||
"oT3mCybbhf0",
|
||||
"ptw2FLKXDQE",
|
||||
"r7VYFiPoZk4",
|
||||
"r8tXjJL3xcM",
|
||||
"rAx5LIul1N8",
|
||||
"rbsPu1z3ugQ",
|
||||
"rrs0B_LM898",
|
||||
"sO4wVSA9UPs",
|
||||
"tzYPr9w22VU",
|
||||
"uK5WDo_3s7s",
|
||||
"ub82Xb1C8os",
|
||||
"wpV-gGA4PSk",
|
||||
"wuggc60TVzU",
|
||||
"cSAp9sBzPbc",
|
||||
"8ybW48rKBME",
|
||||
"Tt7bzxurJ1I",
|
||||
"gidHrKbTpog",
|
||||
"vcq30ywIKlc",
|
||||
"y6120QOlsfU",
|
||||
"QhuZIEkKkXA",
|
||||
"rW7hXs-81hM",
|
||||
"Oo0twK2ZbLU",
|
||||
"0SoNH07Slj0",
|
||||
"LLFhKaqnWwk",
|
||||
"SpZ2FsEfwP4",
|
||||
"SO4c1NlGCpY",
|
||||
"MCjlo7PtXMQ",
|
||||
"TCUPeAlpDVE",
|
||||
"5wOXc03RwVA",
|
||||
"oJl25bABYac",
|
||||
"a6pbjksYUHY",
|
||||
"Dx5i1t0mN78",
|
||||
"Uj1ykZWtPYI",
|
||||
"E50L-JYWm3w",
|
||||
"BjDebmqFRuc",
|
||||
"PibwQR9nRus",
|
||||
"rrs0B_LM898",
|
||||
"cH1NLToRz_o",
|
||||
"j5a0jTc9S10",
|
||||
"p7YXXieghto",
|
||||
"qxeokP0n6V0",
|
||||
"GHMjD0Lp5DY",
|
||||
"bIwVIx5pp88",
|
||||
"7z_1E8VGJOw",
|
||||
"QB7ACr7pUuE",
|
||||
"LjQZaD9EEJ0",
|
||||
"cvh0nX08nRw",
|
||||
"fZi4JxbTwPo",
|
||||
"2ocykBzWDiM",
|
||||
"H01BwSD9eyQ",
|
||||
"PzqQSOaCcnw",
|
||||
"lXMskKTw3Bc",
|
||||
"JzjldPdpT7Q",
|
||||
"7B--1KArxow",
|
||||
"lHyeAtiiL18",
|
||||
"s0akG-V_Y30",
|
||||
"HV8IxKtAlrA",
|
||||
"6_b7RDuLwcI",
|
||||
"rbsPu1z3ugQ",
|
||||
"8O_ifyIIrN4",
|
||||
"xvFZjo5PgG0",
|
||||
"N3MKlU5_Gs0",
|
||||
"AyOqGRjVtls",
|
||||
"bCh5IlXTckA",
|
||||
"pSxJqmMNU-A",
|
||||
"ByqFY-Boq5Y",
|
||||
"G8iEMVr7GFg",
|
||||
"s99hC5WUwjo",
|
||||
"uK5WDo_3s7s",
|
||||
"TzXXHVhGXTQ",
|
||||
"OYPG7j8rKZY",
|
||||
"Kiz3PM387FI",
|
||||
"2l51wyMM9hs",
|
||||
"ptw2FLKXDQE",
|
||||
"wzSVOcgKq04",
|
||||
"rAx5LIul1N8",
|
||||
"ll-mQPDCn-U",
|
||||
"hxCXEX2JOKE",
|
||||
"6RyOsIseJbk",
|
||||
"HUU3kOhjFfg",
|
||||
"3KANI2dpXLw",
|
||||
"-51AfyMqnpI",
|
||||
"6mhmcwmgWbA",
|
||||
"7lEodsmjeQU",
|
||||
"8leAAwMIigI",
|
||||
"xaazUgEKuVA",
|
||||
"dQw4w9WgXcQ",
|
||||
"nHRbZW097Uk",
|
||||
"vkbQmH5MPME",
|
||||
"6vBnqJhP7f8",
|
||||
"xfr64zoBTAQ",
|
||||
"EE-xtCF3T94",
|
||||
"zL19uMsnpSU",
|
||||
"mrThFRR3n8A",
|
||||
"E4ihJMQUmUQ",
|
||||
"kczWpSN6emg",
|
||||
"bkOVXdvijmQ",
|
||||
"cqF6M25kqq4",
|
||||
"cAN30xJp2Cs",
|
||||
"doEqUhFiQS4",
|
||||
"iiUIi5b9RlE",
|
||||
"H8ZH_mkfPUY",
|
||||
"HPk-VhRjNI8",
|
||||
"INbRpclIFsE",
|
||||
"ikFZLI4HLpQ",
|
||||
"dPmZqsQNzGA",
|
||||
"cjBHXvBYw5s",
|
||||
"SjTOn5scRmY",
|
||||
"JkcHqN6YswU",
|
||||
"IO9XlQrEt2Y",
|
||||
"oHg5SJYRHA0",
|
||||
"lpiB2wMc49g",
|
||||
"DIs7dtlMCP0",
|
||||
"gvGyS5j9aFY",
|
||||
"VgojnNgmgVs",
|
||||
"SsiHLiXBlcM",
|
||||
"Q53-mWHvxJo",
|
||||
"XfIIQYnBHrQ",
|
||||
"LWErcuHm_C4",
|
||||
"AACOcpA8i-U",
|
||||
"QdNEtVH9bZE",
|
||||
"dRV6NaciZVk",
|
||||
"ub82Xb1C8os",
|
||||
"ENYalQvZG4Q",
|
||||
"BXuxOeg6PiQ",
|
||||
"0Z0i-nimHkU",
|
||||
"Mdq6sQPKYqQ",
|
||||
"C5GGeuFPVVE",
|
||||
"Gc2u6AFImn8",
|
||||
"klqi_h9FElc",
|
||||
"Eg7XtrH0duI",
|
||||
"aaP6xIkMqzo",
|
||||
"xbXoWRs2C8M",
|
||||
"pKskW7wJ0v0",
|
||||
"HnfkEVtetuE",
|
||||
"9oxRDJjAQKI",
|
||||
"j7gKwxRe7MQ",
|
||||
"42OleX0HR4E",
|
||||
"nrsnN23tmUA",
|
||||
"iik25wqIuFo",
|
||||
"E458nb_pPmk",
|
||||
"06pBzAlItwI",
|
||||
"rTgj1HxmUbg",
|
||||
"epyRUp0BhrA",
|
||||
"rEtZzcxQ_pA",
|
||||
"Yb6dZ1IFlKc",
|
||||
"eBGIQ7ZuuiU",
|
||||
"soq9cLVa5Xo",
|
||||
"r8tXjJL3xcM",
|
||||
"XB3EQrj1maw",
|
||||
"RvBwypGUkPo",
|
||||
"d4N5LnsNpF0",
|
||||
"j8PxqgliIno",
|
||||
"th0pH9srXRY",
|
||||
"sO4wVSA9UPs",
|
||||
"8mkofgRW1II",
|
||||
"fMnIpIMuBJI",
|
||||
"gPkZS92WCIo",
|
||||
"_sWG4uhLiWo",
|
||||
"8VFzHYtOARw",
|
||||
"V-_O7nl0Ii0",
|
||||
"eBsIpefmXvE",
|
||||
"nW0P2hYBm9A",
|
||||
"MAM--whuMcU",
|
||||
"QKr_0DMYV5g",
|
||||
"VZrDxD0Za9I",
|
||||
"WSBK_NePew",
|
||||
"1kj837fWpo",
|
||||
"oAyaw1ohiWs",
|
||||
"iadFGiLRgFo",
|
||||
"A4hJPP0Zn9I",
|
||||
"r1JAZlyhKMc",
|
||||
"DdpBpn6txTk",
|
||||
"yS6LYj-y1HA",
|
||||
"WyltKn3pi9U",
|
||||
];
|
||||
603
badgesSelector/index.tsx
Normal file
603
badgesSelector/index.tsx
Normal file
@@ -0,0 +1,603 @@
|
||||
/*
|
||||
* Vencord, a Discord client mod
|
||||
* Copyright (c) 2025 Vendicated and contributors
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import * as DataStore from "@api/DataStore";
|
||||
import definePlugin from "@utils/types";
|
||||
import { findStoreLazy } from "@webpack";
|
||||
import { Menu, Toasts } from "@webpack/common";
|
||||
const UserProfileStore = findStoreLazy("UserProfileStore");
|
||||
const userBadgesMap = new Map<string, any[]>();
|
||||
|
||||
const removedBadgesMap = new Map<string, Set<string>>();
|
||||
|
||||
function getNitroSinceDate(months: number): string {
|
||||
const currentDate = new Date();
|
||||
const sinceDate = new Date(currentDate);
|
||||
sinceDate.setMonth(currentDate.getMonth() - months);
|
||||
const month = sinceDate.getMonth() + 1;
|
||||
const day = sinceDate.getDate();
|
||||
const year = sinceDate.getFullYear();
|
||||
return `${month}/${day}/${year.toString().slice(-2)}`;
|
||||
}
|
||||
|
||||
function getBoostSinceDate(months: number): string {
|
||||
const currentDate = new Date();
|
||||
const sinceDate = new Date(currentDate);
|
||||
sinceDate.setMonth(currentDate.getMonth() - months);
|
||||
const monthNames = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
|
||||
return `${monthNames[sinceDate.getMonth()]} ${sinceDate.getDate()}, ${sinceDate.getFullYear()}`;
|
||||
}
|
||||
|
||||
const availableBadges = [
|
||||
{
|
||||
id: "staff",
|
||||
title: "Discord Staff",
|
||||
description: "Discord Staff",
|
||||
icon: "5e74e9b61934fc1f67c65515d1f7e60d",
|
||||
link: "https://discord.com/company"
|
||||
},
|
||||
{
|
||||
id: "premium",
|
||||
title: "Nitro Subscriber",
|
||||
description: "Subscriber since Dec 22, 2016",
|
||||
icon: "2ba85e8026a8614b640c2837bcdfe21b",
|
||||
link: "https://discord.com/settings/premium"
|
||||
},
|
||||
{
|
||||
id: "premium_tenure_1_month_v2",
|
||||
title: "Nitro Bronze (1 month)",
|
||||
description: `Subscriber since ${getNitroSinceDate(1)}`,
|
||||
icon: "4f33c4a9c64ce221936bd256c356f91f",
|
||||
link: "https://discord.com/nitro"
|
||||
},
|
||||
{
|
||||
id: "premium_tenure_3_month_v2",
|
||||
title: "Nitro Silver (3 months)",
|
||||
description: `Subscriber since ${getNitroSinceDate(3)}`,
|
||||
icon: "4514fab914bdbfb4ad2fa23df76121a6",
|
||||
link: "https://discord.com/nitro"
|
||||
},
|
||||
{
|
||||
id: "premium_tenure_6_month_v2",
|
||||
title: "Nitro Gold (6 months)",
|
||||
description: `Subscriber since ${getNitroSinceDate(6)}`,
|
||||
icon: "2895086c18d5531d499862e41d1155a6",
|
||||
link: "https://discord.com/nitro"
|
||||
},
|
||||
{
|
||||
id: "premium_tenure_12_month_v2",
|
||||
title: "Nitro Platinum (1 year)",
|
||||
description: `Subscriber since ${getNitroSinceDate(12)}`,
|
||||
icon: "0334688279c8359120922938dcb1d6f8",
|
||||
link: "https://discord.com/nitro"
|
||||
},
|
||||
{
|
||||
id: "premium_tenure_24_month_v2",
|
||||
title: "Nitro Diamond (2 years)",
|
||||
description: `Subscriber since ${getNitroSinceDate(24)}`,
|
||||
icon: "0d61871f72bb9a33a7ae568c1fb4f20a",
|
||||
link: "https://discord.com/nitro"
|
||||
},
|
||||
{
|
||||
id: "premium_tenure_36_month_v2",
|
||||
title: "Nitro Emerald (3 years)",
|
||||
description: `Subscriber since ${getNitroSinceDate(36)}`,
|
||||
icon: "11e2d339068b55d3a506cff34d3780f3",
|
||||
link: "https://discord.com/nitro"
|
||||
},
|
||||
{
|
||||
id: "premium_tenure_60_month_v2",
|
||||
title: "Nitro Ruby (5 years)",
|
||||
description: `Subscriber since ${getNitroSinceDate(60)}`,
|
||||
icon: "cd5e2cfd9d7f27a8cdcd3e8a8d5dc9f4",
|
||||
link: "https://discord.com/nitro"
|
||||
},
|
||||
{
|
||||
id: "premium_tenure_72_month_v2",
|
||||
title: "Nitro Opal (6+ years)",
|
||||
description: `Subscriber since ${getNitroSinceDate(72)}`,
|
||||
icon: "5b154df19c53dce2af92c9b61e6be5e2",
|
||||
link: "https://discord.com/nitro"
|
||||
},
|
||||
{
|
||||
id: "partner",
|
||||
title: "Partnered Server Owner",
|
||||
description: "Partnered Server Owner",
|
||||
icon: "3f9748e53446a137a052f3454e2de41e",
|
||||
link: "https://discord.com/partners"
|
||||
},
|
||||
{
|
||||
id: "certified_moderator",
|
||||
title: "Moderator Programs Alumni",
|
||||
description: "Moderator Programs Alumni",
|
||||
icon: "fee1624003e2fee35cb398e125dc479b",
|
||||
link: "https://discord.com/safety"
|
||||
},
|
||||
{
|
||||
id: "hypesquad",
|
||||
title: "HypeSquad Events",
|
||||
description: "HypeSquad Events",
|
||||
icon: "bf01d1073931f921909045f3a39fd264",
|
||||
link: "https://discord.com/hypesquad"
|
||||
},
|
||||
{
|
||||
id: "hypesquad_house_1",
|
||||
title: "HypeSquad Bravery",
|
||||
description: "HypeSquad Bravery",
|
||||
icon: "8a88d63823d8a71cd5e390baa45efa02",
|
||||
link: "https://discord.com/settings/hypesquad-online"
|
||||
},
|
||||
{
|
||||
id: "hypesquad_house_2",
|
||||
title: "HypeSquad Brilliance",
|
||||
description: "HypeSquad Brilliance",
|
||||
icon: "011940fd013da3f7fb926e4a1cd2e618",
|
||||
link: "https://discord.com/settings/hypesquad-online"
|
||||
},
|
||||
{
|
||||
id: "hypesquad_house_3",
|
||||
title: "HypeSquad Balance",
|
||||
description: "HypeSquad Balance",
|
||||
icon: "3aa41de486fa12454c3761e8e223442e",
|
||||
link: "https://discord.com/settings/hypesquad-online"
|
||||
},
|
||||
{
|
||||
id: "bug_hunter_level_1",
|
||||
title: "Discord Bug Hunter",
|
||||
description: "Discord Bug Hunter",
|
||||
icon: "2717692c7dca7289b35297368a940dd0",
|
||||
link: "https://support.discord.com/hc/en-us/articles/360046057772-Discord-Bugs"
|
||||
},
|
||||
{
|
||||
id: "bug_hunter_level_2",
|
||||
title: "Discord Bug Hunter Gold",
|
||||
description: "Discord Bug Hunter",
|
||||
icon: "848f79194d4be5ff5f81505cbd0ce1e6",
|
||||
link: "https://support.discord.com/hc/en-us/articles/360046057772-Discord-Bugs"
|
||||
},
|
||||
{
|
||||
id: "active_developer",
|
||||
title: "Active Developer",
|
||||
description: "Active Developer",
|
||||
icon: "6bdc42827a38498929a4920da12695d9",
|
||||
link: "https://support-dev.discord.com/hc/en-us/articles/10113997751447?ref=badge"
|
||||
},
|
||||
{
|
||||
id: "verified_developer",
|
||||
title: "Early Verified Bot Developer",
|
||||
description: "Early Verified Bot Developer",
|
||||
icon: "6df5892e0f35b051f8b61eace34f4967",
|
||||
link: "https://discord.com/developers"
|
||||
},
|
||||
{
|
||||
id: "early_supporter",
|
||||
title: "Early Supporter",
|
||||
description: "Early Supporter",
|
||||
icon: "7060786766c9c840eb3019e725d2b358",
|
||||
link: "https://discord.com/settings/premium"
|
||||
},
|
||||
{
|
||||
id: "guild_booster_lvl1",
|
||||
title: "Server Boost 1 Month",
|
||||
description: `Server boosting since ${getBoostSinceDate(1)}`,
|
||||
icon: "51040c70d4f20a921ad6674ff86fc95c",
|
||||
link: "https://discord.com/settings/premium"
|
||||
},
|
||||
{
|
||||
id: "guild_booster_lvl2",
|
||||
title: "Server Boost 2 Months",
|
||||
description: `Server boosting since ${getBoostSinceDate(2)}`,
|
||||
icon: "0e4080d1d333bc7ad29ef6528b6f2fb7",
|
||||
link: "https://discord.com/settings/premium"
|
||||
},
|
||||
{
|
||||
id: "guild_booster_lvl3",
|
||||
title: "Server Boost 3 Months",
|
||||
description: `Server boosting since ${getBoostSinceDate(3)}`,
|
||||
icon: "72bed924410c304dbe3d00a6e593ff59",
|
||||
link: "https://discord.com/settings/premium"
|
||||
},
|
||||
{
|
||||
id: "guild_booster_lvl4",
|
||||
title: "Server Boost 6 Months",
|
||||
description: `Server boosting since ${getBoostSinceDate(6)}`,
|
||||
icon: "df199d2050d3ed4ebf84d64ae83989f8",
|
||||
link: "https://discord.com/settings/premium"
|
||||
},
|
||||
{
|
||||
id: "guild_booster_lvl5",
|
||||
title: "Server Boost 9 Months",
|
||||
description: `Server boosting since ${getBoostSinceDate(9)}`,
|
||||
icon: "996b3e870e8a22ce519b3a50e6bdd52f",
|
||||
link: "https://discord.com/settings/premium"
|
||||
},
|
||||
{
|
||||
id: "guild_booster_lvl6",
|
||||
title: "Server Boost 12 Months",
|
||||
description: `Server boosting since ${getBoostSinceDate(12)}`,
|
||||
icon: "991c9f39ee33d7537d9f408c3e53141e",
|
||||
link: "https://discord.com/settings/premium"
|
||||
},
|
||||
{
|
||||
id: "guild_booster_lvl7",
|
||||
title: "Server Boost 15 Months",
|
||||
description: `Server boosting since ${getBoostSinceDate(15)}`,
|
||||
icon: "cb3ae83c15e970e8f3d410bc62cb8b99",
|
||||
link: "https://discord.com/settings/premium"
|
||||
},
|
||||
{
|
||||
id: "guild_booster_lvl8",
|
||||
title: "Server Boost 18 Months",
|
||||
description: `Server boosting since ${getBoostSinceDate(18)}`,
|
||||
icon: "7142225d31238f6387d9f09efaa02759",
|
||||
link: "https://discord.com/settings/premium"
|
||||
},
|
||||
{
|
||||
id: "guild_booster_lvl9",
|
||||
title: "Server Boost 24 Months",
|
||||
description: `Server boosting since ${getBoostSinceDate(24)}`,
|
||||
icon: "ec92202290b48d0879b7413d2dde3bab",
|
||||
link: "https://discord.com/settings/premium"
|
||||
},
|
||||
{
|
||||
id: "legacy_username",
|
||||
title: "Legacy Username",
|
||||
description: "Originally known as their old username",
|
||||
icon: "6de6d34650760ba5551a79732e98ed60",
|
||||
link: "https://discord.com"
|
||||
},
|
||||
{
|
||||
id: "quest_completed",
|
||||
title: "Quest Completer",
|
||||
description: "Completed a Quest",
|
||||
icon: "7d9ae358c8c5e118768335dbe68b4fb8",
|
||||
link: "https://discord.com/settings/inventory"
|
||||
},
|
||||
{
|
||||
id: "bot_commands",
|
||||
title: "Supports Commands",
|
||||
description: "Supports Commands",
|
||||
icon: "6f9e37f9029ff57aef81db857890005e",
|
||||
link: "https://discord.com/blog/welcome-to-the-new-era-of-discord-apps?ref=badge"
|
||||
},
|
||||
{
|
||||
id: "automod",
|
||||
title: "Uses AutoMod",
|
||||
description: "Uses automod",
|
||||
icon: "f2459b691ac7453ed6039bbcfaccbfcd",
|
||||
link: "https://discord.com"
|
||||
},
|
||||
{
|
||||
id: "application_guild_subscription",
|
||||
title: "Server Subscription",
|
||||
description: "Monetized server",
|
||||
icon: "d2010c413a8da2208b7e4311042a4b9d",
|
||||
link: "https://discord.com"
|
||||
},
|
||||
{
|
||||
id: "orb_profile_badge",
|
||||
title: "Orbs",
|
||||
description: "Collected the Orb Profile Badge",
|
||||
icon: "83d8a1eb09a8d64e59233eec5d4d5c2d",
|
||||
link: "https://discord.com"
|
||||
}
|
||||
];
|
||||
|
||||
async function loadData() {
|
||||
const savedUserBadges = await DataStore.get("userBadges");
|
||||
if (savedUserBadges) {
|
||||
Object.entries(savedUserBadges).forEach(([userId, badges]) => {
|
||||
const updatedBadges = (badges as any[]).map(badge => {
|
||||
const freshBadge = availableBadges.find(b => b.id === badge.id);
|
||||
if (freshBadge && (badge.id.startsWith("premium_tenure_") || badge.id.startsWith("guild_booster_"))) {
|
||||
return { ...badge, description: freshBadge.description };
|
||||
}
|
||||
return badge;
|
||||
});
|
||||
userBadgesMap.set(userId, updatedBadges);
|
||||
});
|
||||
}
|
||||
|
||||
const savedRemovedBadges = await DataStore.get("removedBadges");
|
||||
if (savedRemovedBadges) {
|
||||
Object.entries(savedRemovedBadges).forEach(([userId, badgeIds]) => {
|
||||
removedBadgesMap.set(userId, new Set(badgeIds as string[]));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async function saveData() {
|
||||
const userBadgesObject = Object.fromEntries(userBadgesMap);
|
||||
await DataStore.set("userBadges", userBadgesObject);
|
||||
|
||||
const removedBadgesObject = Object.fromEntries(
|
||||
Array.from(removedBadgesMap.entries()).map(([userId, badgeIds]) => [userId, Array.from(badgeIds)])
|
||||
);
|
||||
await DataStore.set("removedBadges", removedBadgesObject);
|
||||
}
|
||||
|
||||
function addBadgesToUser(userId: string, badges: any[]) {
|
||||
const existingBadges = userBadgesMap.get(userId) || [];
|
||||
badges.forEach(badge => {
|
||||
const existingIndex = existingBadges.findIndex(b => b.id === badge.id);
|
||||
if (existingIndex === -1) {
|
||||
existingBadges.push(badge);
|
||||
}
|
||||
});
|
||||
userBadgesMap.set(userId, existingBadges);
|
||||
saveData();
|
||||
}
|
||||
|
||||
function removeBadgeFromUser(userId: string, badgeId: string) {
|
||||
const existingBadges = userBadgesMap.get(userId) || [];
|
||||
const updatedBadges = existingBadges.filter(b => b.id !== badgeId);
|
||||
if (updatedBadges.length > 0) {
|
||||
userBadgesMap.set(userId, updatedBadges);
|
||||
} else {
|
||||
userBadgesMap.delete(userId);
|
||||
}
|
||||
saveData();
|
||||
}
|
||||
|
||||
function getUserBadges(userId: string): any[] {
|
||||
return userBadgesMap.get(userId) || [];
|
||||
}
|
||||
|
||||
function hideRealBadge(userId: string, badgeId: string) {
|
||||
if (!removedBadgesMap.has(userId)) {
|
||||
removedBadgesMap.set(userId, new Set());
|
||||
}
|
||||
removedBadgesMap.get(userId)!.add(badgeId);
|
||||
saveData();
|
||||
}
|
||||
|
||||
function unhideRealBadge(userId: string, badgeId: string) {
|
||||
if (removedBadgesMap.has(userId)) {
|
||||
removedBadgesMap.get(userId)!.delete(badgeId);
|
||||
if (removedBadgesMap.get(userId)!.size === 0) {
|
||||
removedBadgesMap.delete(userId);
|
||||
}
|
||||
saveData();
|
||||
}
|
||||
}
|
||||
|
||||
function isRealBadgeHidden(userId: string, badgeId: string): boolean {
|
||||
return removedBadgesMap.has(userId) && removedBadgesMap.get(userId)!.has(badgeId);
|
||||
}
|
||||
|
||||
function toggleBadge(userId: string, badge: any, hasActualBadge: boolean) {
|
||||
const hasUserBadge = getUserBadges(userId).find(b => b.id === badge.id);
|
||||
const isHidden = isRealBadgeHidden(userId, badge.id);
|
||||
|
||||
if (hasActualBadge) {
|
||||
if (isHidden) {
|
||||
unhideRealBadge(userId, badge.id);
|
||||
Toasts.show({
|
||||
message: `Restored ${badge.title}`,
|
||||
type: Toasts.Type.SUCCESS,
|
||||
id: Toasts.genId()
|
||||
});
|
||||
} else {
|
||||
hideRealBadge(userId, badge.id);
|
||||
Toasts.show({
|
||||
message: `Removed ${badge.title}`,
|
||||
type: Toasts.Type.SUCCESS,
|
||||
id: Toasts.genId()
|
||||
});
|
||||
}
|
||||
} else {
|
||||
if (hasUserBadge) {
|
||||
removeBadgeFromUser(userId, badge.id);
|
||||
Toasts.show({
|
||||
message: `Removed ${badge.title}`,
|
||||
type: Toasts.Type.SUCCESS,
|
||||
id: Toasts.genId()
|
||||
});
|
||||
} else {
|
||||
addBadgesToUser(userId, [badge]);
|
||||
Toasts.show({
|
||||
message: `Added ${badge.title}`,
|
||||
type: Toasts.Type.SUCCESS,
|
||||
id: Toasts.genId()
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function giveAllBadges(userId: string) {
|
||||
addBadgesToUser(userId, availableBadges);
|
||||
Toasts.show({
|
||||
message: "Added all badges",
|
||||
type: Toasts.Type.SUCCESS,
|
||||
id: Toasts.genId()
|
||||
});
|
||||
}
|
||||
|
||||
function addUserBadge(userId: string) {
|
||||
const badgeId = prompt("Enter badge ID:");
|
||||
if (!badgeId) return;
|
||||
|
||||
const description = prompt("Enter badge description:");
|
||||
if (!description) return;
|
||||
|
||||
const icon = prompt("Enter badge icon hash:");
|
||||
if (!icon) return;
|
||||
|
||||
const link = prompt("Enter badge link (optional):", "https://discord.com");
|
||||
|
||||
const userBadge = {
|
||||
id: badgeId,
|
||||
description: description,
|
||||
icon: icon,
|
||||
link: link || "https://discord.com"
|
||||
};
|
||||
|
||||
addBadgesToUser(userId, [userBadge]);
|
||||
Toasts.show({
|
||||
message: `Added badge: ${badgeId}`,
|
||||
type: Toasts.Type.SUCCESS,
|
||||
id: Toasts.genId()
|
||||
});
|
||||
}
|
||||
|
||||
let originalGetUserProfile: any;
|
||||
|
||||
export default definePlugin({
|
||||
name: "BadgeSelector",
|
||||
description: "Customize user badges - add, remove, or hide any Discord badge",
|
||||
authors: [
|
||||
{ id: 1263457746829705310n, name: ".q1" },
|
||||
{ id: 1147940825330876538n, name: "Jelly" },
|
||||
{ id: 1403404140461297816n, name: "Sami" },
|
||||
],
|
||||
|
||||
async start() {
|
||||
await loadData();
|
||||
originalGetUserProfile = UserProfileStore.getUserProfile;
|
||||
|
||||
UserProfileStore.getUserProfile = function (userId: string) {
|
||||
const userProfile = originalGetUserProfile.call(this, userId);
|
||||
if (!userProfile) return userProfile;
|
||||
|
||||
let newBadges = [...(userProfile.badges || [])];
|
||||
|
||||
if (removedBadgesMap.has(userId)) {
|
||||
const hiddenBadges = removedBadgesMap.get(userId)!;
|
||||
newBadges = newBadges.filter(b => !hiddenBadges.has(b.id));
|
||||
}
|
||||
|
||||
if (userBadgesMap.has(userId)) {
|
||||
const userBadges = userBadgesMap.get(userId)!;
|
||||
userBadges.forEach(badgeObj => {
|
||||
const { id, description, icon, link } = badgeObj;
|
||||
const badgeIndex = newBadges.findIndex(b => b.id === id);
|
||||
if (badgeIndex === -1) {
|
||||
newBadges.push({ id, description, icon, link });
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
newBadges.sort((a, b) => {
|
||||
const orderA = availableBadges.findIndex(badge => badge.id === a.id);
|
||||
const orderB = availableBadges.findIndex(badge => badge.id === b.id);
|
||||
|
||||
const finalOrderA = orderA === -1 ? 9999 : orderA;
|
||||
const finalOrderB = orderB === -1 ? 9999 : orderB;
|
||||
|
||||
return finalOrderA - finalOrderB;
|
||||
});
|
||||
|
||||
return {
|
||||
...userProfile,
|
||||
badges: newBadges
|
||||
};
|
||||
};
|
||||
},
|
||||
|
||||
stop() {
|
||||
if (originalGetUserProfile) {
|
||||
UserProfileStore.getUserProfile = originalGetUserProfile;
|
||||
}
|
||||
userBadgesMap.clear();
|
||||
removedBadgesMap.clear();
|
||||
},
|
||||
|
||||
contextMenus: {
|
||||
"user-context"(children, { user }) {
|
||||
if (!user) return;
|
||||
|
||||
const currentUserBadges = getUserBadges(user.id);
|
||||
const userProfile = originalGetUserProfile ? originalGetUserProfile.call(UserProfileStore, user.id) : UserProfileStore.getUserProfile(user.id);
|
||||
const actualBadges = userProfile?.badges || [];
|
||||
|
||||
children.push(
|
||||
<Menu.MenuItem
|
||||
label="Add Badge"
|
||||
key="add-custom-badge"
|
||||
id="user-context-add-custom"
|
||||
color="brand"
|
||||
action={() => addUserBadge(user.id)}
|
||||
/>,
|
||||
<Menu.MenuItem
|
||||
label="Manage Badges"
|
||||
key="custom-badges"
|
||||
id="user-context-custom-badges"
|
||||
>
|
||||
{availableBadges.map(badge => {
|
||||
const hasUserBadge = currentUserBadges.find(b => b.id === badge.id);
|
||||
const hasActualBadge = actualBadges.find(b => b.id === badge.id);
|
||||
const isHidden = isRealBadgeHidden(user.id, badge.id);
|
||||
const isChecked = !!hasUserBadge || (!!hasActualBadge && !isHidden);
|
||||
|
||||
return (
|
||||
<Menu.MenuCheckboxItem
|
||||
key={badge.id}
|
||||
id={`badge-${badge.id}`}
|
||||
// label={
|
||||
// <div style={{ display: "flex", alignItems: "center", gap: "8px" }}>
|
||||
// <img
|
||||
// src={`https://cdn.discordapp.com/badge-icons/${badge.icon}.png`}
|
||||
// alt=""
|
||||
// width="18"
|
||||
// height="18"
|
||||
// style={{
|
||||
// borderRadius: "3px",
|
||||
// imageRendering: "crisp-edges"
|
||||
// }}
|
||||
// />
|
||||
// <span>{badge.title}</span>
|
||||
// </div>
|
||||
// }
|
||||
label={badge.title}
|
||||
checked={isChecked}
|
||||
action={() => toggleBadge(user.id, badge, !!hasActualBadge)}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
<Menu.MenuSeparator />
|
||||
<Menu.MenuItem
|
||||
label="Give All Badges"
|
||||
id="give-all-badges"
|
||||
color="brand"
|
||||
action={() => giveAllBadges(user.id)}
|
||||
/>
|
||||
<Menu.MenuItem
|
||||
label="Remove All Badges"
|
||||
id="remove-all-badges"
|
||||
color="danger"
|
||||
action={() => {
|
||||
actualBadges.forEach(badge => {
|
||||
hideRealBadge(user.id, badge.id);
|
||||
});
|
||||
userBadgesMap.delete(user.id);
|
||||
|
||||
Toasts.show({
|
||||
message: "Removed all badges",
|
||||
type: Toasts.Type.SUCCESS,
|
||||
id: Toasts.genId()
|
||||
});
|
||||
}}
|
||||
/>
|
||||
<Menu.MenuItem
|
||||
label="Reset to Original"
|
||||
id="reset-badges"
|
||||
color="default"
|
||||
action={() => {
|
||||
userBadgesMap.delete(user.id);
|
||||
removedBadgesMap.delete(user.id);
|
||||
|
||||
Toasts.show({
|
||||
message: "Reset badges to original state",
|
||||
type: Toasts.Type.SUCCESS,
|
||||
id: Toasts.genId()
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</Menu.MenuItem>
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
35
bestPluginEVER/components/IdiotWarning.tsx
Normal file
35
bestPluginEVER/components/IdiotWarning.tsx
Normal file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Vencord, a Discord client mod
|
||||
* Copyright (c) 2025 Vendicated and contributors
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import { Message } from "@vencord/discord-types";
|
||||
import { Text } from "@webpack/common";
|
||||
|
||||
export const IDIOT_REGEX: RegExp[] = [
|
||||
/\b((s+i+x+ s+e+v+e+n+)|(67))\b/i,
|
||||
/skibidi ?(toilets?)?/i,
|
||||
/united kingdom/i,
|
||||
/hitler/i,
|
||||
/we ?are ?charlie ?kirk/i,
|
||||
/darktru/i
|
||||
];
|
||||
|
||||
export function IdiotWarning({
|
||||
message,
|
||||
}: {
|
||||
message: Message;
|
||||
}) {
|
||||
for (const idiot of IDIOT_REGEX) {
|
||||
if (idiot.test(message.content)) {
|
||||
return (
|
||||
<div>
|
||||
<Text color="text-danger" variant="text-xs/semibold">
|
||||
⚠️ This message is stupid.
|
||||
</Text>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
30
bestPluginEVER/components/VeryCool.tsx
Normal file
30
bestPluginEVER/components/VeryCool.tsx
Normal file
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Vencord, a Discord client mod
|
||||
* Copyright (c) 2025 Vendicated and contributors
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import { Button } from "@components/Button";
|
||||
import { Message } from "@vencord/discord-types";
|
||||
|
||||
export const COOL_REGEX: RegExp[] = [
|
||||
/vencord/i,
|
||||
];
|
||||
|
||||
export function VeryCool({
|
||||
message,
|
||||
}: {
|
||||
message: Message;
|
||||
}) {
|
||||
for (const idiot of COOL_REGEX) {
|
||||
if (idiot.test(message.content)) {
|
||||
return (
|
||||
<div>
|
||||
<Button type="button" variant="link" onClick={a => open("roblox://")}>
|
||||
secret :3
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
50
bestPluginEVER/index.tsx
Normal file
50
bestPluginEVER/index.tsx
Normal file
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Vencord, a Discord client mod
|
||||
* Copyright (c) 2025 Vendicated and contributors
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import { addMessageAccessory, removeMessageAccessory } from "@api/MessageAccessories";
|
||||
import definePlugin from "@utils/types";
|
||||
import { Message } from "@vencord/discord-types";
|
||||
|
||||
import { IdiotWarning } from "./components/IdiotWarning";
|
||||
import { VeryCool } from "./components/VeryCool";
|
||||
|
||||
function BigWarning({
|
||||
message
|
||||
}: {
|
||||
message: Message;
|
||||
}) {
|
||||
return <>
|
||||
<IdiotWarning message={message} />
|
||||
<VeryCool message={message} />
|
||||
</>;
|
||||
}
|
||||
|
||||
export default definePlugin({
|
||||
name: "BestPluginEver",
|
||||
description: "Haha funny",
|
||||
authors: [{
|
||||
name: "ocbwoy3",
|
||||
id: 486147449703104523n
|
||||
}],
|
||||
|
||||
start() {
|
||||
addMessageAccessory(
|
||||
"BigWarning",
|
||||
(props: Record<string, any>) => {
|
||||
return (
|
||||
<BigWarning
|
||||
message={props.message as Message}
|
||||
/>
|
||||
);
|
||||
},
|
||||
4
|
||||
);
|
||||
},
|
||||
|
||||
stop() {
|
||||
removeMessageAccessory("BigWarning");
|
||||
}
|
||||
});
|
||||
135
deltaruneProphecy/index.tsx
Normal file
135
deltaruneProphecy/index.tsx
Normal file
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
* Vencord, a Discord client mod
|
||||
* Copyright (c) 2025 Vendicated and contributors
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import { addMessageAccessory, removeMessageAccessory } from "@api/MessageAccessories";
|
||||
import { Button } from "@components/Button";
|
||||
import { Logger } from "@utils/Logger";
|
||||
import definePlugin from "@utils/types";
|
||||
import { Message } from "@vencord/discord-types";
|
||||
|
||||
function SealDarkFountainDecoration({
|
||||
message
|
||||
}: {
|
||||
message: Message;
|
||||
}) {
|
||||
if (/dark (fountain|world)/gi.test(message.content) && /(delta(rune|goon))|prophecy/gi.test(message.content) || /^(hop|get) on deltarune/i.test(message.content.toLowerCase())) {
|
||||
return (
|
||||
<div>
|
||||
<Button type="button" variant="link" onClick={a => open("steam://rungameid/1671210")}>
|
||||
Seal Fountain
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default definePlugin({
|
||||
name: "DeltaruneProphecy",
|
||||
description: "The Legend of Light and Dark. More Kromer!",
|
||||
authors: [{
|
||||
name: "ocbwoy3",
|
||||
id: 486147449703104523n
|
||||
}],
|
||||
patches: [
|
||||
{
|
||||
find: "#{intl::LOADING_DID_YOU_KNOW}",
|
||||
replacement: [
|
||||
{
|
||||
match: /"_loadingText".+?(?=(\i)\[.{0,10}\.random)/,
|
||||
replace: "$&$self.mutateQuotes($1),"
|
||||
},
|
||||
{
|
||||
match: /"_eventLoadingText".+?(?=(\i)\[.{0,10}\.random)/,
|
||||
replace: "$&$self.mutateQuotes($1),",
|
||||
predicate: () => true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
find: "data-testid\":\"app-spinner\"",
|
||||
replacement: {
|
||||
match: /children:\s*\w+/,
|
||||
replace: `
|
||||
children:[
|
||||
(0,r.jsx)("source",{alt:"",src:"https://files.catbox.moe/a5xk7y.webm"},"webm")
|
||||
]
|
||||
`
|
||||
}
|
||||
},
|
||||
{
|
||||
find: "let a=JSON.parse('{\"",
|
||||
replacement: [
|
||||
{
|
||||
match: /Find or start a conversation/gi,
|
||||
replace: "Find or open a Dark Fountain"
|
||||
},
|
||||
{
|
||||
match: /"Active Now"/gi,
|
||||
replace: "\"Sealing the Fountain right now...\""
|
||||
},
|
||||
{
|
||||
match: /Discord Orbs Terms/gi,
|
||||
replace: "Kromer Terms"
|
||||
},
|
||||
{
|
||||
match: /Discord Orbs/gi,
|
||||
replace: "Kromer"
|
||||
},
|
||||
{
|
||||
match: /Earn through Quests/gi,
|
||||
replace: "Earn by opening Dark Fountains"
|
||||
},
|
||||
{
|
||||
match: /Explore Orbs Exclusives/gi,
|
||||
replace: "Explore Dark World Exclusives"
|
||||
},
|
||||
{
|
||||
match: /Orbs/gi,
|
||||
replace: "Kromer"
|
||||
},
|
||||
{
|
||||
match: /Mutual Servers/gi,
|
||||
replace: "Mutual Dark Worlds"
|
||||
},
|
||||
{
|
||||
match: /\b(Member)(s)?\b/g,
|
||||
replace: "Darkner$2"
|
||||
},
|
||||
{
|
||||
match: /"Mutual Friends"/g,
|
||||
replace: "\"Mutual Darkners\""
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
|
||||
mutateQuotes(quotes: string[]) {
|
||||
try {
|
||||
quotes.length = 0;
|
||||
quotes.push("THE LEGEND OF THIS WORLD.\n< DELTARUNE. >");
|
||||
} catch (e) {
|
||||
new Logger("DeltaruneProphecy").error("Failed to mutate quotes", e);
|
||||
}
|
||||
},
|
||||
|
||||
start() {
|
||||
addMessageAccessory(
|
||||
"sealFountainButton",
|
||||
(props: Record<string, any>) => {
|
||||
return (
|
||||
<SealDarkFountainDecoration
|
||||
message={props.message as Message}
|
||||
/>
|
||||
);
|
||||
},
|
||||
4
|
||||
);
|
||||
},
|
||||
|
||||
stop() {
|
||||
removeMessageAccessory("sealFountainButton");
|
||||
}
|
||||
});
|
||||
41
nsfwGateBypass.ts
Normal file
41
nsfwGateBypass.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Vencord, a modification for Discord's desktop app
|
||||
* Copyright (c) 2025 Vendicated and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { Devs } from "@utils/constants";
|
||||
import definePlugin from "@utils/types";
|
||||
|
||||
export default definePlugin({
|
||||
name: "NSFWGateBypass",
|
||||
description: "Bypasses Age Verification",
|
||||
authors: [Devs.Commandtechno],
|
||||
patches: [
|
||||
{
|
||||
find: ".nsfwAllowed=null",
|
||||
replacement: [
|
||||
{
|
||||
match: /(?<=\.nsfwAllowed=)null!=.+?(?=[,;])/,
|
||||
replace: "true", // true
|
||||
},
|
||||
{
|
||||
match: /(?<=\.ageVerificationStatus=)null!=.+?(?=[,;])/,
|
||||
replace: "3", // 3=VERIFIED_ADULT
|
||||
}
|
||||
],
|
||||
}
|
||||
],
|
||||
});
|
||||
20
trustMeBro.ts
Normal file
20
trustMeBro.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Vencord, a Discord client mod
|
||||
* Copyright (c) 2025 Vendicated and contributors
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import definePlugin from "@utils/types";
|
||||
|
||||
export default definePlugin({
|
||||
name: "TrustMeBro",
|
||||
description: "Bypasses Discord’s age verification required under the UK Online Safety Act.",
|
||||
authors: [{ name: "Menhera.st Team", id: 1325012503419420734n }],
|
||||
|
||||
start() {
|
||||
const modules = Object.values((window as any).webpackChunkdiscord_app.push([[Symbol()], {}, (r: any) => r.c])) as any[];
|
||||
const userStore = modules.find((x: any) => x?.exports?.default?.getCurrentUser);
|
||||
const currentUser = userStore.exports.default.getCurrentUser();
|
||||
currentUser.ageVerificationStatus = 3;
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user