Bugfixes + improvements
Stronger setting typings Fixed bug with running settings current in dms Stronger property checks in reply method Locale loader bugfix that prevented certain files from loading properly Make sure bot has permissions in modlog channel before trying to send message
This commit is contained in:
parent
71b025c514
commit
a17420e87a
@ -297,10 +297,10 @@ export type SettingApiDefinitions = {
|
||||
//
|
||||
}
|
||||
export type BaseSetting = object
|
||||
export type SettingOptions = {
|
||||
export type SettingOptions<IsGuildSetting extends boolean> = {
|
||||
name?: string,
|
||||
aliases?: string[],
|
||||
resolve?: SettingTypeResolve,
|
||||
resolve?: If<IsGuildSetting, 'GUILD', 'USER'>,
|
||||
description?: string,
|
||||
display?: string,
|
||||
emoji?: SettingEmojiOption,
|
||||
|
@ -16,10 +16,11 @@ import { Emojis } from '../../constants/index.js';
|
||||
import DiscordClient from '../DiscordClient.js';
|
||||
import { FormatParams } from '../../../@types/Client.js';
|
||||
|
||||
type Languages = {
|
||||
[key: string]: {
|
||||
type Language = {
|
||||
[key: string]: string
|
||||
}
|
||||
type Languages = {
|
||||
[key: string]: Language
|
||||
}
|
||||
|
||||
class LocaleLoader
|
||||
@ -84,14 +85,19 @@ class LocaleLoader
|
||||
const directory = path.join(root, language);
|
||||
const files = Util.readdirRecursive(directory);
|
||||
|
||||
const combined = {};
|
||||
const combined: Language = {};
|
||||
for (let file of files)
|
||||
{
|
||||
file = fs.readFileSync(file, {
|
||||
encoding: 'utf8'
|
||||
});
|
||||
const result = this._loadFile(file);
|
||||
Object.assign(combined, result);
|
||||
for (const [ key, string ] of Object.entries(result))
|
||||
{
|
||||
if (combined[key])
|
||||
throw new Error('Duplicate key ' + key);
|
||||
combined[key] = string;
|
||||
}
|
||||
}
|
||||
|
||||
this.#languages[language] = combined;
|
||||
@ -102,8 +108,8 @@ class LocaleLoader
|
||||
{
|
||||
if (process.platform === 'win32')
|
||||
{
|
||||
file = file.split('\n').join('');
|
||||
file = file.replace(/\r/gu, '\n');
|
||||
// file = file.split('\n').join('');
|
||||
file = file.replace(/\r/gu, '');
|
||||
}
|
||||
|
||||
const lines = file.split('\n');
|
||||
|
@ -75,7 +75,7 @@ class SettingsCommand extends SlashCommand
|
||||
return invoker.reply({ embeds: [ embed ] });
|
||||
}
|
||||
|
||||
async #currentSettings (invoker: InvokerWrapper<true, true>)
|
||||
async #currentSettings (invoker: InvokerWrapper<boolean, true>)
|
||||
{
|
||||
const { guild } = invoker;
|
||||
const { settings } = this.client.registry;
|
||||
@ -83,7 +83,9 @@ class SettingsCommand extends SlashCommand
|
||||
|
||||
for (const setting of settings.values())
|
||||
{
|
||||
const settingFields = await setting.fields(guild);
|
||||
if (setting.resolve === 'GUILD' && !guild)
|
||||
continue;
|
||||
const settingFields = await setting.fields(guild!);
|
||||
if (!settingFields.length)
|
||||
continue;
|
||||
let _field = {
|
||||
@ -94,7 +96,7 @@ class SettingsCommand extends SlashCommand
|
||||
{
|
||||
if (field.name === ZeroWidthChar)
|
||||
continue;
|
||||
const str = `**${guild.format(field.name)}**\n${field.value}`;
|
||||
const str = `**${guild!.format(field.name)}**\n${field.value}`;
|
||||
if (_field.value.length + str.length >= EmbedLimits.fieldValue)
|
||||
{
|
||||
fields.push(_field);
|
||||
@ -126,6 +128,9 @@ class SettingsCommand extends SlashCommand
|
||||
}
|
||||
}
|
||||
|
||||
if (!embeds.length)
|
||||
return { index: 'COMMAND_SETTINGS_NONE' };
|
||||
|
||||
await invoker.reply({ embeds: [ embeds.shift()! ] });
|
||||
for (const emb of embeds)
|
||||
{
|
||||
|
@ -37,10 +37,8 @@ class ChannelIgnore extends Inhibitor
|
||||
}
|
||||
return super._fail({ error: true, silent: true });
|
||||
}
|
||||
|
||||
return super._succeed();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default ChannelIgnore;
|
@ -88,9 +88,10 @@ class IgnoreSetting extends Setting
|
||||
};
|
||||
}
|
||||
|
||||
fields (guild: GuildWrapper)
|
||||
async fields (guild: GuildWrapper)
|
||||
{
|
||||
const setting = guild._settings[this.name] as IgnoreSettings;
|
||||
const settings = await guild.settings();
|
||||
const setting = settings[this.name] as IgnoreSettings;
|
||||
return [
|
||||
{
|
||||
name: 'GENERAL_CHANNELS',
|
||||
@ -101,7 +102,6 @@ class IgnoreSetting extends Setting
|
||||
value: setting.bypass.map((r) => `<@&${r}>`).join(', ') || '**N/A**'
|
||||
}
|
||||
];
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -244,9 +244,13 @@ class InvokerWrapper<InGuild extends boolean = boolean, HasCommand extends boole
|
||||
if (options.embed)
|
||||
options.embeds = [ options.embed ];
|
||||
|
||||
if (options.embeds && !(options.embeds instanceof Array))
|
||||
throw new Error('Invalid embeds type');
|
||||
if (options.embeds)
|
||||
options.embeds.forEach((embed) =>
|
||||
{
|
||||
if (!embed)
|
||||
throw new Error('Embed cannot be undefined');
|
||||
if (embed instanceof EmbedBuilder && !embed.data.color)
|
||||
embed.setColor(Constants.EmbedDefaultColor);
|
||||
else if (!(embed instanceof EmbedBuilder) && !embed.color)
|
||||
|
@ -189,11 +189,15 @@ class Infraction
|
||||
{
|
||||
if (moderation.infractions.includes(this.#type!))
|
||||
{
|
||||
this.#moderationLog = await this.#client.resolver.resolveChannel(moderation.channel, true, this.#guild);
|
||||
if (this.#moderationLog)
|
||||
this.#moderationLog = await this.#guild.resolveChannel<TextChannel>(moderation.channel, true);
|
||||
const perms = this.#moderationLog?.permissionsFor(this.client.user!);
|
||||
const missing = perms?.missing([ 'SendMessages', 'EmbedLinks' ]);
|
||||
if (this.#moderationLog && !missing?.length)
|
||||
{
|
||||
this.#modLogId = this.#moderationLog.id;
|
||||
this.#dmLogMessage = await this.#moderationLog.send({ embeds: [ await this.#embed() ] }).catch(null);
|
||||
this.#dmLogMessage = await this.#moderationLog
|
||||
.send({ embeds: [ await this.#embed() ] })
|
||||
.catch((err) => this.logger.error(err)) ?? null;
|
||||
this.#modLogMessageId = this.#dmLogMessage?.id || null;
|
||||
}
|
||||
}
|
||||
@ -203,9 +207,7 @@ class Infraction
|
||||
}
|
||||
}
|
||||
|
||||
if (dminfraction.enabled && !this.#silent)
|
||||
{
|
||||
if (this.#targetType === 'USER' && dminfraction.infractions.includes(this.#type!))
|
||||
if (dminfraction.enabled && !this.#silent && this.#targetType === 'USER' && dminfraction.infractions.includes(this.#type!))
|
||||
{
|
||||
let message = dminfraction.messages[this.#type!] || dminfraction.messages.default;
|
||||
if (!message)
|
||||
@ -225,7 +227,6 @@ class Infraction
|
||||
this.#dmLogMessageId = logMessage?.id ?? null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (this.#duration)
|
||||
await this.#client.moderation.handleCallbacks([ this.json ]);
|
||||
@ -606,7 +607,17 @@ class Infraction
|
||||
|
||||
protected async _verify ()
|
||||
{
|
||||
const { protection } = await this.#guild.settings();
|
||||
const {
|
||||
protection,
|
||||
// moderation
|
||||
} = await this.#guild.settings();
|
||||
// const modlog = moderation.channel ? await this.guild.resolveChannel<TextChannel>(moderation.channel).catch(() => null) : null;
|
||||
// const perms = modlog?.permissionsFor(this.client.user!);
|
||||
// if (modlog && perms)
|
||||
// {
|
||||
// if (perms.missing([ 'SendMessages', 'EmbedLinks' ]).length)
|
||||
// return this._fail('INFRACTION_MISSING_MODLOG_PERMS');
|
||||
// }
|
||||
if (this.#executor?.id === this.#guild.ownerId)
|
||||
return this._succeed();
|
||||
if (
|
||||
|
@ -1,5 +1,5 @@
|
||||
import Component from './Component.js';
|
||||
import { EmbedBuilder, PermissionsString, TextChannel, APIEmbed, APIEmbedField, User } from 'discord.js';
|
||||
import { EmbedBuilder, PermissionsString, TextChannel, APIEmbed, APIEmbedField, User, If } from 'discord.js';
|
||||
|
||||
import { GuildWrapper, InvokerWrapper, MemberWrapper, UserWrapper } from '../components/wrappers/index.js';
|
||||
import DiscordClient from '../DiscordClient.js';
|
||||
@ -58,7 +58,7 @@ type HelperResult = {
|
||||
* @class Setting
|
||||
* @extends {Component}
|
||||
*/
|
||||
abstract class Setting extends Component
|
||||
abstract class Setting<IsGuildSetting extends boolean = true> extends Component
|
||||
{
|
||||
#name: string;
|
||||
#resolve: SettingTypeResolve;
|
||||
@ -86,7 +86,7 @@ abstract class Setting extends Component
|
||||
* @param {Object} [options={}]
|
||||
* @memberof Setting
|
||||
*/
|
||||
constructor (client: DiscordClient, options: SettingOptions)
|
||||
constructor (client: DiscordClient, options: SettingOptions<IsGuildSetting>)
|
||||
{
|
||||
if (!options)
|
||||
throw new Error('No options provided to setting');
|
||||
@ -266,7 +266,7 @@ abstract class Setting extends Component
|
||||
* @return {Array<void>}
|
||||
* @memberof Setting
|
||||
*/
|
||||
fields (_guild: GuildWrapper): Promise<APIEmbedField[]> | APIEmbedField[]
|
||||
fields (_guild: If<IsGuildSetting, GuildWrapper, GuildWrapper | undefined>): Promise<APIEmbedField[]> | APIEmbedField[]
|
||||
{
|
||||
return Promise.resolve([]);
|
||||
}
|
||||
|
@ -54,6 +54,9 @@ No permissions granted
|
||||
[COMMAND_SETTINGS_HELP]
|
||||
Configure bot settings for the server.
|
||||
|
||||
[COMMAND_SETTINGS_NONE]
|
||||
No settings found.
|
||||
|
||||
[COMMAND_MODERATION_HELP]
|
||||
Configure moderation related settings.
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user