3 Commits

Author SHA1 Message Date
Kevin Dang
12db36d03b Fix: Ollama offline failsafes trigger 2025-06-19 22:39:15 -07:00
Kevin Dang
48c772df23 Fix: Broken commands 2025-06-19 22:30:57 -07:00
Kevin Dang
9c96978789 Update: discordjs to latest 2025-06-19 22:30:48 -07:00
9 changed files with 47 additions and 43 deletions

36
package-lock.json generated
View File

@@ -9,7 +9,7 @@
"version": "0.8.5", "version": "0.8.5",
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"discord.js": "^14.19.3", "discord.js": "^14.20.0",
"dotenv": "^16.5.0", "dotenv": "^16.5.0",
"ollama": "^0.5.15", "ollama": "^0.5.15",
"redis": "^4.7.0" "redis": "^4.7.0"
@@ -171,9 +171,9 @@
} }
}, },
"node_modules/@discordjs/rest": { "node_modules/@discordjs/rest": {
"version": "2.5.0", "version": "2.5.1",
"resolved": "https://registry.npmjs.org/@discordjs/rest/-/rest-2.5.0.tgz", "resolved": "https://registry.npmjs.org/@discordjs/rest/-/rest-2.5.1.tgz",
"integrity": "sha512-PWhchxTzpn9EV3vvPRpwS0EE2rNYB9pvzDU/eLLW3mByJl0ZHZjHI2/wA8EbH2gRMQV7nu+0FoDF84oiPl8VAQ==", "integrity": "sha512-Tg9840IneBcbrAjcGaQzHUJWFNq1MMWZjTdjJ0WS/89IffaNKc++iOvffucPxQTF/gviO9+9r8kEPea1X5J2Dw==",
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"@discordjs/collection": "^2.1.1", "@discordjs/collection": "^2.1.1",
@@ -184,7 +184,7 @@
"discord-api-types": "^0.38.1", "discord-api-types": "^0.38.1",
"magic-bytes.js": "^1.10.0", "magic-bytes.js": "^1.10.0",
"tslib": "^2.6.3", "tslib": "^2.6.3",
"undici": "6.21.1" "undici": "6.21.3"
}, },
"engines": { "engines": {
"node": ">=18" "node": ">=18"
@@ -218,13 +218,13 @@
} }
}, },
"node_modules/@discordjs/ws": { "node_modules/@discordjs/ws": {
"version": "1.2.2", "version": "1.2.3",
"resolved": "https://registry.npmjs.org/@discordjs/ws/-/ws-1.2.2.tgz", "resolved": "https://registry.npmjs.org/@discordjs/ws/-/ws-1.2.3.tgz",
"integrity": "sha512-dyfq7yn0wO0IYeYOs3z79I6/HumhmKISzFL0Z+007zQJMtAFGtt3AEoq1nuLXtcunUE5YYYQqgKvybXukAK8/w==", "integrity": "sha512-wPlQDxEmlDg5IxhJPuxXr3Vy9AjYq5xCvFWGJyD7w7Np8ZGu+Mc+97LCoEc/+AYCo2IDpKioiH0/c/mj5ZR9Uw==",
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"@discordjs/collection": "^2.1.0", "@discordjs/collection": "^2.1.0",
"@discordjs/rest": "^2.5.0", "@discordjs/rest": "^2.5.1",
"@discordjs/util": "^1.1.0", "@discordjs/util": "^1.1.0",
"@sapphire/async-queue": "^1.5.2", "@sapphire/async-queue": "^1.5.2",
"@types/ws": "^8.5.10", "@types/ws": "^8.5.10",
@@ -1572,24 +1572,24 @@
] ]
}, },
"node_modules/discord.js": { "node_modules/discord.js": {
"version": "14.19.3", "version": "14.20.0",
"resolved": "https://registry.npmjs.org/discord.js/-/discord.js-14.19.3.tgz", "resolved": "https://registry.npmjs.org/discord.js/-/discord.js-14.20.0.tgz",
"integrity": "sha512-lncTRk0k+8Q5D3nThnODBR8fR8x2fM798o8Vsr40Krx0DjPwpZCuxxTcFMrXMQVOqM1QB9wqWgaXPg3TbmlHqA==", "integrity": "sha512-5fRTptK2vpuz+bTuAEUQLSo/3AgCSLHl6Mm9+/ofb+8cbbnjWllhtaqRBq7XcpzlBnfNEugKv8HvCwcOtIHpCg==",
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"@discordjs/builders": "^1.11.2", "@discordjs/builders": "^1.11.2",
"@discordjs/collection": "1.5.3", "@discordjs/collection": "1.5.3",
"@discordjs/formatters": "^0.6.1", "@discordjs/formatters": "^0.6.1",
"@discordjs/rest": "^2.5.0", "@discordjs/rest": "^2.5.1",
"@discordjs/util": "^1.1.1", "@discordjs/util": "^1.1.1",
"@discordjs/ws": "^1.2.2", "@discordjs/ws": "^1.2.3",
"@sapphire/snowflake": "3.5.3", "@sapphire/snowflake": "3.5.3",
"discord-api-types": "^0.38.1", "discord-api-types": "^0.38.1",
"fast-deep-equal": "3.1.3", "fast-deep-equal": "3.1.3",
"lodash.snakecase": "4.1.1", "lodash.snakecase": "4.1.1",
"magic-bytes.js": "^1.10.0", "magic-bytes.js": "^1.10.0",
"tslib": "^2.6.3", "tslib": "^2.6.3",
"undici": "6.21.1" "undici": "6.21.3"
}, },
"engines": { "engines": {
"node": ">=18" "node": ">=18"
@@ -2523,9 +2523,9 @@
} }
}, },
"node_modules/undici": { "node_modules/undici": {
"version": "6.21.1", "version": "6.21.3",
"resolved": "https://registry.npmjs.org/undici/-/undici-6.21.1.tgz", "resolved": "https://registry.npmjs.org/undici/-/undici-6.21.3.tgz",
"integrity": "sha512-q/1rj5D0/zayJB2FraXdaWxbhWiNKDvu8naDT2dl1yTlvJp4BLtOcp2a5BvgGNQpYYJzau7tf1WgKv3b+7mqpQ==", "integrity": "sha512-gBLkYIlEnSp8pFbT64yFgGE6UIB9tAkhukC23PmMDCe5Nd+cRqKxSjw5y54MK2AZMgZfJWMaNE4nYUHgi1XEOw==",
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">=18.17" "node": ">=18.17"

View File

@@ -27,7 +27,7 @@
"author": "Kevin Dang", "author": "Kevin Dang",
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"discord.js": "^14.19.3", "discord.js": "^14.20.0",
"dotenv": "^16.5.0", "dotenv": "^16.5.0",
"ollama": "^0.5.15", "ollama": "^0.5.15",
"redis": "^4.7.0" "redis": "^4.7.0"

View File

@@ -1,4 +1,4 @@
import { Client, CommandInteraction, ApplicationCommandOptionType, MessageFlags } from 'discord.js' import { Client, ChatInputCommandInteraction, ApplicationCommandOptionType, MessageFlags } from 'discord.js'
import { openConfig, SlashCommand, UserCommand } from '../utils/index.js' import { openConfig, SlashCommand, UserCommand } from '../utils/index.js'
export const Capacity: SlashCommand = { export const Capacity: SlashCommand = {
@@ -16,14 +16,14 @@ export const Capacity: SlashCommand = {
], ],
// Query for message information and set the style // Query for message information and set the style
run: async (client: Client, interaction: CommandInteraction) => { run: async (client: Client, interaction: ChatInputCommandInteraction) => {
// fetch channel and message // fetch channel and message
const channel = await client.channels.fetch(interaction.channelId) const channel = await client.channels.fetch(interaction.channelId)
if (!channel || !UserCommand.includes(channel.type)) return if (!channel || !UserCommand.includes(channel.type)) return
// set state of bot chat features // set state of bot chat features
openConfig(`${interaction.user.username}-config.json`, interaction.commandName, openConfig(`${interaction.user.username}-config.json`, interaction.commandName,
interaction.options.get('context-capacity')?.value interaction.options.getNumber('context-capacity')
) )
interaction.reply({ interaction.reply({

View File

@@ -1,4 +1,4 @@
import { ApplicationCommandOptionType, Client, CommandInteraction, MessageFlags } from 'discord.js' import { ApplicationCommandOptionType, ChatInputCommandInteraction, Client, CommandInteraction, MessageFlags } from 'discord.js'
import { UserCommand, SlashCommand } from '../utils/index.js' import { UserCommand, SlashCommand } from '../utils/index.js'
import { ollama } from '../client.js' import { ollama } from '../client.js'
import { ModelResponse } from 'ollama' import { ModelResponse } from 'ollama'
@@ -18,10 +18,11 @@ export const DeleteModel: SlashCommand = {
], ],
// Delete Model locally stored // Delete Model locally stored
run: async (client: Client, interaction: CommandInteraction) => { run: async (client: Client, interaction: ChatInputCommandInteraction) => {
// defer reply to avoid timeout // defer reply to avoid timeout
await interaction.deferReply() await interaction.deferReply()
const modelInput: string = interaction.options.get('model-name')!!.value as string const modelInput: string = interaction.options.getString('model-name') as string
let ollamaOffline: boolean = false
// fetch channel and message // fetch channel and message
const channel = await client.channels.fetch(interaction.channelId) const channel = await client.channels.fetch(interaction.channelId)
@@ -40,11 +41,12 @@ export const DeleteModel: SlashCommand = {
const modelExists = await ollama.list() const modelExists = await ollama.list()
.then(response => response.models.some((model: ModelResponse) => model.name.startsWith(modelInput))) .then(response => response.models.some((model: ModelResponse) => model.name.startsWith(modelInput)))
.catch(error => { .catch(error => {
ollamaOffline = true
console.error(`[Command: delete-model] Failed to connect with Ollama service. Error: ${error.message}`) console.error(`[Command: delete-model] Failed to connect with Ollama service. Error: ${error.message}`)
}) })
// Validate for any issue or if service is running // Validate for any issue or if service is running
if (!modelExists) { if (ollamaOffline) {
interaction.editReply({ interaction.editReply({
content: `The Ollama service is not running. Please turn on/download the [service](https://ollama.com/).` content: `The Ollama service is not running. Please turn on/download the [service](https://ollama.com/).`
}) })

View File

@@ -1,4 +1,4 @@
import { Client, CommandInteraction, ApplicationCommandOptionType, MessageFlags } from 'discord.js' import { Client, ChatInputCommandInteraction, ApplicationCommandOptionType, MessageFlags } from 'discord.js'
import { AdminCommand, openConfig, SlashCommand } from '../utils/index.js' import { AdminCommand, openConfig, SlashCommand } from '../utils/index.js'
export const Disable: SlashCommand = { export const Disable: SlashCommand = {
@@ -16,7 +16,7 @@ export const Disable: SlashCommand = {
], ],
// Query for message information and set the style // Query for message information and set the style
run: async (client: Client, interaction: CommandInteraction) => { run: async (client: Client, interaction: ChatInputCommandInteraction) => {
// fetch channel and message // fetch channel and message
const channel = await client.channels.fetch(interaction.channelId) const channel = await client.channels.fetch(interaction.channelId)
if (!channel || !AdminCommand.includes(channel.type)) return if (!channel || !AdminCommand.includes(channel.type)) return
@@ -32,11 +32,11 @@ export const Disable: SlashCommand = {
// set state of bot chat features // set state of bot chat features
openConfig(`${interaction.guildId}-config.json`, interaction.commandName, openConfig(`${interaction.guildId}-config.json`, interaction.commandName,
interaction.options.get('enabled')?.value interaction.options.getBoolean('enabled')
) )
interaction.reply({ interaction.reply({
content: `${client.user?.username} is now **${interaction.options.get('enabled')?.value ? "enabled" : "disabled"}**.`, content: `${client.user?.username} is now **${interaction.options.getBoolean('enabled') ? "enabled" : "disabled"}**.`,
flags: MessageFlags.Ephemeral flags: MessageFlags.Ephemeral
}) })
} }

View File

@@ -1,4 +1,4 @@
import { ApplicationCommandOptionType, Client, CommandInteraction, MessageFlags } from 'discord.js' import { ApplicationCommandOptionType, Client, ChatInputCommandInteraction, MessageFlags } from 'discord.js'
import { openConfig, SlashCommand, UserCommand } from '../utils/index.js' import { openConfig, SlashCommand, UserCommand } from '../utils/index.js'
export const MessageStream: SlashCommand = { export const MessageStream: SlashCommand = {
@@ -16,18 +16,18 @@ export const MessageStream: SlashCommand = {
], ],
// change preferences based on command // change preferences based on command
run: async (client: Client, interaction: CommandInteraction) => { run: async (client: Client, interaction: ChatInputCommandInteraction) => {
// verify channel // verify channel
const channel = await client.channels.fetch(interaction.channelId) const channel = await client.channels.fetch(interaction.channelId)
if (!channel || !UserCommand.includes(channel.type)) return if (!channel || !UserCommand.includes(channel.type)) return
// save value to json and write to it // save value to json and write to it
openConfig(`${interaction.user.username}-config.json`, interaction.commandName, openConfig(`${interaction.user.username}-config.json`, interaction.commandName,
interaction.options.get('stream')?.value interaction.options.getBoolean('stream')
) )
interaction.reply({ interaction.reply({
content: `Message streaming is now set to: \`${interaction.options.get('stream')?.value}\``, content: `Message streaming is now set to: \`${interaction.options.getBoolean('stream')}\``,
flags: MessageFlags.Ephemeral flags: MessageFlags.Ephemeral
}) })
} }

View File

@@ -1,4 +1,4 @@
import { ApplicationCommandOptionType, Client, CommandInteraction, MessageFlags } from "discord.js" import { ApplicationCommandOptionType, Client, ChatInputCommandInteraction, MessageFlags } from "discord.js"
import { ollama } from "../client.js" import { ollama } from "../client.js"
import { ModelResponse } from "ollama" import { ModelResponse } from "ollama"
import { UserCommand, SlashCommand } from "../utils/index.js" import { UserCommand, SlashCommand } from "../utils/index.js"
@@ -18,10 +18,11 @@ export const PullModel: SlashCommand = {
], ],
// Pull for model from Ollama library // Pull for model from Ollama library
run: async (client: Client, interaction: CommandInteraction) => { run: async (client: Client, interaction: ChatInputCommandInteraction) => {
// defer reply to avoid timeout // defer reply to avoid timeout
await interaction.deferReply() await interaction.deferReply()
const modelInput: string = interaction.options.get('model-to-pull')!!.value as string const modelInput: string = interaction.options.getString('model-to-pull') as string
let ollamaOffline: boolean = false
// fetch channel and message // fetch channel and message
const channel = await client.channels.fetch(interaction.channelId) const channel = await client.channels.fetch(interaction.channelId)
@@ -40,11 +41,12 @@ export const PullModel: SlashCommand = {
const modelExists = await ollama.list() const modelExists = await ollama.list()
.then(response => response.models.some((model: ModelResponse) => model.name.startsWith(modelInput))) .then(response => response.models.some((model: ModelResponse) => model.name.startsWith(modelInput)))
.catch(error => { .catch(error => {
ollamaOffline = true
console.error(`[Command: pull-model] Failed to connect with Ollama service. Error: ${error.message}`) console.error(`[Command: pull-model] Failed to connect with Ollama service. Error: ${error.message}`)
}) })
// Validate for any issue or if service is running // Validate for any issue or if service is running
if (!modelExists) { if (ollamaOffline) {
interaction.editReply({ interaction.editReply({
content: `The Ollama service is not running. Please turn on/download the [service](https://ollama.com/).` content: `The Ollama service is not running. Please turn on/download the [service](https://ollama.com/).`
}) })

View File

@@ -1,4 +1,4 @@
import { ApplicationCommandOptionType, Client, CommandInteraction } from "discord.js" import { ApplicationCommandOptionType, Client, ChatInputCommandInteraction } from "discord.js"
import { ollama } from "../client.js" import { ollama } from "../client.js"
import { ModelResponse } from "ollama" import { ModelResponse } from "ollama"
import { openConfig, UserCommand, SlashCommand } from "../utils/index.js" import { openConfig, UserCommand, SlashCommand } from "../utils/index.js"
@@ -18,10 +18,10 @@ export const SwitchModel: SlashCommand = {
], ],
// Switch user preferred model if available in local library // Switch user preferred model if available in local library
run: async (client: Client, interaction: CommandInteraction) => { run: async (client: Client, interaction: ChatInputCommandInteraction) => {
await interaction.deferReply() await interaction.deferReply()
const modelInput: string = interaction.options.get('model-to-use')!!.value as string const modelInput: string = interaction.options.getString('model-to-use') as string
// fetch channel and message // fetch channel and message
const channel = await client.channels.fetch(interaction.channelId) const channel = await client.channels.fetch(interaction.channelId)

View File

@@ -1,4 +1,4 @@
import { CommandInteraction, ChatInputApplicationCommandData, Client, ApplicationCommandOption } from 'discord.js' import { ChatInputCommandInteraction, ChatInputApplicationCommandData, Client, ApplicationCommandOption } from 'discord.js'
/** /**
* interface for how slash commands should be run * interface for how slash commands should be run
@@ -6,7 +6,7 @@ import { CommandInteraction, ChatInputApplicationCommandData, Client, Applicatio
export interface SlashCommand extends ChatInputApplicationCommandData { export interface SlashCommand extends ChatInputApplicationCommandData {
run: ( run: (
client: Client, client: Client,
interaction: CommandInteraction, interaction: ChatInputCommandInteraction,
options?: ApplicationCommandOption[] options?: ApplicationCommandOption[]
) => void ) => void
} }