feat: check for locales

This commit is contained in:
MARCROCK22 2024-06-28 05:58:30 +00:00
parent f05ba46b3a
commit 0be7c73d4a
2 changed files with 82 additions and 33 deletions

View File

@ -284,13 +284,29 @@ export class BaseClient {
throw new Error('Function not implemented'); throw new Error('Function not implemented');
} }
private shouldUploadCommands(cachePath: string) { private shouldUploadCommands(cachePath: string, guildId?: string) {
return this.commands!.shouldUpload(cachePath).then(async should => { return this.commands!.shouldUpload(cachePath, guildId).then(should => {
if (should) await promises.writeFile(cachePath, JSON.stringify(this.commands!.values.map(x => x.toJSON()))); this.logger.debug(
should
? `[${guildId ?? 'global'}] Change(s) detected, uploading commands`
: `[${guildId ?? 'global'}] commands seems to be up to date`,
);
return should; return should;
}); });
} }
private syncCachePath(cachePath: string) {
this.logger.debug('Syncing commands cache');
return promises.writeFile(
cachePath,
JSON.stringify(
this.commands!.values.filter(cmd => !('ignore' in cmd) || cmd.ignore !== IgnoreCommand.Slash).map(x =>
x.toJSON(),
),
),
);
}
async uploadCommands({ applicationId, cachePath }: { applicationId?: string; cachePath?: string } = {}) { async uploadCommands({ applicationId, cachePath }: { applicationId?: string; cachePath?: string } = {}) {
applicationId ??= await this.getRC().then(x => x.applicationId ?? this.applicationId); applicationId ??= await this.getRC().then(x => x.applicationId ?? this.applicationId);
BaseClient.assertString(applicationId, 'applicationId is not a string'); BaseClient.assertString(applicationId, 'applicationId is not a string');
@ -298,17 +314,11 @@ export class BaseClient {
const commands = this.commands!.values; const commands = this.commands!.values;
const filter = filterSplit(commands, command => !command.guildId); const filter = filterSplit(commands, command => !command.guildId);
if (!cachePath || (cachePath && (await this.shouldUploadCommands(cachePath)))) if (!cachePath || (await this.shouldUploadCommands(cachePath)))
await this.proxy await this.proxy.applications(applicationId).commands.put({
.applications(applicationId)
.commands.put({
body: filter.expect body: filter.expect
.filter(cmd => !('ignore' in cmd) || cmd.ignore !== IgnoreCommand.Slash) .filter(cmd => !('ignore' in cmd) || cmd.ignore !== IgnoreCommand.Slash)
.map(x => x.toJSON()), .map(x => x.toJSON()),
})
.catch(async e => {
if (cachePath) await promises.unlink(cachePath);
throw e;
}); });
const guilds = new Set<string>(); const guilds = new Set<string>();
@ -319,18 +329,24 @@ export class BaseClient {
} }
} }
for (const guild of guilds) { for (const guildId of guilds) {
if (!cachePath || (await this.shouldUploadCommands(cachePath, guildId))) {
await this.proxy await this.proxy
.applications(applicationId) .applications(applicationId)
.guilds(guild) .guilds(guildId)
.commands.put({ .commands.put({
body: filter.never body: filter.never
.filter(cmd => cmd.guildId?.includes(guild) && (!('ignore' in cmd) || cmd.ignore !== IgnoreCommand.Slash)) .filter(
cmd => cmd.guildId?.includes(guildId) && (!('ignore' in cmd) || cmd.ignore !== IgnoreCommand.Slash),
)
.map(x => x.toJSON()), .map(x => x.toJSON()),
}); });
} }
} }
if (cachePath) await this.syncCachePath(cachePath);
}
async loadCommands(dir?: string) { async loadCommands(dir?: string) {
dir ??= await this.getRC().then(x => x.commands); dir ??= await this.getRC().then(x => x.commands);
if (dir && this.commands) { if (dir && this.commands) {
@ -363,7 +379,7 @@ export class BaseClient {
T extends InternalRuntimeConfigHTTP | InternalRuntimeConfig = InternalRuntimeConfigHTTP | InternalRuntimeConfig, T extends InternalRuntimeConfigHTTP | InternalRuntimeConfig = InternalRuntimeConfigHTTP | InternalRuntimeConfig,
>() { >() {
const seyfertConfig = (BaseClient._seyfertConfig || const seyfertConfig = (BaseClient._seyfertConfig ||
(await this.options.getRC?.()) || (await this.options?.getRC?.()) ||
(await Promise.any( (await Promise.any(
['.js', '.mjs', '.cjs', '.ts', '.mts', '.cts'].map(ext => ['.js', '.mjs', '.cjs', '.ts', '.mts', '.cts'].map(ext =>
magicImport(join(process.cwd(), `seyfert.config${ext}`)).then(x => x.default ?? x), magicImport(join(process.cwd(), `seyfert.config${ext}`)).then(x => x.default ?? x),

View File

@ -8,6 +8,7 @@ import {
type APIApplicationCommandSubcommandOption, type APIApplicationCommandSubcommandOption,
type APIApplicationCommandSubcommandGroupOption, type APIApplicationCommandSubcommandGroupOption,
type APIApplicationCommandChannelOption, type APIApplicationCommandChannelOption,
type LocalizationMap,
} from 'discord-api-types/v10'; } from 'discord-api-types/v10';
import { basename, dirname } from 'node:path'; import { basename, dirname } from 'node:path';
import type { Logger, MakeRequired, NulleableCoalising, OmitInsert } from '../common'; import type { Logger, MakeRequired, NulleableCoalising, OmitInsert } from '../common';
@ -48,6 +49,24 @@ export class CommandHandler extends BaseHandler {
} }
} }
protected shouldUploadLocales(locales?: LocalizationMap | null, cachedLocales?: LocalizationMap | null) {
if (!locales && !cachedLocales) return false;
if (!locales && cachedLocales) return true;
if (locales && !cachedLocales) return true;
if (locales && cachedLocales) {
const localesEntries = Object.entries(locales);
const cachedLocalesEntries = Object.entries(cachedLocales);
if (localesEntries.length !== cachedLocalesEntries.length) return true;
for (const [key, value] of localesEntries) {
const cached = cachedLocalesEntries.find(x => x[0] === key);
if (!cached) return true;
if (value !== cached[1]) return true;
}
}
return false;
}
protected shouldUploadOption(option: APIApplicationCommandOption, cached: APIApplicationCommandOption) { protected shouldUploadOption(option: APIApplicationCommandOption, cached: APIApplicationCommandOption) {
if (option.description !== cached.description) return true; if (option.description !== cached.description) return true;
if (option.type !== cached.type) return true; if (option.type !== cached.type) return true;
@ -55,6 +74,9 @@ export class CommandHandler extends BaseHandler {
if (option.name !== cached.name) return true; if (option.name !== cached.name) return true;
//TODO: locales //TODO: locales
if (this.shouldUploadLocales(option.name_localizations, cached.name_localizations)) return true;
if (this.shouldUploadLocales(option.description_localizations, cached.description_localizations)) return true;
switch (option.type) { switch (option.type) {
case ApplicationCommandOptionType.String: case ApplicationCommandOptionType.String:
return ( return (
@ -108,24 +130,34 @@ export class CommandHandler extends BaseHandler {
return false; return false;
} }
async shouldUpload(file: string) { async shouldUpload(file: string, guildId?: string) {
const values = this.values.filter(x => {
if (!guildId) return !x.guildId;
return x.guildId?.includes(guildId);
});
if ( if (
!(await promises.access(file).then( !(await promises.access(file).then(
() => true, () => true,
() => false, () => false,
)) ))
) { ) {
await promises.writeFile(file, JSON.stringify(this.values.map(x => x.toJSON()))); await promises.writeFile(file, JSON.stringify(values.map(x => x.toJSON())));
return true; return true;
} }
const cachedCommands: (ReturnType<Command['toJSON']> | ReturnType<ContextMenuCommand['toJSON']>)[] = JSON.parse( const cachedCommands = (
(await promises.readFile(file)).toString(), JSON.parse((await promises.readFile(file)).toString()) as (
); | ReturnType<Command['toJSON']>
| ReturnType<ContextMenuCommand['toJSON']>
)[]
).filter(x => {
if (!guildId) return !x.guild_id;
return x.guild_id?.includes(guildId);
});
if (cachedCommands.length !== this.values.length) return true; if (cachedCommands.length !== values.length) return true;
for (const command of this.values.map(x => x.toJSON())) { for (const command of values.map(x => x.toJSON())) {
const cached = cachedCommands.find(x => { const cached = cachedCommands.find(x => {
if (x.name !== command.name) return false; if (x.name !== command.name) return false;
if (command.guild_id) return command.guild_id.every(id => x.guild_id?.includes(id)); if (command.guild_id) return command.guild_id.every(id => x.guild_id?.includes(id));
@ -140,7 +172,8 @@ export class CommandHandler extends BaseHandler {
if (!!('options' in cached) !== !!('options' in command)) return true; if (!!('options' in cached) !== !!('options' in command)) return true;
if (!!cached.contexts !== !!command.contexts) return true; if (!!cached.contexts !== !!command.contexts) return true;
if (!!cached.integration_types !== !!command.integration_types) return true; if (!!cached.integration_types !== !!command.integration_types) return true;
//TODO: locales if (this.shouldUploadLocales(command.name_localizations, cached.name_localizations)) return true;
if (this.shouldUploadLocales(command.description_localizations, cached.description_localizations)) return true;
if ('contexts' in command && 'contexts' in cached) { if ('contexts' in command && 'contexts' in cached) {
if (command.contexts.length !== cached.contexts.length) return true; if (command.contexts.length !== cached.contexts.length) return true;