2023-07-09 00:57:11 -07:00
import discord
2023-07-10 10:38:28 -07:00
from discord . ext import commands , tasks
2023-07-09 00:57:11 -07:00
from discord . utils import get
import shutil
import json
import random
import time
import os
import asyncio
from dotenv import load_dotenv
import aiohttp
2023-07-13 01:10:28 -07:00
#Stable Diffusion
2023-07-16 22:52:43 -07:00
#Set this env variable to http://host:port or "disabled"
2023-07-13 01:10:28 -07:00
#os.getenv('stablediffusion_url')
2023-07-09 00:57:11 -07:00
#env vars START
load_dotenv ( )
imgflip_username = os . getenv ( ' imgflip_username ' )
imgflip_password = os . getenv ( ' imgflip_password ' )
discord_token = os . getenv ( ' discord_token ' )
ftp_server = os . getenv ( ' ftp_server ' )
ftp_username = os . getenv ( ' ftp_username ' )
ftp_password = os . getenv ( ' ftp_password ' )
ftp_public_html = os . getenv ( ' ftp_public_html ' )
#env vars END
2024-01-17 18:09:45 -08:00
#discord setup START
2024-01-20 23:04:12 -08:00
intents = discord . Intents . all ( )
2023-07-09 00:57:11 -07:00
intents . message_content = True
2024-01-20 21:55:19 -08:00
bot = commands . Bot ( command_prefix = ' ! ' , intents = intents )
2024-01-17 18:09:45 -08:00
#discord setup END
2023-12-27 20:48:57 -08:00
2023-07-09 18:02:15 -07:00
2023-07-11 17:04:28 -07:00
async def handle_error ( error ) :
print ( error )
current_time = time . strftime ( " % Y- % m- %d % H: % M: % S " , time . localtime ( ) )
2023-07-16 16:35:40 -07:00
log_line = current_time + ' : ' + str ( error ) + ' \n '
2024-01-20 01:33:35 -08:00
with open ( " data/error_log.txt " , ' a ' ) as f :
2023-07-11 17:04:28 -07:00
f . write ( log_line )
return error
2023-07-09 00:57:11 -07:00
2024-01-20 17:39:19 -08:00
2023-07-09 00:57:11 -07:00
def create_channel_config ( filepath ) :
config_dict = {
" personality " : " average " ,
" channel_topic " : " casual " ,
" chat_enabled " : False ,
" commands_enabled " : True ,
" chat_history_len " : 5 ,
" look_at_images " : False ,
" react_to_msgs " : False ,
" ftp_enabled " : False
}
with open ( filepath , " w " ) as f :
json . dump ( config_dict , f )
print ( " Wrote config variables to file. " )
async def get_channel_config ( channel_id ) :
2023-07-09 16:06:45 -07:00
filepath = " channels/config/ {0} .json " . format ( str ( channel_id ) )
2023-07-09 00:57:11 -07:00
if not os . path . exists ( filepath ) :
create_channel_config ( filepath )
with open ( filepath , " r " ) as f :
config_dict = json . loads ( f . readline ( ) )
return config_dict
async def react_to_msg ( ctx , react ) :
2023-07-25 17:49:30 -07:00
def is_emoji ( string ) :
if len ( string ) == 1 :
# Range of Unicode codepoints for emojis
2023-08-19 12:40:46 -07:00
if 0x1F300 < = ord ( string ) < = 0x1F6FF :
2023-07-25 17:49:30 -07:00
return True
return False
2023-07-25 17:20:14 -07:00
if react :
2023-07-09 00:57:11 -07:00
if not random . randint ( 0 , 10 ) and ctx . author . id != 1097302679836971038 :
2023-07-11 18:10:44 -07:00
system_msg = " Send only an emoji as a discord reaction to the following chat message "
message = ctx . content [ 0 ]
2023-07-09 00:57:11 -07:00
headers = {
' Content-Type ' : ' application/json ' ,
' Authorization ' : f ' Bearer { os . getenv ( " openai.api_key " ) } ' ,
}
data = {
" model " : " gpt-3.5-turbo " ,
2023-07-11 18:10:44 -07:00
" messages " : [ { " role " : " system " , " content " : system_msg } , { " role " : " user " , " content " : message } ]
2023-07-09 00:57:11 -07:00
}
url = " https://api.openai.com/v1/chat/completions "
2023-07-25 17:49:30 -07:00
2023-07-09 00:57:11 -07:00
try :
2023-07-19 22:05:56 -07:00
async with bot . http_session . post ( url , headers = headers , json = data ) as resp :
response_data = await resp . json ( )
2023-07-25 17:49:30 -07:00
reaction = response_data [ ' choices ' ] [ 0 ] [ ' message ' ] [ ' content ' ] . strip ( )
if is_emoji ( reaction ) :
await ctx . add_reaction ( reaction )
else :
await ctx . add_reaction ( " 😓 " )
2023-07-09 00:57:11 -07:00
except Exception as error :
print ( " Some error happened while trying to react to a message " )
2023-07-11 17:04:28 -07:00
await handle_error ( error )
2023-07-09 00:57:11 -07:00
async def log_chat_and_get_history ( ctx , logfile , channel_vars ) :
2024-01-17 18:27:17 -08:00
log_line = ' '
2023-07-09 00:57:11 -07:00
log_line + = ctx . content
log_line = ctx . author . name + " : " + log_line + " \n "
chat_history = " "
print ( " Logging: " + log_line , end = " " )
with open ( logfile , " a " , encoding = " utf-8 " ) as f :
f . write ( log_line )
with open ( logfile , " r " , encoding = " utf-8 " ) as f :
for line in ( f . readlines ( ) [ - int ( channel_vars [ " chat_history_len " ] ) : ] ) :
chat_history + = line
return chat_history
async def chat_response ( ctx , channel_vars , chat_history_string ) :
async with ctx . channel . typing ( ) :
await asyncio . sleep ( 1 )
prompt = f " You are a { channel_vars [ ' personality ' ] } chat bot named Sparkytron 3000 created by @phixxy.com. Your personality should be { channel_vars [ ' personality ' ] } . You are currently in a { channel_vars [ ' channel_topic ' ] } chatroom. The message history is: { chat_history_string } "
headers = {
' Content-Type ' : ' application/json ' ,
' Authorization ' : f ' Bearer { os . getenv ( " openai.api_key " ) } ' ,
}
data = {
" model " : " gpt-3.5-turbo " ,
" messages " : [ { " role " : " user " , " content " : prompt } ]
}
url = " https://api.openai.com/v1/chat/completions "
2023-07-17 23:06:04 -07:00
try :
2023-07-19 22:05:56 -07:00
async with bot . http_session . post ( url , headers = headers , json = data ) as resp :
response_data = await resp . json ( )
response = response_data [ ' choices ' ] [ 0 ] [ ' message ' ] [ ' content ' ]
if " Sparkytron 3000: " in response [ 0 : 17 ] :
response = response . replace ( " Sparkytron 3000: " , " " )
max_len = 1999
if len ( response ) > max_len :
messages = [ response [ y - max_len : y ] for y in range ( max_len , len ( response ) + max_len , max_len ) ]
else :
messages = [ response ]
for message in messages :
await ctx . channel . send ( message )
2023-07-09 00:57:11 -07:00
except Exception as error :
2023-07-11 17:04:28 -07:00
await handle_error ( error )
2023-07-09 00:57:11 -07:00
2023-07-09 01:57:35 -07:00
async def folder_setup ( ) :
2024-01-20 00:36:56 -08:00
# Only tmp, extensions and data are supported, all other folders only exist for backwards compatibility and will be removed soon!
folder_names = [ " tmp " , " extensions " , " data " , " plugins " , " tmp/sfw " , " tmp/nsfw " , " tmp/meme " , " channels " , " users " , " channels/config " , " channels/logs " , " databases " , " databases/currency " , " databases/currency/players " ]
2023-07-09 01:57:35 -07:00
for folder_name in folder_names :
if not os . path . exists ( folder_name ) :
os . mkdir ( folder_name )
2024-01-17 22:35:46 -08:00
return folder_names
2023-07-09 16:06:45 -07:00
2024-01-21 00:19:28 -08:00
async def delete_all_files ( path , safe_folders = None ) :
2023-07-09 16:06:45 -07:00
for filename in os . listdir ( path ) :
2024-01-17 22:35:46 -08:00
if os . path . isdir ( path + filename ) and not path + filename in safe_folders :
2023-07-09 16:06:45 -07:00
shutil . rmtree ( path + filename )
elif os . path . isfile ( path + filename ) :
os . remove ( path + filename )
2023-07-10 17:44:15 -07:00
2023-07-10 10:38:28 -07:00
2023-07-10 17:44:15 -07:00
@tasks.loop ( seconds = 1 ) # Run the task every second
2023-07-10 10:38:28 -07:00
async def task_loop ( ) :
current_time = time . localtime ( )
2023-07-10 17:44:15 -07:00
#Run daily tasks
2024-01-20 01:33:35 -08:00
if current_time . tm_hour == 0 and current_time . tm_min == 0 and current_time . tm_sec == 0 :
2023-07-10 11:23:05 -07:00
try :
await delete_all_files ( " tmp/ " )
except Exception as error :
2023-07-11 17:04:28 -07:00
await handle_error ( error )
2023-07-16 21:36:42 -07:00
2023-07-19 15:02:50 -07:00
async def create_session ( ) :
2023-07-25 17:13:23 -07:00
return aiohttp . ClientSession ( )
2023-07-19 15:02:50 -07:00
async def close_session ( http_session ) :
await http_session . close ( )
@bot.event
async def on_connect ( ) :
bot . http_session = await create_session ( )
2023-07-21 23:25:55 -07:00
@bot.event
async def on_resumed ( ) :
bot . http_session = await create_session ( )
2023-07-19 15:02:50 -07:00
@bot.event
async def on_disconnect ( ) :
await close_session ( bot . http_session )
2023-07-09 00:57:11 -07:00
@bot.event
async def on_ready ( ) :
2024-01-19 18:51:12 -08:00
folders_made = await folder_setup ( )
await delete_all_files ( " tmp/ " , folders_made )
2024-01-20 00:34:54 -08:00
# Import plugins from extensions folder
2024-01-19 17:57:41 -08:00
for plugin_file in os . listdir ( ' extensions/ ' ) :
if plugin_file != ' __init__.py ' and plugin_file [ - 3 : ] == ' .py ' :
2024-01-20 00:34:54 -08:00
await bot . load_extension ( f ' extensions. { plugin_file [ : - 3 ] } ' )
2023-07-09 00:57:11 -07:00
print ( ' We have logged in as {0.user} ' . format ( bot ) )
2023-07-10 10:38:28 -07:00
task_loop . start ( )
2023-07-09 00:57:11 -07:00
2023-07-21 19:21:40 -07:00
@bot.event
async def on_reaction_add ( reaction , user ) :
if not random . randint ( 0 , 9 ) :
message = reaction . message
emoji = reaction . emoji
await message . add_reaction ( emoji )
2024-01-09 12:10:21 -08:00
2023-07-09 00:57:11 -07:00
@bot.event
async def on_message ( ctx ) :
2024-01-03 08:44:00 -08:00
#log stuff
2023-07-09 16:06:45 -07:00
logfile = " channels/logs/ {0} .log " . format ( str ( ctx . channel . id ) )
2023-07-09 00:57:11 -07:00
channel_vars = await get_channel_config ( ctx . channel . id )
chat_history_string = await log_chat_and_get_history ( ctx , logfile , channel_vars )
2024-01-09 12:10:21 -08:00
2024-01-03 08:44:00 -08:00
#handle non-text channels (dms, etc)
2024-01-06 09:18:25 -08:00
if ctx . channel . type . value != 0 and ctx . author . id != 242018983241318410 :
#This used to notify the user it cannot respond in this channel, but that spammed threads
return
2024-01-03 08:44:00 -08:00
await react_to_msg ( ctx , channel_vars [ " react_to_msgs " ] ) #emoji reactions
2024-01-20 22:28:36 -08:00
if channel_vars [ " commands_enabled " ] or ( ctx . author . id == 242018983241318410 and ctx . content [ 0 ] == " ? " ) :
2023-07-09 00:57:11 -07:00
await bot . process_commands ( ctx )
if not channel_vars [ " commands_enabled " ] :
await ctx . channel . send ( " This command only ran because you set it to allow to run even when commands are disabled " )
if channel_vars [ " chat_enabled " ] and not ctx . author . bot :
if ctx . content and ctx . content [ 0 ] != " ! " :
await chat_response ( ctx , channel_vars , chat_history_string )
elif not ctx . content :
await chat_response ( ctx , channel_vars , chat_history_string )
bot . run ( discord_token )