diff --git a/plugins/sparkytron_openai.py b/plugins/sparkytron_openai.py new file mode 100644 index 0000000..1731dfc --- /dev/null +++ b/plugins/sparkytron_openai.py @@ -0,0 +1,324 @@ +#sparkytron 3000 plugin +import os +import time +from PIL import Image, PngImagePlugin +import io +import base64 + +import aiohttp +import asyncssh +from discord.ext import commands, tasks + +async def upload_sftp(local_filename, server_folder, server_filename): + remotepath = server_folder + server_filename + async with asyncssh.connect(os.getenv('ftp_server'), username=os.getenv('ftp_username'), password=os.getenv('ftp_password')) as conn: + async with conn.start_sftp_client() as sftp: + await sftp.put(local_filename, remotepath=remotepath) + +async def handle_error(error): + print(error) + current_time = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) + log_line = current_time + ': ' + str(error) + '\n' + with open("databases/error_log.txt", 'a') as f: + f.write(log_line) + return error + +async def answer_question(topic, model="gpt-3.5-turbo"): + headers = { + 'Content-Type': 'application/json', + 'Authorization': f'Bearer {os.getenv("openai.api_key")}', + } + + data = { + "model": model, + "messages": [{"role": "user", "content": topic}] + } + + url = "https://api.openai.com/v1/chat/completions" + + try: + http_session = aiohttp.ClientSession() + async with http_session.post(url, headers=headers, json=data) as resp: + response_data = await resp.json() + response = response_data['choices'][0]['message']['content'] + await http_session.close() + return response + + except Exception as error: + return await handle_error(error) + +@commands.command( + description="Blog", + help="Adds your topic to the list of possible future blog topics. Usage: !suggest_blog (topic)", + brief="Suggest a blog topic" + ) +async def blog(ctx, *args): + message = ' '.join(args) + if '\n' in message: + await ctx.send("Send only one topic at a time.") + return + else: + blogpost_file = "databases/blog_topics.txt" + with open(blogpost_file, 'a') as f: + f.writelines(message+'\n') + await ctx.send("Saved suggestion!") + +@commands.command() +async def generate_blog(): + start_time = time.time() + topic = '' + filename = "phixxy.com/ai-blog/index.html" + with open(filename, 'r', encoding="utf-8") as f: + html_data = f.read() + current_time = time.time() + current_struct_time = time.localtime(current_time) + date = time.strftime("%B %d, %Y", current_struct_time) + if date in html_data: + print("I already wrote a blog post today!") + return + blogpost_file = "databases/blog_topics.txt" + #blog_subscribers = ["276197608735637505","242018983241318410"] + if os.path.isfile(blogpost_file): + with open(blogpost_file, 'r') as f: + blogpost_topics = f.read() + f.seek(0) + topic = f.readline() + blogpost_topics = blogpost_topics.replace(topic, '') + with open(blogpost_file, 'w') as f: + f.write(blogpost_topics) + if topic != '': + print("Writing blogpost") + else: + print("No topic given for blogpost, generating one.") + topic = await answer_question("Give me one topic for an absurd blogpost.") + + + post_div = ''' +
{content}
" + content = content.replace('\n\n', "") + content = content.replace("
", '') + + post_div = post_div.replace("", title) + post_div = post_div.replace("", date) + post_div = post_div.replace("", content) + + html_data = html_data.replace("", post_div) + with open(filename, 'w', encoding="utf-8") as f: + f.write(html_data) + await upload_sftp(filename, (os.getenv('ftp_public_html') + 'ai-blog/'), "index.html") + run_time = time.time() - start_time + print("It took " + str(run_time) + " seconds to generate the blog post!") + output = "Blog Updated! (" + str(run_time) + " seconds) https://ai.phixxy.com/ai-blog" + #output += '\nNotifying subscribers: ' + #for subscriber in blog_subscribers: + # output += '<@' + subscriber + '> ' + print(output) + +@commands.command( + description="Question", + help="Ask a raw chatgpt question. Usage: !question (question)", + brief="Get an answer" + ) +async def question(ctx): + question = ctx.message.content.split(" ", maxsplit=1)[1] + answer = await answer_question(question) + chunks = [answer[i:i+1999] for i in range(0, len(answer), 1999)] + 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(ctx): + question = ctx.message.content.split(" ", maxsplit=1)[1] + answer = await answer_question(question, "gpt-4-vision-preview") + chunks = [answer[i:i+1999] for i in range(0, len(answer), 1999)] + for chunk in chunks: + await ctx.send(chunk) + +@commands.command( + description="Image GPT4", + help="Ask GPT4 a question about an image. Usage: !question_gpt4 (link) (question)", + brief="Get an answer" + ) +async def looker(ctx): + image_link = ctx.message.content.split(" ", maxsplit=2)[1] + question = ctx.message.content.split(" ", maxsplit=2)[2] + + headers = { + 'Content-Type': 'application/json', + 'Authorization': f'Bearer {os.getenv("openai.api_key")}', + } + + data = { + "model": "gpt-4-vision-preview", + "messages": [{"role": "user", "content": [{"type": "text", "text": question},{"type": "image_url","image_url": {"url": image_link}}]}], + "max_tokens": 500 + } + + url = "https://api.openai.com/v1/chat/completions" + + try: + http_session = aiohttp.ClientSession() + async with http_session.post(url, headers=headers, json=data) as resp: + response_data = await resp.json() + print(response_data) + answer = response_data['choices'][0]['message']['content'] + await http_session.close() + + + except Exception as error: + return await handle_error(error) + + chunks = [answer[i:i+1999] for i in range(0, len(answer), 1999)] + for chunk in chunks: + await ctx.send(chunk) + +@commands.command( + description="Website", + help="Generates a website using gpt 3.5. Usage: !website (topic)", + brief="Generate a website" + ) +async def website(ctx): + async def delete_local_pngs(local_folder): + for filename in os.listdir(local_folder): + if ".png" in filename: + os.remove(local_folder + filename) + + async def delete_ftp_pngs(server_folder): + async with asyncssh.connect(os.getenv('ftp_server'), username=os.getenv('ftp_username'), password=os.getenv('ftp_password')) as conn: + async with conn.start_sftp_client() as sftp: + for filename in (await sftp.listdir(server_folder)): + if '.png' in filename: + try: + print("Deleting", filename) + await sftp.remove(server_folder+filename) + except: + print("Couldn't delete", filename) + + async def extract_image_tags(code): + count = code.count("This webpage is currently being generated. The page will refresh once it is complete. Please be patient.
") + await upload_sftp(working_file, server_folder, "index.html") + topic = ctx.message.content.split(" ", maxsplit=1)[1] + prompt = "Generate a webpage using html and inline css. The webpage topic should be " + topic + ". Feel free to add image tags with alt text. Leave the image source blank. The images will be added later." + code = await answer_question(prompt) + + + await delete_local_pngs(local_folder) + await delete_ftp_pngs(server_folder) + + tags = await extract_image_tags(code) + alt_texts = await extract_image_alt_text(tags) + file_list = await generate_images(local_folder, alt_texts) + code = await add_image_filenames(code, file_list) + + with open(working_file, 'w') as f: + f.write(code) + f.close() + + await upload_html_and_imgs(local_folder, server_folder) + + await ctx.send("Finished https://ai.phixxy.com/ai-webpage/") + except Exception as error: + await handle_error(error) + await ctx.send("Failed, Try again.") + +@tasks.loop(seconds=1) +async def ai_task_loop(): + current_time = time.localtime() + if current_time.tm_hour == 17 and current_time.tm_min == 0 and current_time.tm_sec == 0: + try: + await generate_blog() + except Exception as error: + await handle_error(error) + +async def setup(bot): + bot.add_command(question) + bot.add_command(question_gpt4) + bot.add_command(generate_blog) + bot.add_command(blog) + bot.add_command(website) + bot.add_command(looker) + #ai_task_loop.start() #I don't know if this will work or not \ No newline at end of file diff --git a/plugins/stable_diffusion.py b/plugins/stable_diffusion.py index 51b35f8..9810f91 100644 --- a/plugins/stable_diffusion.py +++ b/plugins/stable_diffusion.py @@ -424,6 +424,20 @@ async def reimagine(ctx): await ctx.send("My image generation service may not be running.") await handle_error(error) await http_session.close() + +@commands.command( + description="Negative Prompt", + help="Changes the negative prompt for imagine across all channels", + brief="Change the negative prompt for imagine" + ) +async def negative_prompt(ctx, *args): + message = ' '.join(args) + if not message: + message = "easynegative, badhandv4, verybadimagenegative_v1.3" + neg_prompt_file = "databases/negative_prompt.txt" + with open(neg_prompt_file, 'w') as f: + f.writelines(message) + await ctx.send("Changed negative prompt to " + message) async def setup(bot): @@ -432,4 +446,5 @@ async def setup(bot): bot.add_command(describe) bot.add_command(change_model) bot.add_command(lora) - bot.add_command(draw) \ No newline at end of file + bot.add_command(draw) + bot.add_command(negative_prompt) \ No newline at end of file diff --git a/sparkytron3000.py b/sparkytron3000.py index 60f0df6..15a4630 100644 --- a/sparkytron3000.py +++ b/sparkytron3000.py @@ -288,11 +288,6 @@ async def task_loop(): output = 'The following tasks failed:\n```' failed_tasks = [] await bot_stuff.send("<@242018983241318410> The current time is 5pm. Running daily tasks!") - try: - await generate_blog(bot_stuff) - except Exception as error: - await handle_error(error) - failed_tasks.append("Blogpost") try: await delete_all_files("tmp/") except Exception as error: @@ -358,103 +353,12 @@ async def update(ctx): await ctx.send(output.stdout.decode('utf-8')) else: await ctx.send("You don't have permission to do this.") - - -@bot.command( - description="Blog", - help="Adds your topic to the list of possible future blog topics. Usage: !suggest_blog (topic)", - brief="Suggest a blog topic" - ) -async def blog(ctx, *args): - message = ' '.join(args) - if '\n' in message: - await ctx.send("Send only one topic at a time.") - return - else: - blogpost_file = "databases/blog_topics.txt" - with open(blogpost_file, 'a') as f: - f.writelines(message+'\n') - await ctx.send("Saved suggestion!") - -@bot.command( - description="Negative Prompt", - help="Changes the negative prompt for imagine across all channels", - brief="Change the negative prompt for imagine" - ) -async def negative_prompt(ctx, *args): - message = ' '.join(args) - if not message: - message = "easynegative, badhandv4, verybadimagenegative_v1.3" - neg_prompt_file = "databases/negative_prompt.txt" - with open(neg_prompt_file, 'w') as f: - f.writelines(message) - await ctx.send("Changed negative prompt to " + message) -@bot.command() -async def generate_blog(ctx): - start_time = time.time() - topic = '' - filename = "phixxy.com/ai-blog/index.html" - with open(filename, 'r', encoding="utf-8") as f: - html_data = f.read() - current_time = time.time() - current_struct_time = time.localtime(current_time) - date = time.strftime("%B %d, %Y", current_struct_time) - if date in html_data: - await ctx.send("I already wrote a blog post today!") - return - blogpost_file = "databases/blog_topics.txt" - #blog_subscribers = ["276197608735637505","242018983241318410"] - if os.path.isfile(blogpost_file): - with open(blogpost_file, 'r') as f: - blogpost_topics = f.read() - f.seek(0) - topic = f.readline() - blogpost_topics = blogpost_topics.replace(topic, '') - with open(blogpost_file, 'w') as f: - f.write(blogpost_topics) - if topic != '': - await ctx.send("Writing blogpost") - else: - await ctx.send("No topic given for blogpost, generating one.") - topic = await answer_question("Give me one topic for an absurd blogpost.") - - - post_div = ''' -{content}
" - content = content.replace('\n\n', "") - content = content.replace("
", '') - post_div = post_div.replace("", title) - post_div = post_div.replace("", date) - post_div = post_div.replace("", content) - - html_data = html_data.replace("", post_div) - with open(filename, 'w', encoding="utf-8") as f: - f.write(html_data) + + - await upload_sftp(filename, (os.getenv('ftp_public_html') + 'ai-blog/'), "index.html") - run_time = time.time() - start_time - print("It took " + str(run_time) + " seconds to generate the blog post!") - output = "Blog Updated! (" + str(run_time) + " seconds) https://ai.phixxy.com/ai-blog" - #output += '\nNotifying subscribers: ' - #for subscriber in blog_subscribers: - # output += '<@' + subscriber + '> ' - await ctx.send(output) async def update_meme_webpage(filename): server_folder = (os.getenv('ftp_public_html') + 'ai-memes/') @@ -471,66 +375,6 @@ async def update_meme_webpage(filename): os.rename(filename, 'tmp/' + new_file_name) -@bot.command( - description="Question", - help="Ask a raw chatgpt question. Usage: !question (question)", - brief="Get an answer" - ) -async def question(ctx): - question = ctx.message.content.split(" ", maxsplit=1)[1] - answer = await answer_question(question) - chunks = [answer[i:i+1999] for i in range(0, len(answer), 1999)] - for chunk in chunks: - await ctx.send(chunk) - -@bot.command( - description="Question GPT4", - help="Ask GPT4 a question. Usage: !question_gpt4 (question)", - brief="Get an answer" - ) -async def question_gpt4(ctx): - question = ctx.message.content.split(" ", maxsplit=1)[1] - answer = await answer_question(question, "gpt-4-vision-preview") - chunks = [answer[i:i+1999] for i in range(0, len(answer), 1999)] - for chunk in chunks: - await ctx.send(chunk) - -@bot.command( - description="Image GPT4", - help="Ask GPT4 a question about an image. Usage: !question_gpt4 (link) (question)", - brief="Get an answer" - ) -async def looker(ctx): - image_link = ctx.message.content.split(" ", maxsplit=2)[1] - question = ctx.message.content.split(" ", maxsplit=2)[2] - - headers = { - 'Content-Type': 'application/json', - 'Authorization': f'Bearer {os.getenv("openai.api_key")}', - } - - data = { - "model": "gpt-4-vision-preview", - "messages": [{"role": "user", "content": [{"type": "text", "text": question},{"type": "image_url","image_url": {"url": image_link}}]}], - "max_tokens": 500 - } - - url = "https://api.openai.com/v1/chat/completions" - - try: - async with bot.http_session.post(url, headers=headers, json=data) as resp: - response_data = await resp.json() - print(response_data) - answer = response_data['choices'][0]['message']['content'] - - - except Exception as error: - return await handle_error(error) - - chunks = [answer[i:i+1999] for i in range(0, len(answer), 1999)] - for chunk in chunks: - await ctx.send(chunk) - @bot.command( description="Highscores", help="Shows a bar graph of users in this channel and how many messages they have sent.", @@ -549,7 +393,6 @@ async def highscores(ctx, limit=0): if not (character.isalpha() or character.isdigit() or character == '.' or character == '_'): return False return True - user_message_counts = {} for line in data: @@ -569,14 +412,11 @@ async def highscores(ctx, limit=0): dictionary.pop(key) return remove_dict_keys_if_less_than_x(dictionary,x) return dictionary - - - + print(user_message_counts) remove_dict_keys_if_less_than_x(user_message_counts,limit) keys = list(user_message_counts.keys()) values = list(user_message_counts.values()) - fig, ax = plt.subplots() bar_container = ax.barh(keys, values) ax.set_xlabel("Message Count") @@ -588,20 +428,21 @@ async def highscores(ctx, limit=0): f = discord.File(fh, filename=str(ctx.channel.id) + '_hiscores.png') await ctx.send(file=f) + @bot.command( description="Highscores Server", help="Shows a bar graph of users across all servers I am in and how many messages they have sent.", brief="Display chat highscores" ) async def highscores_server(ctx, limit=0): - user_message_counts = {} - data = [] - for filename in os.listdir("channels/logs/"): - with open("channels/logs/" + filename, 'r', encoding="utf-8") as logfile: - data += logfile.readlines() - logfile.close() - + def remove_dict_keys_if_less_than_x(dictionary,x): + for key in dictionary: + if dictionary[key] <= x: + dictionary.pop(key) + return remove_dict_keys_if_less_than_x(dictionary,x) + return dictionary + def is_username(user): for character in user: if character.isupper(): @@ -609,8 +450,13 @@ async def highscores_server(ctx, limit=0): if not (character.isalpha() or character.isdigit() or character == '.' or character == '_'): return False return True - + user_message_counts = {} + data = [] + for filename in os.listdir("channels/logs/"): + with open("channels/logs/" + filename, 'r', encoding="utf-8") as logfile: + data += logfile.readlines() + logfile.close() user_message_counts = {} for line in data: try: @@ -622,20 +468,12 @@ async def highscores_server(ctx, limit=0): user_message_counts[user] += 1 except Exception as error: await handle_error(error) - - def remove_dict_keys_if_less_than_x(dictionary,x): - for key in dictionary: - if dictionary[key] <= x: - dictionary.pop(key) - return remove_dict_keys_if_less_than_x(dictionary,x) - return dictionary print(user_message_counts) print("printed") user_message_counts = remove_dict_keys_if_less_than_x(user_message_counts,limit) keys = list(user_message_counts.keys()) values = list(user_message_counts.values()) - fig, ax = plt.subplots() bar_container = ax.barh(keys, values) ax.set_xlabel("Message Count") @@ -647,122 +485,6 @@ async def highscores_server(ctx, limit=0): f = discord.File(fh, filename=str(ctx.channel.id) + '_hiscores.png') await ctx.send(file=f) -@bot.command( - description="Website", - help="Generates a website using gpt 3.5. Usage: !website (topic)", - brief="Generate a website" - ) -async def website(ctx): - async def delete_local_pngs(local_folder): - for filename in os.listdir(local_folder): - if ".png" in filename: - os.remove(local_folder + filename) - - async def delete_ftp_pngs(server_folder): - async with asyncssh.connect(ftp_server, username=ftp_username, password=ftp_password) as conn: - async with conn.start_sftp_client() as sftp: - for filename in (await sftp.listdir(server_folder)): - if '.png' in filename: - try: - print("Deleting", filename) - await sftp.remove(server_folder+filename) - except: - print("Couldn't delete", filename) - - async def extract_image_tags(code): - count = code.count("This webpage is currently being generated. The page will refresh once it is complete. Please be patient.
") - await upload_sftp(working_file, server_folder, "index.html") - topic = ctx.message.content.split(" ", maxsplit=1)[1] - prompt = "Generate a webpage using html and inline css. The webpage topic should be " + topic + ". Feel free to add image tags with alt text. Leave the image source blank. The images will be added later." - code = await answer_question(prompt) - - - await delete_local_pngs(local_folder) - await delete_ftp_pngs(server_folder) - - tags = await extract_image_tags(code) - alt_texts = await extract_image_alt_text(tags) - file_list = await generate_images(local_folder, alt_texts) - code = await add_image_filenames(code, file_list) - - with open(working_file, 'w') as f: - f.write(code) - f.close() - - await upload_html_and_imgs(local_folder, server_folder) - - await ctx.send("Finished https://ai.phixxy.com/ai-webpage/") - except Exception as error: - await handle_error(error) - await ctx.send("Failed, Try again.") - '''@bot.command( description="Python",