diff --git a/.eslintrc.json b/.eslintrc.json index 3e77cbe..88c772c 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -1,8 +1,15 @@ { - "extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended"], + "extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended-type-checked"], "parser": "@typescript-eslint/parser", + "parserOptions": { + "project": "./tsconfig.json" + }, "rules": { + "@typescript-eslint/no-floating-promises": "warn", + "@typescript-eslint/no-unsafe-declaration-merging": "warn", "@typescript-eslint/semi": ["error", "always"], - "eol-last": ["error", "always"] + "semi": "off", + "eol-last": ["error", "always"], + "eqeqeq": ["error", "always"] } } diff --git a/src/commands/summon.ts b/src/commands/summon.ts index 0ce7407..6138005 100644 --- a/src/commands/summon.ts +++ b/src/commands/summon.ts @@ -10,7 +10,7 @@ export default class Summon extends Command { type = ApplicationCommandType.ChatInput; dm_permission = false; - async execute(interaction: ChatInputCommandInteraction) { - queueRequest(interaction); + execute(interaction: ChatInputCommandInteraction) { + return queueRequest(interaction); } } diff --git a/src/execution.ts b/src/execution.ts index 99acd35..0560417 100644 --- a/src/execution.ts +++ b/src/execution.ts @@ -134,9 +134,9 @@ function canReplyToRequest(request: apiRequest) { export async function queueRequest(request: apiRequest) { if (!request.channelId) { if (request instanceof DiscordApi.Message) - request.reply("request does not have channelId"); + await request.reply("request does not have channelId"); else if (request.isRepliable()) - request.reply("request does not have channelId"); + await request.reply("request does not have channelId"); console.log("There was incoming execution without channelId set, ignoring"); console.log(request); return; @@ -148,7 +148,7 @@ export async function queueRequest(request: apiRequest) { if (userLimit !== false && userLimit.remaining <= 0) { if (request instanceof DiscordApi.Message) { - request.react("🛑").catch(/*it's okay*/); + request.react("🛑").catch(() => { /* NOTE: We send an informaton about limit reached in DM */ }); if (!request.author.dmChannel) await request.author.createDM(); request.author.dmChannel?.send({ embeds: [{ @@ -157,13 +157,13 @@ export async function queueRequest(request: apiRequest) { "You've used up your message limit for today,\n" + `${userLimit.limit} requests in last 24 hours`, }] - }); + }).catch(() => {/* GRACEFAIL: */}); } else if (request.isRepliable()) { request.reply({ content: `You've used up your message limit for today, ${userLimit.limit} requests in last 24 hours`, ephemeral: true, - }); + }).catch(() => { /* Impossible to get there unless connection lost*/ }); } return; } @@ -172,7 +172,7 @@ export async function queueRequest(request: apiRequest) { request.channelId, () => { return []; }, ); - const shouldStart = messagesForChannel.length == 0; + const shouldStart = messagesForChannel.length === 0; messagesForChannel.push(request as request); if (shouldStart) executeFromQueue(request.channelId); @@ -191,7 +191,7 @@ function logUsedTokens( ) { const usage = answer.data.usage; const functionName = answer.data.choices[0].message?.function_call?.name; - if (usage != undefined) { + if (usage !== undefined) { const channelName: string = !message.channel.isDMBased() ? `${message.channel.name} (${message.guild?.name})` : `@${getAuthor(message).tag}`; console.log(`Used ${usage.total_tokens} (${usage.prompt_tokens} + ${usage.completion_tokens}) tokens for ${getAuthor(message).tag} (${getAuthor(message).id}) in #${channelName}${functionName ? " [Function: " + functionName + "]" : ""}`); @@ -231,7 +231,7 @@ async function executeFromQueue(channel: string) { messages = messages.filter(m => message.createdTimestamp - m.createdTimestamp < config.limits.time ); - messages.forEach(m => Moderation.checkMessage(m)); + messages.forEach(m => { Moderation.checkMessage(m); }); if (message instanceof DiscordApi.Message) { message.channel.sendTyping(); @@ -269,7 +269,7 @@ async function executeFromQueue(channel: string) { const answerContent = answer.data.choices[0].message?.content; - if (answerContent == undefined || answerContent == "") { + if (answerContent === undefined || answerContent === "") { if (message instanceof DiscordApi.Message) message.react("😶").catch(/*it's okay*/); } else { @@ -293,7 +293,7 @@ async function executeFromQueue(channel: string) { } catch (e) { console.error(`Error ocurred while handling chat completion request (${(e as object).constructor.name}):`); console.error(e); - if (OpenAImessages.length != 0) { + if (OpenAImessages.length !== 0) { console.error("Messages:"); console.error(OpenAImessages); } @@ -319,7 +319,7 @@ async function executeFromQueue(channel: string) { } channelQueue.shift(); - if (channelQueue.length == 0) + if (channelQueue.length === 0) channelsRunning.delete(channel); else executeFromQueue(channel); diff --git a/src/funcitonManager.ts b/src/funcitonManager.ts index 4a0910e..5168328 100644 --- a/src/funcitonManager.ts +++ b/src/funcitonManager.ts @@ -76,15 +76,18 @@ export default class FunctionManager { } try { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment parsedArguments = JSON.parse(request.arguments ?? ""); } catch (e) { console.error("Function arguments raw: " + request.arguments); throw new Error(`Failed to parse the function JSON arguments when running function [${request.name}]`, {cause: e}); } + // FIXME: Verify if the parsedArguments matches the requested function argument declaration. return { role: "function", name: request.name, + // eslint-disable-next-line @typescript-eslint/no-unsafe-argument content: functionToRun.execute(parsedArguments), }; } diff --git a/src/index.ts b/src/index.ts index dbfa66d..bc732ba 100644 --- a/src/index.ts +++ b/src/index.ts @@ -23,11 +23,11 @@ export const database = new PrismaClient(); const interactionManager = new InteractionManager(); interactionManager.bindClient(discord); -discord.on("ready", async event => { +discord.on("ready", event => { console.log(`Connected to Discord as ${event.user.tag} (${event.user.id})`); }); -discord.on("messageCreate", async message => { +discord.on("messageCreate", message => { if (message.author.bot) return; if (!message.mentions.has(message.client.user)) return; diff --git a/src/interactionManager.ts b/src/interactionManager.ts index d6ef69a..df7895b 100644 --- a/src/interactionManager.ts +++ b/src/interactionManager.ts @@ -12,6 +12,7 @@ export default class CommandManager { try { // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore + // eslint-disable-next-line @typescript-eslint/no-unsafe-argument this.commands.push(new (files[i].default as Command)()); } catch (e) { @@ -27,13 +28,13 @@ export default class CommandManager { interaction.isMessageContextMenuCommand() || interaction.isUserContextMenuCommand() ) { - const foundCommand = this.commands.find((command) => command.name == interaction.commandName ); + const foundCommand = this.commands.find((command) => command.name === interaction.commandName ); if (!foundCommand) throw new Error(`Unknown command received (${interaction.commandName}). Did you forgot to push updated commands?`); foundCommand.execute(interaction); return; } if (interaction.isAutocomplete()) { - const foundCommand = this.commands.find((command) => command.name == interaction.commandName ); + const foundCommand = this.commands.find((command) => command.name === interaction.commandName ); if (!foundCommand) throw new Error(`Unknown command received (${interaction.commandName}). Did you forgot to push updated commands?`); if (!foundCommand.autocomplete) return; foundCommand.autocomplete(interaction); diff --git a/src/moderation.ts b/src/moderation.ts index 2e84d09..038c046 100644 --- a/src/moderation.ts +++ b/src/moderation.ts @@ -31,11 +31,11 @@ export default class Moderation { const flagged = answer.data.results[0].flagged; this.cache.set(message.id, flagged); if (flagged) if (message instanceof Message) { - message.react("⚠"); + message.react("⚠").catch(() => { /* GRACEFAIL: We don't inform the enduser then */ }); } else { const channelMessage = await message.fetch(); - channelMessage.react("⚠"); + channelMessage.react("⚠").catch(() => { /* GRACEFAIL: We don't inform the enduser then */ }); } return flagged; diff --git a/src/scripts/pushCommands.ts b/src/scripts/pushCommands.ts index e06cf18..ecd03f3 100644 --- a/src/scripts/pushCommands.ts +++ b/src/scripts/pushCommands.ts @@ -14,6 +14,7 @@ requireDirectory<{default: Command}, void>(module, "../commands", { console.log(obj); // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore + // eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call post.push(new obj.default().toRESTPostApplicationCommands()); }, }); @@ -22,7 +23,7 @@ const rest = new REST().setToken(config.tokens.Discord); (async () => { const me = await rest.get(Routes.oauth2CurrentApplication()) as RESTGetAPIOAuth2CurrentApplicationResult; - if (guildId && guildId != "") { + if (guildId && guildId !== "") { console.log(`Started refreshing ${post.length} application guild (${guildId}) commands.`); await rest.put( Routes.applicationGuildCommands(me.id, guildId), diff --git a/src/toOpenAIMessages.ts b/src/toOpenAIMessages.ts index b1a432d..0d5e1c2 100644 --- a/src/toOpenAIMessages.ts +++ b/src/toOpenAIMessages.ts @@ -108,7 +108,7 @@ export default function toOpenAIMessages(messages: Collection config.limits.tokens) break; rvalue.push({ - role: message.author.id == message.client.user.id ? "assistant" : "user", + role: message.author.id === message.client.user.id ? "assistant" : "user", content: content, name: getAuthorUsername(message), });