Clear User Channel History Command (#88)

* Add: Clear user channel message history command

* Update: Checks if messages are empty and has clearer replies

* Fix: Issue where duplication happens on channel-toggle true in threads

* Update: version increment

* Fix: Missing test case for commands.test.ts

* Readability fix

---------

Co-authored-by: Jonathan Smoley <67881240+JT2M0L3Y@users.noreply.github.com>
This commit is contained in:
Kevin Dang
2024-07-25 14:26:50 -07:00
committed by GitHub
parent e60c2f88b8
commit 352d88ee9d
8 changed files with 99 additions and 9 deletions

View File

@@ -8,7 +8,7 @@ services:
build: ./ # find docker file in designated path
container_name: discord
restart: always # rebuild container always
image: discord/bot:0.5.5
image: discord/bot:0.5.6
environment:
CLIENT_TOKEN: ${CLIENT_TOKEN}
GUILD_ID: ${GUILD_ID}

4
package-lock.json generated
View File

@@ -1,12 +1,12 @@
{
"name": "discord-ollama",
"version": "0.5.5",
"version": "0.5.6",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "discord-ollama",
"version": "0.5.5",
"version": "0.5.6",
"license": "ISC",
"dependencies": {
"discord.js": "^14.15.3",

View File

@@ -1,6 +1,6 @@
{
"name": "discord-ollama",
"version": "0.5.5",
"version": "0.5.6",
"description": "Ollama Integration into discord",
"main": "build/index.js",
"exports": "./build/index.js",

View File

@@ -0,0 +1,34 @@
import { ChannelType, Client, CommandInteraction, TextChannel } from 'discord.js'
import { SlashCommand } from '../utils/commands.js'
import { clearChannelInfo } from '../utils/index.js'
export const ClearUserChannelHistory: SlashCommand = {
name: 'clear-user-channel-history',
description: 'clears history for user running this command in current channel',
// Clear channel history for intended user
run: async (client: Client, interaction: CommandInteraction) => {
// fetch current channel
const channel = await client.channels.fetch(interaction.channelId)
// if not an existing channel or a GuildText, fail command
if (!channel || channel.type !== ChannelType.GuildText) return
// clear channel info for user
const successfulWipe = await clearChannelInfo(interaction.channelId,
interaction.channel as TextChannel,
interaction.user.username)
// check result of clearing history
if (successfulWipe)
interaction.reply({
content: `Channel history in **${channel.name}** 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.`,
ephemeral: true
})
}
}

View File

@@ -7,6 +7,7 @@ import { Shutoff } from './shutoff.js'
import { Capacity } from './capacity.js'
import { PrivateThreadCreate } from './threadPrivateCreate.js'
import { ChannelToggle } from './channelToggle.js'
import { ClearUserChannelHistory } from './cleanUserChannelHistory.js'
export default [
ThreadCreate,
@@ -16,5 +17,6 @@ export default [
Disable,
Shutoff,
Capacity,
ChannelToggle
ChannelToggle,
ClearUserChannelHistory
] as SlashCommand[]

View File

@@ -19,7 +19,7 @@ export const ThreadCreate: SlashCommand = {
})
// Send a message in the thread
thread.send(`Hello ${interaction.user} and others! \n\nIt's nice to meet you. Please talk to me by typing **@${client.user?.username}** with your prompt.`)
thread.send(`Hello ${interaction.user} and others! \n\nIt's nice to meet you. Please talk to me by typing **@${client.user?.username}** with your prompt.\n\nIf I do not respond, ensure \`channel-toggle\` is set to \`false\``)
// handle storing this chat channel
// store: thread.id, thread.name

View File

@@ -58,6 +58,61 @@ export async function getThread(filename: string, callback: (config: Thread | un
}
}
/**
* Method to check if a thread history file exists
*
* @param channel parent thread of the requested thread (can be GuildText)
* @returns true if channel does not exist, false otherwise
*/
async function checkChannelInfoExists(channel: TextChannel, user: string) {
// thread exist handler
const isThread: boolean = await new Promise((resolve) => {
getThread(`${channel.id}-${user}.json`, (channelInfo) => {
if (channelInfo?.messages)
resolve(true)
else
resolve(false)
})
})
return isThread
}
/**
* Method to clear channel history for requesting user
*
* @param filename guild id string
* @param channel the TextChannel in the Guild
* @param user username of user
* @returns nothing
*/
export async function clearChannelInfo(filename: string, channel: TextChannel, user: string): Promise<boolean> {
const channelInfoExists: boolean = await checkChannelInfoExists(channel, user)
// If thread does not exist, file can't be found
if (!channelInfoExists) return false
// Attempt to clear user channel history
const fullFileName = `data/${filename}-${user}.json`
const cleanedHistory: boolean = await new Promise((resolve) => {
fs.readFile(fullFileName, 'utf8', (error, data) => {
if (error)
console.log(`[Error: openChannelInfo] Incorrect file format`)
else {
const object = JSON.parse(data)
if (object['messages'].length === 0) // already empty, let user know
resolve(false)
else {
object['messages'] = [] // cleared history
fs.writeFileSync(fullFileName, JSON.stringify(object, null, 2))
resolve(true)
}
}
})
})
console.log(cleanedHistory)
return cleanedHistory
}
/**
* Method to open the channel history
*
@@ -67,7 +122,6 @@ export async function getThread(filename: string, callback: (config: Thread | un
* @param messages their messages
*/
export async function openChannelInfo(filename: string, channel: TextChannel, user: string, messages: UserMessage[] = []): Promise<void> {
// thread exist handler
const isThread: boolean = await new Promise((resolve) => {
getThread(`${channel.id}.json`, (threadInfo) => {
if (threadInfo?.messages)
@@ -77,7 +131,7 @@ export async function openChannelInfo(filename: string, channel: TextChannel, us
})
})
// This is an existing thread, don't create another json
// this is a thread channel, do not duplicate files
if (isThread) return
const fullFileName = `data/${filename}-${user}.json`

View File

@@ -22,6 +22,6 @@ describe('#commands', () => {
// test specific commands in the object
it('references specific commands', () => {
const commandsString = commands.map(e => e.name).join(', ')
expect(commandsString).toBe('thread, private-thread, message-style, message-stream, toggle-chat, shutoff, modify-capacity, channel-toggle')
expect(commandsString).toBe('thread, private-thread, message-style, message-stream, toggle-chat, shutoff, modify-capacity, channel-toggle, clear-user-channel-history')
})
})