sparkytron3000/sparkytron3000.py

259 lines
9.1 KiB
Python
Raw Normal View History

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
2023-07-09 00:57:11 -07:00
import aiohttp
2023-07-13 01:10:28 -07:00
#Stable Diffusion
#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
#discord setup START
2024-01-21 00:17:12 -08:00
intents = discord.Intents.all()
2023-07-09 00:57:11 -07:00
intents.message_content = True
bot = commands.Bot(command_prefix='!', intents=intents)
#discord setup END
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'
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
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):
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:
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:
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",
"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-09 00:57:11 -07:00
try:
async with bot.http_session.post(url, headers=headers, json=data) as resp:
response_data = await resp.json()
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):
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:
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)
return folder_names
2023-07-09 16:06:45 -07:00
async def delete_all_files(path, safe_folders):
2023-07-09 16:06:45 -07:00
for filename in os.listdir(path):
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
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)
async def create_session():
2023-07-25 17:13:23 -07:00
return aiohttp.ClientSession()
async def close_session(http_session):
await http_session.close()
@bot.event
async def on_connect():
bot.http_session = await create_session()
@bot.event
async def on_resumed():
bot.http_session = await create_session()
@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():
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
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
@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)
async def pkmn_msg(discord_id):
path = "databases/pokemon/"+str(discord_id)+'.json'
if os.path.isfile(path):
with open(path, 'r') as f:
json_data = json.loads(f.readline())
json_data['buddy_xp'] += random.randint(1,5)
json_data = json.dumps(json_data)
with open(path, 'w') as f:
f.writelines(json_data)
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)
#add pokemon xp
await pkmn_msg(ctx.author.id)
2024-01-03 08:44:00 -08:00
#handle non-text channels (dms, etc)
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
2023-07-09 00:57:11 -07:00
if channel_vars["commands_enabled"] or (ctx.author.id == 242018983241318410 and ctx.content[0] == "!"):
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)