diff --git a/README.md b/README.md index 65feaf1..236f046 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,6 @@ This Bot uses the PyCord Library ([PyCord](https://pycord.dev/)) and the OpenAI There are three ways to use this bot: 1. By just inviting [this Bot](https://discord.com/api/oauth2/authorize?client_id=1083786070786850959&permissions=2147486720&scope=bot) to your Server - 2. Using Docker 3. Without using Docker @@ -27,7 +26,7 @@ There are three ways to use this bot: - Server Members Intent - Message Content Intent 4. Get an OpenAI API Key from [OpenAI](https://platform.openai.com/account/api-keys) -6. Go to the `configs`-folder and create a file called `.env` in the config folder and add the following: +6. Go to the `config`-folder and create a file called `.env` in the config folder and add the following: ```shell DISCORD_TOKEN=Your_Bot_Token @@ -50,36 +49,26 @@ OPENAI_API_KEY=Your_OpenAI_API_Key - Message Content Intent 3. Get an OpenAI API Key from [OpenAI](https://platform.openai.com/account/api-keys) 4. Use `docker build -t discord-bot .` to build the Docker Image -5. Make a folder called `chat` -6. Make a folder called `config` and create a file called `.env` in the configs folder and add the following: +5. Make a folder called `config` and create a file called `.env` in the configs folder and add the following: ```shell DISCORD_TOKEN=Your_Bot_Token OPENAI_API_KEY=Your_OpenAI_API_Key ``` -7. Run the bot using `docker run -v /path/to/config:/usr/share/dcbot/configs -v /path/to/chat:/usr/share/dcbot/chats -d --name discord-bot discord-bot` -8. To stop the Bot use `docker stop ` +7. Run the bot using `docker run -v /path/to/config:/usr/share/dcbot/config -d --name discord-bot discord-bot` +8. To stop the Bot use `docker stop discord-bot` ## How to use the Bot Once the Bot is running and you have invited it to your Server, you can use the following commands: -- /add text (channel-id) to Add the Bot to listen in a channel. The Bot will listen to all messages in that channel and answer them using GPT-3.5. The Bot will ignore Messages with a Prefix (Default - $) -- /add prefix (channel-id) to Add the Bot to listen in a channel. The Bot will listen to all messages in that channel that start with the prefix and answer them using GPT-3.5 (Default - !) -- /remove text/prefix (channel-id) to remove the Bot from listening in a channel. -- /list text/prefix to list all channels the Bot is listening in. -- /delete to delete the bots history from specific channels. -- /help to get a list of all commands. -- /ping to check if the Bot is online. -- /setup (channelid) (System-Message) Changes the System-Message. See OenAI's Documentation for more information. [OpenAI Docs](https://platform.openai.com/docs/guides/chat/instructing-chat-models) - - -### Future Improvements - -- Currently I am working on an SQLite DB to store all information needed (eg. Servers, Channels, Configs, etc) -- Also I am working on a way to toggle between GPT 3.5-turbo and GPT-4 -- Need to find and fix Bugs +- /add - Opens a Dialog to add a new Server to the Bot +- /setup - Same as Add, but you can change the Channel ID +- /remove - Removes the current Channel from the Bot +- /clear - Clears the Message History used by the Bot. Does not remove Messages from Discord, only from the Bot +- /system - Opens a Dialog to change the System-Messege set to the Bot. More in OpenAI's Docs +- /ping - Checks if the Bot is responding ### How to Contribute @@ -89,4 +78,3 @@ If you want to contribute to this project, feel free to open a PR or Issue. - [OpenAI](https://openai.com/) for the GPT API - [PyCord](https://pycord.dev/) for the Discord API Wrapper -- [Drone](https://drone.io/) for the CI/CD diff --git a/bot/bot.py b/bot/bot.py index 880b42e..8346197 100644 --- a/bot/bot.py +++ b/bot/bot.py @@ -85,42 +85,32 @@ class SetupModal(discord.ui.Modal): embed.add_field(name="GPT", value=self.children[2].value) embed.add_field(name="System Message", value=self.children[3].value) - await interaction.response.send_message(embeds=[embed], ephemeral=True) - + # Check if Server is in DB if await dbm.get_server_by_id(interaction.guild.id) is None: - print("Server not in DB") await dbm.add_server(interaction.guild.id) - await dbm.add_channel(interaction.guild.id, self.children[0].value) - if dbm.is_premium(interaction.guild.id): - await dbm.add_config(interaction.guild.id, self.children[0].value, self.children[1].value, self.children[2].value, self.children[3].value) - else: - await dbm.add_config(interaction.guild.id, self.children[0].value, 3, self.children[2].value, self.children[3].value) - await dbm.add_summary_zero(interaction.guild.id, self.children[0].value) - await dbm.default_premium(interaction.guild.id) - print("Setup: Server") + print("Added Server to DB") - elif await dbm.get_server_by_id(interaction.guild.id) is not None and await dbm.get_channel_by_id(interaction.guild.id, self.children[0].value) is None: - print("Server in DB, but Channel not") - await dbm.add_channel(interaction.guild.id, self.children[0].value) - if dbm.is_premium(interaction.guild.id): - await dbm.add_config(interaction.guild.id, self.children[0].value, self.children[1].value, self.children[2].value, self.children[3].value) - else: - await dbm.add_config(interaction.guild.id, self.children[0].value, 3, self.children[2].value, self.children[3].value) - - await dbm.add_summary_zero(interaction.guild.id, self.children[0].value) - print("Setup: Channel, Config") - - elif await dbm.get_server_by_id(interaction.guild.id) is not None and await dbm.get_channel_by_id(interaction.guild.id, self.children[0].value) is not None: - print("Server and Channel in DB, rerun Setup") + # Check if Channel is already in DB. If so delete old config + if await dbm.get_channel_by_id(interaction.guild.id, self.children[0].value) is not None: await dbm.remove_channel(interaction.guild.id, self.children[0].value) await dbm.remove_config(interaction.guild.id, self.children[0].value) + print("Removed old Channel from DB") + + # Check if Channel is in DB. If not add it + if await dbm.get_channel_by_id(interaction.guild.id, self.children[0].value) is None: + print("Added Channel to DB") await dbm.add_channel(interaction.guild.id, self.children[0].value) - if dbm.is_premium(interaction.guild.id): + + # Check for "Premium" + if await dbm.is_premium(interaction.guild.id): await dbm.add_config(interaction.guild.id, self.children[0].value, self.children[1].value, self.children[2].value, self.children[3].value) else: - await dbm.add_config(interaction.guild.id, self.children[0].value, 3, self.children[2].value, self.children[3].value) + await dbm.add_config(interaction.guild.id, self.children[0].value, self.children[1], "3", self.children[3].value) + await dbm.add_summary_zero(interaction.guild.id, self.children[0].value) - print("Setup: Channel, Config") + + await interaction.response.send_message(embeds=[embed], ephemeral=True) + ### Add Modal class AddModal(discord.ui.Modal): @@ -131,43 +121,40 @@ class AddModal(discord.ui.Modal): self.add_item(discord.ui.InputText(label="System Message", placeholder="System Message", required=False, style=discord.InputTextStyle.long)) async def callback(self, interaction: discord.Interaction): + + print(f"Server-Type: {type(interaction.guild.id)}" + f"Channel-Type: {type(interaction.channel.id)}" + f"Prefix-Type: {type(self.children[0].value)}" + f"GPT-Type: {type(self.children[1].value)}" + f"System-Type: {type(self.children[2].value)}") + + # Check if Server is in DB if await dbm.get_server_by_id(interaction.guild.id) is None: - print("Server not in DB") await dbm.add_server(interaction.guild.id) - await dbm.add_channel(interaction.guild.id, interaction.channel.id) - if dbm.is_premium(interaction.guild.id): - await dbm.add_config(interaction.guild.id, interaction.channel.id, self.children[0].value, self.children[1].value, self.children[2].value) - else: - await dbm.add_config(interaction.guild.id, interaction.channel.id, self.children[0].value, 3, self.children[2].value) - await dbm.add_summary_zero(interaction.guild.id, interaction.channel.id) - print("Setup: Channel, Server, Config") - elif await dbm.get_server_by_id(interaction.guild.id) is not None and await dbm.get_channel_by_id(interaction.guild.id, interaction.channel.id) is None: - await dbm.add_channel(interaction.guild.id, interaction.channel.id) - if dbm.is_premium(interaction.guild.id): - await dbm.add_config(interaction.guild.id, interaction.channel.id, self.children[0].value, - self.children[1].value, self.children[2].value) - else: - await dbm.add_config(interaction.guild.id, interaction.channel.id, self.children[0].value, 3, - self.children[2].value) - await dbm.add_summary_zero(interaction.guild.id, interaction.channel.id) - print("Setup: Channel, Config") - elif await dbm.get_server_by_id(interaction.guild.id) is not None and await dbm.get_channel_by_id(interaction.guild.id, interaction.channel.id) is not None: + print("Added Server to DB") + + # Check if Channel is already in DB. If so delete old config + if await dbm.get_channel_by_id(interaction.guild.id, interaction.channel.id) is not None: await dbm.remove_channel(interaction.guild.id, interaction.channel.id) await dbm.remove_config(interaction.guild.id, interaction.channel.id) - if dbm.is_premium(interaction.guild.id): - await dbm.add_config(interaction.guild.id, interaction.channel.id, self.children[0].value, - self.children[1].value, self.children[2].value) - else: - await dbm.add_config(interaction.guild.id, interaction.channel.id, self.children[0].value, 3, - self.children[2].value) - await dbm.add_config(interaction.guild.id, interaction.channel.id, self.children[0].value, self.children[1].value, self.children[2].value) - await dbm.add_summary_zero(interaction.guild.id, interaction.channel.id) - print("Setup: Channel, Config") + print("Removed old Channel from DB") - if dbm.is_premium(interaction.guild.id): - await interaction.response.send_message('Setup Channel', ephemeral=True) + # Check if Channel is in DB. If not add it + if await dbm.get_channel_by_id(interaction.guild.id, interaction.channel.id) is None: + await dbm.add_channel(interaction.guild.id, interaction.channel.id) + print("Added Channel to DB") + + # Check for "Premium" + if await dbm.is_premium(interaction.guild.id): + await dbm.add_config(interaction.guild.id, interaction.channel.id, self.children[0].value, self.children[1].value, self.children[2].value) + print(f"Added with Premium-Permission {self.children[1].value}") else: - await interaction.response.send_message('Setup Channel (Using GPT-3.5)', ephemeral=True) + await dbm.add_config(interaction.guild.id, interaction.channel.id, self.children[0].value, "3", self.children[2].value) + print(f"Added without Premium-Permission 3") + + await dbm.add_summary_zero(interaction.guild.id, interaction.channel.id) + await interaction.response.send_message("Configured Channel", ephemeral=True) + ### Edit Modal class EditSystemModal(discord.ui.Modal): @@ -196,11 +183,8 @@ async def setup(ctx: discord.ApplicationContext): @bot.command(name="add", description="Used to add Bot answering to specific Channels") @commands.has_permissions(administrator=True) async def add(ctx: discord.ApplicationContext): - if await dbm.get_channel_by_id(ctx.guild.id, ctx.channel.id) is None: - modal = AddModal(title="Add Channel") - await ctx.send_modal(modal) - else: - await ctx.respond("Channel has already been added. Use /setup", ephemeral=True) + modal = AddModal(title="Add Channel") + await ctx.send_modal(modal) @bot.command(name="remove", description="Used to remove Bot answering to specific Channels") @@ -208,29 +192,18 @@ async def add(ctx: discord.ApplicationContext): async def remove(ctx: discord.ApplicationContext): if await dbm.get_channel_by_id(ctx.guild.id, ctx.channel.id) is not None: await dbm.remove_channel(ctx.guild.id, ctx.channel.id) + await dbm.remove_config(ctx.guild.id, ctx.channel.id) await ctx.respond("Channel removed", ephemeral=True) else: await ctx.respond("Channel not active. Nothing Done", ephemeral=True) -@bot.command(name="list", description="Used to list all Channels in the Server") -@commands.has_permissions(administrator=True) -async def list(ctx: discord.ApplicationContext): - - await ctx.respond("This command is WIP") - - @bot.command(name="clear", description="Used to clear chat history of specific Channels/Users") @commands.has_permissions(administrator=True) async def clear(ctx: discord.ApplicationContext): await dbm.add_summary_zero(ctx.guild.id, ctx.channel.id) await ctx.respond("Bot got Amnesia", ephemeral=True) -# Old System, Rewrite needed -@bot.command(name="help", description="Used to get help") -async def help(ctx: discord.ApplicationContext): - await ctx.respond(f'Here is a list of all commands:\n' - 'Needs Rewrite\n', ephemeral=True) @bot.command(name="ping", description="Used to check if the bot is alive") async def ping(ctx: discord.ApplicationContext): diff --git a/bot/modules/dbmanagement.py b/bot/modules/dbmanagement.py index a67dc55..4f0f111 100644 --- a/bot/modules/dbmanagement.py +++ b/bot/modules/dbmanagement.py @@ -22,7 +22,7 @@ async def init_db(): (server_id TEXT, channel_id TEXT, prefix TEXT, - gpt INTEGER, + gpt TEXT, systemmsg TEXT, FOREIGN KEY(server_id) REFERENCES servers(id), FOREIGN KEY(channel_id) REFERENCES channels(id))''' @@ -56,10 +56,9 @@ async def init_db(): async def add_server(server_id): async with aiosqlite.connect(DB_FILE) as db: - await db.execute('INSERT OR IGNORE INTO servers (server_id) VALUES (?)', (server_id,)) + await db.execute('INSERT INTO servers (server_id, is_premium) VALUES (?, ?)', (server_id, 0)) await db.commit() - async def remove_server(server_id): async with aiosqlite.connect(DB_FILE) as db: await db.execute('DELETE FROM servers WHERE server_id = ?', (server_id,)) @@ -125,9 +124,9 @@ async def get_channel_by_id(server_id, channel_id): return channel async def add_config(server_id, channel_id, prefix, gpt, systemmsg): - msg = f'Users are named like this: Username#1234 the #1234 is an identifier and can be ignored. {systemmsg}' + msg = f'You are talking to multiple users and can see their usernames. Usernames are named like this: Username#1234 the #1234 is an identifier and can be ignored. You do not add a username to your message. {systemmsg}' async with aiosqlite.connect(DB_FILE) as db: - await db.execute('INSERT OR IGNORE INTO config (server_id, channel_id, prefix, gpt, systemmsg) VALUES (?, ?, ?, ?, ?)', (server_id, channel_id, prefix, gpt, msg)) + await db.execute('INSERT OR IGNORE INTO config (server_id, channel_id, prefix, gpt, systemmsg) VALUES (?, ?, ?, ?, ?)', (server_id, channel_id, str(prefix), str(gpt), str(msg))) await db.commit() async def remove_config(server_id, channel_id): diff --git a/bot/modules/gpt.py b/bot/modules/gpt.py index efcff53..27e8855 100644 --- a/bot/modules/gpt.py +++ b/bot/modules/gpt.py @@ -60,10 +60,10 @@ async def get_answer(server_id=0, channel_id=0, mode=0, msg=''): if mode == 0: ### Normal Mode gptversion = await dbm.get_config_by_id(server_id, channel_id) gptversion = gptversion[3] - if gptversion == 3: - usemodel = "gpt-3.5-turbo" - elif gptversion == 4: + if int(gptversion) == 4: usemodel = "gpt-4" + else: + usemodel = "gpt-3.5-turbo" history = await load_history(server_id, channel_id, 0)