forked from Galactic/galactic-bot
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 BaseSetting = object
|
||||||
export type SettingOptions = {
|
export type SettingOptions<IsGuildSetting extends boolean> = {
|
||||||
name?: string,
|
name?: string,
|
||||||
aliases?: string[],
|
aliases?: string[],
|
||||||
resolve?: SettingTypeResolve,
|
resolve?: If<IsGuildSetting, 'GUILD', 'USER'>,
|
||||||
description?: string,
|
description?: string,
|
||||||
display?: string,
|
display?: string,
|
||||||
emoji?: SettingEmojiOption,
|
emoji?: SettingEmojiOption,
|
||||||
|
@ -16,10 +16,11 @@ import { Emojis } from '../../constants/index.js';
|
|||||||
import DiscordClient from '../DiscordClient.js';
|
import DiscordClient from '../DiscordClient.js';
|
||||||
import { FormatParams } from '../../../@types/Client.js';
|
import { FormatParams } from '../../../@types/Client.js';
|
||||||
|
|
||||||
|
type Language = {
|
||||||
|
[key: string]: string
|
||||||
|
}
|
||||||
type Languages = {
|
type Languages = {
|
||||||
[key: string]: {
|
[key: string]: Language
|
||||||
[key: string]: string
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class LocaleLoader
|
class LocaleLoader
|
||||||
@ -84,14 +85,19 @@ class LocaleLoader
|
|||||||
const directory = path.join(root, language);
|
const directory = path.join(root, language);
|
||||||
const files = Util.readdirRecursive(directory);
|
const files = Util.readdirRecursive(directory);
|
||||||
|
|
||||||
const combined = {};
|
const combined: Language = {};
|
||||||
for (let file of files)
|
for (let file of files)
|
||||||
{
|
{
|
||||||
file = fs.readFileSync(file, {
|
file = fs.readFileSync(file, {
|
||||||
encoding: 'utf8'
|
encoding: 'utf8'
|
||||||
});
|
});
|
||||||
const result = this._loadFile(file);
|
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;
|
this.#languages[language] = combined;
|
||||||
@ -102,8 +108,8 @@ class LocaleLoader
|
|||||||
{
|
{
|
||||||
if (process.platform === 'win32')
|
if (process.platform === 'win32')
|
||||||
{
|
{
|
||||||
file = file.split('\n').join('');
|
// file = file.split('\n').join('');
|
||||||
file = file.replace(/\r/gu, '\n');
|
file = file.replace(/\r/gu, '');
|
||||||
}
|
}
|
||||||
|
|
||||||
const lines = file.split('\n');
|
const lines = file.split('\n');
|
||||||
|
@ -75,7 +75,7 @@ class SettingsCommand extends SlashCommand
|
|||||||
return invoker.reply({ embeds: [ embed ] });
|
return invoker.reply({ embeds: [ embed ] });
|
||||||
}
|
}
|
||||||
|
|
||||||
async #currentSettings (invoker: InvokerWrapper<true, true>)
|
async #currentSettings (invoker: InvokerWrapper<boolean, true>)
|
||||||
{
|
{
|
||||||
const { guild } = invoker;
|
const { guild } = invoker;
|
||||||
const { settings } = this.client.registry;
|
const { settings } = this.client.registry;
|
||||||
@ -83,7 +83,9 @@ class SettingsCommand extends SlashCommand
|
|||||||
|
|
||||||
for (const setting of settings.values())
|
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)
|
if (!settingFields.length)
|
||||||
continue;
|
continue;
|
||||||
let _field = {
|
let _field = {
|
||||||
@ -94,7 +96,7 @@ class SettingsCommand extends SlashCommand
|
|||||||
{
|
{
|
||||||
if (field.name === ZeroWidthChar)
|
if (field.name === ZeroWidthChar)
|
||||||
continue;
|
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)
|
if (_field.value.length + str.length >= EmbedLimits.fieldValue)
|
||||||
{
|
{
|
||||||
fields.push(_field);
|
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()! ] });
|
await invoker.reply({ embeds: [ embeds.shift()! ] });
|
||||||
for (const emb of embeds)
|
for (const emb of embeds)
|
||||||
{
|
{
|
||||||
|
@ -37,10 +37,8 @@ class ChannelIgnore extends Inhibitor
|
|||||||
}
|
}
|
||||||
return super._fail({ error: true, silent: true });
|
return super._fail({ error: true, silent: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
return super._succeed();
|
return super._succeed();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default ChannelIgnore;
|
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 [
|
return [
|
||||||
{
|
{
|
||||||
name: 'GENERAL_CHANNELS',
|
name: 'GENERAL_CHANNELS',
|
||||||
@ -101,7 +102,6 @@ class IgnoreSetting extends Setting
|
|||||||
value: setting.bypass.map((r) => `<@&${r}>`).join(', ') || '**N/A**'
|
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)
|
if (options.embed)
|
||||||
options.embeds = [ options.embed ];
|
options.embeds = [ options.embed ];
|
||||||
|
|
||||||
|
if (options.embeds && !(options.embeds instanceof Array))
|
||||||
|
throw new Error('Invalid embeds type');
|
||||||
if (options.embeds)
|
if (options.embeds)
|
||||||
options.embeds.forEach((embed) =>
|
options.embeds.forEach((embed) =>
|
||||||
{
|
{
|
||||||
|
if (!embed)
|
||||||
|
throw new Error('Embed cannot be undefined');
|
||||||
if (embed instanceof EmbedBuilder && !embed.data.color)
|
if (embed instanceof EmbedBuilder && !embed.data.color)
|
||||||
embed.setColor(Constants.EmbedDefaultColor);
|
embed.setColor(Constants.EmbedDefaultColor);
|
||||||
else if (!(embed instanceof EmbedBuilder) && !embed.color)
|
else if (!(embed instanceof EmbedBuilder) && !embed.color)
|
||||||
|
@ -189,11 +189,15 @@ class Infraction
|
|||||||
{
|
{
|
||||||
if (moderation.infractions.includes(this.#type!))
|
if (moderation.infractions.includes(this.#type!))
|
||||||
{
|
{
|
||||||
this.#moderationLog = await this.#client.resolver.resolveChannel(moderation.channel, true, this.#guild);
|
this.#moderationLog = await this.#guild.resolveChannel<TextChannel>(moderation.channel, true);
|
||||||
if (this.#moderationLog)
|
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.#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;
|
this.#modLogMessageId = this.#dmLogMessage?.id || null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -203,27 +207,24 @@ class Infraction
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dminfraction.enabled && !this.#silent)
|
if (dminfraction.enabled && !this.#silent && this.#targetType === 'USER' && dminfraction.infractions.includes(this.#type!))
|
||||||
{
|
{
|
||||||
if (this.#targetType === 'USER' && dminfraction.infractions.includes(this.#type!))
|
let message = dminfraction.messages[this.#type!] || dminfraction.messages.default;
|
||||||
{
|
if (!message)
|
||||||
let message = dminfraction.messages[this.#type!] || dminfraction.messages.default;
|
message = '';
|
||||||
if (!message)
|
message = message
|
||||||
message = '';
|
.replace(/\{(guild|server)\}/ugim, this.#guild.name)
|
||||||
message = message
|
.replace(/\{user\}/ugim, (this.#target as UserWrapper)?.tag)
|
||||||
.replace(/\{(guild|server)\}/ugim, this.#guild.name)
|
.replace(/\{infraction\}/ugim, this.dictionary.past)
|
||||||
.replace(/\{user\}/ugim, (this.#target as UserWrapper)?.tag)
|
.replace(/\{from\|on\}/ugim, Constants.RemovedInfractions.includes(this.#type!) ? 'from' : 'on'); // add more if you want i should probably add a better system for this...
|
||||||
.replace(/\{infraction\}/ugim, this.dictionary.past)
|
|
||||||
.replace(/\{from\|on\}/ugim, Constants.RemovedInfractions.includes(this.#type!) ? 'from' : 'on'); // add more if you want i should probably add a better system for this...
|
|
||||||
|
|
||||||
if (Util.isSendable(this.#target))
|
if (Util.isSendable(this.#target))
|
||||||
{
|
{
|
||||||
const logMessage = await this.#target.send({
|
const logMessage = await this.#target.send({
|
||||||
content: message,
|
content: message,
|
||||||
embeds: [ await this.#embed(true) ]
|
embeds: [ await this.#embed(true) ]
|
||||||
}).catch(() => null);
|
}).catch(() => null);
|
||||||
this.#dmLogMessageId = logMessage?.id ?? null;
|
this.#dmLogMessageId = logMessage?.id ?? null;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -606,7 +607,17 @@ class Infraction
|
|||||||
|
|
||||||
protected async _verify ()
|
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)
|
if (this.#executor?.id === this.#guild.ownerId)
|
||||||
return this._succeed();
|
return this._succeed();
|
||||||
if (
|
if (
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import Component from './Component.js';
|
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 { GuildWrapper, InvokerWrapper, MemberWrapper, UserWrapper } from '../components/wrappers/index.js';
|
||||||
import DiscordClient from '../DiscordClient.js';
|
import DiscordClient from '../DiscordClient.js';
|
||||||
@ -58,7 +58,7 @@ type HelperResult = {
|
|||||||
* @class Setting
|
* @class Setting
|
||||||
* @extends {Component}
|
* @extends {Component}
|
||||||
*/
|
*/
|
||||||
abstract class Setting extends Component
|
abstract class Setting<IsGuildSetting extends boolean = true> extends Component
|
||||||
{
|
{
|
||||||
#name: string;
|
#name: string;
|
||||||
#resolve: SettingTypeResolve;
|
#resolve: SettingTypeResolve;
|
||||||
@ -86,7 +86,7 @@ abstract class Setting extends Component
|
|||||||
* @param {Object} [options={}]
|
* @param {Object} [options={}]
|
||||||
* @memberof Setting
|
* @memberof Setting
|
||||||
*/
|
*/
|
||||||
constructor (client: DiscordClient, options: SettingOptions)
|
constructor (client: DiscordClient, options: SettingOptions<IsGuildSetting>)
|
||||||
{
|
{
|
||||||
if (!options)
|
if (!options)
|
||||||
throw new Error('No options provided to setting');
|
throw new Error('No options provided to setting');
|
||||||
@ -266,7 +266,7 @@ abstract class Setting extends Component
|
|||||||
* @return {Array<void>}
|
* @return {Array<void>}
|
||||||
* @memberof Setting
|
* @memberof Setting
|
||||||
*/
|
*/
|
||||||
fields (_guild: GuildWrapper): Promise<APIEmbedField[]> | APIEmbedField[]
|
fields (_guild: If<IsGuildSetting, GuildWrapper, GuildWrapper | undefined>): Promise<APIEmbedField[]> | APIEmbedField[]
|
||||||
{
|
{
|
||||||
return Promise.resolve([]);
|
return Promise.resolve([]);
|
||||||
}
|
}
|
||||||
|
@ -1,87 +1,90 @@
|
|||||||
// Permissions management
|
// Permissions management
|
||||||
[COMMAND_PERMISSIONS_HELP]
|
[COMMAND_PERMISSIONS_HELP]
|
||||||
Grant roles or users permissions to use commands or modules.
|
Grant roles or users permissions to use commands or modules.
|
||||||
To view all grantable permissions, use the command `permissions list`.
|
To view all grantable permissions, use the command `permissions list`.
|
||||||
|
|
||||||
Permissions look like `command:<commandname>` or `module:<modulename>`
|
Permissions look like `command:<commandname>` or `module:<modulename>`
|
||||||
|
|
||||||
[COMMAND_PERMISSIONS_NO_TARGET]
|
[COMMAND_PERMISSIONS_NO_TARGET]
|
||||||
Missing either member or role.
|
Missing either member or role.
|
||||||
|
|
||||||
[COMMAND_PERMISSIONS_NO_RESOLVE]
|
[COMMAND_PERMISSIONS_NO_RESOLVE]
|
||||||
Failed to resolve any permissions.
|
Failed to resolve any permissions.
|
||||||
|
|
||||||
[COMMAND_PERMISSIONS_DB_ERROR]
|
[COMMAND_PERMISSIONS_DB_ERROR]
|
||||||
Database error while updating permissions.
|
Database error while updating permissions.
|
||||||
Permissions in memory should be updated but they will not persist.
|
Permissions in memory should be updated but they will not persist.
|
||||||
**Please report this**
|
**Please report this**
|
||||||
|
|
||||||
[COMMAND_PERMISSIONS_SUCCESS_GRANT]
|
[COMMAND_PERMISSIONS_SUCCESS_GRANT]
|
||||||
Successfully granted **{targets}** the following permissions: `{permissions}`
|
Successfully granted **{targets}** the following permissions: `{permissions}`
|
||||||
|
|
||||||
[COMMAND_PERMISSIONS_SUCCESS_REVOKE]
|
[COMMAND_PERMISSIONS_SUCCESS_REVOKE]
|
||||||
Successfully revoked the following permissions from **{targets}**: `{permissions}`
|
Successfully revoked the following permissions from **{targets}**: `{permissions}`
|
||||||
|
|
||||||
[COMMAND_PERMISSIONS_WARNING]
|
[COMMAND_PERMISSIONS_WARNING]
|
||||||
You granted a command from the **Administration** module. This is potentially dangerous, as whoever you granted the administration commands to could have access to vital parts of the server. Only grant administration commands to people you trust.
|
You granted a command from the **Administration** module. This is potentially dangerous, as whoever you granted the administration commands to could have access to vital parts of the server. Only grant administration commands to people you trust.
|
||||||
|
|
||||||
[COMMAND_PERMISSIONS_LIST]
|
[COMMAND_PERMISSIONS_LIST]
|
||||||
You can **grant**/**revoke** the following permissions
|
You can **grant**/**revoke** the following permissions
|
||||||
`{permissions}`
|
`{permissions}`
|
||||||
|
|
||||||
[COMMAND_PERMISSIONS_RESET]
|
[COMMAND_PERMISSIONS_RESET]
|
||||||
Successfully reset permissions{for}{in}
|
Successfully reset permissions{for}{in}
|
||||||
|
|
||||||
[COMMAND_PERMISSIONS_RESET_FOR]
|
[COMMAND_PERMISSIONS_RESET_FOR]
|
||||||
__ __for **{targets}**
|
__ __for **{targets}**
|
||||||
// ... avoiding a trim that clears the space
|
// ... avoiding a trim that clears the space
|
||||||
[COMMAND_PERMISSIONS_RESET_IN]
|
[COMMAND_PERMISSIONS_RESET_IN]
|
||||||
__ __in {channels}
|
__ __in {channels}
|
||||||
|
|
||||||
[COMMAND_PERMISSIONS_GLOBAL_PERMS]
|
[COMMAND_PERMISSIONS_GLOBAL_PERMS]
|
||||||
Global permissions
|
Global permissions
|
||||||
|
|
||||||
[COMMAND_PERMISSIONS_SHOW_TITLE]
|
[COMMAND_PERMISSIONS_SHOW_TITLE]
|
||||||
Granted permissions
|
Granted permissions
|
||||||
|
|
||||||
[COMMAND_PERMISSIONS_DESC]
|
[COMMAND_PERMISSIONS_DESC]
|
||||||
Showing permissions {forin} **{target}**
|
Showing permissions {forin} **{target}**
|
||||||
|
|
||||||
[COMMAND_PERMISSIONS_NO_PERMS]
|
[COMMAND_PERMISSIONS_NO_PERMS]
|
||||||
No permissions granted
|
No permissions granted
|
||||||
|
|
||||||
// Settings
|
// Settings
|
||||||
[COMMAND_SETTINGS_HELP]
|
[COMMAND_SETTINGS_HELP]
|
||||||
Configure bot settings for the server.
|
Configure bot settings for the server.
|
||||||
|
|
||||||
[COMMAND_MODERATION_HELP]
|
[COMMAND_SETTINGS_NONE]
|
||||||
Configure moderation related settings.
|
No settings found.
|
||||||
|
|
||||||
[COMMAND_LOGGING_HELP]
|
[COMMAND_MODERATION_HELP]
|
||||||
Configure logging settings.
|
Configure moderation related settings.
|
||||||
|
|
||||||
[COMMAND_UTILITY_HELP]
|
[COMMAND_LOGGING_HELP]
|
||||||
Configure utility settings.
|
Configure logging settings.
|
||||||
|
|
||||||
[COMMAND_ADMINISTRATION_HELP]
|
[COMMAND_UTILITY_HELP]
|
||||||
Configure administrative settings.
|
Configure utility settings.
|
||||||
|
|
||||||
// Import
|
[COMMAND_ADMINISTRATION_HELP]
|
||||||
[COMMAND_IMPORT_HELP]
|
Configure administrative settings.
|
||||||
Import configuration and data from old versions of the bot.
|
|
||||||
|
// Import
|
||||||
[COMMAND_IMPORT_ERROR]
|
[COMMAND_IMPORT_HELP]
|
||||||
Error during import, contact a developer about this issue:
|
Import configuration and data from old versions of the bot.
|
||||||
{message}
|
|
||||||
|
[COMMAND_IMPORT_ERROR]
|
||||||
[COMMAND_SETTINGS_IMPORT_SUCCESS]
|
Error during import, contact a developer about this issue:
|
||||||
Successfully imported settings!
|
{message}
|
||||||
|
|
||||||
[COMMAND_INFRACTIONS_IMPORT_SUCCESS]
|
[COMMAND_SETTINGS_IMPORT_SUCCESS]
|
||||||
Successfully imported {cases} infractions.
|
Successfully imported settings!
|
||||||
|
|
||||||
[COMMAND_IMPORT_IMPORTED]
|
[COMMAND_INFRACTIONS_IMPORT_SUCCESS]
|
||||||
**{thing}** are already imported
|
Successfully imported {cases} infractions.
|
||||||
|
|
||||||
[COMMAND_IMPORT_WORKING]
|
[COMMAND_IMPORT_IMPORTED]
|
||||||
|
**{thing}** are already imported
|
||||||
|
|
||||||
|
[COMMAND_IMPORT_WORKING]
|
||||||
Working...
|
Working...
|
Loading…
Reference in New Issue
Block a user