diff --git a/src/plugins/showBadgesInChat/README.md b/src/plugins/showBadgesInChat/README.md
new file mode 100644
index 0000000000..86daa1e2e3
--- /dev/null
+++ b/src/plugins/showBadgesInChat/README.md
@@ -0,0 +1,24 @@
+# ShowBadgesInChat
+
+Shows profile badges in chat. The badges include all built-in Discord badges. It also proudly displays your Vencord donor/contributor badges.
+
+---
+
+The settings editor lets you:
+
+- Drag to reorder
+- Click to enable/disable a specific badge type
+- Hover over a badge for the tool-tip about what badges it represents
+
+https://github.com/Vendicated/Vencord/assets/119569726/c7543516-f691-42c5-baa2-68dbda96d46a
+
+![](https://github.com/Vendicated/Vencord/assets/119569726/ca736d0d-c09a-4737-9cfa-4fc88cfc91ae)
+
+---
+
+All badges can fit easily, for example here's Vencord's creator: Vee (vending.machine):
+![](https://github.com/Vendicated/Vencord/assets/119569726/fc768079-5027-482b-ac52-a652812d482d)
+
+---
+
+_Discord currently has a small bug where an author who isn't the current user will return their premiumType as undefined. There is nothing we can do about this until Discord fixes this bug_
diff --git a/src/plugins/showBadgesInChat/index.tsx b/src/plugins/showBadgesInChat/index.tsx
new file mode 100644
index 0000000000..1a708637cf
--- /dev/null
+++ b/src/plugins/showBadgesInChat/index.tsx
@@ -0,0 +1,129 @@
+/*
+ * Vencord, a Discord client mod
+ * Copyright (c) 2024 Vendicated and contributors
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+import { addDecoration, removeDecoration } from "@api/MessageDecorations";
+import { Devs } from "@utils/constants";
+import { isPluginDev } from "@utils/misc";
+import definePlugin from "@utils/types";
+import { findByPropsLazy, findComponentByCodeLazy } from "@webpack";
+import badges from "plugins/_api/badges";
+const roleIconClassName = findByPropsLazy("roleIcon", "separator").roleIcon;
+const RoleIconComponent = findComponentByCodeLazy("#{intl::ROLE_ICON_ALT_TEXT}");
+import "./styles.css";
+
+import { User } from "discord-types/general";
+import { JSX } from "react";
+
+import settings from "./settings";
+
+const discordBadges: readonly [number, string, string][] = Object.freeze([
+ [0, "Discord Staff", "5e74e9b61934fc1f67c65515d1f7e60d"],
+ [1, "Partnered Server Owner", "3f9748e53446a137a052f3454e2de41e"],
+ [2, "HypeSquad Events", "bf01d1073931f921909045f3a39fd264"],
+ [6, "HypeSquad Bravery", "8a88d63823d8a71cd5e390baa45efa02"],
+ [7, "HypeSquad Brilliance", "011940fd013da3f7fb926e4a1cd2e618"],
+ [8, "HypeSquad Balance", "3aa41de486fa12454c3761e8e223442e"],
+ [3, "Discord Bug Hunter", "2717692c7dca7289b35297368a940dd0"],
+ [14, "Discord Bug Hunter", "848f79194d4be5ff5f81505cbd0ce1e6"],
+ [22, "Active Developer", "6bdc42827a38498929a4920da12695d9"],
+ [17, "Early Verified Bot Developer", "6df5892e0f35b051f8b61eace34f4967"],
+ [9, "Early Supporter", "7060786766c9c840eb3019e725d2b358"],
+ [18, "Moderator Programs Alumni", "fee1624003e2fee35cb398e125dc479b"]
+]);
+
+function CheckBadge({ badge, author }: { badge: string; author: User; }): JSX.Element | null {
+
+ switch (badge) {
+ case "VencordDonor":
+ return (
+
+ {badges.getDonorBadges(author.id)?.map(badge => (
+
+
+ ))}
+
+ );
+ case "VencordContributer":
+ return isPluginDev(author.id) ? (
+
+
+
+ ) : null;
+ case "DiscordProfile":
+ const chatBadges = discordBadges
+ .filter(badge => (author.flags || author.publicFlags) & (1 << badge[0]))
+
+ .map(badge => (
+
+
+ ));
+ return chatBadges.length > 0 ? (
+
+ {chatBadges}
+
+ ) : null;
+ case "DiscordNitro":
+ return (author?.premiumType ?? 0) > 0 ? (
+
+
+
+ ) : null;
+ default:
+ return null;
+ }
+}
+
+function ChatBadges({ author }: { author: User; }) {
+
+ return (
+
+ {settings.store.showVencordDonor && }
+ {settings.store.showVencordContributor && }
+ {settings.store.showDiscordProfile && }
+ {settings.store.showDiscordNitro && }
+
+ );
+}
+
+export default definePlugin({
+ name: "ShowBadgesInChat",
+ authors: [Devs.Inbestigator, Devs.KrystalSkull],
+ description: "Shows the message author's badges beside their name in chat.",
+ dependencies: ["MessageDecorationsAPI"],
+ settings,
+ start: () => {
+ addDecoration("vc-show-badges-in-chat", props => props.message?.author ? : null);
+
+ },
+ stop: () => {
+ removeDecoration("vc-show-badges-in-chat");
+ }
+});
diff --git a/src/plugins/showBadgesInChat/settings.tsx b/src/plugins/showBadgesInChat/settings.tsx
new file mode 100644
index 0000000000..a1446b6c5f
--- /dev/null
+++ b/src/plugins/showBadgesInChat/settings.tsx
@@ -0,0 +1,163 @@
+/*
+ * Vencord, a Discord client mod
+ * Copyright (c) 2024 Vendicated and contributors
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+import { definePluginSettings } from "@api/Settings";
+import { OptionType } from "@utils/types";
+import { Text, useEffect, UserStore, useState } from "@webpack/common";
+
+const settings = definePluginSettings({
+ showVencordDonor: {
+ type: OptionType.BOOLEAN,
+ description: "Enable to show Vencord donor badges in chat.",
+ hidden: true,
+ default: true
+ },
+ VencordDonorPosition: {
+ type: OptionType.NUMBER,
+ description: "The position of the Vencord Donor badges.",
+ hidden: true,
+ default: 0
+ },
+ showVencordContributor: {
+ type: OptionType.BOOLEAN,
+ description: "Enable to show Vencord contributor badges in chat.",
+ hidden: true,
+ default: true
+ },
+ VencordContributorPosition: {
+ type: OptionType.NUMBER,
+ description: "The position of the Vencord Contributor badge.",
+ hidden: true,
+ default: 1
+ },
+ showDiscordProfile: {
+ type: OptionType.BOOLEAN,
+ description: "Enable to show Discord profile badges in chat.",
+ hidden: true,
+ default: true
+ },
+ DiscordProfilePosition: {
+ type: OptionType.NUMBER,
+ description: "The position of the Discord profile badges.",
+ hidden: true,
+ default: 2
+ },
+ showDiscordNitro: {
+ type: OptionType.BOOLEAN,
+ description: "Enable to show Discord Nitro badges in chat.",
+ hidden: true,
+ default: true
+ },
+ DiscordNitroPosition: {
+ type: OptionType.NUMBER,
+ description: "The position of the Discord Nitro badge.",
+ hidden: true,
+ default: 3
+ },
+ badgeSettings: {
+ type: OptionType.COMPONENT,
+ description: "Setup badge layout and visibility",
+ component: () =>
+ }
+});
+
+export default settings;
+
+const BadgeSettings = () => {
+ const [images, setImages] = useState([
+ { src: "https://cdn.discordapp.com/emojis/1026533070955872337.png", shown: settings.store.showVencordDonor, title: "Vencord donor badges", key: "VencordDonor", position: settings.store.VencordDonorPosition },
+ { src: "https://vencord.dev/assets/favicon.png", shown: settings.store.showVencordContributor, title: "Vencord contributor badge", key: "VencordContributer", position: settings.store.VencordContributorPosition },
+ { src: "https://cdn.discordapp.com/badge-icons/bf01d1073931f921909045f3a39fd264.png", shown: settings.store.showDiscordProfile, title: "Discord profile badges (HypeSquad, Discord Staff, Active Developer, etc.)", key: "DiscordProfile", position: settings.store.DiscordProfilePosition },
+ { src: "https://cdn.discordapp.com/badge-icons/2ba85e8026a8614b640c2837bcdfe21b.png", shown: settings.store.showDiscordNitro, title: "Nitro badge", key: "DiscordNitro", position: settings.store.DiscordNitroPosition }
+ ]);
+
+ useEffect(() => {
+ images.forEach(image => {
+ switch (image.key) {
+ case "VencordDonor":
+ settings.store.VencordDonorPosition = image.position;
+ settings.store.showVencordDonor = image.shown;
+ break;
+ case "VencordContributer":
+ settings.store.VencordContributorPosition = image.position;
+ settings.store.showVencordContributor = image.shown;
+ break;
+ case "DiscordProfile":
+ settings.store.DiscordProfilePosition = image.position;
+ settings.store.showDiscordProfile = image.shown;
+ break;
+ case "DiscordNitro":
+ settings.store.DiscordNitroPosition = image.position;
+ settings.store.showDiscordNitro = image.shown;
+ break;
+ default:
+ break;
+ }
+ });
+ }, [images]);
+
+ const handleDragStart = (e: any, index: number) => {
+ if (!images[index].shown) {
+ e.preventDefault();
+ } else {
+ e.dataTransfer.setData("index", index);
+ }
+ };
+
+ const handleDragOver = e => {
+ e.preventDefault();
+ };
+
+ const handleDrop = (e: any, dropIndex: number) => {
+ const dragIndex = e.dataTransfer.getData("index");
+ const newImages = [...images];
+ const draggedImage = newImages[dragIndex];
+
+ newImages.splice(dragIndex, 1);
+ newImages.splice(dropIndex, 0, draggedImage);
+
+ newImages.forEach((image, index) => {
+ image.position = index;
+ });
+
+ setImages(newImages);
+ };
+
+ const toggleDisable = (index: number) => {
+ const newImages = [...images];
+ newImages[index].shown = !newImages[index].shown;
+ setImages(newImages);
+ };
+
+ return (
+ <>
+ Drag the badges to reorder them, you can click to enable/disable a specific badge type.
+
+
+
{(UserStore.getCurrentUser() as any).globalName}
+ {images
+ .sort((a, b) => a.position - b.position)
+ .map((image, index) => (
+
handleDragOver(e)}
+ onDrop={e => handleDrop(e, index)}
+ onClick={() => toggleDisable(index)}
+ >
+
handleDragStart(e, index)}
+ title={image.title}
+ />
+
+ ))
+ }
+
+ >
+ );
+};
diff --git a/src/plugins/showBadgesInChat/styles.css b/src/plugins/showBadgesInChat/styles.css
new file mode 100644
index 0000000000..6507e9c5a1
--- /dev/null
+++ b/src/plugins/showBadgesInChat/styles.css
@@ -0,0 +1,41 @@
+.vc-sbic-badge-settings {
+ display: flex;
+ gap: 5px;
+ flex-direction: row;
+}
+
+.vc-sbic-image-container {
+ position: relative;
+ transition: 0.15s;
+}
+
+.vc-sbic-image-container img {
+ width: 25px;
+ height: 25px;
+ cursor: pointer;
+}
+
+.vc-sbic-disabled {
+ opacity: 0.5;
+ scale: 0.95;
+}
+
+.vc-sbic-settings-avatar {
+ width: 50px;
+ height: 50px;
+ border-radius: 50%;
+ margin-right: 12px;
+}
+
+.vc-sbic-settings-username {
+ font-size: 22px;
+ color: white;
+ margin-right: 5px;
+}
+
+.vc-sbic-badge-row {
+ display: inline-flex;
+ margin-left: 2;
+ vertical-align: top;
+ height: 1rem;
+}
diff --git a/src/utils/constants.ts b/src/utils/constants.ts
index e758259125..3fa187e46d 100644
--- a/src/utils/constants.ts
+++ b/src/utils/constants.ts
@@ -579,6 +579,10 @@ export const Devs = /* #__PURE__*/ Object.freeze({
name: "jamesbt365",
id: 158567567487795200n,
},
+ KrystalSkull: {
+ name: "KrystalSkullOfficial",
+ id: 929208515883569182n
+ },
} satisfies Record);
// iife so #__PURE__ works correctly