2022-12-08 22:21:53 +01:00
import discord
2023-03-31 16:11:03 +02:00
from config import debug , con_data , curs_data , moderate
2023-03-01 21:32:52 +01:00
from discord import default_permissions
2023-03-06 14:32:44 +01:00
import openai
2023-03-31 14:09:06 +02:00
2023-03-17 11:27:25 +01:00
models = [ " davinci " , " chatGPT " , " gpt-4 " ]
2023-03-15 22:30:54 +01:00
images_recognition = [ " enable " , " disable " ]
2023-03-31 14:09:06 +02:00
class Settings ( discord . Cog ) :
2022-12-08 22:21:53 +01:00
def __init__ ( self , bot : discord . Bot ) - > None :
super ( ) . __init__ ( )
self . bot = bot
2023-03-31 14:09:06 +02:00
# 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
2022-12-08 22:21:53 +01:00
@discord.slash_command ( name = " advanced " , description = " Advanced settings " )
##@discord.commands.permissions(administrator=True)
2023-03-31 14:09:06 +02:00
# add the options
2022-12-08 22:21:53 +01:00
@discord.option ( name = " max_tokens " , description = " The max tokens " , required = False )
@discord.option ( name = " temperature " , description = " The temperature " , required = False )
2023-03-31 14:09:06 +02:00
@discord.option (
name = " frequency_penalty " , description = " The frequency penalty " , required = False
)
@discord.option (
name = " presence_penalty " , description = " The presence penalty " , required = False
)
2022-12-08 22:21:53 +01:00
@discord.option ( name = " prompt_size " , description = " The prompt size " , required = False )
2023-03-31 14:09:06 +02:00
async def advanced (
self ,
ctx : discord . ApplicationContext ,
max_tokens : int = None ,
temperature : float = None ,
frequency_penalty : float = None ,
presence_penalty : float = None ,
prompt_size : int = None ,
) :
debug (
f " The user { ctx . author } ran the advanced command in the channel { ctx . channel } of the guild { ctx . guild } , named { ctx . guild . name } "
)
# check if the guild is in the database
2023-03-31 16:11:03 +02:00
curs_data . execute ( " SELECT * FROM data WHERE guild_id = ? " , ( ctx . guild . id , ) )
if curs_data . fetchone ( ) is None :
2022-12-08 22:21:53 +01:00
await ctx . respond ( " This server is not setup " , ephemeral = True )
return
2023-03-31 14:09:06 +02:00
# check if the user has entered at least one argument
if (
max_tokens is None
and temperature is None
and frequency_penalty is None
and presence_penalty is None
and prompt_size is None
) :
2022-12-08 22:21:53 +01:00
await ctx . respond ( " You must enter at least one argument " , ephemeral = True )
return
2023-03-31 14:09:06 +02:00
# check if the user has entered valid arguments
2023-03-15 22:30:54 +01:00
if max_tokens is not None and ( max_tokens < 1 or max_tokens > 4000 ) :
2022-12-08 22:21:53 +01:00
await ctx . respond ( " Invalid max tokens " , ephemeral = True )
return
if temperature is not None and ( temperature < 0.0 or temperature > 1.0 ) :
await ctx . respond ( " Invalid temperature " , ephemeral = True )
return
2023-03-31 14:09:06 +02:00
if frequency_penalty is not None and (
frequency_penalty < 0.0 or frequency_penalty > 2.0
) :
2022-12-08 22:21:53 +01:00
await ctx . respond ( " Invalid frequency penalty " , ephemeral = True )
return
2023-03-31 14:09:06 +02:00
if presence_penalty is not None and (
presence_penalty < 0.0 or presence_penalty > 2.0
) :
2022-12-08 22:21:53 +01:00
await ctx . respond ( " Invalid presence penalty " , ephemeral = True )
return
if prompt_size is not None and ( prompt_size < 1 or prompt_size > 10 ) :
await ctx . respond ( " Invalid prompt size " , ephemeral = True )
return
if max_tokens is None :
2023-03-31 14:09:06 +02:00
if (
2023-03-31 16:11:03 +02:00
curs_data . execute (
2023-03-31 14:09:06 +02:00
" SELECT max_tokens FROM data WHERE guild_id = ? " , ( ctx . guild . id , )
) . fetchone ( ) [ 0 ]
is not None
and max_tokens is None
) :
2023-03-31 16:11:03 +02:00
max_tokens = curs_data . execute (
2023-03-31 14:09:06 +02:00
" SELECT max_tokens FROM data WHERE guild_id = ? " , ( ctx . guild . id , )
) . fetchone ( ) [ 0 ]
2022-12-08 22:21:53 +01:00
else :
max_tokens = 64
if temperature is None :
2023-03-31 14:09:06 +02:00
if (
2023-03-31 16:11:03 +02:00
curs_data . execute (
2023-03-31 14:09:06 +02:00
" SELECT temperature FROM data WHERE guild_id = ? " , ( ctx . guild . id , )
) . fetchone ( ) [ 0 ]
is not None
and temperature is None
) :
2023-03-31 16:11:03 +02:00
temperature = curs_data . execute (
2023-03-31 14:09:06 +02:00
" SELECT temperature FROM data WHERE guild_id = ? " , ( ctx . guild . id , )
) . fetchone ( ) [ 0 ]
2022-12-08 22:21:53 +01:00
else :
temperature = 0.9
if frequency_penalty is None :
2023-03-31 14:09:06 +02:00
if (
2023-03-31 16:11:03 +02:00
curs_data . execute (
2023-03-31 14:09:06 +02:00
" SELECT frequency_penalty FROM data WHERE guild_id = ? " ,
( ctx . guild . id , ) ,
) . fetchone ( ) [ 0 ]
is not None
and frequency_penalty is None
) :
2023-03-31 16:11:03 +02:00
frequency_penalty = curs_data . execute (
2023-03-31 14:09:06 +02:00
" SELECT frequency_penalty FROM data WHERE guild_id = ? " ,
( ctx . guild . id , ) ,
) . fetchone ( ) [ 0 ]
2022-12-08 22:21:53 +01:00
else :
frequency_penalty = 0.0
if presence_penalty is None :
2023-03-31 14:09:06 +02:00
if (
2023-03-31 16:11:03 +02:00
curs_data . execute (
2023-03-31 14:09:06 +02:00
" SELECT presence_penalty FROM data WHERE guild_id = ? " ,
( ctx . guild . id , ) ,
) . fetchone ( ) [ 0 ]
is not None
and presence_penalty is None
) :
2023-03-31 16:11:03 +02:00
presence_penalty = curs_data . execute (
2023-03-31 14:09:06 +02:00
" SELECT presence_penalty FROM data WHERE guild_id = ? " ,
( ctx . guild . id , ) ,
) . fetchone ( ) [ 0 ]
2022-12-08 22:21:53 +01:00
else :
presence_penalty = 0.0
if prompt_size is None :
2023-03-31 14:09:06 +02:00
if (
2023-03-31 16:11:03 +02:00
curs_data . execute (
2023-03-31 14:09:06 +02:00
" SELECT prompt_size FROM data WHERE guild_id = ? " , ( ctx . guild . id , )
) . fetchone ( ) [ 0 ]
is not None
and prompt_size is None
) :
2023-03-31 16:11:03 +02:00
prompt_size = curs_data . execute (
2023-03-31 14:09:06 +02:00
" SELECT prompt_size FROM data WHERE guild_id = ? " , ( ctx . guild . id , )
) . fetchone ( ) [ 0 ]
2022-12-08 22:21:53 +01:00
else :
prompt_size = 1
2023-03-31 14:09:06 +02:00
# update the database
2023-03-31 16:11:03 +02:00
curs_data . execute (
2023-03-31 14:09:06 +02:00
" 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 ,
) ,
)
2023-03-31 16:11:03 +02:00
con_data . commit ( )
2022-12-08 22:21:53 +01:00
await ctx . respond ( " Advanced settings updated " , ephemeral = True )
2023-03-31 14:09:06 +02:00
# 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
2022-12-08 22:21:53 +01:00
@discord.slash_command ( name = " default " , description = " Default settings " )
##@discord.commands.permissions(administrator=True)
async def default ( self , ctx : discord . ApplicationContext ) :
2023-03-31 14:09:06 +02:00
debug (
f " The user { ctx . author } ran the default command in the channel { ctx . channel } of the guild { ctx . guild } , named { ctx . guild . name } "
)
# check if the guild is in the database
2023-03-31 16:11:03 +02:00
curs_data . execute ( " SELECT * FROM data WHERE guild_id = ? " , ( ctx . guild . id , ) )
if curs_data . fetchone ( ) is None :
2023-03-31 14:09:06 +02:00
await ctx . respond (
" This server is not setup, please run /setup " , ephemeral = True
)
2022-12-08 22:21:53 +01:00
return
2023-03-31 14:09:06 +02:00
# set the advanced settings (max_tokens, temperature, frequency_penalty, presence_penalty, prompt_size) and also prompt_prefix to their default values
2023-03-31 16:11:03 +02:00
curs_data . execute (
2023-03-31 14:09:06 +02:00
" UPDATE data SET max_tokens = ?, temperature = ?, frequency_penalty = ?, presence_penalty = ?, prompt_size = ? WHERE guild_id = ? " ,
( 64 , 0.9 , 0.0 , 0.0 , 5 , ctx . guild . id ) ,
)
2023-03-31 16:11:03 +02:00
con_data . commit ( )
2023-03-31 14:09:06 +02:00
await ctx . respond (
" The advanced settings have been set to their default values " ,
ephemeral = True ,
)
2022-12-08 22:21:53 +01:00
2023-03-31 14:09:06 +02:00
# create a command called "cancel" that deletes the last message sent by the bot in the response channel
# when a message is sent into a channel check if the guild is in the database and if the bot is enabled
@discord.slash_command (
name = " info " , description = " Show the information stored about this server "
)
2022-12-08 22:21:53 +01:00
async def info ( self , ctx : discord . ApplicationContext ) :
2023-03-31 14:09:06 +02:00
debug (
f " The user { ctx . author } ran the info command in the channel { ctx . channel } of the guild { ctx . guild } , named { ctx . guild . name } "
)
# this command sends all the data about the guild, including the api key, the channel id, the advanced settings and the uses_count_today
# check if the guild is in the database
try :
2023-03-31 16:11:03 +02:00
curs_data . execute ( " SELECT * FROM data WHERE guild_id = ? " , ( ctx . guild . id , ) )
data = curs_data . fetchone ( )
2023-03-31 14:09:06 +02:00
except :
data = None
2023-03-02 18:04:27 +01:00
if data [ 2 ] is None :
2022-12-08 22:21:53 +01:00
await ctx . respond ( " This server is not setup " , ephemeral = True )
return
2023-03-02 18:04:27 +01:00
try :
2023-03-31 16:11:03 +02:00
curs_data . execute ( " SELECT * FROM model WHERE guild_id = ? " , ( ctx . guild . id , ) )
model = curs_data . fetchone ( ) [ 1 ]
2023-03-31 14:09:06 +02:00
except :
model = None
if model is None :
model = " davinci "
embed = discord . Embed (
title = " Info " , description = " Here is the info page " , color = 0x00FF00
)
2022-12-08 22:21:53 +01:00
embed . add_field ( name = " guild_id " , value = data [ 0 ] , inline = False )
2023-03-02 18:04:27 +01:00
embed . add_field ( name = " API Key " , value = " secret " , inline = False )
embed . add_field ( name = " Main channel ID " , value = data [ 1 ] , inline = False )
embed . add_field ( name = " Model " , value = model , inline = False )
2022-12-08 22:21:53 +01:00
embed . add_field ( name = " Is Active " , value = data [ 3 ] , inline = False )
embed . add_field ( name = " Max Tokens " , value = data [ 4 ] , inline = False )
embed . add_field ( name = " Temperature " , value = data [ 5 ] , inline = False )
embed . add_field ( name = " Frequency Penalty " , value = data [ 6 ] , inline = False )
embed . add_field ( name = " Presence Penalty " , value = data [ 7 ] , inline = False )
embed . add_field ( name = " Prompt Size " , value = data [ 9 ] , inline = False )
embed . add_field ( name = " Uses Count Today " , value = data [ 8 ] , inline = False )
2022-12-10 00:28:30 +01:00
if data [ 10 ] :
embed . add_field ( name = " Prompt prefix " , value = data [ 10 ] , inline = False )
2022-12-08 22:21:53 +01:00
await ctx . respond ( embed = embed , ephemeral = True )
2023-03-31 14:09:06 +02:00
# add a slash command called "prefix" that changes the prefix of the bot
2022-12-08 22:21:53 +01:00
@discord.slash_command ( name = " prefix " , description = " Change the prefix of the prompt " )
2023-03-06 14:32:44 +01:00
async def prefix ( self , ctx : discord . ApplicationContext , prefix : str = " " ) :
2023-03-31 14:09:06 +02:00
debug (
f " The user { ctx . author . name } ran the prefix command command in the channel { ctx . channel } of the guild { ctx . guild } , named { ctx . guild . name } "
)
2023-03-06 14:32:44 +01:00
try :
2023-03-31 16:11:03 +02:00
curs_data . execute ( " SELECT * FROM data WHERE guild_id = ? " , ( ctx . guild . id , ) )
data = curs_data . fetchone ( )
2023-03-06 14:32:44 +01:00
api_key = data [ 2 ]
2023-03-31 14:09:06 +02:00
except :
2023-03-06 14:32:44 +01:00
await ctx . respond ( " This server is not setup " , ephemeral = True )
return
if api_key is None or api_key == " " :
await ctx . respond ( " This server is not setup " , ephemeral = True )
return
if prefix != " " :
await ctx . defer ( )
if await moderate ( api_key = api_key , text = prefix ) :
2023-03-31 14:09:06 +02:00
await ctx . respond (
" This has been flagged as inappropriate by OpenAI, please choose another prefix " ,
ephemeral = True ,
)
2023-03-06 14:32:44 +01:00
return
await ctx . respond ( " Prefix changed ! " , ephemeral = True , delete_after = 5 )
2023-03-31 16:11:03 +02:00
curs_data . execute (
2023-03-31 14:09:06 +02:00
" UPDATE data SET prompt_prefix = ? WHERE guild_id = ? " ,
( prefix , ctx . guild . id ) ,
)
2023-03-31 16:11:03 +02:00
con_data . commit ( )
2022-12-08 22:21:53 +01:00
2023-03-31 14:09:06 +02:00
# when someone mentions the bot, check if the guild is in the database and if the bot is enabled. If it is, send a message answering the mention
@discord.slash_command (
name = " pretend " , description = " Make the bot pretend to be someone else "
)
@discord.option (
name = " pretend to be... " ,
description = " The person/thing you want the bot to pretend to be. Leave blank to disable pretend mode " ,
required = False ,
)
2023-03-06 14:32:44 +01:00
async def pretend ( self , ctx : discord . ApplicationContext , pretend_to_be : str = " " ) :
2023-03-31 14:09:06 +02:00
debug (
f " The user { ctx . author } ran the pretend command in the channel { ctx . channel } of the guild { ctx . guild } , named { ctx . guild . name } "
)
# check if the guild is in the database
try :
2023-03-31 16:11:03 +02:00
curs_data . execute ( " SELECT * FROM data WHERE guild_id = ? " , ( ctx . guild . id , ) )
data = curs_data . fetchone ( )
2023-03-06 14:32:44 +01:00
api_key = data [ 2 ]
except :
2022-12-08 22:21:53 +01:00
await ctx . respond ( " This server is not setup " , ephemeral = True )
return
2023-03-06 14:32:44 +01:00
if api_key is None or api_key == " " :
await ctx . respond ( " This server is not setup " , ephemeral = True )
2022-12-08 22:21:53 +01:00
return
2023-03-06 14:32:44 +01:00
if pretend_to_be is not None or pretend_to_be != " " :
await ctx . defer ( )
if await moderate ( api_key = api_key , text = pretend_to_be ) :
2023-03-31 14:09:06 +02:00
await ctx . respond (
" This has been flagged as inappropriate by OpenAI, please choose another name " ,
ephemeral = True ,
)
2023-03-06 14:32:44 +01:00
return
2023-03-06 15:13:23 +01:00
if pretend_to_be == " " :
2022-12-10 17:51:36 +01:00
pretend_to_be = " "
2023-03-31 16:11:03 +02:00
curs_data . execute (
2023-03-31 14:09:06 +02:00
" UPDATE data SET pretend_enabled = 0 WHERE guild_id = ? " ,
( ctx . guild . id , ) ,
)
2023-03-31 16:11:03 +02:00
con_data . commit ( )
2023-03-06 14:32:44 +01:00
await ctx . respond ( " Pretend mode disabled " , ephemeral = True , delete_after = 5 )
2022-12-08 22:21:53 +01:00
await ctx . guild . me . edit ( nick = None )
2022-12-10 17:51:36 +01:00
return
2022-12-08 22:21:53 +01:00
else :
2023-03-31 16:11:03 +02:00
curs_data . execute (
2023-03-31 14:09:06 +02:00
" UPDATE data SET pretend_enabled = 1 WHERE guild_id = ? " ,
( ctx . guild . id , ) ,
)
2023-03-31 16:11:03 +02:00
con_data . commit ( )
2023-03-06 14:32:44 +01:00
await ctx . respond ( " Pretend mode enabled " , ephemeral = True , delete_after = 5 )
2023-03-31 14:09:06 +02:00
# change the bots name on the server wit ctx.guild.me.edit(nick=pretend_to_be)
2022-12-16 12:51:26 +01:00
await ctx . guild . me . edit ( nick = pretend_to_be )
2023-03-31 16:11:03 +02:00
curs_data . execute (
2023-03-31 14:09:06 +02:00
" UPDATE data SET pretend_to_be = ? WHERE guild_id = ? " ,
( pretend_to_be , ctx . guild . id ) ,
)
2023-03-31 16:11:03 +02:00
con_data . commit ( )
2023-03-31 14:09:06 +02:00
# if the usename is longer than 32 characters, shorten it
if len ( pretend_to_be ) > 31 :
2023-03-06 14:32:44 +01:00
pretend_to_be = pretend_to_be [ : 32 ]
2022-12-10 19:56:28 +01:00
await ctx . guild . me . edit ( nick = pretend_to_be )
2022-12-10 17:51:36 +01:00
return
2022-12-08 22:21:53 +01:00
@discord.slash_command ( name = " enable_tts " , description = " Enable TTS when chatting " )
async def enable_tts ( self , ctx : discord . ApplicationContext ) :
2023-03-31 14:09:06 +02:00
# get the guild id
2022-12-08 22:21:53 +01:00
guild_id = ctx . guild . id
2023-03-31 14:09:06 +02:00
# connect to the database
# update the tts value in the database
2023-03-31 16:11:03 +02:00
curs_data . execute ( " UPDATE data SET tts = 1 WHERE guild_id = ? " , ( guild_id , ) )
con_data . commit ( )
2023-03-31 14:09:06 +02:00
# send a message
2022-12-08 22:21:53 +01:00
await ctx . respond ( " TTS has been enabled " , ephemeral = True )
@discord.slash_command ( name = " disable_tts " , description = " Disable TTS when chatting " )
async def disable_tts ( self , ctx : discord . ApplicationContext ) :
2023-03-31 14:09:06 +02:00
# get the guild id
2022-12-08 22:21:53 +01:00
guild_id = ctx . guild . id
2023-03-31 14:09:06 +02:00
# connect to the database
# update the tts value in the database
2023-03-31 16:11:03 +02:00
curs_data . execute ( " UPDATE data SET tts = 0 WHERE guild_id = ? " , ( guild_id , ) )
con_data . commit ( )
2023-03-31 14:09:06 +02:00
# send a message
2022-12-08 22:21:53 +01:00
await ctx . respond ( " TTS has been disabled " , ephemeral = True )
2023-03-31 14:09:06 +02:00
# autocompletition
2023-03-01 21:30:16 +01:00
async def autocomplete ( ctx : discord . AutocompleteContext ) :
return [ model for model in models if model . startswith ( ctx . value ) ]
2023-03-31 14:09:06 +02:00
2023-03-01 21:30:16 +01:00
@discord.slash_command ( name = " model " , description = " Change the model used by the bot " )
2023-03-31 14:09:06 +02:00
@discord.option (
name = " model " ,
description = " The model you want to use. Leave blank to use the davinci model " ,
required = False ,
autocomplete = autocomplete ,
)
2023-03-01 21:32:52 +01:00
@default_permissions ( administrator = True )
2023-03-01 21:30:16 +01:00
async def model ( self , ctx : discord . ApplicationContext , model : str = " davinci " ) :
2023-03-31 14:09:06 +02:00
try :
2023-03-31 16:11:03 +02:00
curs_data . execute ( " SELECT * FROM model WHERE guild_id = ? " , ( ctx . guild . id , ) )
data = curs_data . fetchone ( ) [ 1 ]
2023-03-01 21:30:16 +01:00
except :
data = None
2023-03-31 14:09:06 +02:00
if data is None :
2023-03-31 16:11:03 +02:00
curs_data . execute ( " INSERT INTO model VALUES (?, ?) " , ( ctx . guild . id , model ) )
2023-03-31 14:09:06 +02:00
else :
2023-03-31 16:11:03 +02:00
curs_data . execute (
2023-03-31 14:09:06 +02:00
" UPDATE model SET model_name = ? WHERE guild_id = ? " ,
( model , ctx . guild . id ) ,
)
2023-03-31 16:11:03 +02:00
con_data . commit ( )
2023-03-15 22:30:54 +01:00
await ctx . respond ( " Model changed ! " , ephemeral = True )
2023-03-31 14:09:06 +02:00
2023-03-15 22:30:54 +01:00
async def images_recognition_autocomplete ( ctx : discord . AutocompleteContext ) :
2023-03-17 11:27:25 +01:00
return [ state for state in images_recognition if state . startswith ( ctx . value ) ]
2023-03-31 14:09:06 +02:00
@discord.slash_command (
name = " images " , description = " Enable or disable images recognition "
)
@discord.option (
name = " enable_disable " ,
description = " Enable or disable images recognition " ,
autocomplete = images_recognition_autocomplete ,
)
2023-03-15 22:30:54 +01:00
@default_permissions ( administrator = True )
async def images ( self , ctx : discord . ApplicationContext , enable_disable : str ) :
try :
2023-03-31 16:11:03 +02:00
curs_data . execute ( " SELECT * FROM images WHERE guild_id = ? " , ( ctx . guild . id , ) )
data = curs_data . fetchone ( )
2023-03-15 22:30:54 +01:00
except :
data = None
2023-03-31 14:09:06 +02:00
if enable_disable == " enable " :
enable_disable = 1
elif enable_disable == " disable " :
enable_disable = 0
if data is None :
2023-03-31 16:11:03 +02:00
curs_data . execute (
2023-03-31 14:09:06 +02:00
" INSERT INTO images VALUES (?, ?, ?) " , ( ctx . guild . id , 0 , enable_disable )
)
else :
2023-03-31 16:11:03 +02:00
curs_data . execute (
2023-03-31 14:09:06 +02:00
" UPDATE images SET is_enabled = ? WHERE guild_id = ? " ,
( enable_disable , ctx . guild . id ) ,
)
2023-03-31 16:11:03 +02:00
con_data . commit ( )
2023-03-31 14:09:06 +02:00
await ctx . respond (
" Images recognition has been "
+ ( " enabled " if enable_disable == 1 else " disabled " ) ,
ephemeral = True ,
)