Compare commits

..

No commits in common. "main" and "web_ui" have entirely different histories.
main ... web_ui

11 changed files with 81 additions and 394 deletions

2
.gitignore vendored
View file

@ -10,5 +10,3 @@ extensions/
databases/
channels/
.gitignore
cogs/dailies.py
cogs/idlegame.py

View file

@ -23,6 +23,7 @@ class ChatGPT(commands.Cog):
self.folder_setup()
self.remind_me_loop.start()
self.http_session = self.create_aiohttp_session()
self.dalle_budget = self.get_budget()
self.logger = logging.getLogger("bot")
self.headers = {
'Content-Type': 'application/json',
@ -51,7 +52,7 @@ class ChatGPT(commands.Cog):
self.logger.exception(f"ChatGPT failed to make directories: {e}")
def text_cost_calc(self, model, input_tokens, output_tokens):
cost_table = {"gpt-4o-mini":{"input_tokens":0.00000015,"output_tokens":0.0000006},
cost_table = {"gpt-3.5-turbo":{"input_tokens":0.0000005,"output_tokens":0.0000015},
"gpt-4-turbo-preview":{"input_tokens":0.00001,"output_tokens":0.00003},
"gpt-4-vision-preview":{"input_tokens":0.00001,"output_tokens":0.00003},
"gpt-4o":{"input_tokens":0.000005,"output_tokens":0.000015}
@ -61,6 +62,36 @@ class ChatGPT(commands.Cog):
cost = input_cost + output_cost
return cost
def get_budget(self):
month = time.strftime("%B")
year = time.strftime("%Y")
key = f"{month}_{year}"
budget_file = f"{self.data_dir}budget.json"
if not os.path.exists(budget_file):
with open(budget_file, "w") as f:
json.dump({key:self.default_budget},f)
with open(budget_file, "r") as f:
budget_dict = json.loads(f.readline())
if key not in budget_dict:
budget_dict[key] = self.default_budget
with open(budget_file, "w") as f:
json.dump(budget_dict,f)
return self.default_budget
else:
return budget_dict[key]
def budget_add(self, amount):
month = time.strftime("%B")
year = time.strftime("%Y")
key = f"{month}_{year}"
budget_file = f"{self.data_dir}budget.json"
with open(budget_file, "r") as f:
budget_dict = json.loads(f.readline())
budget_dict[key] += amount
with open(budget_file, "w") as f:
json.dump(budget_dict,f)
self.dalle_budget += amount
def add_cost(self, category: str, cost: float):
day = time.strftime("%d")
month = time.strftime("%B")
@ -125,6 +156,28 @@ class ChatGPT(commands.Cog):
category_scores = response_data['results'][0]['category_scores']
return (flagged, categories, category_scores)
@commands.command()
async def budget(self, ctx, command=None, budget=None):
try:
if ctx.author.id == self.admin_id:
if command == "add" and budget!= None:
self.budget_add(float(budget))
await ctx.send(f"Budget increased by {budget}")
elif command == "remove" and budget!= None:
self.budget_add(-float(budget))
await ctx.send(f"Budget decreased by {budget}")
elif command == "set" and budget!= None:
self.budget_add(float(budget) - self.dalle_budget)
await ctx.send(f"Budget set to {budget}")
else:
await ctx.send(f"The current budget is {self.dalle_budget}")
else:
await ctx.send(f"The current budget is {self.dalle_budget}")
except Exception as e:
self.logger.exception(f"Budget command failed: {e}")
await ctx.send(f"Budget command failed")
@commands.command(
name="costs",
brief="Get the costs for a given month and year.",
@ -234,7 +287,7 @@ class ChatGPT(commands.Cog):
user = self.bot.get_user(reminder_dict["user_id"])
return await user.send(reminder_dict["response"])
async def answer_question(self, topic, model="gpt-4o-mini"):
async def answer_question(self, topic, model="gpt-3.5-turbo"):
data = {
"model": model,
"messages": [{"role": "user", "content": topic}]
@ -259,25 +312,6 @@ class ChatGPT(commands.Cog):
self.logger.exception("Error occurred in answer_question")
return "Error occurred in answer_question"
@commands.command()
async def translate(self, ctx):
if ctx.message.attachments:
attachment = ctx.message.attachments[0] # assuming only one attachment
await attachment.save(self.working_dir + '/' + attachment.filename)
with open(self.working_dir + '/' + attachment.filename, 'r') as file:
text = file.read()
question = f"Translate the following text to english: {text}"
# Now text contains the content of the downloaded file
translated_text = await self.answer_question(question)
# Save the translated text to a new file
with open(f'{self.working_dir}/translated_text.txt', 'w') as new_file:
new_file.write(translated_text)
# Send the text file as an attachment
file = discord.File(f'{self.working_dir}/translated_text.txt')
await ctx.send(file=file)
@commands.command(
description="Personality",
@ -369,6 +403,19 @@ class ChatGPT(commands.Cog):
for chunk in chunks:
await ctx.send(chunk)
@commands.command(
description="Question GPT4",
help="Ask GPT4 a question. Usage: !question_gpt4 (question)",
brief="Get an answer"
)
async def question_gpt4(self, ctx):
await ctx.send("One moment, let me think...")
question = ctx.message.content.split(" ", maxsplit=1)[1]
answer = await self.answer_question(question, "gpt-4o")
chunks = [answer[i:i+1999] for i in range(0, len(answer), 1999)]
for chunk in chunks:
await ctx.send(chunk)
async def dalle_api_call(self, prompt: str, model: str="dall-e-2", quality: str="standard", size: str="1024x1024") -> tuple:
if self.dalle_budget <= await self.get_monthly_cost():
self.logger.info("DALL-E API call failed due to budget")
@ -635,7 +682,7 @@ class ChatGPT(commands.Cog):
message = ctx.content[0]
data = {
"model": "gpt-4o-mini",
"model": "gpt-3.5-turbo",
"messages": [{"role": "system", "content": system_msg}, {"role": "user", "content": message}]
}

View file

@ -146,6 +146,4 @@ class InkyScreen(commands.Cog):
async def setup(bot):
#await bot.add_cog(InkyScreen(bot))
#Temporarily disable as this is probably unused for everyone including me
pass
await bot.add_cog(InkyScreen(bot))

View file

@ -159,17 +159,12 @@ class Llama(commands.Cog):
channel_vars = await self.get_channel_config(message.channel.id)
chat_history_string = await self.log_chat_and_get_history(message, logfile, channel_vars)
# Chat Response
try:
if channel_vars["llama_enabled"] and not message.author.bot or self.bot_id in [x.id for x in message.mentions]:
if message.content and message.content[0] != "!":
await self.chat_response(message, channel_vars, chat_history_string)
elif not message.content:
await self.chat_response(message, channel_vars, chat_history_string)
except:
self.edit_channel_config(message.channel.id, "llama_enabled", False)
async def setup(bot):
#await bot.add_cog(Llama(bot))
#Temporarily disable this as it isn't really working properly
pass
await bot.add_cog(Llama(bot))

View file

@ -1,169 +0,0 @@
from discord.ext import commands
import discord
import json
import os
from cogs.base_cog.bot_base_cog import BotBaseCog
class MessageXP(BotBaseCog):
def __init__(self, bot):
super().__init__(bot)
self.setup(__class__.__name__)
@commands.command()
async def stats(self, ctx):
author_id = str(ctx.author.id)
try:
xp_data = read_xp_file(self)
if author_id in xp_data:
level = get_level_from_xp(xp_data[author_id])
await ctx.send(f"You are level {level} with {xp_data[author_id]} XP")
else:
await ctx.send("You have 0 XP")
except:
await ctx.send("Error getting XP")
@commands.command()
async def show_json(self, ctx):
with open(os.path.join(self.data_dir, "xp.json"), "r") as xp_file:
xp_data = json.load(xp_file)
await ctx.send(xp_data)
@commands.Cog.listener()
async def on_message(self, message: discord.Message):
try:
author_id = str(message.author.id)
if message.author.bot:
return
else:
xp_data = read_xp_file(self)
if author_id in xp_data:
xp_data[author_id] += 1
else:
xp_data[author_id] = 1
with open(os.path.join(self.data_dir, "xp.json"), "w") as xp_file:
json.dump(xp_data, xp_file)
except Exception as e:
self.logger.error(f"Error adding XP: {e}")
def read_xp_file(self):
try:
with open(os.path.join(self.data_dir, "xp.json"), "r") as xp_file:
xp_data = json.load(xp_file)
return xp_data
except Exception as e:
self.logger.error(f"No XP file found. Returning empty json object: {e}")
return {}
def get_level_from_xp(xp):
xp_dict = {
1: 0,
2: 83,
3: 174,
4: 276,
5: 388,
6: 512,
7: 650,
8: 801,
9: 801,
10: 1_154,
11: 1_358,
12: 1_584,
13: 1_833,
14: 2_107,
15: 2_411,
16: 2_746,
17: 3_115,
18: 3_523,
19: 3_973,
20: 4_470,
21: 5_018,
22: 5_624,
23: 6_291,
24: 7_028,
25: 7_842,
26: 8_740,
27: 9_730,
28: 10_824,
29: 12_031,
30: 13_363,
31: 14_833,
32: 16_456,
33: 18_247,
34: 20_224,
35: 22_406,
36: 24_815,
37: 27_473,
38: 30_408,
39: 33_648,
40: 37_224,
41: 41_171,
42: 45_529,
43: 50_339,
44: 55_649,
45: 61_512,
46: 67_983,
47: 75_127,
48: 83_014,
49: 91_721,
50: 101_333,
51: 111_945,
52: 123_660,
53: 136_594,
54: 150_872,
55: 166_636,
56: 184_040,
57: 203_254,
58: 224_466,
59: 247_886,
60: 273_742,
61: 302_288,
62: 333_804,
63: 368_599,
64: 407_015,
65: 449_428,
66: 496_254,
67: 547_953,
68: 605_032,
69: 668_051,
70: 737_627,
71: 814_445,
72: 899_257,
73: 992_895,
74: 1_096_278,
75: 1_210_421,
76: 1_336_443,
77: 1_475_581,
78: 1_629_200,
79: 1_798_808,
80: 1_986_068,
81: 2_192_818,
82: 2_421_087,
83: 2_673_114,
84: 2_951_373,
85: 3_258_594,
86: 3_597_792,
87: 3_972_294,
88: 4_385_776,
89: 4_842_295,
90: 5_346_332,
91: 5_902_831,
92: 6_517_253,
93: 7_195_629,
94: 7_944_614,
95: 8_771_558,
96: 9_684_577,
97: 10_692_629,
98: 11_805_606,
99: 13_034_431
}
for level, xp_threshold in xp_dict.items():
if xp < xp_threshold:
return level - 1
return 99
async def setup(bot):
await bot.add_cog(MessageXP(bot))

View file

@ -192,7 +192,7 @@ class PhixxyCom(commands.Cog):
except:
self.logger.exception("Something went wrong in upload_ftp_ai_images")
async def answer_question(self, topic, model="gpt-4o-mini"):
async def answer_question(self, topic, model="gpt-3.5-turbo"):
headers = {
'Content-Type': 'application/json',
'Authorization': f'Bearer {os.getenv("openai.api_key")}',
@ -265,7 +265,7 @@ class PhixxyCom(commands.Cog):
topic = await self.answer_question(question)
self.logger.info("Writing blogpost")
title_prompt = 'generate an absurd essay title about ' + topic
title = await self.answer_question(title_prompt, model="gpt-4o-mini")
title = await self.answer_question(title_prompt, model="gpt-3.5-turbo")
prompt = 'Write a satirical essay with a serious tone titled: "' + title + '". Do not label parts of the essay.'
content = await self.answer_question(prompt, model="gpt-4o")
if title in content[:len(title)]:

View file

@ -1,35 +0,0 @@
from discord.ext import commands, tasks
from cogs.base_cog.bot_base_cog import BotBaseCog
import feedparser
import asyncio
class RSSCog(BotBaseCog):
def __init__(self, bot):
super().__init__(bot)
self.setup(__class__.__name__)
self.rss_base_url = 'https://secure.runescape.com/m=adventurers-log/rssfeed?searchName='
self.usernames = ['Deadifyed', 'Frozener', 'Tsuki no ko', 'blue boomer4']
self.last_items = {key: None for key in self.usernames}
self.check_rss.start()
@tasks.loop(minutes=5)
async def check_rss(self):
for name in self.usernames:
rss_url = self.rss_base_url + name.replace(' ','%20')
feed = feedparser.parse(rss_url)
latest_item = feed.entries[0] if feed.entries else None
if latest_item and latest_item.title != self.last_items[name]:
self.last_items[name] = latest_item.title
channel = self.bot.get_channel(895388842834673696)
await channel.send(f"{name}: {latest_item.description}")
await asyncio.sleep(60)
@check_rss.before_loop
async def before_check_rss(self):
await self.bot.wait_until_ready()
async def setup(bot):
await bot.add_cog(RSSCog(bot))

View file

@ -1,93 +0,0 @@
import os
import subprocess
import asyncio
from discord.ext import commands, tasks
from cogs.base_cog.bot_base_cog import BotBaseCog
class YoutubeDL(BotBaseCog):
def __init__(self, bot):
super().__init__(bot)
self.setup(__class__.__name__)
self.check_for_downloads.start()
''' @commands.command()
async def youtubedl(self, ctx):
try:
# Expecting the command format to be !youtubedl <url> <video|audio>
parts = ctx.message.content.split(" ")
if len(parts) < 3:
await ctx.send("Usage: !youtubedl <url> <video|audio>")
return
url = parts[1]
video_or_audio = parts[2]
# Run the subprocess
process = subprocess.Popen(
["python3", "youtubedl.py", url, video_or_audio],
cwd="data/ytdl",
stdout=subprocess.PIPE,
stderr=subprocess.PIPE
)
# Wait for the process to complete and read the output
stdout, stderr = process.communicate()
# Send the output back to the user
#await ctx.send(f"std out: {stdout.decode('utf-8')}") if stdout else await ctx.send("No stdout output")
#await ctx.send(f"std err: {stderr.decode('utf-8')}") if stderr else await ctx.send("No stderr output")
await ctx.send(f"Downloading {video_or_audio} from {url}...", suppress_embeds=True)
except Exception as e:
#await ctx.send(f"Error: {e}")
await ctx.send("Usage: !youtubedl <url> <video|audio>")'''
@commands.command()
async def youtubedl(self, ctx):
try:
# Expecting the command format to be !youtubedl <url> <video|audio>
parts = ctx.message.content.split(" ")
if len(parts) < 3:
await ctx.send("Usage: !youtubedl <url> <video|audio>")
return
url = parts[1]
video_or_audio = parts[2]
# Create a subprocess
process = await asyncio.create_subprocess_exec(
"python3", "youtubedl.py", url, video_or_audio,
cwd="data/ytdl",
stdout=asyncio.subprocess.PIPE,
stderr=asyncio.subprocess.PIPE
)
# Write a message that the download has started
await ctx.send(f"Downloading {video_or_audio} from {url}...")
# Read stdout and stderr (non-blocking)
stdout, stderr = await process.communicate()
# Send the output back to the user
if stdout:
await ctx.send(f"std out: {stdout.decode('utf-8')}")
if stderr:
await ctx.send(f"std err: {stderr.decode('utf-8')}")
except Exception as e:
await ctx.send(f"Error: {e}")
#create a task
@tasks.loop(seconds=10)
async def check_for_downloads(self):
for file in os.listdir("data/ytdl"):
if file.endswith(".txt"):
with open(f"data/ytdl/{file}", "r") as f:
url = f.read()
await self.bot.get_channel(544408659174883328).send(f"{url}")
os.remove(f"data/ytdl/{file}")
async def setup(bot):
await bot.add_cog(YoutubeDL(bot))

View file

@ -1,54 +0,0 @@
from sys import argv
import os
import time
import subprocess
#usage python3 youtubedl.py <url> <video|audio>
def download(url, video_or_audio):
if video_or_audio == "video":
process = subprocess.Popen(["yt-dlp", "--yes-playlist", f"{url}"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
process.wait()
return True
elif video_or_audio == "audio":
process = subprocess.Popen(["yt-dlp", "-x", "--yes-playlist", url], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
process.wait()
return True
else:
print("Invalid argument")
return False
def zip_all_files():
#zip all files
current_epoch = time.time()
output_file = f"{current_epoch}.zip"
os.system(f"zip -r {output_file} *")
return output_file
def upload_to_litterbox(input_file):
''' If you want to make curl requests to the API, here is an example. Allowed values for "time" are 1h, 12h, 24h, and 72h.
curl -F "reqtype=fileupload" -F "time=1h" -F "fileToUpload=@cutie.png" https://litterbox.catbox.moe/resources/internals/api.php'''
command = f"curl -F 'reqtype=fileupload' -F 'time=1h' -F 'fileToUpload=@{input_file}' https://litterbox.catbox.moe/resources/internals/api.php"
output_url = os.popen(command).read()
#delete all files in current directory except this script
file_types = ["zip", "mp4", "mp3", "webm", "wav", "m4a", "flac", "ogg", "opus", "wma", "aac", "m4p", "m4b", "m4r", "m4v", "mp2", "mp3", "mp4", "mpa", "mpeg", "mpg", "mpv", "mxf", "ogg", "oga", "ogv", "ogx", "spx", "wav", "webm", "wma", "wv", "wvx", "weba", "webm", "webp", "wmv"]
for file in os.listdir():
if file.split(".")[-1] in file_types:
os.remove(f"{file}")
pass
return output_url
def main():
url, video_or_audio = argv[1], argv[2]
print(url, video_or_audio)
if download(url, video_or_audio):
zip_file = zip_all_files()
output_url = upload_to_litterbox(zip_file)
print(output_url)
with open(f"{time.time()}.txt", "w") as output_file:
output_file.write(output_url)
output_file.close()
else:
print("Invalid argument")
if __name__ == "__main__":
main()

View file

@ -12,4 +12,3 @@ wakeonlan
beautifulsoup4
Flask[async]
waitress
feedparser

View file

@ -38,6 +38,7 @@ async def index():
with open('.env', 'w') as file:
for key, value in form_dict.items():
file.write(f"{key}='{value}'\n")
print(form_dict)
flask_app.bot_process.terminate()
flask_app.bot_process = subprocess.Popen([sys.executable, "sparkytron3000.py"])
message = "Variables Updated!"