mirror of
https://github.com/RobinRMC/VencordPlus.git
synced 2025-05-10 17:35:39 +02:00
153 lines
4 KiB
TypeScript
153 lines
4 KiB
TypeScript
/*
|
|
* Vencord, a Discord client mod
|
|
* Copyright (c) 2024 Vendicated and contributors
|
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
|
*/
|
|
|
|
import { Constants, FluxDispatcher, GuildStore, RestAPI, SnowflakeUtils, UserStore, UserUtils } from "@webpack/common";
|
|
import { waitForStore } from "webpack/common/internal";
|
|
|
|
import { refreshNotesData, refreshUsersCache } from "./components/NotesDataModal";
|
|
import * as t from "./types";
|
|
|
|
let NoteStore: t.NoteStore;
|
|
|
|
waitForStore("NoteStore", s => NoteStore = s);
|
|
|
|
export const getNotes = () => {
|
|
return NoteStore.getNotes();
|
|
};
|
|
|
|
export const onNoteUpdate = () => {
|
|
refreshNotesData();
|
|
};
|
|
|
|
export const updateNote = (userId: string, note: string | null) => {
|
|
RestAPI.put({
|
|
url: Constants.Endpoints.NOTE(userId),
|
|
body: { note: note },
|
|
oldFormErrors: true
|
|
});
|
|
};
|
|
|
|
export const usersCache: t.UsersCache = new Map();
|
|
|
|
export const onUserUpdate = ({ user }: { user: t.User; }) => {
|
|
if (!getNotes()[user.id]) return;
|
|
|
|
// doesn't have .getAvatarURL
|
|
const userFromStore = UserStore.getUser(user.id);
|
|
|
|
if (!userFromStore) return;
|
|
|
|
cacheUser(userFromStore);
|
|
};
|
|
|
|
const fetchUser = async (userId: string) => {
|
|
for (let _ = 0; _ < 5; _++) {
|
|
try {
|
|
return await UserUtils.getUser(userId);
|
|
} catch (error: any) {
|
|
const wait = error?.body?.retry_after;
|
|
|
|
if (!wait) return;
|
|
|
|
await new Promise(resolve => setTimeout(resolve, wait * 1000 + 100));
|
|
}
|
|
}
|
|
};
|
|
|
|
const cacheUser = (user: t.User) => {
|
|
usersCache.set(user.id, {
|
|
id: user.id,
|
|
globalName: user.globalName ?? user.username,
|
|
username: user.username,
|
|
avatar: user.getAvatarURL(void 0, void 0, false),
|
|
});
|
|
};
|
|
|
|
export const cacheUsers = async () => {
|
|
const toRequest: string[] = [];
|
|
|
|
for (const userId of Object.keys(getNotes())) {
|
|
const user = UserStore.getUser(userId);
|
|
|
|
if (user) {
|
|
cacheUser(user);
|
|
continue;
|
|
}
|
|
|
|
toRequest.push(userId);
|
|
}
|
|
|
|
if (usersCache.size >= Object.keys(getNotes()).length) {
|
|
return;
|
|
}
|
|
|
|
const sentNonce = SnowflakeUtils.fromTimestamp(Date.now());
|
|
|
|
const allGuildIds = Object.keys(GuildStore.getGuilds());
|
|
let count = allGuildIds.length * Math.ceil(toRequest.length / 100);
|
|
|
|
const processed = new Set<string>();
|
|
|
|
const callback = async ({ chunks }) => {
|
|
for (const chunk of chunks) {
|
|
const { nonce, members }: {
|
|
nonce: string;
|
|
members: {
|
|
user: t.User;
|
|
}[];
|
|
} = chunk;
|
|
|
|
if (nonce !== sentNonce) {
|
|
return;
|
|
}
|
|
|
|
members.forEach(({ user }) => {
|
|
if (processed.has(user.id)) return;
|
|
|
|
processed.add(user.id);
|
|
|
|
cacheUser(UserStore.getUser(user.id));
|
|
});
|
|
|
|
refreshUsersCache();
|
|
|
|
if (--count === 0) {
|
|
FluxDispatcher.unsubscribe("GUILD_MEMBERS_CHUNK_BATCH", callback);
|
|
|
|
const userIds = Object.keys(getNotes());
|
|
|
|
if (usersCache.size !== userIds.length) {
|
|
|
|
for (const userId of userIds) {
|
|
if (usersCache.has(userId)) continue;
|
|
|
|
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
|
|
const user = await fetchUser(userId);
|
|
|
|
if (user) {
|
|
cacheUser(user);
|
|
refreshUsersCache();
|
|
}
|
|
}
|
|
|
|
} else
|
|
refreshUsersCache();
|
|
}
|
|
}
|
|
};
|
|
|
|
FluxDispatcher.subscribe("GUILD_MEMBERS_CHUNK_BATCH", callback);
|
|
|
|
for (let i = 0; i < toRequest.length; i += 100) {
|
|
FluxDispatcher.dispatch({
|
|
type: "GUILD_MEMBERS_REQUEST",
|
|
guildIds: allGuildIds,
|
|
userIds: toRequest.slice(i, i + 100),
|
|
nonce: sentNonce,
|
|
});
|
|
}
|
|
};
|