Plugin
GlobalBadges
Adds global badges from other client mods
1
/*2
* FiveCord — a Discord client mod3
* Copyright (c) 2025 FiveCord4
* SPDX-License-Identifier: GPL-3.0-or-later5
*/6
7
import { addBadge, BadgePosition, ProfileBadge, removeBadge } from "@api/Badges";8
import { Devs } from "@utils/constants";9
import definePlugin, { OptionType } from "@utils/types";10
import { React, Tooltip } from "@webpack/common";11
import { User } from "discord-types/general";12
13
type CustomBadge = string | {14
name: string;15
badge: string;16
custom?: boolean;17
};18
19
interface BadgeCache {20
badges: { [mod: string]: CustomBadge[]; };21
expires: number;22
}23
24
const API_URL = "https:class="ts-cmt">//clientmodbadges-api.herokuapp.com/";25
26
const cache = new Map<string, BadgeCache>();27
const EXPIRES = 1000 * 60 * 15;28
29
const fetchBadges = (id: string): BadgeCache["badges"] | undefined => {30
const cachedValue = cache.get(id);31
if (!cache.has(id) || (cachedValue && cachedValue.expires < Date.now())) {32
fetch(`${API_URL}users/${id}`)33
.then(res => res.json() as Promise<BadgeCache["badges"]>)34
.then(body => {35
cache.set(id, { badges: body, expires: Date.now() + EXPIRES });36
return body;37
});38
} else if (cachedValue) {39
return cachedValue.badges;40
}41
};42
43
const BadgeComponent = ({ name, img }: { name: string, img: string; }) => {44
return (45
<Tooltip text={name} >46
{(tooltipProps: any) => (47
<img48
{...tooltipProps}49
src={img}50
style={{ width: "22px", height: "22px", transform: name.includes("Replugged") ? "scale(0.9)" : null, margin: "0 2px" }}51
/>52
)}53
</Tooltip>54
);55
};56
57
const GlobalBadges = ({ user }: { user: User; }) => {58
const [badges, setBadges] = React.useState<BadgeCache["badges"]>({});59
React.useEffect(() => setBadges(fetchBadges(user.id) ?? {}), [user.id]);60
61
if (!badges) return null;62
const globalBadges: JSX.Element[] = [];63
64
Object.keys(badges).forEach(mod => {65
if (mod.toLowerCase() === "vencord") return;66
badges[mod].forEach(badge => {67
if (typeof badge === "string") {68
const fullNames = { "hunter": "Bug Hunter", "early": "Early User" };69
badge = {70
name: fullNames[badge as string] ? fullNames[badge as string] : badge,71
badge: `${API_URL}badges/${mod}/${(badge as string).replace(mod, "").trim().split(" ")[0]}`72
};73
} else if (typeof badge === "object") badge.custom = true;74
if (!showCustom() && badge.custom) return;75
const cleanName = badge.name.replace(mod, "").trim();76
const prefix = showPrefix() ? mod : "";77
if (!badge.custom) badge.name = `${prefix} ${cleanName.charAt(0).toUpperCase() + cleanName.slice(1)}`;78
globalBadges.push(<BadgeComponent name={badge.name} img={badge.badge} />);79
});80
});81
82
return (83
<div className="vc-global-badges" style={{ alignItems: "center", display: "flex" }}>84
{globalBadges}85
</div>86
);87
};88
89
const Badge: ProfileBadge = {90
component: b => <GlobalBadges {...b} />,91
position: BadgePosition.START,92
shouldShow: userInfo => !!Object.keys(fetchBadges(userInfo.user.id) ?? {}).length,93
key: "GlobalBadges"94
};95
96
const showPrefix = () => FiveCord.Settings.plugins.GlobalBadges.showPrefix;97
const showCustom = () => FiveCord.Settings.plugins.GlobalBadges.showCustom;98
99
export default definePlugin({100
name: "GlobalBadges",101
description: "Adds global badges from other client mods",102
authors: [Devs.FiveCord],103
104
start: () => addBadge(Badge),105
stop: () => removeBadge(Badge),106
107
options: {108
showPrefix: {109
type: OptionType.BOOLEAN,110
description: "Shows the Mod as Prefix",111
default: true,112
restartNeeded: false113
},114
showCustom: {115
type: OptionType.BOOLEAN,116
description: "Show Custom Badges",117
default: true,118
restartNeeded: false119
}120
}121
});122