From 33152b33f3e964edc77b90796679f4a66a1142de Mon Sep 17 00:00:00 2001 From: Kevin Dang <77701718+kevinthedang@users.noreply.github.com> Date: Fri, 8 Nov 2024 20:09:01 -0800 Subject: [PATCH] Pull/Switch Model Commands Fix (#137) * Update: Channel checker and channel name gone * Add: note of where problem can be * Update: Check if model already exists for Pull Command * Add: User/Admin Command Constants * Update: version increment --- docker-compose.yml | 2 +- package-lock.json | 4 ++-- package.json | 2 +- src/commands/capacity.ts | 6 ++--- src/commands/cleanUserChannelHistory.ts | 12 +++++----- src/commands/disable.ts | 4 ++-- src/commands/messageStream.ts | 6 ++--- src/commands/messageStyle.ts | 6 ++--- src/commands/pullModel.ts | 28 ++++++++++++++++-------- src/commands/shutoff.ts | 5 +++-- src/commands/switchModel.ts | 7 +++--- src/commands/threadCreate.ts | 4 ++-- src/commands/threadPrivateCreate.ts | 4 ++-- src/utils/configInterfaces.ts | 16 ++++++++++++++ src/utils/handlers/chatHistoryHandler.ts | 1 - 15 files changed, 67 insertions(+), 40 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index ac29be0..b104062 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -7,7 +7,7 @@ services: build: ./ # find docker file in designated path container_name: discord restart: always # rebuild container always - image: kevinthedang/discord-ollama:0.7.1 + image: kevinthedang/discord-ollama:0.7.2 environment: CLIENT_TOKEN: ${CLIENT_TOKEN} OLLAMA_IP: ${OLLAMA_IP} diff --git a/package-lock.json b/package-lock.json index 3ed2c87..4292283 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "discord-ollama", - "version": "0.7.1", + "version": "0.7.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "discord-ollama", - "version": "0.7.1", + "version": "0.7.2", "license": "ISC", "dependencies": { "discord.js": "^14.16.3", diff --git a/package.json b/package.json index f65c24e..4338419 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "discord-ollama", - "version": "0.7.1", + "version": "0.7.2", "description": "Ollama Integration into discord", "main": "build/index.js", "exports": "./build/index.js", diff --git a/src/commands/capacity.ts b/src/commands/capacity.ts index 7420740..5de3033 100644 --- a/src/commands/capacity.ts +++ b/src/commands/capacity.ts @@ -1,5 +1,5 @@ -import { ChannelType, Client, CommandInteraction, ApplicationCommandOptionType } from 'discord.js' -import { openConfig, SlashCommand } from '../utils/index.js' +import { Client, CommandInteraction, ApplicationCommandOptionType } from 'discord.js' +import { openConfig, SlashCommand, UserCommand } from '../utils/index.js' export const Capacity: SlashCommand = { name: 'modify-capacity', @@ -19,7 +19,7 @@ export const Capacity: SlashCommand = { run: async (client: Client, interaction: CommandInteraction) => { // fetch channel and message const channel = await client.channels.fetch(interaction.channelId) - if (!channel || channel.type !== (ChannelType.PrivateThread && ChannelType.PublicThread && ChannelType.GuildText)) return + if (!channel || !UserCommand.includes(channel.type)) return // set state of bot chat features openConfig(`${interaction.user.username}-config.json`, interaction.commandName, interaction.options.get('context-capacity')?.value) diff --git a/src/commands/cleanUserChannelHistory.ts b/src/commands/cleanUserChannelHistory.ts index c227294..c388b97 100644 --- a/src/commands/cleanUserChannelHistory.ts +++ b/src/commands/cleanUserChannelHistory.ts @@ -1,5 +1,5 @@ -import { ChannelType, Client, CommandInteraction, TextChannel } from 'discord.js' -import { clearChannelInfo, SlashCommand } from '../utils/index.js' +import { Channel, Client, CommandInteraction, TextChannel } from 'discord.js' +import { clearChannelInfo, SlashCommand, UserCommand } from '../utils/index.js' export const ClearUserChannelHistory: SlashCommand = { name: 'clear-user-channel-history', @@ -8,10 +8,10 @@ export const ClearUserChannelHistory: SlashCommand = { // Clear channel history for intended user run: async (client: Client, interaction: CommandInteraction) => { // fetch current channel - const channel = await client.channels.fetch(interaction.channelId) + const channel: Channel | null = await client.channels.fetch(interaction.channelId) // if not an existing channel or a GuildText, fail command - if (!channel || channel.type !== ChannelType.GuildText) return + if (!channel || !UserCommand.includes(channel.type)) return // clear channel info for user const successfulWipe = await clearChannelInfo(interaction.channelId, @@ -21,12 +21,12 @@ export const ClearUserChannelHistory: SlashCommand = { // check result of clearing history if (successfulWipe) interaction.reply({ - content: `Channel history in **${channel.name}** cleared for **${interaction.user.username}**.`, + content: `Channel history in **this channel** successfully cleared for **${interaction.user.username}**.`, ephemeral: true }) else interaction.reply({ - content: `Channel history could not be found for **${interaction.user.username}** in **${channel.name}**.\n\nPlease chat with **${client.user?.username}** to start a chat history.`, + content: `Channel history could not be found for **${interaction.user.username}** in **this channel**.\n\nPlease chat with **${client.user?.username}** to start a chat history.`, ephemeral: true }) } diff --git a/src/commands/disable.ts b/src/commands/disable.ts index e6180e2..1081843 100644 --- a/src/commands/disable.ts +++ b/src/commands/disable.ts @@ -1,5 +1,5 @@ import { ChannelType, Client, CommandInteraction, ApplicationCommandOptionType } from 'discord.js' -import { openConfig, SlashCommand } from '../utils/index.js' +import { AdminCommand, openConfig, SlashCommand } from '../utils/index.js' export const Disable: SlashCommand = { name: 'toggle-chat', @@ -19,7 +19,7 @@ export const Disable: SlashCommand = { run: async (client: Client, interaction: CommandInteraction) => { // fetch channel and message const channel = await client.channels.fetch(interaction.channelId) - if (!channel || channel.type !== ChannelType.GuildText) return + if (!channel || !AdminCommand.includes(channel.type)) return // check if runner is an admin if (!interaction.memberPermissions?.has('Administrator')) { diff --git a/src/commands/messageStream.ts b/src/commands/messageStream.ts index 549ac98..ede7fd6 100644 --- a/src/commands/messageStream.ts +++ b/src/commands/messageStream.ts @@ -1,5 +1,5 @@ -import { ApplicationCommandOptionType, ChannelType, Client, CommandInteraction } from 'discord.js' -import { openConfig, SlashCommand } from '../utils/index.js' +import { ApplicationCommandOptionType, Client, CommandInteraction } from 'discord.js' +import { openConfig, SlashCommand, UserCommand } from '../utils/index.js' export const MessageStream: SlashCommand = { name: 'message-stream', @@ -19,7 +19,7 @@ export const MessageStream: SlashCommand = { run: async (client: Client, interaction: CommandInteraction) => { // verify channel const channel = await client.channels.fetch(interaction.channelId) - if (!channel || channel.type !== (ChannelType.PrivateThread && ChannelType.PublicThread && ChannelType.GuildText)) return + if (!channel || !UserCommand.includes(channel.type)) return // save value to json and write to it openConfig(`${interaction.user.username}-config.json`, interaction.commandName, interaction.options.get('stream')?.value) diff --git a/src/commands/messageStyle.ts b/src/commands/messageStyle.ts index bfb20a7..955dcd2 100644 --- a/src/commands/messageStyle.ts +++ b/src/commands/messageStyle.ts @@ -1,5 +1,5 @@ -import { ChannelType, Client, CommandInteraction, ApplicationCommandOptionType } from 'discord.js' -import { openConfig, SlashCommand } from '../utils/index.js' +import { Client, CommandInteraction, ApplicationCommandOptionType } from 'discord.js' +import { openConfig, SlashCommand, UserCommand } from '../utils/index.js' export const MessageStyle: SlashCommand = { name: 'message-style', @@ -19,7 +19,7 @@ export const MessageStyle: SlashCommand = { run: async (client: Client, interaction: CommandInteraction) => { // fetch channel and message const channel = await client.channels.fetch(interaction.channelId) - if (!channel || channel.type !== (ChannelType.PrivateThread && ChannelType.PublicThread && ChannelType.GuildText)) return + if (!channel || !UserCommand.includes(channel.type)) return // set the message style openConfig(`${interaction.user.username}-config.json`, interaction.commandName, interaction.options.get('embed')?.value) diff --git a/src/commands/pullModel.ts b/src/commands/pullModel.ts index 64bd6bd..8b8b88f 100644 --- a/src/commands/pullModel.ts +++ b/src/commands/pullModel.ts @@ -1,6 +1,8 @@ -import { ApplicationCommandOptionType, ChannelType, Client, CommandInteraction } from "discord.js"; +import { ApplicationCommandOptionType, Client, CommandInteraction } from "discord.js"; import { SlashCommand } from "../utils/commands.js"; import { ollama } from "../client.js"; +import { ModelResponse } from "ollama"; +import { UserCommand } from "../utils/index.js"; export const PullModel: SlashCommand = { name: 'pull-model', @@ -24,13 +26,16 @@ export const PullModel: SlashCommand = { // fetch channel and message const channel = await client.channels.fetch(interaction.channelId) - if (!channel || channel.type !== (ChannelType.PrivateThread && ChannelType.PublicThread && ChannelType.GuildText)) return + if (!channel || !UserCommand.includes(channel.type)) return + + // check if model was already pulled + const modelExists: boolean = await ollama.list() + .then(response => response.models.some((model: ModelResponse) => model.name.startsWith(modelInput))) try { // call ollama to pull desired model - await ollama.pull({ - model: modelInput - }) + if (!modelExists) + await ollama.pull({ model: modelInput }) } catch (error) { // could not resolve pull or model unfound interaction.editReply({ @@ -39,9 +44,14 @@ export const PullModel: SlashCommand = { return } - // successful pull - interaction.editReply({ - content: `Successfully added **${modelInput}** into your local model library.` - }) + // successful interaction + if (modelExists) + interaction.editReply({ + content: `**${modelInput}** is already in your local model library.` + }) + else + interaction.editReply({ + content: `Successfully added **${modelInput}** into your local model library.` + }) } } \ No newline at end of file diff --git a/src/commands/shutoff.ts b/src/commands/shutoff.ts index b3ab5f1..83ba3ba 100644 --- a/src/commands/shutoff.ts +++ b/src/commands/shutoff.ts @@ -1,5 +1,6 @@ -import { ChannelType, Client, CommandInteraction, ApplicationCommandOptionType } from 'discord.js' +import { Client, CommandInteraction, ApplicationCommandOptionType } from 'discord.js' import { SlashCommand } from '../utils/commands.js' +import { AdminCommand } from '../utils/index.js' export const Shutoff: SlashCommand = { name: 'shutoff', @@ -19,7 +20,7 @@ export const Shutoff: SlashCommand = { run: async (client: Client, interaction: CommandInteraction) => { // fetch channel and message const channel = await client.channels.fetch(interaction.channelId) - if (!channel || channel.type !== ChannelType.GuildText) return + if (!channel || !AdminCommand.includes(channel.type)) return // log this, this will probably be improtant for logging who did this console.log(`User -> ${interaction.user.tag} attempting to shutdown ${client.user!!.tag}`) diff --git a/src/commands/switchModel.ts b/src/commands/switchModel.ts index 217d595..82163e7 100644 --- a/src/commands/switchModel.ts +++ b/src/commands/switchModel.ts @@ -1,8 +1,8 @@ -import { ApplicationCommandOptionType, ChannelType, Client, CommandInteraction } from "discord.js"; +import { ApplicationCommandOptionType, Client, CommandInteraction } from "discord.js"; import { SlashCommand } from "../utils/commands.js"; import { ollama } from "../client.js"; import { ModelResponse } from "ollama"; -import { openConfig } from "../utils/index.js"; +import { openConfig, UserCommand } from "../utils/index.js"; export const SwitchModel: SlashCommand = { name: 'switch-model', @@ -26,7 +26,7 @@ export const SwitchModel: SlashCommand = { // fetch channel and message const channel = await client.channels.fetch(interaction.channelId) - if (!channel || channel.type !== (ChannelType.PrivateThread && ChannelType.PublicThread && ChannelType.GuildText)) return + if (!channel || !UserCommand.includes(channel.type)) return try { // Phase 1: Set the model @@ -46,6 +46,7 @@ export const SwitchModel: SlashCommand = { } } }) + // todo: problem can be here if async messes up if (switchSuccess) return // Phase 2: Try to get it regardless diff --git a/src/commands/threadCreate.ts b/src/commands/threadCreate.ts index 0d34b9d..c00c390 100644 --- a/src/commands/threadCreate.ts +++ b/src/commands/threadCreate.ts @@ -1,5 +1,5 @@ import { ChannelType, Client, CommandInteraction, TextChannel, ThreadChannel } from 'discord.js' -import { openChannelInfo, SlashCommand } from '../utils/index.js' +import { AdminCommand, openChannelInfo, SlashCommand } from '../utils/index.js' export const ThreadCreate: SlashCommand = { name: 'thread', @@ -9,7 +9,7 @@ export const ThreadCreate: SlashCommand = { run: async (client: Client, interaction: CommandInteraction) => { // fetch the channel const channel = await client.channels.fetch(interaction.channelId) - if (!channel || channel.type !== ChannelType.GuildText) return + if (!channel || !AdminCommand.includes(channel.type)) return const thread = await (channel as TextChannel).threads.create({ name: `${client.user?.username}-support-${Date.now()}`, diff --git a/src/commands/threadPrivateCreate.ts b/src/commands/threadPrivateCreate.ts index 222abda..cd2dc24 100644 --- a/src/commands/threadPrivateCreate.ts +++ b/src/commands/threadPrivateCreate.ts @@ -1,5 +1,5 @@ import { ChannelType, Client, CommandInteraction, TextChannel, ThreadChannel } from 'discord.js' -import { openChannelInfo, SlashCommand } from '../utils/index.js' +import { AdminCommand, openChannelInfo, SlashCommand } from '../utils/index.js' export const PrivateThreadCreate: SlashCommand = { name: 'private-thread', @@ -9,7 +9,7 @@ export const PrivateThreadCreate: SlashCommand = { run: async (client: Client, interaction: CommandInteraction) => { // fetch the channel const channel = await client.channels.fetch(interaction.channelId) - if (!channel || channel.type !== ChannelType.GuildText) return + if (!channel || !AdminCommand.includes(channel.type)) return const thread = await (channel as TextChannel).threads.create({ name: `${client.user?.username}-private-support-${Date.now()}`, diff --git a/src/utils/configInterfaces.ts b/src/utils/configInterfaces.ts index b5985f2..2eca167 100644 --- a/src/utils/configInterfaces.ts +++ b/src/utils/configInterfaces.ts @@ -1,3 +1,4 @@ +import { ChannelType } from 'discord.js' import { UserMessage } from './index.js' export interface UserConfiguration { @@ -42,6 +43,21 @@ export interface Channel { messages: UserMessage[] } +/** + * The following 2 types is allow for better readability in commands + * Admin Command -> Don't run in Threads + * User Command -> Used anywhere + */ +export const AdminCommand = [ + ChannelType.GuildText +] + +export const UserCommand = [ + ChannelType.GuildText, + ChannelType.PublicThread, + ChannelType.PrivateThread +] + /** * Check if the configuration we are editing/taking from is a Server Config * @param key name of command we ran diff --git a/src/utils/handlers/chatHistoryHandler.ts b/src/utils/handlers/chatHistoryHandler.ts index 80bbb4e..8895739 100644 --- a/src/utils/handlers/chatHistoryHandler.ts +++ b/src/utils/handlers/chatHistoryHandler.ts @@ -53,7 +53,6 @@ export async function clearChannelInfo(filename: string, channel: TextChannel, u } }) }) - console.log(cleanedHistory) return cleanedHistory }