From 8aeb0142a68319c7a25d207b020f51b81e5d7a33 Mon Sep 17 00:00:00 2001 From: phixxy Date: Wed, 17 Jan 2024 19:04:21 -0800 Subject: [PATCH] separated currency and meme commands into plugins --- plugins/currency.py | 215 +++++++++++++++++++++++++++++++ plugins/meme.py | 140 ++++++++++++++++++++ sparkytron3000.py | 304 -------------------------------------------- 3 files changed, 355 insertions(+), 304 deletions(-) create mode 100644 plugins/currency.py create mode 100644 plugins/meme.py diff --git a/plugins/currency.py b/plugins/currency.py new file mode 100644 index 0000000..ab5c106 --- /dev/null +++ b/plugins/currency.py @@ -0,0 +1,215 @@ +#plugin for sparkytron3000 +import time +import random +import json +import math + +from discord.ext import commands + +@commands.command( + description="Currency", + help="Server currency. You can run !currency claim to get started!", #This needs an overhaul + brief="Server currency tools" + ) +async def currency(ctx, arg1=None, arg2=None, arg3=None, arg4=None): + + def read_db(filepath): + with open(filepath,"r") as fileobj: + db_content = json.load(fileobj) + #print(db_content,type(db_content)) + return db_content + + def save_to_db(filepath,db_content): + with open(filepath,"w") as fileobj: + json.dump(db_content,fileobj,indent=4) + + def add_currency(filepath,amount): + player_db = read_db(filepath) + player_db["currency"] += amount + save_to_db(filepath,player_db) + return player_db + + def calc_level_from_xp(xp): + level = min(100,math.floor(0.262615*xp**0.3220627)) + return level + + def add_xp(filepath,player_db,time_spent): + activity = player_db["status"]["current_activity"] + starting_xp = player_db["skills"][activity]["xp"] + starting_level = player_db["skills"][activity]["level"] + + + if activity == "mining": + equipment_level = player_db["equipment"]["pickaxe"]["level"] + xp_gained = (time_spent) * equipment_level # SKILL LEVEL of XP / SEC + player_db["skills"][activity]["xp"] += xp_gained + new_xp = starting_xp + xp_gained + new_level = calc_level_from_xp(new_xp) #calculate with curve here + player_db["skills"][activity]["level"] = new_level + levels_gained = new_level - starting_level + + summary = "" #summary should include xp gained, levels gained (only if any were gained), current level (or new level) + summary += "You gained {} {} xp!".format(xp_gained, activity) + if levels_gained > 0: #if levels gained > 0, then include levels gained in summary + summary += "\nYou gained {} {} level(s)! You are now level {}.".format(levels_gained, activity, new_level) + + save_to_db(filepath, player_db) + return player_db,summary + + def add_resources(filepath,player_db,time_spent): + + mining_resources = { + "sapphire": { + "value": 100, + "amount": 0 + }, + "emerald": { + "value": 250, + "amount": 0 + }, + "ruby": { + "value": 1000, + "amount": 0 + }, + "diamond": { + "value": 3000, + "amount": 0 + } + } + + if player_db["status"]["current_activity"] == "mining": + pick_power = player_db["equipment"]["pickaxe"]["power"] + pick_level = player_db["equipment"]["pickaxe"]["level"] + mining_level = player_db["skills"]["mining"]["level"] + numerator = pick_power + pick_level + mining_level + denominator = 1000 + items_gained = [] + time_summary = time.strftime("%H:%M:%S", time.gmtime(time_spent)) + + for second in range(0,time_spent): + roll = random.randint(0,denominator) + if roll <= numerator: #get a resource + roll2 = random.randint(0,100) + if roll2 <= 50: + mining_resources["sapphire"]["amount"] += 1 + elif roll2 <=80: + mining_resources["emerald"]["amount"] += 1 + elif roll2 <= 95: + mining_resources["ruby"]["amount"] += 1 + else: + mining_resources["diamond"]["amount"] += 1 + for item in mining_resources: + mined_amount = mining_resources[item]["amount"] + if item in player_db["items"]: + player_db["items"][item]["amount"] += mined_amount + items_gained.append(item.title()) + items_gained.append(mined_amount) + else: + player_db["items"][item] = mining_resources[item] + items_gained.append(item.title()) + items_gained.append(mined_amount) + + save_to_db(filepath, player_db) + + summary = "You spent {} mining. You mined {} x{}, {} x{}, {} x{}, and {} x{}.".format(time_summary, *items_gained) + + return player_db,summary + + async def transfer_currency(filepath, player_db, player_id, amount): + try: + amount = int(amount) + player2_filepath = "currency/players/" + str(player_id) + ".json" + player2_db = read_db(player2_filepath) + if player_db["currency"] >= amount: + add_currency(filepath, -amount) + add_currency(player2_filepath,amount) + await ctx.send("Sent " + str(amount) + " sparks to " + str(player_id)) + except FileNotFoundError: + await ctx.send("They don't seem to be playing the game.") + + + async def show_levels(player_db): + output = '' + for skill in player_db["skills"]: + output += skill + ': ' + str(player_db["skills"][skill]["level"]) + '\n' + await ctx.send(output) + + async def show_currency(player_db): + output = 'Sparks: ' + str(player_db["currency"]) + await ctx.send(output) + + async def show_items(player_db): + output = '' + for item in player_db["items"]: + output += item + ': ' + str(player_db["items"][item]["amount"]) + '\n' + await ctx.send(output) + + + async def stop_activity(filepath,player_db): + if player_db["status"]["current_activity"] == "idle": + await ctx.send("You are currently idle. There is no activity to stop.") + else: + time_spent = int(time.time() - player_db["status"]["start_time"]) #integer in seconds + player_db, xp_summary = add_xp(filepath,player_db,time_spent) + player_db, resources_summary = add_resources(filepath,player_db,time_spent) + await ctx.send(xp_summary) + await ctx.send(resources_summary) + player_db["status"]["current_activity"] = "idle" + save_to_db(filepath,player_db) + + async def claim(filepath, player_db): + if time.time() - player_db["status"]["last_claimed"] >= 86400: + player_db = add_currency(filepath, 100) + player_db["status"]["last_claimed"] = time.time() + save_to_db(filepath,player_db) + await ctx.send("You claimed 100 sparks!") + else: + await ctx.send("Sorry, you already claimed your sparks today.") + + async def mine(filepath, player_db): + if player_db["status"]["current_activity"] == "idle": + player_db["status"]["current_activity"] = "mining" + player_db["status"]["start_time"] = time.time() + save_to_db(filepath, player_db) + await ctx.send("You start mining.") + elif player_db["status"]["current_activity"] == "mining": + await ctx.send("You are already mining!") + else: + await ctx.send("You must stop " + player_db["status"]["current_activity"] + " before you start mining!") + + async def gamble(filepath, player_db): + pass + + working_dir = "databases/currency/" + players_dir = "players/" + sender_id = str(ctx.author.id) + default_db = read_db("{0}{1}default.json".format(working_dir, players_dir)) + filepath = '{0}{1}{2}.json'.format(working_dir, players_dir, sender_id) + + try: + player_db = read_db(filepath) + except FileNotFoundError: + save_to_db(filepath,default_db) + player_db = read_db(filepath) + + if arg1 == "claim": + await claim(filepath, player_db) + player_db = read_db(filepath) + elif arg1 == "stop": + await stop_activity(filepath, player_db) + player_db = read_db(filepath) + elif arg1 == "mine": + await mine(filepath, player_db) + player_db = read_db(filepath) + elif arg1 == "levels": + await show_levels(player_db) + elif arg1 == "items": + await show_items(player_db) + elif (arg1 == "send" or arg1 == "give") and arg2 and arg3: + await transfer_currency(filepath, player_db, arg2, arg3) + player_db = read_db(filepath) + else: + await show_currency(player_db) + +async def setup(bot): + bot.add_command(currency) \ No newline at end of file diff --git a/plugins/meme.py b/plugins/meme.py new file mode 100644 index 0000000..7dfb51e --- /dev/null +++ b/plugins/meme.py @@ -0,0 +1,140 @@ +#plugin for sparkytron3000 +import os +import random +import time +import aiohttp + +from discord.ext import commands + +async def answer_question(topic, model="gpt-3.5-turbo"): # Only needed for draw command + 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'] + return response + + except Exception as error: + return await handle_error(error) + +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 + +@commands.command( + description="Meme", + help="Generates a meme based on input. Usage: !meme (topic)", + brief="Generate a meme" + ) +async def meme(ctx): + '''async def update_meme_webpage(filename): + server_folder = (os.getenv('ftp_public_html') + 'ai-memes/') + new_file_name = str(time.time_ns()) + ".png" + await upload_sftp(filename, server_folder, new_file_name) + print("Uploaded", new_file_name) + with open("phixxy.com/ai-memes/index.html", 'r') as f: + html_data = f.read() + html_insert = '\n ' + html_data = html_data.replace('',html_insert) + with open("phixxy.com/ai-memes/index.html", "w") as f: + f.writelines(html_data) + await upload_sftp("phixxy.com/ai-memes/index.html", server_folder, "index.html")''' + + + async def generate_random_meme(topic): + http_session = aiohttp.ClientSession() + async with http_session.get('https://api.imgflip.com/get_memes') as resp: + response_data = await resp.json() + response = response_data['data']['memes'] + memepics = [{'name':image['name'],'url':image['url'],'id':image['id']} for image in response] + + #Pick a meme format + memenumber = random.randint(1,99) + meme_name = response[memenumber-1]['name'] + panel_count = response[memenumber-1]['box_count'] + print("panel_count ",panel_count) + panel_text = await answer_question("Create text for a meme. The meme is " + meme_name + ". It has " + str(panel_count) + " panels. Only create one meme. Do not use emojis or hashtags! Use the topic: " + topic + ". Use the output format (DO NOT USE EXTRA NEWLINES AND DO NOT DESCRIBE THE PICTURE IN YOUR OUTPUT): \n1: [panel 1 text]\n2: [panel 2 text]") + + id = memenumber + imgflip_username = os.getenv('imgflip_username') + imgflip_password = os.getenv('imgflip_password') + params = { + 'username':imgflip_username, + 'password':imgflip_password, + 'template_id':memepics[id-1]['id'] + } + boxes = [] + text = panel_text.split('\n') + for x in range(len(text)): + if text[x].strip() != "": + item = text[x][3:] + if len(params)-3 < panel_count: + dictionary = {"text":item, "color": "#ffffff", "outline_color": "#000000"} + boxes.append(dictionary) + + for i, box in enumerate(boxes): + params[f"boxes[{i}][text]"] = box["text"] + params[f"boxes[{i}][color]"] = box["color"] + params[f"boxes[{i}][outline_color]"] = box["outline_color"] + + URL = 'https://api.imgflip.com/caption_image' + + try: + http_session = aiohttp.ClientSession() + async with http_session.post(URL, params=params) as resp: + response = await resp.json() + print(f"Generated Meme = {response['success']}\nImage Link = {response['data']['url']}\nPage Link = {response['data']['page_url']}") + image_link = response['data']['url'] + except Exception as error: + await handle_error(error) + try: + #------------------------------------Saving Image Using Aiohttp---------------------------------# + filename = memepics[id-1]['name'] + async with http_session.get(image_link) as response: + folder = "tmp/" + filename = folder + topic + str(len(os.listdir(folder))) + ".jpg" + + with open(filename, "wb") as file: + while True: + chunk = await response.content.read(1024) # Read the response in chunks + if not chunk: + break + file.write(chunk) + except Exception as error: + await handle_error(error) + print("Something's Wrong with the urllib So try again") + return image_link, filename + + try: + topic = ctx.message.content.split(" ", maxsplit=1)[1] + link, filepath = await generate_random_meme(topic) + '''channel_vars = await get_channel_config(ctx.channel.id) + try: + if channel_vars["ftp_enabled"]: + await update_meme_webpage(filepath) + except Exception as error: + print("COULDN'T UPLOAD TO FTP!") + await handle_error(error)''' + await ctx.send(link) + except Exception as error: + await handle_error(error) + await ctx.send('Something went wrong try again. Usage: !meme (topic)') + +async def setup(bot): + bot.add_command(meme) \ No newline at end of file diff --git a/sparkytron3000.py b/sparkytron3000.py index 1691543..1d9a6c2 100644 --- a/sparkytron3000.py +++ b/sparkytron3000.py @@ -343,310 +343,6 @@ async def update(ctx): else: await ctx.send("You don't have permission to do this.") -@bot.command( - description="Currency", - help="Server currency. You can run !currency claim to get started!", #This needs an overhaul - brief="Server currency tools" - ) -async def currency(ctx, arg1=None, arg2=None, arg3=None, arg4=None): - - def read_db(filepath): - with open(filepath,"r") as fileobj: - db_content = json.load(fileobj) - #print(db_content,type(db_content)) - return db_content - - def save_to_db(filepath,db_content): - with open(filepath,"w") as fileobj: - json.dump(db_content,fileobj,indent=4) - - def add_currency(filepath,amount): - player_db = read_db(filepath) - player_db["currency"] += amount - save_to_db(filepath,player_db) - return player_db - - def calc_level_from_xp(xp): - level = min(100,math.floor(0.262615*xp**0.3220627)) - return level - - def add_xp(filepath,player_db,time_spent): - activity = player_db["status"]["current_activity"] - starting_xp = player_db["skills"][activity]["xp"] - starting_level = player_db["skills"][activity]["level"] - - - if activity == "mining": - equipment_level = player_db["equipment"]["pickaxe"]["level"] - xp_gained = (time_spent) * equipment_level # SKILL LEVEL of XP / SEC - player_db["skills"][activity]["xp"] += xp_gained - new_xp = starting_xp + xp_gained - new_level = calc_level_from_xp(new_xp) #calculate with curve here - player_db["skills"][activity]["level"] = new_level - levels_gained = new_level - starting_level - - summary = "" #summary should include xp gained, levels gained (only if any were gained), current level (or new level) - summary += "You gained {} {} xp!".format(xp_gained, activity) - if levels_gained > 0: #if levels gained > 0, then include levels gained in summary - summary += "\nYou gained {} {} level(s)! You are now level {}.".format(levels_gained, activity, new_level) - - save_to_db(filepath, player_db) - return player_db,summary - - def add_resources(filepath,player_db,time_spent): - - mining_resources = { - "sapphire": { - "value": 100, - "amount": 0 - }, - "emerald": { - "value": 250, - "amount": 0 - }, - "ruby": { - "value": 1000, - "amount": 0 - }, - "diamond": { - "value": 3000, - "amount": 0 - } - } - - if player_db["status"]["current_activity"] == "mining": - pick_power = player_db["equipment"]["pickaxe"]["power"] - pick_level = player_db["equipment"]["pickaxe"]["level"] - mining_level = player_db["skills"]["mining"]["level"] - numerator = pick_power + pick_level + mining_level - denominator = 1000 - items_gained = [] - time_summary = time.strftime("%H:%M:%S", time.gmtime(time_spent)) - - for second in range(0,time_spent): - roll = random.randint(0,denominator) - if roll <= numerator: #get a resource - roll2 = random.randint(0,100) - if roll2 <= 50: - mining_resources["sapphire"]["amount"] += 1 - elif roll2 <=80: - mining_resources["emerald"]["amount"] += 1 - elif roll2 <= 95: - mining_resources["ruby"]["amount"] += 1 - else: - mining_resources["diamond"]["amount"] += 1 - for item in mining_resources: - mined_amount = mining_resources[item]["amount"] - if item in player_db["items"]: - player_db["items"][item]["amount"] += mined_amount - items_gained.append(item.title()) - items_gained.append(mined_amount) - else: - player_db["items"][item] = mining_resources[item] - items_gained.append(item.title()) - items_gained.append(mined_amount) - - save_to_db(filepath, player_db) - - summary = "You spent {} mining. You mined {} x{}, {} x{}, {} x{}, and {} x{}.".format(time_summary, *items_gained) - - return player_db,summary - - async def transfer_currency(filepath, player_db, player_id, amount): - try: - amount = int(amount) - player2_filepath = "currency/players/" + str(player_id) + ".json" - player2_db = read_db(player2_filepath) - if player_db["currency"] >= amount: - add_currency(filepath, -amount) - add_currency(player2_filepath,amount) - await ctx.send("Sent " + str(amount) + " sparks to " + str(player_id)) - except FileNotFoundError: - await ctx.send("They don't seem to be playing the game.") - - - async def show_levels(player_db): - output = '' - for skill in player_db["skills"]: - output += skill + ': ' + str(player_db["skills"][skill]["level"]) + '\n' - await ctx.send(output) - - async def show_currency(player_db): - output = 'Sparks: ' + str(player_db["currency"]) - await ctx.send(output) - - async def show_items(player_db): - output = '' - for item in player_db["items"]: - output += item + ': ' + str(player_db["items"][item]["amount"]) + '\n' - await ctx.send(output) - - - async def stop_activity(filepath,player_db): - if player_db["status"]["current_activity"] == "idle": - await ctx.send("You are currently idle. There is no activity to stop.") - else: - time_spent = int(time.time() - player_db["status"]["start_time"]) #integer in seconds - player_db, xp_summary = add_xp(filepath,player_db,time_spent) - player_db, resources_summary = add_resources(filepath,player_db,time_spent) - await ctx.send(xp_summary) - await ctx.send(resources_summary) - player_db["status"]["current_activity"] = "idle" - save_to_db(filepath,player_db) - - async def claim(filepath, player_db): - if time.time() - player_db["status"]["last_claimed"] >= 86400: - player_db = add_currency(filepath, 100) - player_db["status"]["last_claimed"] = time.time() - save_to_db(filepath,player_db) - await ctx.send("You claimed 100 sparks!") - else: - await ctx.send("Sorry, you already claimed your sparks today.") - - async def mine(filepath, player_db): - if player_db["status"]["current_activity"] == "idle": - player_db["status"]["current_activity"] = "mining" - player_db["status"]["start_time"] = time.time() - save_to_db(filepath, player_db) - await ctx.send("You start mining.") - elif player_db["status"]["current_activity"] == "mining": - await ctx.send("You are already mining!") - else: - await ctx.send("You must stop " + player_db["status"]["current_activity"] + " before you start mining!") - - async def gamble(filepath, player_db): - pass - - working_dir = "databases/currency/" - players_dir = "players/" - sender_id = str(ctx.author.id) - default_db = read_db("{0}{1}default.json".format(working_dir, players_dir)) - filepath = '{0}{1}{2}.json'.format(working_dir, players_dir, sender_id) - - try: - player_db = read_db(filepath) - except FileNotFoundError: - save_to_db(filepath,default_db) - player_db = read_db(filepath) - - if arg1 == "claim": - await claim(filepath, player_db) - player_db = read_db(filepath) - elif arg1 == "stop": - await stop_activity(filepath, player_db) - player_db = read_db(filepath) - elif arg1 == "mine": - await mine(filepath, player_db) - player_db = read_db(filepath) - elif arg1 == "levels": - await show_levels(player_db) - elif arg1 == "items": - await show_items(player_db) - elif (arg1 == "send" or arg1 == "give") and arg2 and arg3: - await transfer_currency(filepath, player_db, arg2, arg3) - player_db = read_db(filepath) - else: - await show_currency(player_db) - - - -@bot.command( - description="Meme", - help="Generates a meme based on input. Usage: !meme (topic)", - brief="Generate a meme" - ) -async def meme(ctx): - async def update_meme_webpage(filename): - server_folder = (os.getenv('ftp_public_html') + 'ai-memes/') - new_file_name = str(time.time_ns()) + ".png" - await upload_sftp(filename, server_folder, new_file_name) - print("Uploaded", new_file_name) - with open("phixxy.com/ai-memes/index.html", 'r') as f: - html_data = f.read() - html_insert = '\n ' - html_data = html_data.replace('',html_insert) - with open("phixxy.com/ai-memes/index.html", "w") as f: - f.writelines(html_data) - await upload_sftp("phixxy.com/ai-memes/index.html", server_folder, "index.html") - - - async def generate_random_meme(topic): - async with bot.http_session.get('https://api.imgflip.com/get_memes') as resp: - response_data = await resp.json() - response = response_data['data']['memes'] - memepics = [{'name':image['name'],'url':image['url'],'id':image['id']} for image in response] - - #Pick a meme format - memenumber = random.randint(1,99) - meme_name = response[memenumber-1]['name'] - panel_count = response[memenumber-1]['box_count'] - print("panel_count ",panel_count) - panel_text = await answer_question("Create text for a meme. The meme is " + meme_name + ". It has " + str(panel_count) + " panels. Only create one meme. Do not use emojis or hashtags! Use the topic: " + topic + ". Use the output format (DO NOT USE EXTRA NEWLINES AND DO NOT DESCRIBE THE PICTURE IN YOUR OUTPUT): \n1: [panel 1 text]\n2: [panel 2 text]") - - id = memenumber - imgflip_username = os.getenv('imgflip_username') - imgflip_password = os.getenv('imgflip_password') - params = { - 'username':imgflip_username, - 'password':imgflip_password, - 'template_id':memepics[id-1]['id'] - } - boxes = [] - text = panel_text.split('\n') - for x in range(len(text)): - if text[x].strip() != "": - item = text[x][3:] - if len(params)-3 < panel_count: - dictionary = {"text":item, "color": "#ffffff", "outline_color": "#000000"} - boxes.append(dictionary) - - for i, box in enumerate(boxes): - params[f"boxes[{i}][text]"] = box["text"] - params[f"boxes[{i}][color]"] = box["color"] - params[f"boxes[{i}][outline_color]"] = box["outline_color"] - - URL = 'https://api.imgflip.com/caption_image' - - try: - async with bot.http_session.post(URL, params=params) as resp: - response = await resp.json() - print(f"Generated Meme = {response['success']}\nImage Link = {response['data']['url']}\nPage Link = {response['data']['page_url']}") - image_link = response['data']['url'] - except Exception as error: - await handle_error(error) - try: - #------------------------------------Saving Image Using Aiohttp---------------------------------# - filename = memepics[id-1]['name'] - async with bot.http_session.get(image_link) as response: - folder = "tmp/" - filename = folder + topic + str(len(os.listdir(folder))) + ".jpg" - - with open(filename, "wb") as file: - while True: - chunk = await response.content.read(1024) # Read the response in chunks - if not chunk: - break - file.write(chunk) - except Exception as error: - await handle_error(error) - print("Something's Wrong with the urllib So try again") - return image_link, filename - - try: - topic = ctx.message.content.split(" ", maxsplit=1)[1] - link, filepath = await generate_random_meme(topic) - channel_vars = await get_channel_config(ctx.channel.id) - try: - if channel_vars["ftp_enabled"]: - await update_meme_webpage(filepath) - except Exception as error: - print("COULDN'T UPLOAD TO FTP!") - await handle_error(error) - await ctx.send(link) - except Exception as error: - await handle_error(error) - await ctx.send('Something went wrong try again. Usage: !meme (topic)') - @bot.command( description="Errors",