ReactionTracker/index.tsx
2024-08-08 14:44:13 -04:00

152 lines
5.4 KiB
TypeScript

import { DataStore } from "@api/index";
import { definePluginSettings } from "@api/Settings";
import { Devs } from "@utils/constants";
import definePlugin, { OptionType } from "@utils/types";
import { cache } from "@webpack";
import { Constants, Forms, MessageStore, Parser, RestAPI, useEffect, UserStore, useState } from "@webpack/common";
import { Message } from "discord-types/general";
const DATA_STORE_KEY = "huskchart";
type Husk = {
userId: string;
channelId: string;
messageId: string;
};
type SortedHusk = {
id: string;
count: number;
};
const messageCache = new Map<string, {
message?: Message;
fetched: boolean;
}>();
async function getMessage(channelId: string, messageId: string): Promise<Message | undefined> {
const cached = messageCache.get(messageId);
if (cached) return cached?.message;
const storeMessage = MessageStore.getMessage(channelId, messageId);
if (storeMessage) {
messageCache.set(storeMessage.id, {
message: storeMessage,
fetched: false
});
return storeMessage;
}
const apiMessage = await RestAPI.get({
url: Constants.Endpoints.MESSAGES(channelId),
query: {
limit: 1,
around: messageId
},
retries: 2
}).catch(() => null);
if (apiMessage) {
messageCache.set(apiMessage.body[0].id, {
message: apiMessage,
fetched: true
});
return apiMessage.body[0];
}
}
const UserData = () => {
const [data, setData] = useState([]);
const [collapsed, collapse] = useState(true);
useEffect(() => {
const fetchData = async () => {
const rawHusks: Husk[] = await DataStore.get(DATA_STORE_KEY) || [];
const unsortedHuskCountPerUser: SortedHusk[] = [];
for (const husk of rawHusks) {
let shouldAddInitialHusk = true;
for (const [i, hc] of unsortedHuskCountPerUser.entries()) {
const unsortedHusker: SortedHusk = hc;
if (unsortedHusker.id == husk.userId) {
unsortedHuskCountPerUser[i].count++;
shouldAddInitialHusk = false;
}
}
if (!shouldAddInitialHusk) continue;
unsortedHuskCountPerUser.push({ id: husk.userId, count: 1 });
}
const sortedHuskers = unsortedHuskCountPerUser.sort((a, b) => b.count - a.count);
// @ts-ignore EXPLODEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE
setData(sortedHuskers);
};
fetchData();
}, []);
return (
<>
<Forms.FormText style={{ fontSize: "1.07rem", fontWeight: "500" }}>User stats <a onClick={() => { collapsed ? collapse(false) : collapse(true); }}>[{collapsed ? "View all" : "Collapse"}]</a></Forms.FormText>
<div style={{ display: "grid", gridTemplateColumns: "auto auto" }}>
{
data && data.map(user => <>
{
collapsed && <>
{
data.indexOf(user) < 6 &&
<div style={{ marginTop: data.indexOf(user) < 2 ? "0" : "7px" }}>
{/* @ts-ignore */}
{Parser.parse(`<@${user.id}>`)} <Forms.FormText style={{ marginTop: "4px" }}>with {user.count} {user.count > 1 ? "husks" : "husk"}</Forms.FormText>
</div>
}
</>
}
{
!collapsed && <>
{
<div style={{ marginTop: data.indexOf(user) < 2 ? "0" : "7px" }}>
{/* @ts-ignore */}
{Parser.parse(`<@${user.id}>`)} <Forms.FormText style={{ marginTop: "4px" }}>with {user.count} {user.count > 1 ? "husks" : "husk"}</Forms.FormText>
</div>
}
</>
}
</>)
}
</div>
</>
);
};
export default definePlugin({
name: "HuskChart",
description: "See how much you've been husked, and by who",
authors: [Devs.nin0dev],
flux: {
async MESSAGE_REACTION_ADD(event) {
try {
if (event.userId === "428188716641812481") return;
const msg = await getMessage(event.channelId, event.messageId);
if (msg!.author.id !== UserStore.getCurrentUser().id) return;
if (!event.emoji.name.includes("husk")) return;
let husks: Husk[] = await DataStore.get(DATA_STORE_KEY) || [];
husks.push({
userId: event.userId,
channelId: event.channelId,
messageId: event.messageId
});
DataStore.set(DATA_STORE_KEY, husks);
}
catch {
// explode
}
}
},
settings: definePluginSettings({
buttons: {
type: OptionType.COMPONENT,
description: "User stats",
component: (aaa) => (
<>
<UserData />
</>
)
}
})
});