diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index c023cd4..da731d7 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -1,31 +1,38 @@ + +## Naming Conventions +* Branches + * prefix your branch name with the type of contribution: + * features: `'feature/**'` + * releases: `'releases/**'` + * bugs: `'bug/**'` + ## Run the Bot * Refer to all sections below before running the bot. * You should now have `Ollama`, `NodeJS`, ran `npm install`. * You will also need a discord bot to run. Refer to the [developer portal](https://discord.com/developers/) to learn how to set one up and invite it to your server. If that does not help then look up a YouTube video like this [one](https://www.youtube.com/watch?v=KZ3tIGHU314&ab_channel=UnderCtrl). -* Now run `npm run start` to run the client and ollama at the same time (this must be one in wsl or a Linux distro) - +* Now run `npm run client` to run the client (this must be done in wsl or a Linux distro) ## Set up (Development-side) * Pull the repository using `https://github.com/kevinthedang/discord-ollama.git`. -* Refer to `Ollama Setup` in the readme to set up Ollama. +* Refer to `Environment Setup` in the readme to set up Ollama. * This must be set up in a Linux environment or wsl2. * Install NodeJS `v18.18.2` - * You can check out `Resources` and `To Run` in the readme for a bit of help. + * You can check out `Resources` in the readme for a bit of help. * You can also reference [NodeJS Setup](#nodejs-setup) * When you have the project pulled from github, open up a terminal and run `npm i` or `npm install` to get all of the packages for the project. * In some kind of terminal (`git bash` is good) to run the client. You can run Ollama but opening up wsl2 and typing `ollama serve`. * Refer to `Ollama Setup` if there are any issues. ## Environment -* You will need two environment files: +* You will need an environment file: * `.env`: for running the bot * Please refer to `.env.sample` for all environment variables to include - * `.env.dev.local`: also runs the bot, but with development variables - * Currently there are no differences between the two, but when needed, you may add environment variables as needed. ## NodeJS Setup * Install [nvm](https://github.com/nvm-sh/nvm?tab=readme-ov-file#installing-and-updating) using `curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash` diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml new file mode 100644 index 0000000..bd20715 --- /dev/null +++ b/.github/workflows/coverage.yml @@ -0,0 +1,51 @@ +name: Coverage +run-name: Code Coverage +on: + push: + branches: + - master + +jobs: + Discord-Node-Coverage: + runs-on: ubuntu-latest + environment: coverage + timeout-minutes: 2 + steps: + - name: Checkout Repository + uses: actions/checkout@v4 + + - name: Set up Node Environment lts/hydrogen + uses: actions/setup-node@v4 + with: + node-version: lts/hydrogen + cache: "npm" + + - name: Install Project Dependencies + run: | + npm install + + - name: Create Environment Variables + run: | + touch .env + echo CLIENT_TOKEN = ${{ secrets.BOT_TOKEN }} >> .env + echo MODEL = ${{ secrets.MODEL }} >> .env + echo CLIENT_UID = ${{ secrets.CLIENT_UID }} >> .env + echo OLLAMA_IP = ${{ secrets.OLLAMA_IP }} >> .env + echo OLLAMA_PORT = ${{ secrets.OLLAMA_PORT }} >> .env + + - name: Collect Code Coverage + run: | + LINE_PCT=$(npm run test:coverage | tail -2 | head -1 | awk '{print $3}') + echo "COVERAGE=$LINE_PCT" >> $GITHUB_ENV + + - name: Upload Code Coverage + uses: schneegans/dynamic-badges-action@v1.7.0 + with: + auth: ${{ secrets.GIST_SECRET }} + gistID: ${{ vars.GIST_ID }} + filename: coverage.json + label: Coverage + message: ${{ env.COVERAGE }} + valColorRange: ${{ env.COVERAGE }} + maxColorRange: 100 + minColorRange: 0 diff --git a/README.md b/README.md index 1cd0058..3c2432d 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,7 @@ Build Status Release Status Testing Status + Code Coverage ## About/Goals @@ -54,4 +55,4 @@ The project aims to: * [Kevin Dang](https://github.com/kevinthedang) * [Jonathan Smoley](https://github.com/JT2M0L3Y) -[discord-ollama](https://github.com/kevinthedang/discord-ollama) © 2023 by [Kevin Dang](https://github.com/kevinthedang) is licensed under [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/) \ No newline at end of file +[discord-ollama](https://github.com/kevinthedang/discord-ollama) © 2023 by [Kevin Dang](https://github.com/kevinthedang) is licensed under [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/) diff --git a/src/client.ts b/src/client.ts index 0494674..21337d9 100644 --- a/src/client.ts +++ b/src/client.ts @@ -1,10 +1,8 @@ import { Client, GatewayIntentBits } from 'discord.js' -import { UserMessage, registerEvents } from './utils/events.js' -import Events from './events/index.js' import { Ollama } from 'ollama' import { Queue } from './queues/queue.js' - -// Import keys/tokens +import { UserMessage, registerEvents } from './utils/index.js' +import Events from './events/index.js' import Keys from './keys.js' @@ -26,13 +24,7 @@ const ollama = new Ollama({ // Create Queue managed by Events const messageHistory: Queue = new Queue -/** - * register events for bot to listen to in discord - * @param messageHistory message history for the llm - * @param Events events to register - * @param client the bot reference - * @param Keys tokens from .env files - */ +// register all events registerEvents(client, Events, messageHistory, Keys, ollama) // Try to log in the client diff --git a/src/commands/capacity.ts b/src/commands/capacity.ts index a3c663d..7420740 100644 --- a/src/commands/capacity.ts +++ b/src/commands/capacity.ts @@ -1,6 +1,5 @@ import { ChannelType, Client, CommandInteraction, ApplicationCommandOptionType } from 'discord.js' -import { SlashCommand } from '../utils/commands.js' -import { openConfig } from '../utils/index.js' +import { openConfig, SlashCommand } from '../utils/index.js' export const Capacity: SlashCommand = { name: 'modify-capacity', diff --git a/src/commands/cleanUserChannelHistory.ts b/src/commands/cleanUserChannelHistory.ts index 856ad35..c227294 100644 --- a/src/commands/cleanUserChannelHistory.ts +++ b/src/commands/cleanUserChannelHistory.ts @@ -1,6 +1,5 @@ import { ChannelType, Client, CommandInteraction, TextChannel } from 'discord.js' -import { SlashCommand } from '../utils/commands.js' -import { clearChannelInfo } from '../utils/index.js' +import { clearChannelInfo, SlashCommand } from '../utils/index.js' export const ClearUserChannelHistory: SlashCommand = { name: 'clear-user-channel-history', diff --git a/src/commands/disable.ts b/src/commands/disable.ts index a2dd86d..e6180e2 100644 --- a/src/commands/disable.ts +++ b/src/commands/disable.ts @@ -1,6 +1,5 @@ import { ChannelType, Client, CommandInteraction, ApplicationCommandOptionType } from 'discord.js' -import { SlashCommand } from '../utils/commands.js' -import { openConfig } from '../utils/index.js' +import { openConfig, SlashCommand } from '../utils/index.js' export const Disable: SlashCommand = { name: 'toggle-chat', diff --git a/src/commands/messageStream.ts b/src/commands/messageStream.ts index 5239201..549ac98 100644 --- a/src/commands/messageStream.ts +++ b/src/commands/messageStream.ts @@ -1,6 +1,5 @@ import { ApplicationCommandOptionType, ChannelType, Client, CommandInteraction } from 'discord.js' -import { SlashCommand } from '../utils/commands.js' -import { openConfig } from '../utils/index.js' +import { openConfig, SlashCommand } from '../utils/index.js' export const MessageStream: SlashCommand = { name: 'message-stream', diff --git a/src/commands/messageStyle.ts b/src/commands/messageStyle.ts index 1daec97..bfb20a7 100644 --- a/src/commands/messageStyle.ts +++ b/src/commands/messageStyle.ts @@ -1,6 +1,5 @@ import { ChannelType, Client, CommandInteraction, ApplicationCommandOptionType } from 'discord.js' -import { SlashCommand } from '../utils/commands.js' -import { openConfig } from '../utils/index.js' +import { openConfig, SlashCommand } from '../utils/index.js' export const MessageStyle: SlashCommand = { name: 'message-style', diff --git a/src/commands/threadCreate.ts b/src/commands/threadCreate.ts index 5b676ba..0d34b9d 100644 --- a/src/commands/threadCreate.ts +++ b/src/commands/threadCreate.ts @@ -1,6 +1,5 @@ import { ChannelType, Client, CommandInteraction, TextChannel, ThreadChannel } from 'discord.js' -import { SlashCommand } from '../utils/commands.js' -import { openChannelInfo } from '../utils/index.js' +import { openChannelInfo, SlashCommand } from '../utils/index.js' export const ThreadCreate: SlashCommand = { name: 'thread', diff --git a/src/commands/threadPrivateCreate.ts b/src/commands/threadPrivateCreate.ts index cc941a2..222abda 100644 --- a/src/commands/threadPrivateCreate.ts +++ b/src/commands/threadPrivateCreate.ts @@ -1,6 +1,5 @@ import { ChannelType, Client, CommandInteraction, TextChannel, ThreadChannel } from 'discord.js' -import { SlashCommand } from '../utils/commands.js' -import { openChannelInfo } from '../utils/index.js' +import { openChannelInfo, SlashCommand } from '../utils/index.js' export const PrivateThreadCreate: SlashCommand = { name: 'private-thread', diff --git a/src/events/messageCreate.ts b/src/events/messageCreate.ts index 39dd558..b9950dc 100644 --- a/src/events/messageCreate.ts +++ b/src/events/messageCreate.ts @@ -1,7 +1,6 @@ -import { embedMessage, event, Events, normalMessage, UserMessage } from '../utils/index.js' -import { getChannelInfo, getServerConfig, getUserConfig, openChannelInfo, openConfig, UserConfig, getAttachmentData } from '../utils/index.js' -import { clean } from '../utils/mentionClean.js' import { TextChannel } from 'discord.js' +import { embedMessage, event, Events, normalMessage, UserMessage, clean } from '../utils/index.js' +import { getChannelInfo, getServerConfig, getUserConfig, openChannelInfo, openConfig, UserConfig, getAttachmentData } from '../utils/index.js' /** * Max Message length for free users is 2000 characters (bot or not). diff --git a/src/events/ready.ts b/src/events/ready.ts index 8744e40..1d8c447 100644 --- a/src/events/ready.ts +++ b/src/events/ready.ts @@ -1,5 +1,5 @@ -import { event, Events, registerCommands } from '../utils/index.js' import { ActivityType } from 'discord.js' +import { event, Events, registerCommands } from '../utils/index.js' import commands from '../commands/index.js' // Log when the bot successfully logs in and export it diff --git a/src/keys.ts b/src/keys.ts index c376e9d..0b9be4d 100644 --- a/src/keys.ts +++ b/src/keys.ts @@ -1,4 +1,4 @@ -import { getEnvVar } from './utils/env.js' +import { getEnvVar } from './utils/index.js' export const Keys = { clientToken: getEnvVar('CLIENT_TOKEN'), diff --git a/src/utils/configInterfaces.ts b/src/utils/configInterfaces.ts index ec16ba4..e8e51bc 100644 --- a/src/utils/configInterfaces.ts +++ b/src/utils/configInterfaces.ts @@ -1,4 +1,4 @@ -import { UserMessage } from './events.js' +import { UserMessage } from './index.js' export interface UserConfiguration { 'message-stream'?: boolean, diff --git a/src/utils/env.ts b/src/utils/env.ts index 813a77c..bf0b13a 100644 --- a/src/utils/env.ts +++ b/src/utils/env.ts @@ -1,11 +1,8 @@ import { resolve } from 'path' import { config } from 'dotenv' -// Find config - ONLY WORKS WITH NODEMON -const envFile = process.env.NODE_ENV === 'development' ? '.env.dev.local' : '.env' - // resolve config file -const envFilePath = resolve(process.cwd(), envFile) +const envFilePath = resolve(process.cwd(), '.env') // set current environment variable file config({ path: envFilePath }) diff --git a/src/utils/events.ts b/src/utils/events.ts index ae83074..0ff02bc 100644 --- a/src/utils/events.ts +++ b/src/utils/events.ts @@ -1,4 +1,4 @@ -import type { ClientEvents, Awaitable, Client, User } from 'discord.js' +import type { ClientEvents, Awaitable, Client } from 'discord.js' import { Ollama } from 'ollama' import { Queue } from '../queues/queue.js' diff --git a/src/utils/index.ts b/src/utils/index.ts index 4e3e5ea..846316f 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -5,6 +5,7 @@ export * from './messageEmbed.js' export * from './messageNormal.js' export * from './commands.js' export * from './configInterfaces.js' +export * from './mentionClean.js' // handler imports export * from './handlers/chatHistoryHandler.js' diff --git a/src/utils/mentionClean.ts b/src/utils/mentionClean.ts index dbe329e..884fa82 100644 --- a/src/utils/mentionClean.ts +++ b/src/utils/mentionClean.ts @@ -8,7 +8,7 @@ import Keys from "../keys.js" * - replace function works well for this * * @param message - * @returns + * @returns message without client id */ export function clean(message: string): string { const cleanedMessage: string = message.replace(`<@${Keys.clientUid}>`, '').trim() diff --git a/tests/commands.test.ts b/tests/commands.test.ts index 2167406..2589048 100644 --- a/tests/commands.test.ts +++ b/tests/commands.test.ts @@ -2,7 +2,7 @@ // expect takes a value from an expression // it marks a test case import { describe, expect, it } from 'vitest' -import commands from '../src/commands' +import commands from '../src/commands/index.js' /** * Commands test suite, tests the commands object @@ -12,7 +12,7 @@ import commands from '../src/commands' * @param name name of the test suite * @param fn function holding tests to run */ -describe('#commands', () => { +describe('Commands Existence', () => { // test definition of commands object it('references defined object', () => { // toBe compares the value to the expected value @@ -24,4 +24,49 @@ describe('#commands', () => { const commandsString = commands.map(e => e.name).join(', ') expect(commandsString).toBe('thread, private-thread, message-style, message-stream, toggle-chat, shutoff, modify-capacity, clear-user-channel-history') }) +}) + +/** + * User Commands Test suite for testing out commands + * that would be run by users when using the application. + */ +describe('User Command Tests', () => { + // test capacity command + it('run modify-capacity command', () => { + + }) + + it('run clear-user-channel-history command', () => { + + }) + + it('run message-stream command', () => { + + }) + + it('run message-style command', () => { + + }) + + it('run thread command', () => { + + }) + + it('run private-thread command', () => { + + }) +}) + +/** + * Admin Commands Test suite for running administrative + * commands with the application. + */ +describe('Admin Command Tests', () => { + it('run shutoff command', () => { + + }) + + it('run toggle-chat command', () => { + + }) }) \ No newline at end of file diff --git a/tests/events.test.ts b/tests/events.test.ts index 229e2a0..34916a0 100644 --- a/tests/events.test.ts +++ b/tests/events.test.ts @@ -1,5 +1,5 @@ import { describe, expect, it } from 'vitest' -import events from '../src/events' +import events from '../src/events/index.js' /** * Events test suite, tests the events object @@ -9,7 +9,7 @@ import events from '../src/events' * @param name name of the test suite * @param fn function holding tests to run */ -describe('#events', () => { +describe('Events Existence', () => { // test definition of events object it('references defined object', () => { expect(typeof events).toBe('object') diff --git a/tests/getEnvVar.test.ts b/tests/getEnvVar.test.ts index 8cf1217..071edea 100644 --- a/tests/getEnvVar.test.ts +++ b/tests/getEnvVar.test.ts @@ -1,5 +1,5 @@ import { describe, expect, it } from 'vitest' -import { getEnvVar } from '../src/utils' +import { getEnvVar } from '../src/utils/index.js' /** * getEnvVar test suite, tests the getEnvVar function @@ -7,7 +7,7 @@ import { getEnvVar } from '../src/utils' * @param name name of the test suite * @param fn function holding tests to run */ -describe('#getEnvVar', () => { +describe('Environment Setup', () => { // dummy set of keys const keys = { clientToken: 'CLIENT_TOKEN', diff --git a/tests/mentionClean.test.ts b/tests/mentionClean.test.ts index eec8031..eb06931 100644 --- a/tests/mentionClean.test.ts +++ b/tests/mentionClean.test.ts @@ -1,6 +1,5 @@ import { describe, expect, it } from 'vitest' -import { clean } from '../src/utils/mentionClean' -import { getEnvVar } from '../src/utils' +import { getEnvVar, clean } from '../src/utils/index.js' /** * MentionClean test suite, tests the clean function @@ -8,7 +7,7 @@ import { getEnvVar } from '../src/utils' * @param name name of the test suite * @param fn function holding tests to run */ -describe('#clean', () => { +describe('Mentions Cleaned', () => { // test for id removal from message it('removes the mention from a message', () => { const message = `<@${getEnvVar('CLIENT_UID')}> Hello, World!` diff --git a/tests/queue.test.ts b/tests/queue.test.ts index 3a20e57..622cc99 100644 --- a/tests/queue.test.ts +++ b/tests/queue.test.ts @@ -1,5 +1,5 @@ import { describe, expect, it } from 'vitest' -import { Queue } from '../src/queues/queue' +import { Queue } from '../src/queues/queue.js' /** * Queue test suite, tests the Queue class @@ -7,7 +7,7 @@ import { Queue } from '../src/queues/queue' * @param name name of the test suite * @param fn function holding tests to run */ -describe('#queue', () => { +describe('Queue Structure', () => { let queue= new Queue() // test for queue creation diff --git a/vitest.config.ts b/vitest.config.ts index 7678190..0ecac27 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -4,9 +4,10 @@ import { defineConfig, configDefaults } from 'vitest/config' export default defineConfig({ test: { globals: true, // <-- reduces test file imports + reporters: ['verbose'], // <-- verbose output coverage: { exclude: [...configDefaults.exclude, 'build/*', 'tests/*'], // <-- exclude JS build - reporter: ['text', 'html'] // <-- reports in text, html + reporter: ['text-summary'] // <-- report in text-summary } } }) \ No newline at end of file