Plugin

IrcColors

Makes username colors in chat unique, like in IRC clients

Appearance Customisation
index.ts
Download

Source

src/plugins/ircColors/index.ts
1import { definePluginSettings } from "@api/Settings";
2import { hash as h64 } from "@intrnl/xxhash64";
3import { Devs } from "@utils/constants";
4import definePlugin, { OptionType } from "@utils/types";
5import { useMemo } from "@webpack/common";
6
7// Calculate a CSS color string based on the user ID
8function calculateNameColorForUser(id?: string) {
9 const { lightness } = settings.use(["lightness"]);
10 const idHash = useMemo(() => id ? h64(id) : null, [id]);
11
12 return idHash && `hsl(${idHash % 360n}, 100%, ${lightness}%)`;
13}
14
15const settings = definePluginSettings({
16 lightness: {
17 description: "Lightness, in %. Change if the colors are too light or too dark",
18 type: OptionType.NUMBER,
19 default: 70,
20 },
21 memberListColors: {
22 description: "Replace role colors in the member list",
23 restartNeeded: true,
24 type: OptionType.BOOLEAN,
25 default: true
26 },
27 applyColorOnlyToUsersWithoutColor: {
28 description: "Apply colors only to users who don't have a predefined color",
29 restartNeeded: false,
30 type: OptionType.BOOLEAN,
31 default: false
32 },
33 applyColorOnlyInDms: {
34 displayName: "Apply Color Only In DMs",
35 description: "Apply colors only in direct messages; do not apply colors in servers.",
36 restartNeeded: false,
37 type: OptionType.BOOLEAN,
38 default: false
39 }
40});
41
42export default definePlugin({
43 name: "IrcColors",
44 description: "Makes username colors in chat unique, like in IRC clients",
45 tags: ["Appearance", "Customisation"],
46 authors: [Devs.Grzesiek11, Devs.jamesbt365],
47 settings,
48
49 patches: [
50 {
51 find: '="SYSTEM_TAG"',
52 replacement: {
53 // Override colorString with our custom color and disable gradients if applying the custom color.
54 match: /(?<=colorString:\i,colorStrings:\i,colorRoleName:\i.*?}=)(\i),/,
55 replace: "$self.wrapMessageColorProps($1, arguments[0]),"
56 }
57 },
58 {
59 find: "#{intl::GUILD_OWNER}),children:",
60 replacement: {
61 match: /(?<=roleName:\i,)colorString:/,
62 replace: "colorString:$self.calculateNameColorForListContext(arguments[0]),originalColor:"
63 },
64 predicate: () => settings.store.memberListColors
65 }
66 ],
67
68 wrapMessageColorProps(colorProps: { colorString: string, colorStrings?: Record<"primaryColor" | "secondaryColor" | "tertiaryColor", string>; }, context: any) {
69 try {
70 const colorString = this.calculateNameColorForMessageContext(context);
71 if (colorString === colorProps.colorString) {
72 return colorProps;
73 }
74
75 return {
76 ...colorProps,
77 colorString,
78 colorStrings: colorProps.colorStrings && {
79 primaryColor: colorString,
80 secondaryColor: undefined,
81 tertiaryColor: undefined
82 }
83 };
84 } catch (e) {
85 console.error("Failed to calculate message color strings:", e);
86 return colorProps;
87 }
88 },
89
90 calculateNameColorForMessageContext(context: any) {
91 const userId: string | undefined = context?.message?.author?.id;
92 const colorString = context?.author?.colorString;
93 const color = calculateNameColorForUser(userId);
94
95 // Color preview in role settings
96 if (context?.message?.channel_id === "1337" && userId === "313337")
97 return colorString;
98
99 if (settings.store.applyColorOnlyInDms && !context?.channel?.isPrivate()) {
100 return colorString;
101 }
102
103 return (!settings.store.applyColorOnlyToUsersWithoutColor || !colorString)
104 ? color
105 : colorString;
106 },
107
108 calculateNameColorForListContext(context: any) {
109 try {
110 const id = context?.user?.id;
111 const colorString = context?.colorString;
112 const color = calculateNameColorForUser(id);
113
114 if (settings.store.applyColorOnlyInDms && context?.guildId !== undefined) {
115 return colorString;
116 }
117
118 return (!settings.store.applyColorOnlyToUsersWithoutColor || !colorString)
119 ? color
120 : colorString;
121 } catch (e) {
122 console.error("Failed to calculate name color for list context:", e);
123 }
124 }
125});
126