Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
"flat-cache": "^6.1.1",
"mongoose": "^8.12.1",
"obscenity": "^0.4.5",
"ps-client": "^5.4.0",
"ps-client": "^6.0.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-json-tree": "^0.20.0",
Expand Down
33 changes: 23 additions & 10 deletions src/cache/showdown/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { FlatCache } from 'flat-cache';
import { fetch as fetchPSDatacenters } from 'ps-client/tools';

import { ShowdownDataKeys } from '@/cache/showdown/types';
import { applyPSDatacenters } from '@/ps/datacenters';
import { fsPath } from '@/utils/fsPath';

import type { ShowdownDataType } from '@/cache/showdown/types';
Expand All @@ -10,6 +12,7 @@ const RANDOMS_SETS_URL =

export const ShowdownData: ShowdownDataType = {
[ShowdownDataKeys.RandomSetsGen9]: {},
[ShowdownDataKeys.PSDatacenters]: {},
};

const ShowdownMetadata: {
Expand All @@ -28,25 +31,35 @@ const ShowdownMetadata: {
return (await res.json()) as ShowdownDataType[ShowdownDataKeys.RandomSetsGen9];
},
},
[ShowdownDataKeys.PSDatacenters]: {
key: ShowdownDataKeys.PSDatacenters,
cacheId: 'ps-datacenters.json',
update: () => fetchPSDatacenters(),
},
};

const ShowdownFlatCaches = Object.fromEntries(
Object.values(ShowdownMetadata).map(({ key, cacheId }) => {
const flatCache = new FlatCache({ cacheId, cacheDir: fsPath('cache', 'flat-cache') });
flatCache.load(cacheId);
function hydrateShowdownData<Key extends ShowdownDataKeys>(key: Key, data: ShowdownDataType[Key]) {
ShowdownData[key] = data;
if (key === ShowdownDataKeys.PSDatacenters) applyPSDatacenters(data as ShowdownDataType[ShowdownDataKeys.PSDatacenters]);
}

const ShowdownFlatCaches = {} as Record<ShowdownDataKeys, FlatCache>;
for (const key of Object.keys(ShowdownMetadata) as ShowdownDataKeys[]) {
const { cacheId } = ShowdownMetadata[key];
const flatCache = new FlatCache({ cacheId, cacheDir: fsPath('cache', 'flat-cache') });
flatCache.load(cacheId);

const existing = flatCache.get<ShowdownDataType[typeof key]>('value');
if (existing) ShowdownData[key] = existing;
return [key, flatCache];
})
) as Record<ShowdownDataKeys, FlatCache>;
const existing = flatCache.get<ShowdownDataType[typeof key]>('value');
if (existing) hydrateShowdownData(key, existing);
ShowdownFlatCaches[key] = flatCache;
}

export async function updateShowdownData(keys?: ShowdownDataKeys[]): Promise<void> {
const toUpdate = keys ?? (Object.keys(ShowdownMetadata) as ShowdownDataKeys[]);
await Promise.all(
toUpdate.map(async key => {
const data = await ShowdownMetadata[key].update();
ShowdownData[key] = data;
hydrateShowdownData(key, data);
ShowdownFlatCaches[key].set('value', data);
ShowdownFlatCaches[key].save();
})
Expand Down
8 changes: 6 additions & 2 deletions src/cache/showdown/types.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import type { Datacenters } from 'ps-client/data';

export enum ShowdownDataKeys {
RandomSetsGen9 = 'random-sets-gen-9',
PSDatacenters = 'ps-datacenters',
}

export type Gen9ShowdownSet = {
Expand All @@ -9,6 +12,7 @@ export type Gen9ShowdownSet = {
teraTypes: string[];
};

export interface ShowdownDataType extends Record<ShowdownDataKeys, unknown> {
export type ShowdownDataType = {
[ShowdownDataKeys.RandomSetsGen9]: Record<string, { level: number; sets: Gen9ShowdownSet[] }>;
}
[ShowdownDataKeys.PSDatacenters]: Partial<Datacenters>;
};
2 changes: 1 addition & 1 deletion src/database/games.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { Temporal } from '@js-temporal/polyfill';
import mongoose, { type HydratedDocument } from 'mongoose';
import { pokedex } from 'ps-client/data';

import { IS_ENABLED } from '@/enabled';
import { pokedex } from '@/ps/datacenters';
import { ScrabbleMods } from '@/ps/games/scrabble/constants';
import { GamesList } from '@/ps/games/types';
import { TimeZone } from '@/ps/handlers/cron/constants';
Expand Down
2 changes: 1 addition & 1 deletion src/eval.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@

import _fsSync, { promises as _fs } from 'fs';
import _path from 'path';
import { pokedex } from 'ps-client/data';
import { inspect } from 'util';

import * as _cache from '@/cache';
import { pokedex } from '@/ps/datacenters';
import _Sentinel from '@/sentinel';
import { ansiToHtml } from '@/utils/ansiToHtml';
import { cachebust as _cachebust } from '@/utils/cachebust';
Expand Down
20 changes: 13 additions & 7 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
import 'dotenv/config';
import '@/globals';
import { Logger } from '@/utils/logger';

Logger.log('PartBot is starting up...');
(async () => {
await import('@/cache/showdown');
const { ensurePSDatacenters } = await import('@/ps/datacenters');
await ensurePSDatacenters();

import '@/discord';
import '@/ps';
import '@/web';
await import('@/globals');
const { Logger } = await import('@/utils/logger');

import '@/sentinel';
Logger.log('PartBot is starting up...');

await import('@/discord');
await import('@/ps');
await import('@/web');
await import('@/sentinel');
})();
3 changes: 1 addition & 2 deletions src/ps/commands/filter.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { abilities, items, moves, pokedex } from 'ps-client/data';

import { abilities, items, moves, pokedex } from '@/ps/datacenters';
import { ChatError } from '@/utils/chatError';
import { toId } from '@/utils/toId';

Expand Down
7 changes: 2 additions & 5 deletions src/ps/commands/kunc.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import { pokedex } from 'ps-client/data';

import { PSKuncInProgress } from '@/cache';
import { ShowdownData } from '@/cache/showdown';
import { ShowdownDataKeys } from '@/cache/showdown/types';
import { prefix } from '@/config/ps';
import { pokedex } from '@/ps/datacenters';
import { ChatError } from '@/utils/chatError';
import { debounce } from '@/utils/debounce';
import { DeferredPromise } from '@/utils/deferredPromise';
Expand Down Expand Up @@ -73,9 +72,7 @@ export const command: PSCommand = {

if (solved.length > 0) {
const guessers = solved.map(user => user.name).list($T);
message.reply(
$T('COMMANDS.KUNC.CORRECT_GUESSERS', { guessers, solution: matchingNames.list($T('GRAMMAR.OR')) })
);
message.reply($T('COMMANDS.KUNC.CORRECT_GUESSERS', { guessers, solution: matchingNames.list($T('GRAMMAR.OR')) }));
return solved;
} else {
message.reply($T('COMMANDS.KUNC.NO_GUESSERS', { solution: matchingNames.list($T('GRAMMAR.OR')) }));
Expand Down
5 changes: 3 additions & 2 deletions src/ps/commands/modnote.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { HSL, formatText } from 'ps-client/tools';
import { formatText } from 'ps-client/tools';

import { isGlobalBot, prefix } from '@/config/ps';
import { psHSL } from '@/ps/datacenters';
import { ChatError } from '@/utils/chatError';
import { Button, Form } from '@/utils/components/ps';
import { toId } from '@/utils/toId';
Expand Down Expand Up @@ -55,7 +56,7 @@ export const command: PSCommand = {
if (!isStaff(userInRoom)) throw new ChatError($T('ACCESS_DENIED'));

const nonGlobalPrefix = !isGlobalBot ? `/msgroom ${targetRoom.id},` : '';
const [h, s, l] = HSL(message.author.id).hsl;
const [h, s, l] = psHSL(message.author.id).hsl;
targetRoom.sendHTML(
<div className="infobox">
<div className="chat chatmessage-partbot" style={{ display: 'inline-block' }}>
Expand Down
5 changes: 2 additions & 3 deletions src/ps/commands/namecolour.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { Tools as ClientTools } from 'ps-client';

import { psHSL } from '@/ps/datacenters';
import { HslToRgb, HslToString, RgbToHex, RgbToString } from '@/utils/color';

import type { PSCommand } from '@/types/chat';
Expand All @@ -21,7 +20,7 @@ export const command: PSCommand = {
categories: ['utility'],
async run({ message, arg, broadcastHTML }) {
const target = arg || message.author.name;
const data = ClientTools.HSL(target);
const data = psHSL(target);
const current = convertedColors(data.hsl);
const original = data.base ? convertedColors(data.base.hsl) : null;

Expand Down
60 changes: 60 additions & 0 deletions src/ps/datacenters.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { HSL as hslFromTools } from 'ps-client/tools';

import type { Datacenters } from 'ps-client/data';

export type { Ability, Item, Move, Species } from 'ps-client/data';

export const abilities: Datacenters['abilities'] = {};
export const aliases: Datacenters['aliases'] = {};
export const formatsData: Datacenters['formatsData'] = {};
export const formats: Datacenters['formats'] = [];
export const items: Datacenters['items'] = {};
export const learnsets: Datacenters['learnsets'] = {};
export const moves: Datacenters['moves'] = {};
export const pokedex: Datacenters['pokedex'] = {};
export const typechart: Datacenters['typechart'] = {} as Datacenters['typechart'];
export const colors: Datacenters['colors'] = {};

const tables: Record<keyof Omit<Datacenters, 'formats' | 'colors'>, Record<string, unknown>> = {
abilities,
aliases,
formatsData,
items,
learnsets,
moves,
pokedex,
typechart,
};

function inplaceReplace(target: Record<string, unknown>, source: Record<string, unknown>) {
for (const key of Object.keys(target)) delete target[key];
Object.assign(target, source);
}

export function applyPSDatacenters(data: Partial<Datacenters>) {
for (const [key, value] of Object.entries(data) as [keyof Datacenters, Datacenters[keyof Datacenters]][]) {
if (key === 'formats') {
formats.length = 0;
formats.push(...(value as Datacenters['formats']));
} else if (key === 'colors') {
inplaceReplace(colors, value as Record<string, unknown>);
} else {
inplaceReplace(tables[key as keyof typeof tables], value as Record<string, unknown>);
}
}
}

export function datacentersLoaded() {
return Object.keys(pokedex).length > 0;
}

export async function ensurePSDatacenters() {
if (datacentersLoaded()) return;
const { updateShowdownData } = await import('@/cache/showdown');
const { ShowdownDataKeys } = await import('@/cache/showdown/types');
await updateShowdownData([ShowdownDataKeys.PSDatacenters]);
}

export function psHSL(name: string, opts?: { original?: boolean }) {
return hslFromTools(name, { ...opts, customColors: colors });
}
3 changes: 1 addition & 2 deletions src/ps/games/scrabble/checker.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { abilities, items, moves, pokedex } from 'ps-client/data';

import { abilities, items, moves, pokedex } from '@/ps/datacenters';
import { Dictionaries, ScrabbleMods } from '@/ps/games/scrabble/constants';
import { CRAZYMONS_SCORING, POKEMON_SCORING, ScrabbleModData } from '@/ps/games/scrabble/mods';

Expand Down
5 changes: 2 additions & 3 deletions src/ps/games/snakesladders/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { HSL } from 'ps-client/tools';

import { psHSL } from '@/ps/datacenters';
import { BaseGame } from '@/ps/games/game';
import { TOKEN_COLORS } from '@/ps/games/snakesladders/constants';
import { render } from '@/ps/games/snakesladders/render';
Expand Down Expand Up @@ -53,7 +52,7 @@ export class SnakesLadders extends BaseGame<State, RenderCtx> {

onStart(): ActionResponse {
const playerColors = Object.values(this.players).map<{ id: string; color: Hex }>(player => {
const [H, S, L] = HSL(player.id).hsl;
const [H, S, L] = psHSL(player.id).hsl;
return { id: player.turn, color: HslToHex({ H, S, L, colorspace: 'hsla' }) };
});

Expand Down
2 changes: 1 addition & 1 deletion src/ps/handlers/cron/hindi.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { pokedex } from 'ps-client/data';
import { uploadToPastie } from 'ps-client/tools';

import { PSCommands, PSRoomConfigs } from '@/cache';
import { queryPoints, resetPoints } from '@/database/points';
import { HINDI_LOGS } from '@/discord/constants/servers/hindi';
import { getChannel } from '@/discord/loaders/channels';
import { i18n } from '@/i18n';
import { pokedex } from '@/ps/datacenters';
import { TimeZone } from '@/ps/handlers/cron/constants';
import { hasPoints } from '@/ps/handlers/cron/utils';
import { Logger } from '@/utils/logger';
Expand Down
5 changes: 2 additions & 3 deletions src/sentinel/hotpatch.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { promises as fs } from 'fs';
import path from 'path';
import { update as updatePSData } from 'ps-client/tools';

import { PSRoomConfigs } from '@/cache';
import { updateShowdownData } from '@/cache/showdown';
import { ShowdownDataKeys } from '@/cache/showdown/types';
import { fetchRoomConfigs } from '@/database/psrooms';
import PS from '@/ps';
import { registers } from '@/sentinel/registers';
Expand Down Expand Up @@ -71,8 +71,7 @@ export async function hotpatch(this: Sentinel, hotpatchType: HotpatchType, by: s
}

case 'data': {
await updatePSData();
// TODO: cachebust
await updateShowdownData([ShowdownDataKeys.PSDatacenters]);
break;
}

Expand Down
4 changes: 2 additions & 2 deletions src/utils/components/username.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Tools as ClientTools } from 'ps-client';
import { psHSL } from '@/ps/datacenters';

import type { ReactElement } from 'react';

Expand All @@ -13,7 +13,7 @@ export function Username({
clickable?: boolean;
children?: string;
}): ReactElement {
const namecolour = ClientTools.HSL(name);
const namecolour = psHSL(name);
const [h, s, l] = useOriginalColor ? (namecolour.base?.hsl ?? namecolour.hsl) : namecolour.hsl;
const nameEl = <strong style={{ color: `hsl(${h},${s}%,${l}%)` }}>{children ?? name}</strong>;
if (clickable) return <span className="username">{nameEl}</span>;
Expand Down
4 changes: 1 addition & 3 deletions src/utils/queryMon.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
import { type Species, pokedex } from 'ps-client/data';


import { type Species, pokedex } from '@/ps/datacenters';
import { toId } from '@/utils/toId';

export function queryMon(input: string): Species | null {
Expand Down
Loading