Compare commits

..

No commits in common. "a898d0d9b8b4f9715af7d5fc79d6e199c330249f" and "c2df6f91926097c03088b5b8fd7ae6da8e83ff13" have entirely different histories.

10 changed files with 382 additions and 549 deletions

View File

@ -8,12 +8,9 @@ This is a Discord Bot that Uses OpenAI's new Chat API-Endpoint to generate text
This Bot uses the PyCord Library ([PyCord](https://pycord.dev/)) and the OpenAI Python Library ([OpenAI](https://platform.openai.com/docs/libraries))
There are three ways to use this bot:
There are two 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
Using Docker or without Docker.
### The No Docker Way

View File

@ -1,16 +1,22 @@
import asyncio
import discord
from discord.ext import commands
from dotenv import load_dotenv
import os
import modules.gpt as gpt
import modules.dbmanagement as dbm
import modules.tts as tts
import modules.summarize as summarize
import modules.channelconfig as config
description = "ChatGPT Bot for Discord"
configfolder = "config"
configfolder = "configs"
audiofolder = "audio"
load_dotenv(dotenv_path=os.path.join(configfolder, ".env"))
text_channels, prefix_channels = config.load_config()
tts_language = "de-DE"
intents = discord.Intents.default()
intents.message_content = True
intents.members = True
@ -21,234 +27,131 @@ bot = discord.Bot(
intents=intents,
)
### \/ Events Area \/ ###
@bot.event
async def on_ready():
print(f"We have logged in as {bot.user}")
await dbm.init_db()
### Message Listener
@bot.event
async def on_message(message):
if message.author == bot.user:
return
### Check if Channel is Configured
if await dbm.get_channel_by_id(message.guild.id, message.channel.id) is not None:
config = await dbm.get_config_by_id(message.guild.id, message.channel.id)
if message.content.startswith(config[2]):
### Count Messages for Summary
counter = 0
if await dbm.get_last_chat(message.guild.id, message.channel.id) is not None:
counter = await dbm.get_last_chat(message.guild.id, message.channel.id)
counter = counter[8]
counter = counter + 1
else:
await dbm.add_summary_zero(message.guild.id, message.channel.id)
if str(message.channel.id) in text_channels and not message.content.startswith("$"):
await message.channel.trigger_typing()
print(f'{message.author} asked: {message.content}')
answer = await gpt.get_answer(message.channel.id, message.author, message.content)
print(f'Answer: {answer}')
await message.channel.send(answer)
### Read and Send Message/Answer
if str(message.channel.id) in prefix_channels:
if message.content.startswith("!"):
msg_split = message.content.split("!")[1]
await message.channel.trigger_typing()
msg = message.content.replace(config[2], "", 1)
await dbm.add_chat(message.guild.id, message.channel.id, message.author.id, message.author.name, "user", message.id, f'{message.author}: {msg}', counter)
answer = await gpt.get_answer(message.guild.id, message.channel.id)
sendmsg = await message.channel.send(answer)
await dbm.add_chat(message.guild.id, message.channel.id, bot.user.id, bot.user.name, "assistant", sendmsg.id, answer, counter+1)
### Check if Summary is needed
last_summary = await dbm.get_latest_summary(message.guild.id, message.channel.id)
last_summary = last_summary[4]
last_message = await dbm.get_last_chat(message.guild.id, message.channel.id)
last_message = last_message[8]
### Check if Last Summary is older than 20 Messages
if last_message - last_summary >= 30:
await summarize.new_summarize(message.guild.id, message.channel.id)
### /\ End Events Area /\ ###
### \/ Modal Area \/ ###
### Modal Class for Setup
class SetupModal(discord.ui.Modal):
def __init__(self, *args, **kwargs) -> None:
super().__init__(*args, **kwargs)
self.add_item(discord.ui.InputText(label="Channel-ID", placeholder="Channel-ID", required=True))
self.add_item(discord.ui.InputText(label="Prefix", placeholder="!", required=False))
self.add_item(discord.ui.InputText(label="GPT", placeholder="3", required=True))
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):
embed = discord.Embed(title="Setup Vals")
embed.add_field(name="Channel-ID", value=self.children[0].value)
embed.add_field(name="Prefix", value=self.children[1].value)
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)
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")
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")
await dbm.remove_channel(interaction.guild.id, self.children[0].value)
await dbm.remove_config(interaction.guild.id, self.children[0].value)
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")
### Add Modal
class AddModal(discord.ui.Modal):
def __init__(self, *args, **kwargs) -> None:
super().__init__(*args, **kwargs)
self.add_item(discord.ui.InputText(label="Prefix (Leave empty for no Prefix)", placeholder="!", required=False))
self.add_item(discord.ui.InputText(label="GPT (3 - GPT-3.5-Turbo; 4- GPT-4)", placeholder="3", required=True))
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):
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:
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")
if dbm.is_premium(interaction.guild.id):
await interaction.response.send_message('Setup Channel', ephemeral=True)
else:
await interaction.response.send_message('Setup Channel (Using GPT-3.5)', ephemeral=True)
### Edit Modal
class EditSystemModal(discord.ui.Modal):
def __init__(self, *args, **kwargs) -> None:
super().__init__(*args, **kwargs)
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):
server, channel, prefix, gptver, systemmsg = await dbm.get_config_by_id(interaction.guild.id, interaction.channel.id)
await dbm.remove_config(interaction.guild.id, interaction.channel.id)
await dbm.add_config(interaction.guild.id, interaction.channel.id, prefix, gptver, self.children[0].value)
await interaction.response.send_message("System Message changed", ephemeral=True)
### /\ End Modal Area /\ ###
### \/ Commands Area \/ ###
### Setup Command
@bot.command(name="setup", description="Used to setup the Bot")
@commands.has_permissions(administrator=True)
async def setup(ctx: discord.ApplicationContext):
modal = SetupModal(title="Setup ChatGPT")
await ctx.send_modal(modal)
print(f'{message.author} asked: {message.content}')
answer = await gpt.get_answer(message.channel.id, message.author, msg_split)
print(f'Answer: {answer}')
await message.channel.send(answer)
@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)
async def add(
ctx: discord.ApplicationContext,
option: discord.Option(str, choices=["text","prefix"], description="Type of Channel to Add"),
id: discord.Option(str, description="Channel-ID -> Activate Developer-Options to Copy")):
if ctx.author.guild_permissions.administrator:
try:
config.add_channel(option, id)
if option == "text":
text_channels.append(id)
elif option == "prefix":
prefix_channels.append(id)
await ctx.respond(f'{option} channel {id} added', ephemeral=True)
except ValueError as e:
await ctx.respond(f'Error: {e}', ephemeral=True)
else:
await ctx.respond(f'Error: You need to be an Administrator to use this command', ephemeral=True)
@bot.command(name="remove", description="Used to remove Bot answering to specific Channels")
@commands.has_permissions(administrator=True)
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 ctx.respond("Channel removed", ephemeral=True)
async def remove(
ctx: discord.ApplicationContext,
option: discord.Option(str, choices=["text", "prefix"], description="Type of Channel to Add"),
id: discord.Option(str, description="Channel-ID -> Activate Developer-Options to Copy")):
if ctx.author.guild_permissions.administrator:
try:
config.remove_channel(option, id)
if option == "text":
text_channels.remove(id)
elif option == "prefix":
prefix_channels.remove(id)
await ctx.respond(f'{option} channel {id} removed', ephemeral=True)
except ValueError as e:
await ctx.respond(f'Error: {e}', ephemeral=True)
else:
await ctx.respond("Channel not active. Nothing Done", ephemeral=True)
await ctx.respond(f'Error: You need to be an Administrator to use this command', ephemeral=True)
@bot.command(name="list", description="Used to list all Channels the Bot is answering to")
async def list(
ctx: discord.ApplicationContext,
option: discord.Option(str, choices=["text", "prefix"], description="Type of Channels to List")):
@bot.command(name="list", description="Used to list all Channels in the Server")
@commands.has_permissions(administrator=True)
async def list(ctx: discord.ApplicationContext):
if ctx.author.guild_permissions.administrator:
if option == "text":
await ctx.respond(f'{option} channels: {str(text_channels)}', ephemeral=True)
elif option == "prefix":
await ctx.respond(f'{option} channels: {str(prefix_channels)}', ephemeral=True)
else:
await ctx.respond(f'Error: You need to be an Administrator to use this command', ephemeral=True)
await ctx.respond("This command is WIP")
@bot.command(name="delete", description="Used to delete chat history of specific Channels/Users")
async def delete(
ctx: discord.ApplicationContext,
option: discord.Option(str, choices=["text", "prefix"], description="Type of Channel to Delete"),
id: discord.Option(str, description="Channel-ID -> Activate Developer-Options to Copy")):
if ctx.author.guild_permissions.administrator:
try:
gpt.delete_history(id)
await ctx.respond(f'{option} channel {id} history deleted', ephemeral=True)
except Exception as e:
await ctx.respond(f'Error: {e}', ephemeral=True)
else:
await ctx.respond(f'Error: You need to be an Administrator to use this command', ephemeral=True)
@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)
f'/ping\n'
f'/setup <channel-id> <system-message>\n'
f'/add <text/prefix> <channel-id>\n'
f'/remove <text/prefix> <channel-id>\n'
f'/list <text/prefix>\n'
f'/delete <text/prefix> <channel-id>\n'
f'/help', ephemeral=True)
@bot.command(name="ping", description="Used to check if the bot is alive")
async def ping(ctx: discord.ApplicationContext):
await ctx.respond(f'pong', ephemeral=True)
# Old System, Rewrite needed
@bot.command(name="system", description="Used to setup the bot with a custom system message")
@commands.has_permissions(administrator=True)
async def system(ctx: discord.ApplicationContext):
try:
modal = EditSystemModal(title="Change System Message")
await ctx.send_modal(modal)
except:
await ctx.respond("No Config found for this Channel", ephemeral=True)
### /\ End Commands Area /\ ###
@bot.command(name="setup", description="Used to setup the bot with a custom system message")
async def setup(ctx: discord.ApplicationContext,
id: discord.Option(str, description="Channel-ID -> Activate Developer-Options to Copy"),
message: discord.Option(str, description="System Message")):
if ctx.author.guild_permissions.administrator:
try:
gpt.setup_history(id, message)
await ctx.respond(f'Setup successful', ephemeral=True)
except Exception as e:
await ctx.respond(f'Error: {e}', ephemeral=True)
else:
await ctx.respond(f'Error: You need to be an Administrator to use this command', ephemeral=True)
bot.run(str(os.environ.get('DISCORD_TOKEN')))

51
bot/featuretest.py Normal file
View File

@ -0,0 +1,51 @@
import modules.channelconfig as config
import modules.gpt as gpt
import os
text_channels = config.load_config()
def listen_input(username, channel):
message = input(f'{username} {channel}: ')
if message.startswith("/"):
print(slash_command(username, channel, message))
elif message.startswith("$") and channel in text_channels:
ask_gpt(username, channel, message)
else:
print(log_message(username, channel, message))
def log_message(user, channel, message):
return f'User {user} sent "{message}" in {channel}'
# Slash Command Wrapper
def slash_command(user, channel, message):
message = message.split("/")[1].split(" ")
# Add Channels to Config
if message[0] == "add":
pass
if message[1] == "text":
config.add_channel("text", message[2])
print("Added Channel to Config")
# Remove Channels from Config
elif message[0] == "remove":
if message[1] == "text":
return config.remove_channel("text", message[2])
# Reload Config
elif message[0] == "reload":
text_channels = config.load_config()
return text_channels
else:
return "Invalid Command"
def ask_gpt(user, id, message):
message = message.split('$')[1]
answer = gpt.get_answer(id, user, message)
print(answer)
username = "XYZ"
channel = "112233445566"
while True:
text_channels = config.load_config()
listen_input(username, channel)

View File

@ -0,0 +1,88 @@
# Rewrite of Channelmgmt
from os import path
folder = "configs"
text_channel_file = "text_channels.txt"
prefix_channel_file = "prefix_channels.txt"
def load_config():
# Load Text-Channel Config
try:
with open(path.join(folder,text_channel_file), "r") as f:
text_channels = f.read().split("\n")
except Exception as error:
print(f'File not Fount, creating new. {error}')
with open(path.join(folder,text_channel_file), "w") as f:
f.write('')
text_channels = []
# Load Prefix-Channel Config
try:
with open(path.join(folder, prefix_channel_file), "r") as f:
prefix_channels = f.read().split("\n")
except Exception as error:
print(f'File not Fount, creating new. {error}')
with open(path.join(folder, prefix_channel_file), "w") as f:
f.write('')
prefix_channels = []
return text_channels, prefix_channels
# Add Channel to Config
def add_channel(type, id):
try:
if type == "text":
text_channels = load_config()
if id in text_channels:
# Throw Error if already in List
raise ValueError("Channel already in List")
else:
with open(path.join(folder, text_channel_file), 'a') as f:
f.write(f'{id}\n')
return True
elif type == "prefix":
prefix_channels = load_config()
if id in prefix_channels:
# Throw Error if already in List
raise ValueError("Channel already in List")
else:
with open(path.join(folder, prefix_channel_file), 'a') as f:
f.write(f'{id}\n')
return True
except FileNotFoundError as error:
load_config()
add_channel(type, id)
def remove_channel(type, id):
try:
if type == "text":
text_channels = load_config()
if id in text_channels:
text_channels.remove(id)
new_conf = ""
for x in text_channels:
new_conf += f'{x}\n'
with open(path.join(folder, text_channel_file), 'w') as f:
f.write(new_conf)
return True
else:
raise ValueError("Channel not in List")
elif type == "prefix":
prefix_channels = load_config()
if id in prefix_channels:
prefix_channels.remove(id)
new_conf = ""
for x in prefix_channels:
new_conf += f'{x}\n'
with open(path.join(folder, prefix_channel_file), 'w') as f:
f.write(new_conf)
return True
else:
raise ValueError("Channel not in List")
except Exception as error:
print(error)
return False

View File

@ -1,259 +0,0 @@
import os
import aiosqlite
DB_FILE = os.path.join("config", "database.db")
async def init_db():
async with aiosqlite.connect(DB_FILE) as db:
await db.execute(
'''CREATE TABLE IF NOT EXISTS servers
(id INTEGER PRIMARY KEY AUTOINCREMENT, server_id TEXT UNIQUE, is_premium INTEGER)'''
)
await db.execute(
'''CREATE TABLE IF NOT EXISTS channels
(id INTEGER PRIMARY KEY AUTOINCREMENT,
server_id TEXT,
channel_id TEXT UNIQUE,
FOREIGN KEY(server_id) REFERENCES servers(id))'''
)
await db.execute(
'''CREATE TABLE IF NOT EXISTS config
(server_id TEXT,
channel_id TEXT,
prefix TEXT,
gpt INTEGER,
systemmsg TEXT,
FOREIGN KEY(server_id) REFERENCES servers(id),
FOREIGN KEY(channel_id) REFERENCES channels(id))'''
)
await db.execute(
'''CREATE TABLE IF NOT EXISTS chats
(id INTEGER PRIMARY KEY AUTOINCREMENT,
server_id TEXT,
channel_id TEXT,
user_id TEXT,
username TEXT,
msgrole TEXT,
message_id TEXT UNIQUE,
message TEXT,
messagecount INTEGER,
FOREIGN KEY(server_id) REFERENCES servers(id),
FOREIGN KEY(channel_id) REFERENCES channels(id))'''
)
await db.execute(
'''CREATE TABLE IF NOT EXISTS summaries
(id INTEGER PRIMARY KEY AUTOINCREMENT,
server_id TEXT,
channel_id TEXT,
summary TEXT,
summarycount INTEGER,
FOREIGN KEY(server_id) REFERENCES servers(id),
FOREIGN KEY(channel_id) REFERENCES channels(id))'''
)
await db.commit()
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.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,))
await db.commit()
async def list_servers():
async with aiosqlite.connect(DB_FILE) as db:
cursor = await db.execute('SELECT * FROM servers')
servers = await cursor.fetchall()
return servers
async def is_premium(server_id):
async with aiosqlite.connect(DB_FILE) as db:
cursor = await db.execute('SELECT * FROM servers WHERE server_id = ?', (server_id,))
server = await cursor.fetchone()
if server[2] == 1:
return True
else:
return False
async def default_premium(server_id):
async with aiosqlite.connect(DB_FILE) as db:
await db.execute('UPDATE servers SET is_premium = 0 WHERE server_id = ?', (server_id,))
await db.commit()
async def set_premium(server_id):
async with aiosqlite.connect(DB_FILE) as db:
await db.execute('UPDATE servers SET is_premium = 1 WHERE server_id = ?', (server_id,))
await db.commit()
async def unset_premium(server_id):
async with aiosqlite.connect(DB_FILE) as db:
await db.execute('UPDATE servers SET is_premium = 0 WHERE server_id = ?', (server_id,))
await db.commit()
async def get_server_by_id(server_id):
async with aiosqlite.connect(DB_FILE) as db:
cursor = await db.execute('SELECT * FROM servers WHERE server_id = ?', (server_id,))
server = await cursor.fetchone()
return server
async def add_channel(server_id, channel_id):
async with aiosqlite.connect(DB_FILE) as db:
await db.execute('INSERT OR IGNORE INTO channels (server_id, channel_id) VALUES (?, ?)', (server_id, channel_id))
await db.commit()
async def remove_channel(server_id, channel_id):
async with aiosqlite.connect(DB_FILE) as db:
await db.execute('DELETE FROM channels WHERE server_id = ? AND channel_id = ?', (server_id, channel_id))
await db.commit()
async def list_channels(server_id):
async with aiosqlite.connect(DB_FILE) as db:
cursor = await db.execute('SELECT * FROM channels WHERE server_id = ?', (server_id,))
channels = await cursor.fetchall()
return channels
async def get_channel_by_id(server_id, channel_id):
async with aiosqlite.connect(DB_FILE) as db:
cursor = await db.execute('SELECT * FROM channels WHERE server_id = ? AND channel_id = ?', (server_id, channel_id))
channel = await cursor.fetchone()
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}'
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.commit()
async def remove_config(server_id, channel_id):
async with aiosqlite.connect(DB_FILE) as db:
await db.execute('DELETE FROM config WHERE server_id = ? AND channel_id = ?', (server_id, channel_id))
await db.commit()
async def list_configs(server_id):
async with aiosqlite.connect(DB_FILE) as db:
cursor = await db.execute('SELECT * FROM config WHERE server_id = ?', (server_id,))
configs = await cursor.fetchall()
return configs
async def get_config_by_id(server_id, channel_id):
async with aiosqlite.connect(DB_FILE) as db:
cursor = await db.execute('SELECT * FROM config WHERE server_id = ? AND channel_id = ?', (server_id, channel_id))
config = await cursor.fetchone()
return config
async def get_channels_by_server(server_id):
async with aiosqlite.connect(DB_FILE) as db:
cursor = await db.execute('SELECT * FROM channels WHERE server_id = ?', (server_id,))
channels = await cursor.fetchall()
return channels
async def get_configs_by_server(server_id):
async with aiosqlite.connect(DB_FILE) as db:
cursor = await db.execute('SELECT * FROM config WHERE server_id = ?', (server_id,))
configs = await cursor.fetchall()
return configs
async def add_chat(server_id, channel_id, user_id, username, msgrole, message_id, message, messagecount):
async with aiosqlite.connect(DB_FILE) as db:
await db.execute('INSERT OR IGNORE INTO chats (server_id, channel_id, user_id, username, msgrole, message_id, message, messagecount) VALUES (?, ?, ?, ?, ?, ?, ?, ?)', (server_id, channel_id, user_id, username, msgrole, message_id, message, messagecount))
await db.commit()
async def remove_chat(server_id, channel_id, message_id):
async with aiosqlite.connect(DB_FILE) as db:
await db.execute('DELETE FROM chats WHERE server_id = ? AND channel_id = ? AND message_id = ?', (server_id, channel_id, message_id))
await db.commit()
async def remove_all_chats(server_id, channel_id):
async with aiosqlite.connect(DB_FILE) as db:
await db.execute('DELETE FROM chats WHERE server_id = ? AND channel_id = ?', (server_id, channel_id))
await db.commit()
async def list_chats(server_id, channel_id):
async with aiosqlite.connect(DB_FILE) as db:
cursor = await db.execute('SELECT * FROM chats WHERE server_id = ? AND channel_id = ? ORDER BY id ASC LIMIT 150', (server_id, channel_id))
chats = await cursor.fetchall()
return chats
async def get_chats_custom(server_id, channel_id, limit):
async with aiosqlite.connect(DB_FILE) as db:
cursor = await db.execute('SELECT * FROM chats WHERE server_id = ? AND channel_id = ? ORDER BY id ASC LIMIT ?', (server_id, channel_id, limit))
chats = await cursor.fetchall()
return chats
async def get_chat_by_id(server_id, channel_id, message_id):
async with aiosqlite.connect(DB_FILE) as db:
cursor = await db.execute('SELECT * FROM chats WHERE server_id = ? AND channel_id = ? AND message_id = ?', (server_id, channel_id, message_id))
chat = await cursor.fetchone()
return chat
async def get_last_chat(server_id, channel_id):
async with aiosqlite.connect(DB_FILE) as db:
cursor = await db.execute('SELECT * FROM chats WHERE server_id = ? AND channel_id = ? ORDER BY id DESC LIMIT 1', (server_id, channel_id))
chat = await cursor.fetchone()
return chat
async def get_chat_range(server_id, channel_id, start, end):
async with aiosqlite.connect(DB_FILE) as db:
cursor = await db.execute('SELECT * FROM chats WHERE server_id = ? AND channel_id = ? AND messagecount >= ? AND messagecount <= ? ORDER BY id ASC', (server_id, channel_id, start, end))
chats = await cursor.fetchall()
return chats
async def get_last_twenty_chats(server_id, channel_id):
async with aiosqlite.connect(DB_FILE) as db:
cursor = await db.execute('SELECT * FROM chats WHERE server_id = ? AND channel_id = ? ORDER BY id ASC LIMIT 20', (server_id, channel_id))
chats = await cursor.fetchall()
return chats
async def add_summary(server_id, channel_id, summary, summarycount):
async with aiosqlite.connect(DB_FILE) as db:
await db.execute('INSERT OR IGNORE INTO summaries (server_id, channel_id, summary, summarycount) VALUES (?, ?, ?, ?)', (server_id, channel_id, summary, summarycount))
await db.commit()
async def remove_summary(id, server_id, channel_id):
async with aiosqlite.connect(DB_FILE) as db:
await db.execute('DELETE FROM summaries WHERE id = ? AND server_id = ? AND channel_id = ?', (id, server_id, channel_id))
await db.commit()
async def list_summaries(server_id, channel_id):
async with aiosqlite.connect(DB_FILE) as db:
cursor = await db.execute('SELECT * FROM summaries WHERE server_id = ? AND channel_id = ?', (server_id, channel_id))
summaries = await cursor.fetchall()
return summaries
async def get_summary_by_id(id, server_id, channel_id):
async with aiosqlite.connect(DB_FILE) as db:
cursor = await db.execute('SELECT * FROM summaries WHERE id = ? AND server_id = ? AND channel_id = ?', (id, server_id, channel_id))
summary = await cursor.fetchone()
return summary
async def get_summary_by_count(server_id, channel_id, summarycount):
async with aiosqlite.connect(DB_FILE) as db:
cursor = await db.execute('SELECT * FROM summaries WHERE server_id = ? AND channel_id = ? AND summarycount = ?', (server_id, channel_id, summarycount))
summary = await cursor.fetchone()
return summary
async def get_latest_summary(server_id, channel_id):
async with aiosqlite.connect(DB_FILE) as db:
cursor = await db.execute('SELECT * FROM summaries WHERE server_id = ? AND channel_id = ? ORDER BY id DESC LIMIT 1', (server_id, channel_id))
summary = await cursor.fetchone()
return summary
async def add_summary_zero(server_id, channel_id):
summary = ''
summarycount = 0
if await get_latest_summary(server_id, channel_id) is not None:
if await get_last_chat(server_id, channel_id) is not None:
new_summary_point = await get_last_chat(server_id, channel_id)
new_summary_point = int(new_summary_point[8])
summarycount = new_summary_point + 1
async with aiosqlite.connect(DB_FILE) as db:
await db.execute('INSERT OR IGNORE INTO summaries (server_id, channel_id, summary, summarycount) VALUES (?, ?, ?, ?)', (server_id, channel_id, summary, summarycount))
await db.commit()

View File

@ -2,91 +2,110 @@ import openai
import json
import os
from dotenv import load_dotenv
try:
import summarize
import dbmanagement as dbm
except:
import modules.summarize as summarize
import modules.dbmanagement as dbm
import modules.summarize as summarize
import asyncio
load_dotenv(os.path.join("config", ".env"))
load_dotenv(os.path.join("configs", ".env"))
openai.api_key = os.environ.get('OPENAI_API_KEY')
folder = 'chats'
async def load_history(server_id, channel_id, mode):
if mode == 0: ### Normal History with System Messages
systemmsg = await dbm.get_config_by_id(server_id, channel_id)
systemmsg = systemmsg[4]
checkpoint = await dbm.get_latest_summary(server_id, channel_id)
checkpoint = checkpoint[4]
msgpoint = await dbm.get_last_chat(server_id, channel_id)
print(str(msgpoint))
msgpoint = msgpoint[8]
def load_history(id):
filename = f'{id}.json'
try:
with open(os.path.join(folder, filename), 'r') as f:
json.load(f)
results = await dbm.get_chat_range(server_id, channel_id, checkpoint, msgpoint)
except FileNotFoundError as error:
print(f'File not Found, creating... {error}')
if id == "199":
data = 'summarize:'
setup_history(id, data)
else:
data = 'default:'
setup_history(id, data)
messages = [{'role': result[5], 'content': result[7]} for result in results]
messages.insert(0, {'role': 'system', 'content': f'{systemmsg}'})
except json.JSONDecodeError as error:
os.remove(os.path.join(folder, filename))
print(f'File is empty, creating... {error}')
load_history(id)
summary = await dbm.get_latest_summary(server_id, channel_id)
summary = summary[3]
if summary != '':
messages.insert(1, {'role': 'system', 'content': 'This is the Summary of previous conversations:\n\n' + summary})
with open(os.path.join(folder, filename), 'r') as f:
f = json.load(f)
return messages
return f
if mode == 1: ### Summary Mode without System Messages and Formatted differently
checkpoint = await dbm.get_latest_summary(server_id, channel_id)
checkpoint = checkpoint[4]
msgpoint = await dbm.get_last_chat(server_id, channel_id)
msgpoint = msgpoint[8]
def update_history(id, data):
filename = f'{id}.json'
try:
with open(os.path.join(folder, filename), "r") as f:
loaded = json.load(f)
loaded.append(data)
results = await dbm.get_chat_range(server_id, channel_id, checkpoint, msgpoint-10)
with open(os.path.join(folder, filename), "w") as f:
json.dump(loaded, f)
messages = ''
for result in results:
if result[5] == 'assistant':
messages += f"Assistant: {result[7]}\n"
elif result[5] == 'user':
messages += f"{result[7]}\n"
except Exception as error:
print(error)
return messages
def delete_history(id):
filename = f'{id}.json'
try:
os.remove(os.path.join(folder, filename))
return "Successfully deleted"
except Exception as error:
return error
async def get_answer(id, user, message):
try:
history = load_history(id)
add_history = {"role": "user", "content": f'{user}: {message}'}
update_history(id, add_history)
history.append(add_history)
answer = openai.ChatCompletion.create(
model="gpt-3.5-turbo",
messages=history
)
answer = answer['choices'][0]['message']['content']
update_history(id, {"role": "assistant", "content": f"{answer}"})
if len(history) >= 26:
await summarize.summarize(id)
# add optional parameter for mode
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:
usemodel = "gpt-4"
return answer
except Exception as error:
return "Error while trying to use ChatAPI: " + str(error)
history = await load_history(server_id, channel_id, 0)
# def get_answergpt4(id, user, message):
# try:
# update_history(id, {"role": "user", "content": f'{user}: {message}'})
# history = load_history(id)
# answer = openai.ChatCompletion.create(
# model="gpt-4",
# messages=history
# )
# answer = answer['choices'][0]['message']['content']
# update_history(id, {"role": "assistant", "content": f"{answer}"})
# print(len(history))
# if len(history) >= 23:
# summarize.summarize(id)
#
# return answer
# except Exception as error:
# return "Error while trying to use ChatAPI " + str(error)
try:
answer = openai.ChatCompletion.create(
model=usemodel,
messages=history
)
answer = answer['choices'][0]['message']['content']
def setup_history(id, message):
filename = f'{id}.json'
return answer
except Exception as e:
return "Error while trying to use ChatAPI: " + str(e)
elif mode == 1: ### Summarize Mode
try:
answer = openai.ChatCompletion.create(
model="gpt-4",
messages=[{'role': 'user',
'content': f'Please summarize the following conversation: {msg}'}])
answer = answer['choices'][0]['message']['content']
return answer
except Exception as e:
return "Error while trying to use ChatAPI: " + str(e)
if message == "summarize":
message = [{"role": "system", "content": "You summarize conversation. You keep the most important things. Everything else can be removed."}]
elif message == "default":
message = [{"role": "system", "content": "You are an helpful assistant. Every Message the user writes starts with their username, the numbers and # must be ignored"}]
else:
message = [{"role": "system", "content": f"The Username consists of a name#numbers. The numbers can be ignored. {message}"}]
# If file exists, delete it
if os.path.exists(os.path.join(folder, filename)):
os.remove(os.path.join(folder, filename))
# Create new file
with open(os.path.join(folder, filename), "w") as f:
json.dump(message, f)

View File

@ -1,11 +1,7 @@
import modules.gpt as gpt
import json
import os
try:
import dbmanagement as dbm
import gpt
except:
import modules.dbmanagement as dbm
import modules.gpt as gpt
import asyncio
folder = 'chats'
async def summarize(id):
@ -35,13 +31,4 @@ async def summarize(id):
os.remove(os.path.join(folder, '199.json'))
return summarised
async def new_summarize(server_id, channel_id):
### Get
print(f'new_summarize called with {server_id} and {channel_id}')
history = await gpt.load_history(server_id, channel_id, 1)
summary = await gpt.get_answer(mode=1, msg=history)
msgpoint = await dbm.get_last_chat(server_id, channel_id)
msgpoint = msgpoint[8]
await dbm.add_summary(server_id, channel_id, summary, msgpoint-10)
return summarised

24
bot/modules/tts.py Normal file
View File

@ -0,0 +1,24 @@
# from TTS.api import TTS
# import uuid
# import os
# import asyncio
#
# # Use Model tts_models/de/thorsten/tacotron2-DCA
# # coqui-ai
#
# async def generate_audio(text):
# loop = asyncio.get_event_loop()
# folder = "audio"
# filename = f"{uuid.uuid4().hex}.wav"
# path = os.path.join(folder, filename)
#
# try:
# def tts_to_file_blocking():
# tts = TTS(model_name="tts_models/de/thorsten/tacotron2-DDC", progress_bar=True, gpu=False)
# tts.tts_to_file(text=text, file_path=path)
#
# await loop.run_in_executor(None, tts_to_file_blocking)
# return path
# except Exception as e:
# print(e)
# return str(e)

24
bot/summary.py Normal file
View File

@ -0,0 +1,24 @@
import modules.summarize as summarize
import modules.gpt as gpt
history = gpt.load_history('112233445566')
#print(summarize.summarize('112233445566'))
new_string = ''
if history[1]['role'] == 'system':
new_string += f"System:{history[1]['content']}\n"
for x in history[:-3]:
if x['role'] == "assistant":
new_string += f"Assistant: {x['content']}\n"
elif x['role'] == "user":
new_string += f"{x['content']}\n"
print(new_string)
print(history[1])
history[1] = {'test'}
print(history)

View File

@ -1,6 +1,5 @@
aiohttp==3.8.4
aiosignal==1.3.1
aiosqlite==0.18.0
async-timeout==4.0.2
attrs==22.2.0
certifi==2022.12.7