mirror of
https://github.com/Paillat-dev/Botator.git
synced 2026-01-02 01:06:19 +00:00
188 lines
9.4 KiB
Python
188 lines
9.4 KiB
Python
import openai # pip install openai
|
|
import discord # pip install pycord
|
|
from discord import File, Intents # pip install pycord
|
|
import logging # pip install logging
|
|
import sqlite3 # pip install sqlite3
|
|
#set the debug mode to the maximum
|
|
logging.basicConfig(level=logging.INFO)
|
|
def debug(message):
|
|
logging.info(message)
|
|
|
|
#create a database called "database.db" if the database does not exist, else connect to it
|
|
conn = sqlite3.connect('data.db')
|
|
c = conn.cursor()
|
|
|
|
# Create table called "data" if it does not exist with the following columns: guild_id, channel_id, api_key, is_active, max_tokens, temperature, frequency_penalty, presence_penalty, uses_count_today, prompt_size
|
|
c.execute('''CREATE TABLE IF NOT EXISTS data (guild_id text, channel_id text, api_key text, is_active boolean, max_tokens integer, temperature real, frequency_penalty real, presence_penalty real)''')
|
|
Intents =discord.Intents.all() # enable all intents
|
|
Intents.members = True
|
|
bot = discord.Bot(intents=Intents.all())
|
|
#create a command called "setup" that takes 2 arguments: the channel id and the api key
|
|
@bot.command()
|
|
@discord.commands.option(name="channel_id", description="The channel id", required=True)
|
|
@discord.commands.option(name="api_key", description="The api key", required=True)
|
|
async def setup(ctx, channel: discord.TextChannel, api_key):
|
|
#check if the api key is valid
|
|
openai.api_key = api_key
|
|
try:
|
|
openai.Completion.create(engine="davinci", prompt="Hello world", max_tokens=1)
|
|
except:
|
|
await ctx.respond("Invalid api key", ephemeral=True)
|
|
return
|
|
#check if the channel is valid
|
|
if channel is None:
|
|
await ctx.respond("Invalid channel id", ephemeral=True)
|
|
return
|
|
#check if the guild is already in the database
|
|
c.execute("SELECT * FROM data WHERE guild_id = ?", (ctx.guild.id,))
|
|
if c.fetchone() is not None:
|
|
await ctx.respond("This server is already setup", ephemeral=True)
|
|
return
|
|
#add the guild to the database
|
|
c.execute("INSERT INTO data VALUES (?, ?, ?, ?, ?, ?, ?, ?)", (ctx.guild.id, channel.id, api_key, False, 150, 0.5, 0.5, 0.5))
|
|
conn.commit()
|
|
await ctx.send("The guild has been added to the database")
|
|
#create a command called "enable" taht only admins can use
|
|
@bot.command()
|
|
@discord.commands.has_permissions(administrator=True)
|
|
async def enable(ctx):
|
|
#check if the guild is in the database
|
|
c.execute("SELECT * FROM data WHERE guild_id = ?", (ctx.guild.id,))
|
|
if c.fetchone() is None:
|
|
await ctx.respond("This server is not setup", ephemeral=True)
|
|
return
|
|
#enable the guild
|
|
c.execute("UPDATE data SET is_active = ? WHERE guild_id = ?", (True, ctx.guild.id))
|
|
conn.commit()
|
|
await ctx.send("The guild has been enabled")
|
|
#create a command called "disable" that only admins can use
|
|
@bot.command()
|
|
@discord.commands.has_permissions(administrator=True)
|
|
async def disable(ctx):
|
|
#check if the guild is in the database
|
|
c.execute("SELECT * FROM data WHERE guild_id = ?", (ctx.guild.id,))
|
|
if c.fetchone() is None:
|
|
await ctx.respond("This server is not setup", ephemeral=True)
|
|
return
|
|
#disable the guild
|
|
c.execute("UPDATE data SET is_active = ? WHERE guild_id = ?", (False, ctx.guild.id))
|
|
conn.commit()
|
|
await ctx.send("The guild has been disabled")
|
|
#create a command called "advanced" that only admins can use, wich sets the advanced settings up: max_tokens, temperature, frequency_penalty, presence_penalty, prompt_size
|
|
@bot.command()
|
|
@discord.commands.has_permissions(administrator=True)
|
|
#set the first argument: max_tokens, with a default value of 150
|
|
@discord.commands.option(name="max_tokens", description="The max tokens", required=False)
|
|
#set the second argument: temperature, with a default value of 0.5
|
|
@discord.commands.option(name="temperature", description="The temperature", required=False)
|
|
#set the third argument: frequency_penalty, with a default value of 0.5
|
|
@discord.commands.option(name="frequency_penalty", description="The frequency penalty", required=False)
|
|
#set the fourth argument: presence_penalty, with a default value of 0.5
|
|
@discord.commands.option(name="presence_penalty", description="The presence penalty", required=False)
|
|
#set the fifth argument: prompt_size, with a default value of 5
|
|
@discord.commands.option(name="prompt_size", description="The number of messages to use as a prompt", required=False)
|
|
async def advanced(ctx, max_tokens=150, temperature=0.5, frequency_penalty=0.5, presence_penalty=0.5, prompt_size=5):
|
|
#check if the guild is in the database
|
|
c.execute("SELECT * FROM data WHERE guild_id = ?", (ctx.guild.id,))
|
|
if c.fetchone() is None:
|
|
await ctx.respond("This server is not setup, please run /setup", ephemeral=True)
|
|
return
|
|
#update the advanced settings
|
|
c.execute("UPDATE data SET max_tokens = ?, temperature = ?, frequency_penalty = ?, presence_penalty = ?, prompt_size = ? WHERE guild_id = ?", (max_tokens, temperature, frequency_penalty, presence_penalty, prompt_size, ctx.guild.id))
|
|
conn.commit()
|
|
await ctx.respond("The advanced settings have been updated", ephemeral=True)
|
|
#create a command called "delete" that only admins can use wich deletes the guild id, the api key, the channel id and the advanced settings from the database
|
|
@bot.command()
|
|
@discord.commands.has_permissions(administrator=True)
|
|
async def delete(ctx):
|
|
#check if the guild is in the database
|
|
c.execute("SELECT * FROM data WHERE guild_id = ?", (ctx.guild.id,))
|
|
if c.fetchone() is None:
|
|
await ctx.respond("This server is not setup", ephemeral=True)
|
|
return
|
|
#delete the guild from the database
|
|
c.execute("DELETE FROM data WHERE guild_id = ?", (ctx.guild.id,))
|
|
conn.commit()
|
|
await ctx.send("The guild has been deleted from the database")
|
|
@bot.command()
|
|
async def help(ctx):
|
|
embed = discord.Embed(title="Help", description="Here is the help page", color=0x00ff00)
|
|
embed.add_field(name="/setup", value="Setup the bot", inline=False)
|
|
embed.add_field(name="/enable", value="Enable the bot", inline=False)
|
|
embed.add_field(name="/disable", value="Disable the bot", inline=False)
|
|
embed.add_field(name="/advanced", value="Set the advanced settings", inline=False)
|
|
embed.add_field(name="/delete", value="Delete all your data from our server", inline=False)
|
|
embed.add_field(name="/help", value="Show this message", inline=False)
|
|
await ctx.respond(embed=embed, ephemeral=True)
|
|
#when a message is sent into a channel check if the guild is in the database and if the bot is enabled
|
|
@bot.event
|
|
async def on_message(message):
|
|
#check if the message is from a bot
|
|
if message.author.bot:
|
|
return
|
|
#check if the guild is in the database
|
|
c.execute("SELECT * FROM data WHERE guild_id = ?", (message.guild.id,))
|
|
if c.fetchone() is None:
|
|
return
|
|
#check if the bot is enabled
|
|
c.execute("SELECT is_active FROM data WHERE guild_id = ?", (message.guild.id,))
|
|
if c.fetchone()[0] == False:
|
|
return
|
|
#check if the message has been sent in the channel set in the database
|
|
c.execute("SELECT channel_id FROM data WHERE guild_id = ?", (message.guild.id,))
|
|
if str(message.channel.id) != str(c.fetchone()[0]):
|
|
return
|
|
|
|
#get the api key from the database
|
|
c.execute("SELECT api_key FROM data WHERE guild_id = ?", (message.guild.id,))
|
|
api_key = c.fetchone()[0]
|
|
#get the advanced settings from the database
|
|
c.execute("SELECT max_tokens, temperature, frequency_penalty, presence_penalty, prompt_size FROM data WHERE guild_id = ?", (message.guild.id,))
|
|
max_tokens, temperature, frequency_penalty, presence_penalty, prompt_size = c.fetchone()
|
|
messages = await message.channel.history(limit=prompt_size).flatten()
|
|
messages.reverse()
|
|
prompt = ""
|
|
for msg in messages:
|
|
if msg.author.bot:
|
|
prompt += f"AI: {msg.content}\n"
|
|
else:
|
|
prompt += f"{msg.author.display_name}: {msg.content}\n"
|
|
prompt = f"This is a conversation with an AI. Only the {prompt_size} last messages are used as a prompt. The AI will continue the conversation. The AI is very intelligent and smart. \n\n" + prompt
|
|
#send the request to the api
|
|
debug("Sending request to the api")
|
|
debug(prompt)
|
|
openai.api_key = api_key
|
|
response = openai.Completion.create(
|
|
engine="text-davinci-002",
|
|
prompt=str(prompt),
|
|
max_tokens=int(max_tokens),
|
|
top_p=1,
|
|
temperature=float(temperature),
|
|
frequency_penalty=float(frequency_penalty),
|
|
presence_penalty=float(presence_penalty),
|
|
stop=[" Human:", " AI:"]
|
|
)
|
|
#send the response
|
|
if response["choices"][0] ["text"] != "":
|
|
await message.channel.send(response["choices"][0]["text"])
|
|
else:
|
|
await message.channel.send("The AI is not sure what to say (the response was empty)")
|
|
debug("The response was empty")
|
|
debug("The response has been sent")
|
|
|
|
#get the message content
|
|
# add a slash command called "say" that sends a message to the channel
|
|
@bot.slash_command()
|
|
async def say(ctx, message: str):
|
|
await ctx.respond("message sent!", ephemeral=True)
|
|
await ctx.send(message)
|
|
#add a slash command called "clear" that deletes all the messages in the channel
|
|
@bot.slash_command()
|
|
async def clear(ctx):
|
|
await ctx.respond("messages deleted!", ephemeral=True)
|
|
return await ctx.channel.purge()
|
|
|
|
#run the bot
|
|
# Replace the following with your bot's token
|
|
bot.run("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")
|