mirror of
https://github.com/Vendicated/Vencord.git
synced 2025-02-25 15:58:31 +00:00
Bulk fetch timezones to not spam the API
Although this doesn't currently work as CORS is fucking us over.
This commit is contained in:
parent
0d656f5e00
commit
ddd22b4029
2 changed files with 72 additions and 24 deletions
|
@ -19,6 +19,7 @@
|
||||||
const PreloadedUserSettings = findLazy(m => m.ProtoClass?.typeName === "discord_protos.discord_users.v1.PreloadedUserSettings");
|
const PreloadedUserSettings = findLazy(m => m.ProtoClass?.typeName === "discord_protos.discord_users.v1.PreloadedUserSettings");
|
||||||
|
|
||||||
import * as DataStore from "@api/DataStore";
|
import * as DataStore from "@api/DataStore";
|
||||||
|
import { debounce } from "@utils/debounce";
|
||||||
import { findLazy } from "@webpack";
|
import { findLazy } from "@webpack";
|
||||||
export const DATASTORE_KEY = "plugins.Timezones.savedTimezones";
|
export const DATASTORE_KEY = "plugins.Timezones.savedTimezones";
|
||||||
import type { timezones } from "./all_timezones";
|
import type { timezones } from "./all_timezones";
|
||||||
|
@ -28,31 +29,78 @@ export interface TimezoneDB {
|
||||||
[userId: string]: typeof timezones[number];
|
[userId: string]: typeof timezones[number];
|
||||||
}
|
}
|
||||||
|
|
||||||
const API_URL = "https://timezonedb.catvibers.me/";
|
const API_URL = "https://timezonedb.catvibers.me";
|
||||||
const Cache = new Map<string, string | null>();
|
const Cache: Record<string, typeof timezones[number]> = {};
|
||||||
|
|
||||||
export async function getUserTimezone(discordID: string): Promise<string | null> {
|
|
||||||
const timezone = (await DataStore.get(DATASTORE_KEY) as TimezoneDB | undefined)?.[discordID];
|
|
||||||
if (timezone) return timezone;
|
|
||||||
|
|
||||||
if (Cache.has(discordID)) {
|
|
||||||
return Cache.get(discordID) as string | null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const response = await fetch(API_URL + "api/user/" + discordID);
|
|
||||||
const timezone_res = await response.json();
|
|
||||||
|
|
||||||
if (response.status !== 200) {
|
|
||||||
Cache.set(discordID, null);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
Cache.set(discordID, timezone_res.timezoneId);
|
|
||||||
return timezone_res.timezoneId;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getTimeString(timezone: string, timestamp = new Date()): string {
|
export function getTimeString(timezone: string, timestamp = new Date()): string {
|
||||||
const locale = PreloadedUserSettings.getCurrentValue().localization.locale.value;
|
const locale = PreloadedUserSettings.getCurrentValue().localization.locale.value;
|
||||||
|
|
||||||
return new Intl.DateTimeFormat(locale, { hour: "numeric", minute: "numeric", timeZone: timezone }).format(timestamp); // we hate javascript
|
return new Intl.DateTimeFormat(locale, { hour: "numeric", minute: "numeric", timeZone: timezone }).format(timestamp); // we hate javascript
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// A map of ids and callbacks that should be triggered on fetch
|
||||||
|
const requestQueue: Record<string, ((timezone: typeof timezones[number]) => void)[]> = {};
|
||||||
|
|
||||||
|
|
||||||
|
async function bulkFetchTimezones(ids: string[]): Promise<TimezoneDB | undefined> {
|
||||||
|
try {
|
||||||
|
const req = await fetch(`${API_URL}/api/user/bulk`, {
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
"Accept": "application/json",
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
body: JSON.stringify(ids)
|
||||||
|
});
|
||||||
|
|
||||||
|
return await req.json()
|
||||||
|
.then((res: { [userId: string]: { timezoneId: string; } | null; }) => {
|
||||||
|
const tzs = (Object.keys(res).map(userId => {
|
||||||
|
return res[userId] && { [userId]: res[userId]!.timezoneId as typeof timezones[number] };
|
||||||
|
}).filter(Boolean) as TimezoneDB[]).reduce((acc, cur) => ({ ...acc, ...cur }), {});
|
||||||
|
|
||||||
|
Object.assign(Cache, tzs);
|
||||||
|
return tzs;
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
console.error("Timezone fetching failed: ", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Executes all queued requests and calls their callbacks
|
||||||
|
const bulkFetch = debounce(async () => {
|
||||||
|
const ids = Object.keys(requestQueue);
|
||||||
|
const timezones = await bulkFetchTimezones(ids);
|
||||||
|
if (!timezones) {
|
||||||
|
// retry after 15 seconds
|
||||||
|
setTimeout(bulkFetch, 15000);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const id of ids) {
|
||||||
|
// Call all callbacks for the id
|
||||||
|
requestQueue[id].forEach(c => c(timezones[id]));
|
||||||
|
delete requestQueue[id];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export function getUserTimezone(discordID: string): Promise<typeof timezones[number] | undefined> {
|
||||||
|
return new Promise(res => {
|
||||||
|
if (discordID in Cache) res(Cache[discordID]);
|
||||||
|
|
||||||
|
const timezone = (DataStore.get(DATASTORE_KEY) as Promise<TimezoneDB | undefined>).then(tzs => tzs?.[discordID]);
|
||||||
|
timezone.then(tz => {
|
||||||
|
if (tz) res(tz);
|
||||||
|
else {
|
||||||
|
if (discordID in requestQueue) requestQueue[discordID].push(res);
|
||||||
|
// If not already added, then add it and call the debounced function to make sure the request gets executed
|
||||||
|
else {
|
||||||
|
requestQueue[discordID] = [res];
|
||||||
|
bulkFetch();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
|
@ -183,7 +183,7 @@ export default definePlugin({
|
||||||
|
|
||||||
const user = e.user as User;
|
const user = e.user as User;
|
||||||
|
|
||||||
const [timezone, setTimezone] = React.useState<string | null>(null);
|
const [timezone, setTimezone] = React.useState<string | undefined>();
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
getUserTimezone(user.id).then(timezone => setTimezone(timezone));
|
getUserTimezone(user.id).then(timezone => setTimezone(timezone));
|
||||||
|
@ -219,7 +219,7 @@ export default definePlugin({
|
||||||
|
|
||||||
const message = e.message as Message;
|
const message = e.message as Message;
|
||||||
|
|
||||||
const [timezone, setTimezone] = React.useState<string | null>(null);
|
const [timezone, setTimezone] = React.useState<string | undefined>();
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
getUserTimezone(e.message.author.id).then(timezone => setTimezone(timezone));
|
getUserTimezone(e.message.author.id).then(timezone => setTimezone(timezone));
|
||||||
|
|
Loading…
Add table
Reference in a new issue