formatter: Use semicolons (#4686)

I prefer semicolors, they also help avoiding certain pitfalls in JavaScript/TypeScript, such as the following code sample:
```js
const xyz = "test"
(something.else as string) = "another"
```
This results in a TypeError: "test" is not a function, this is because js thinks we are trying to call the string "test" as a function.
To fix this it requires a `;` somewhere before the `(`, such as `;(something ... ` which in my opinion is ugly and less clean overall.
This commit is contained in:
Fleny
2026-01-17 21:54:15 +01:00
committed by GitHub
parent f713b4ab7b
commit 27c261fee2
403 changed files with 11250 additions and 11217 deletions
+5 -5
View File
@@ -1,6 +1,6 @@
import { createBot, Intents } from '@discordeno/bot'
import { createProxyCache } from 'dd-cache-proxy'
import { configs } from './config.js'
import { createBot, Intents } from '@discordeno/bot';
import { createProxyCache } from 'dd-cache-proxy';
import { configs } from './config.js';
const rawBot = createBot({
token: configs.token,
@@ -22,7 +22,7 @@ const rawBot = createBot({
username: true,
},
},
})
});
export const bot = createProxyCache(rawBot, {
desiredProps: {
@@ -32,4 +32,4 @@ export const bot = createProxyCache(rawBot, {
guild: true,
default: false,
},
})
});
+15 -15
View File
@@ -1,27 +1,27 @@
import { type ApplicationCommandOption, type ApplicationCommandTypes, Collection } from '@discordeno/bot'
import type { bot } from './bot.js'
import { type ApplicationCommandOption, type ApplicationCommandTypes, Collection } from '@discordeno/bot';
import type { bot } from './bot.js';
export const commands = new Collection<string, Command>()
export const commands = new Collection<string, Command>();
export function createCommand(command: Command): void {
commands.set(command.name, command)
commands.set(command.name, command);
}
export interface Command {
name: string
description: string
usage?: string[]
options?: ApplicationCommandOption[]
type: ApplicationCommandTypes
name: string;
description: string;
usage?: string[];
options?: ApplicationCommandOption[];
type: ApplicationCommandTypes;
/** Defaults to `Guild` */
scope?: 'Global' | 'Guild'
execute: (interaction: typeof bot.transformers.$inferredTypes.interaction) => unknown
subcommands?: Array<SubCommandGroup | SubCommand>
scope?: 'Global' | 'Guild';
execute: (interaction: typeof bot.transformers.$inferredTypes.interaction) => unknown;
subcommands?: Array<SubCommandGroup | SubCommand>;
}
export type SubCommand = Omit<Command, 'subcommands'>
export type SubCommand = Omit<Command, 'subcommands'>;
export interface SubCommandGroup {
name: string
subCommands: SubCommand[]
name: string;
subCommands: SubCommand[];
}
+6 -6
View File
@@ -1,6 +1,6 @@
import { ApplicationCommandTypes, snowflakeToTimestamp } from '@discordeno/bot'
import { createCommand } from '../commands.js'
import { humanizeMilliseconds } from '../utils/helpers.js'
import { ApplicationCommandTypes, snowflakeToTimestamp } from '@discordeno/bot';
import { createCommand } from '../commands.js';
import { humanizeMilliseconds } from '../utils/helpers.js';
createCommand({
name: 'ping',
@@ -8,8 +8,8 @@ createCommand({
type: ApplicationCommandTypes.ChatInput,
scope: 'Global',
async execute(interaction) {
const ping = Date.now() - snowflakeToTimestamp(interaction.id)
const ping = Date.now() - snowflakeToTimestamp(interaction.id);
await interaction.respond(`🏓 Pong! Ping ${ping}ms (${humanizeMilliseconds(ping)})`)
await interaction.respond(`🏓 Pong! Ping ${ping}ms (${humanizeMilliseconds(ping)})`);
},
})
});
+4 -4
View File
@@ -1,12 +1,12 @@
const token = process.env.BOT_TOKEN
const token = process.env.BOT_TOKEN;
if (!token) throw new Error('Missing BOT_TOKEN environment variable')
if (!token) throw new Error('Missing BOT_TOKEN environment variable');
export const configs: Config = {
/** Get token from ENV variable */
token,
}
};
export interface Config {
token: string
token: string;
}
+3 -3
View File
@@ -1,4 +1,4 @@
import { bot } from '../bot.js'
import { updateGuildCommands } from '../utils/helpers.js'
import { bot } from '../bot.js';
import { updateGuildCommands } from '../utils/helpers.js';
bot.events.guildCreate = async (guild) => await updateGuildCommands(guild)
bot.events.guildCreate = async (guild) => await updateGuildCommands(guild);
@@ -1,94 +1,94 @@
import { ApplicationCommandOptionTypes, hasProperty } from '@discordeno/bot'
import chalk from 'chalk'
import { bot } from '../bot.js'
import { commands } from '../commands.js'
import { getGuildFromId, isSubCommand, isSubCommandGroup } from '../utils/helpers.js'
import { createLogger } from '../utils/logger.js'
import { ApplicationCommandOptionTypes, hasProperty } from '@discordeno/bot';
import chalk from 'chalk';
import { bot } from '../bot.js';
import { commands } from '../commands.js';
import { getGuildFromId, isSubCommand, isSubCommandGroup } from '../utils/helpers.js';
import { createLogger } from '../utils/logger.js';
const logger = createLogger({ name: 'Event: InteractionCreate' })
const logger = createLogger({ name: 'Event: InteractionCreate' });
bot.events.interactionCreate = async (interaction) => {
if (!interaction.data || !interaction.id) return
if (!interaction.data || !interaction.id) return;
let guildName = 'Direct Message'
let guild = {} as typeof bot.transformers.$inferredTypes.guild
let guildName = 'Direct Message';
let guild = {} as typeof bot.transformers.$inferredTypes.guild;
// Set guild, if there was an error getting the guild, then just say it was a DM. (What else are we going to do?)
if (interaction.guildId) {
const guildOrVoid = await getGuildFromId(interaction.guildId).catch((err) => {
logger.error(err)
})
logger.error(err);
});
if (guildOrVoid) {
guild = guildOrVoid
guildName = guild.name
guild = guildOrVoid;
guildName = guild.name;
}
}
logger.info(
`[Command: ${chalk.bgYellow.black(interaction.data.name)} - ${chalk.bgBlack.white(`Trigger`)}] by @${interaction.user.username} in ${guildName}${guildName !== 'Direct Message' ? ` (${guild.id})` : ``}`,
)
);
let command = commands.get(interaction.data.name)
let command = commands.get(interaction.data.name);
if (!command) {
logger.warn(
`[Command: ${chalk.bgYellow.black(interaction.data.name)} - ${chalk.bgBlack.yellow(`Not Found`)}] by @${interaction.user.username} in ${guildName}${guildName !== 'Direct Message' ? ` (${guild.id})` : ``}`,
)
);
return
return;
}
if (interaction.data.options?.[0]) {
const optionType = interaction.data.options[0].type
const optionType = interaction.data.options[0].type;
if (optionType === ApplicationCommandOptionTypes.SubCommandGroup) {
// Check if command has subcommand and handle types
if (!command.subcommands) return
if (!command.subcommands) return;
// Try to find the subcommand group
const subCommandGroup = command.subcommands?.find((command) => command.name === interaction.data?.options?.[0].name)
if (!subCommandGroup) return
const subCommandGroup = command.subcommands?.find((command) => command.name === interaction.data?.options?.[0].name);
if (!subCommandGroup) return;
if (isSubCommand(subCommandGroup)) return
if (isSubCommand(subCommandGroup)) return;
// Get name of the command which we are looking for
const targetCmdName = interaction.data.options?.[0].options?.[0].name ?? interaction.data.options?.[0].options?.[0].name
if (!targetCmdName) return
const targetCmdName = interaction.data.options?.[0].options?.[0].name ?? interaction.data.options?.[0].options?.[0].name;
if (!targetCmdName) return;
// Try to find the command
command = subCommandGroup.subCommands.find((c) => c.name === targetCmdName)
command = subCommandGroup.subCommands.find((c) => c.name === targetCmdName);
}
if (optionType === ApplicationCommandOptionTypes.SubCommand) {
// Check if command has subcommand and handle types
if (!command?.subcommands) return
if (!command?.subcommands) return;
// Try to find the command
const found = command.subcommands.find((command) => command.name === interaction.data?.options?.[0].name)
if (!found) return
const found = command.subcommands.find((command) => command.name === interaction.data?.options?.[0].name);
if (!found) return;
if (isSubCommandGroup(found)) return
if (isSubCommandGroup(found)) return;
command = found
command = found;
}
}
try {
if (!command) throw new Error('Not command could be found')
if (!command) throw new Error('Not command could be found');
await command.execute(interaction)
await command.execute(interaction);
logger.info(
`[Command: ${chalk.bgYellow.black(interaction.data.name)} - ${chalk.bgBlack.green(`Success`)}] by @${interaction.user.username} in ${guildName}${guildName !== 'Direct Message' ? ` (${guild.id})` : ``}`,
)
);
} catch (err) {
logger.error(
`[Command: ${chalk.bgYellow.black(interaction.data.name)} - ${chalk.bgBlack.red(`Error`)}] by @${interaction.user.username} in ${guildName}${guildName !== 'Direct Message' ? ` (${guild.id})` : ``}`,
)
);
if (typeof err !== 'object' || !err || !hasProperty(err, 'message') || err.message === 'Not command could be found') return
if (typeof err !== 'object' || !err || !hasProperty(err, 'message') || err.message === 'Not command could be found') return;
logger.error(err)
logger.error(err);
}
}
};
+7 -7
View File
@@ -1,11 +1,11 @@
import { ActivityTypes } from '@discordeno/bot'
import { bot } from '../bot.js'
import { createLogger } from '../utils/logger.js'
import { ActivityTypes } from '@discordeno/bot';
import { bot } from '../bot.js';
import { createLogger } from '../utils/logger.js';
const logger = createLogger({ name: 'Event: Ready' })
const logger = createLogger({ name: 'Event: Ready' });
bot.events.ready = async ({ shardId }) => {
logger.info('Bot Ready')
logger.info('Bot Ready');
await bot.gateway.editShardStatus(shardId, {
status: 'online',
@@ -18,5 +18,5 @@ bot.events.ready = async ({ shardId }) => {
},
},
],
})
}
});
};
+10 -10
View File
@@ -1,15 +1,15 @@
import 'dotenv/config'
import 'dotenv/config';
import { bot } from './bot.js'
import importDirectory from './utils/loader.js'
import logger from './utils/logger.js'
import { bot } from './bot.js';
import importDirectory from './utils/loader.js';
import logger from './utils/logger.js';
logger.info('Starting bot...')
logger.info('Starting bot...');
logger.info('Loading commands...')
await importDirectory('./dist/commands')
logger.info('Loading commands...');
await importDirectory('./dist/commands');
logger.info('Loading events...')
await importDirectory('./dist/events')
logger.info('Loading events...');
await importDirectory('./dist/events');
await bot.start()
await bot.start();
+10 -10
View File
@@ -1,16 +1,16 @@
import 'dotenv/config'
import 'dotenv/config';
import { bot } from './bot.js'
import { updateCommands } from './utils/helpers.js'
import importDirectory from './utils/loader.js'
import { bot } from './bot.js';
import { updateCommands } from './utils/helpers.js';
import importDirectory from './utils/loader.js';
bot.logger.info('Loading commands...')
await importDirectory('./dist/commands')
bot.logger.info('Loading commands...');
await importDirectory('./dist/commands');
bot.logger.info('Updating commands...')
await updateCommands()
bot.logger.info('Updating commands...');
await updateCommands();
bot.logger.info('Done!')
bot.logger.info('Done!');
// We need to manually exit as the REST Manager has timeouts that will keep NodeJS alive
process.exit()
process.exit();
+34 -34
View File
@@ -1,14 +1,14 @@
import { type CreateApplicationCommand, hasProperty } from '@discordeno/bot'
import { bot } from '../bot.js'
import { commands, type SubCommand, type SubCommandGroup } from '../commands.js'
import { createLogger } from './logger.js'
import { type CreateApplicationCommand, hasProperty } from '@discordeno/bot';
import { bot } from '../bot.js';
import { commands, type SubCommand, type SubCommandGroup } from '../commands.js';
import { createLogger } from './logger.js';
const logger = createLogger({ name: 'Helpers' })
const logger = createLogger({ name: 'Helpers' });
/** This function will update all commands, or the defined scope */
export async function updateCommands(scope?: 'Guild' | 'Global'): Promise<void> {
const globalCommands: MakeRequired<CreateApplicationCommand, 'name'>[] = []
const perGuildCommands: MakeRequired<CreateApplicationCommand, 'name'>[] = []
const globalCommands: MakeRequired<CreateApplicationCommand, 'name'>[] = [];
const perGuildCommands: MakeRequired<CreateApplicationCommand, 'name'>[] = [];
for (const command of commands.values()) {
if (command.scope === 'Guild') {
@@ -17,34 +17,34 @@ export async function updateCommands(scope?: 'Guild' | 'Global'): Promise<void>
description: command.description,
type: command.type,
options: command.options ? command.options : undefined,
})
});
} else {
globalCommands.push({
name: command.name,
description: command.description,
type: command.type,
options: command.options ? command.options : undefined,
})
});
}
}
if (globalCommands.length && (scope === 'Global' || scope === undefined)) {
logger.info('Updating Global Commands, changes should apply in short...')
await bot.helpers.upsertGlobalApplicationCommands(globalCommands).catch(logger.error)
logger.info('Updating Global Commands, changes should apply in short...');
await bot.helpers.upsertGlobalApplicationCommands(globalCommands).catch(logger.error);
}
if (perGuildCommands.length && (scope === 'Guild' || scope === undefined)) {
await Promise.all(
bot.cache.guilds.memory.map(async (guild) => {
await bot.helpers.upsertGuildApplicationCommands(guild.id, perGuildCommands)
await bot.helpers.upsertGuildApplicationCommands(guild.id, perGuildCommands);
}),
)
);
}
}
/** Update commands for a guild */
export async function updateGuildCommands(guild: typeof bot.transformers.$inferredTypes.guild): Promise<void> {
const perGuildCommands: MakeRequired<CreateApplicationCommand, 'name'>[] = []
const perGuildCommands: MakeRequired<CreateApplicationCommand, 'name'>[] = [];
for (const command of commands.values()) {
if (command.scope === 'Guild') {
@@ -53,49 +53,49 @@ export async function updateGuildCommands(guild: typeof bot.transformers.$inferr
description: command.description,
type: command.type,
options: command.options ? command.options : undefined,
})
});
}
}
if (perGuildCommands.length) {
await bot.helpers.upsertGuildApplicationCommands(guild.id, perGuildCommands)
await bot.helpers.upsertGuildApplicationCommands(guild.id, perGuildCommands);
}
}
export async function getGuildFromId(guildId: bigint) {
const cached = await bot.cache.guilds.get(guildId)
const cached = await bot.cache.guilds.get(guildId);
if (cached) return cached
if (cached) return cached;
return await bot.helpers.getGuild(guildId)
return await bot.helpers.getGuild(guildId);
}
export function humanizeMilliseconds(milliseconds: number): string {
// Gets ms into seconds
const time = milliseconds / 1000
if (time < 1) return '< 1s'
const time = milliseconds / 1000;
if (time < 1) return '< 1s';
const days = Math.floor(time / 86400)
const hours = Math.floor((time % 86400) / 3600)
const minutes = Math.floor(((time % 86400) % 3600) / 60)
const seconds = Math.floor(((time % 86400) % 3600) % 60)
const days = Math.floor(time / 86400);
const hours = Math.floor((time % 86400) / 3600);
const minutes = Math.floor(((time % 86400) % 3600) / 60);
const seconds = Math.floor(((time % 86400) % 3600) % 60);
const dayString = days ? `${days}d ` : ''
const hourString = hours ? `${hours}h ` : ''
const minuteString = minutes ? `${minutes}m ` : ''
const secondString = seconds ? `${seconds}s ` : ''
const dayString = days ? `${days}d ` : '';
const hourString = hours ? `${hours}h ` : '';
const minuteString = minutes ? `${minutes}m ` : '';
const secondString = seconds ? `${seconds}s ` : '';
return `${dayString}${hourString}${minuteString}${secondString}`
return `${dayString}${hourString}${minuteString}${secondString}`;
}
export function isSubCommand(data: SubCommand | SubCommandGroup): data is SubCommand {
return !hasProperty(data, 'subCommands')
return !hasProperty(data, 'subCommands');
}
export function isSubCommandGroup(data: SubCommand | SubCommandGroup): data is SubCommandGroup {
return hasProperty(data, 'subCommands')
return hasProperty(data, 'subCommands');
}
type MakeRequired<TObj, TKey extends keyof TObj> = TObj & {
[Key in TKey]-?: TObj[Key]
}
[Key in TKey]-?: TObj[Key];
};
+5 -5
View File
@@ -1,15 +1,15 @@
import { readdir } from 'node:fs/promises'
import logger from './logger.js'
import { readdir } from 'node:fs/promises';
import logger from './logger.js';
export default async function importDirectory(folder: string): Promise<void> {
const files = await readdir(folder, { recursive: true })
const files = await readdir(folder, { recursive: true });
for (const filename of files) {
if (!filename.endsWith('.js')) continue
if (!filename.endsWith('.js')) continue;
// Using `file://` and `process.cwd()` to avoid weird issues with relative paths and/or Windows
await import(`file://${process.cwd()}/${folder}/${filename}`).catch((x) =>
logger.fatal(`Cannot import file (${folder}/${filename}) for reason:`, x),
)
);
}
}
+31 -31
View File
@@ -1,5 +1,5 @@
/* eslint-disable @typescript-eslint/no-unsafe-argument */
import chalk from 'chalk'
import chalk from 'chalk';
export enum LogLevels {
Debug,
@@ -15,70 +15,70 @@ const prefixes = new Map<LogLevels, string>([
[LogLevels.Warn, 'WARN'],
[LogLevels.Error, 'ERROR'],
[LogLevels.Fatal, 'FATAL'],
])
]);
const noColor: (str: string) => string = (msg) => msg
const noColor: (str: string) => string = (msg) => msg;
const colorFunctions = new Map<LogLevels, (str: string) => string>([
[LogLevels.Debug, chalk.gray],
[LogLevels.Info, chalk.cyan],
[LogLevels.Warn, chalk.yellow],
[LogLevels.Error, (str: string) => chalk.red(str)],
[LogLevels.Fatal, (str: string) => chalk.red.bold.italic(str)],
])
]);
export function createLogger({ logLevel = LogLevels.Info, name }: { logLevel?: LogLevels; name?: string } = {}): Logger {
function log(level: LogLevels, ...args: any[]): void {
if (level < logLevel) return
if (level < logLevel) return;
let color = colorFunctions.get(level)
if (!color) color = noColor
let color = colorFunctions.get(level);
if (!color) color = noColor;
const date = new Date()
const date = new Date();
const log = [
`[${date.toLocaleDateString()} ${date.toLocaleTimeString()}]`,
color(prefixes.get(level) ?? 'DEBUG'),
name ? `${name} >` : '>',
...args,
]
];
switch (level) {
case LogLevels.Debug:
return console.debug(...log)
return console.debug(...log);
case LogLevels.Info:
return console.info(...log)
return console.info(...log);
case LogLevels.Warn:
return console.warn(...log)
return console.warn(...log);
case LogLevels.Error:
return console.error(...log)
return console.error(...log);
case LogLevels.Fatal:
return console.error(...log)
return console.error(...log);
default:
return console.log(...log)
return console.log(...log);
}
}
function setLevel(level: LogLevels): void {
logLevel = level
logLevel = level;
}
function debug(...args: any[]): void {
log(LogLevels.Debug, ...args)
log(LogLevels.Debug, ...args);
}
function info(...args: any[]): void {
log(LogLevels.Info, ...args)
log(LogLevels.Info, ...args);
}
function warn(...args: any[]): void {
log(LogLevels.Warn, ...args)
log(LogLevels.Warn, ...args);
}
function error(...args: any[]): void {
log(LogLevels.Error, ...args)
log(LogLevels.Error, ...args);
}
function fatal(...args: any[]): void {
log(LogLevels.Fatal, ...args)
log(LogLevels.Fatal, ...args);
}
return {
@@ -89,18 +89,18 @@ export function createLogger({ logLevel = LogLevels.Info, name }: { logLevel?: L
warn,
error,
fatal,
}
};
}
export const logger = createLogger({ name: 'Main' })
export default logger
export const logger = createLogger({ name: 'Main' });
export default logger;
export interface Logger {
log: (level: LogLevels, ...args: any[]) => void
debug: (...args: any[]) => void
info: (...args: any[]) => void
warn: (...args: any[]) => void
error: (...args: any[]) => void
fatal: (...args: any[]) => void
setLevel: (level: LogLevels) => void
log: (level: LogLevels, ...args: any[]) => void;
debug: (...args: any[]) => void;
info: (...args: any[]) => void;
warn: (...args: any[]) => void;
error: (...args: any[]) => void;
fatal: (...args: any[]) => void;
setLevel: (level: LogLevels) => void;
}