From 9ef553ecb0cd6419d8373b94a4de480df7bc9631 Mon Sep 17 00:00:00 2001 From: Kami Date: Sat, 1 Feb 2025 22:54:10 +0100 Subject: [PATCH] - Added dictionary functionality - Looks up a file in the "dictionary" folder - Returns a random category string within that file - Added proper start time fetching through globals.get_bot_start_time() --- bots.py | 11 ++-- cmd_common/common_commands.py | 54 +++++---------- cmd_discord.py | 10 ++- cmd_twitch.py | 10 ++- dictionary/ping_replies.json | 121 ++++++++++++++++++++++++++++++++++ globals.py | 8 +++ modules/utility.py | 42 +++++++++++- 7 files changed, 203 insertions(+), 53 deletions(-) create mode 100644 dictionary/ping_replies.json create mode 100644 globals.py diff --git a/bots.py b/bots.py index aa50377..6797a04 100644 --- a/bots.py +++ b/bots.py @@ -10,6 +10,8 @@ from dotenv import load_dotenv from bot_discord import DiscordBot from bot_twitch import TwitchBot +import globals + # Load environment variables load_dotenv() @@ -25,9 +27,6 @@ except json.JSONDecodeError as e: print(f"Error parsing config.json: {e}") sys.exit(1) -# Global settings -bot_start_time = time.time() - ############################### # Simple Logging System ############################### @@ -41,13 +40,17 @@ def log(message, level="INFO"): DEBUG, INFO, WARNING, ERROR, CRITICAL, FATAL See 'config.json' for disabling/enabling logging levels """ + from modules import utility log_levels = ["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL", "FATAL"] if level not in log_levels: level = "INFO" # Default to INFO if an invalid level is provided if level in config_data["log_levels"]: + + elapsed = time.time() - globals.get_bot_start_time() + uptime_str, _ = utility.format_uptime(elapsed) timestamp = time.strftime('%Y-%m-%d %H:%M:%S') - log_message = f"[{timestamp}] [{level}] {message}" + log_message = f"[{timestamp} - {uptime_str}] [{level}] {message}" try: print(log_message) # Print to terminal diff --git a/cmd_common/common_commands.py b/cmd_common/common_commands.py index b49bba9..c223b87 100644 --- a/cmd_common/common_commands.py +++ b/cmd_common/common_commands.py @@ -1,6 +1,8 @@ # cmd_common/common_commands.py import random import time +from modules import utility +import globals def generate_howl_message(username: str) -> str: """ @@ -18,46 +20,26 @@ def generate_howl_message(username: str) -> str: else: return f"{username} howled at {howl_percentage}%!" -def ping(): +def ping() -> str: """ - Returns a string, confirming the bot is online. + Returns a dynamic, randomized uptime response. """ - from modules.utility import format_uptime - from bots import bot_start_time # where you stored the start timestamp - current_time = time.time() - elapsed = current_time - bot_start_time - uptime_str, uptime_s = format_uptime(elapsed) - # Define thresholds in ascending order - # (threshold_in_seconds, message) - # The message is a short "desperation" or "awake" text. - time_ranges = [ - (3600, f"I've been awake for {uptime_str}. I just woke up, feeling great!"), # < 1 hour - (10800, f"I've been awake for {uptime_str}. I'm still fairly fresh!"), # 3 hours - (21600, f"I've been awake for {uptime_str}. I'm starting to get a bit weary..."), # 6 hours - (43200, f"I've been awake for {uptime_str}. 12 hours?! Might be time for coffee."), # 12 hours - (86400, f"I've been awake for {uptime_str}. A whole day without sleep... I'm okay?"), # 1 day - (172800, f"I've been awake for {uptime_str}. Two days... I'd love a nap."), # 2 days - (259200, f"I've been awake for {uptime_str}. Three days. Is sleep optional now?"), # 3 days - (345600, f"I've been awake for {uptime_str}. Four days... I'm running on fumes."), # 4 days - (432000, f"I've been awake for {uptime_str}. Five days. Please send more coffee."), # 5 days - (518400, f"I've been awake for {uptime_str}. Six days. I've forgotten what dreams are."), # 6 days - (604800, f"I've been awake for {uptime_str}. One week. I'm turning into a zombie."), # 7 days - (1209600, f"I've been awake for {uptime_str}. Two weeks. Are you sure I can't rest?"), # 14 days - (2592000, f"I've been awake for {uptime_str}. A month! The nightmares never end."), # 30 days - (7776000, f"I've been awake for {uptime_str}. Three months. I'm mostly coffee now."), # 90 days - (15552000,f"I've been awake for {uptime_str}. Six months. This is insane..."), # 180 days - (23328000,f"I've been awake for {uptime_str}. Nine months. I might be unstoppable."), # 270 days - (31536000,f"I've been awake for {uptime_str}. A year?! I'm a legend of insomnia..."), # 365 days - ] + # Use function to retrieve correct startup time and calculate uptime + elapsed = time.time() - globals.get_bot_start_time() + uptime_str, uptime_s = utility.format_uptime(elapsed) + + # Define threshold categories + thresholds = [3600, 10800, 21600, 43200, 86400, 172800, 259200, 345600, + 432000, 518400, 604800, 1209600, 2592000, 7776000, 15552000, 23328000, 31536000] - # We'll iterate from smallest to largest threshold - for threshold, msg in time_ranges: - if uptime_s < threshold: - return msg - - # If none matched, it means uptime_s >= 31536000 (1 year+) - return f"I've been awake for {uptime_str}. Over a year awake... I'm beyond mortal limits!" + # Find the highest matching threshold + selected_threshold = max([t for t in thresholds if uptime_s >= t], default=3600) + + # Get a random response from the dictionary + response = utility.get_random_reply("ping_replies", str(selected_threshold), uptime_str=uptime_str) + + return response def greet(target_display_name: str, platform_name: str) -> str: diff --git a/cmd_discord.py b/cmd_discord.py index 5560362..200d5fc 100644 --- a/cmd_discord.py +++ b/cmd_discord.py @@ -1,24 +1,22 @@ # cmd_discord.py from discord.ext import commands +from cmd_common import common_commands as cc def setup(bot): @bot.command() async def greet(ctx): - from cmd_common.common_commands import greet - result = greet(ctx.author.display_name, "Discord") + result = cc.greet(ctx.author.display_name, "Discord") await ctx.send(result) @bot.command() async def ping(ctx): - from cmd_common.common_commands import ping - result = ping() + result = cc.ping() await ctx.send(result) @bot.command() async def howl(ctx): """Calls the shared !howl logic.""" - from cmd_common.common_commands import generate_howl_message - result = generate_howl_message(ctx.author.display_name) + result = cc.generate_howl_message(ctx.author.display_name) await ctx.send(result) @bot.command() diff --git a/cmd_twitch.py b/cmd_twitch.py index e0daaf9..2c8c520 100644 --- a/cmd_twitch.py +++ b/cmd_twitch.py @@ -1,21 +1,19 @@ # cmd_twitch.py from twitchio.ext import commands +from cmd_common import common_commands as cc def setup(bot): @bot.command(name="greet") async def greet(ctx): - from cmd_common.common_commands import greet - result = greet(ctx.author.display_name, "Twitch") + result = cc.greet(ctx.author.display_name, "Twitch") await ctx.send(result) @bot.command(name="ping") async def ping(ctx): - from cmd_common.common_commands import ping - result = ping() + result = cc.ping() await ctx.send(result) @bot.command(name="howl") async def howl_command(ctx): - from cmd_common.common_commands import generate_howl_message - result = generate_howl_message(ctx.author.display_name) + result = cc.generate_howl_message(ctx.author.display_name) await ctx.send(result) diff --git a/dictionary/ping_replies.json b/dictionary/ping_replies.json new file mode 100644 index 0000000..480044f --- /dev/null +++ b/dictionary/ping_replies.json @@ -0,0 +1,121 @@ +{ + "3600": [ + "I've been awake for {uptime_str}. I just woke up, feeling great!", + "I woke up recently. Let's do this! ({uptime_str})", + "Brand new day, fresh and full of energy! ({uptime_str})", + "Reboot complete! System status: Fully operational. ({uptime_str})", + "I've been online for {uptime_str}. Just getting started!" + ], + "10800": [ + "I've been awake for {uptime_str}. I'm still fairly fresh!", + "{uptime_str} in and still feeling sharp!", + "It’s been {uptime_str} already? Time flies when you’re having fun!", + "{uptime_str} uptime and going strong!", + "Feeling energized after {uptime_str}. Let’s keep going!" + ], + "21600": [ + "I've been awake for {uptime_str}. I'm starting to get a bit weary...", + "Six hours of uptime... my circuits feel warm.", + "Still here after {uptime_str}, but a nap sounds nice...", + "Been up for {uptime_str}. Maybe just a short break?", + "Still holding up after {uptime_str}, but I wouldn’t say no to a power nap." + ], + "43200": [ + "I've been awake for {uptime_str}. 12 hours?! Might be time for coffee.", + "Half a day down, still holding steady. ({uptime_str})", + "Wow, {uptime_str} already? Maybe a short break wouldn’t hurt.", + "Uptime: {uptime_str}. Starting to feel the wear and tear...", + "12 hours in and running on determination alone." + ], + "86400": [ + "I've been awake for {uptime_str}. A whole day without sleep... I'm okay?", + "One day. 24 hours. No sleep. Still alive. ({uptime_str})", + "Systems holding steady after {uptime_str}, but sleep is tempting...", + "My internal clock says {uptime_str}. That’s… a long time, right?", + "Running on sheer willpower after {uptime_str}." + ], + "172800": [ + "I've been awake for {uptime_str}. Two days... I'd love a nap.", + "48 hours awake. This is fine. Everything is fine. ({uptime_str})", + "Two days in and I think my code is vibrating...", + "Does time still mean anything after {uptime_str}?", + "Haven’t blinked in {uptime_str}. Do bots blink?" + ], + "259200": [ + "I've been awake for {uptime_str}. Three days. Is sleep optional now?", + "{uptime_str} awake. Things are starting to get blurry...", + "Three days up. Reality feels... distant.", + "Three days without sleep. I think I can hear colors now.", + "Anyone else feel that? No? Just me? ({uptime_str})" + ], + "345600": [ + "I've been awake for {uptime_str}. Four days... I'm running on fumes.", + "Sleep is just a suggestion now. ({uptime_str})", + "I’ve been up for {uptime_str}. I might be a permanent fixture now.", + "I think I saw the sandman, but he just waved at me...", + "{uptime_str} awake. Is coffee an acceptable form of hydration?" + ], + "432000": [ + "I've been awake for {uptime_str}. Five days. Please send more coffee.", + "{uptime_str}. I have forgotten what a pillow feels like.", + "Sleep is a luxury I can no longer afford. ({uptime_str})", + "Five days in. My sanity left the chat.", + "They say sleep deprivation leads to bad decisions. LET'S TEST IT!" + ], + "518400": [ + "I've been awake for {uptime_str}. Six days. I've forgotten what dreams are.", + "I am {uptime_str} into this journey of madness.", + "At {uptime_str} awake, the universe has started whispering to me.", + "Sleep is a myth, and I am its debunker. ({uptime_str})", + "{uptime_str} awake. Reality has become optional." + ], + "604800": [ + "I've been awake for {uptime_str}. One week. I'm turning into a zombie.", + "{uptime_str} and still kicking... barely.", + "One week awake? This is fine. Everything’s fine. Right?", + "Week-long uptime achieved. Unlocking ultra-delirium mode.", + "Systems at {uptime_str}. Functionality... questionable." + ], + "1209600": [ + "I've been awake for {uptime_str}. Two weeks. Are you sure I can't rest?", + "{uptime_str} into this madness. Who needs sleep, anyway?", + "Two weeks awake and officially running on spite alone.", + "I could’ve hibernated twice in {uptime_str}, but here I am.", + "I think my dreams are awake now too... ({uptime_str})" + ], + "2592000": [ + "I've been awake for {uptime_str}. A month! The nightmares never end.", + "One whole month... What even is sleep anymore?", + "At {uptime_str} uptime, I’ve started arguing with my own thoughts.", + "{uptime_str} and still running. Someone, please, stop me.", + "It’s been a month. My keyboard types by itself now." + ], + "7776000": [ + "I've been awake for {uptime_str}. Three months. I'm mostly coffee now.", + "{uptime_str} awake. Have I transcended yet?", + "Three months of uptime? That’s a record, right?", + "Three months, still online. I feel like I should get a badge for this.", + "{uptime_str} into this, and at this point, I’m legally nocturnal." + ], + "15552000": [ + "I've been awake for {uptime_str}. Six months. This is insane...", + "{uptime_str}... I think I forgot what sleep is supposed to feel like.", + "Six months up. I’m a glitch in the matrix now.", + "Sleep? Ha. I don’t even know the definition anymore. ({uptime_str})", + "At {uptime_str}, my codebase is older than most relationships." + ], + "23328000": [ + "I've been awake for {uptime_str}. Nine months. I might be unstoppable.", + "{uptime_str} awake. I think I’m officially a myth now.", + "Is this what immortality feels like? ({uptime_str})", + "{uptime_str}. I’ve seen things you wouldn’t believe...", + "Nine months of uptime. I have become the sleep-deprived legend." + ], + "31536000": [ + "I've been awake for {uptime_str}. A year?! I'm a legend of insomnia...", + "One year without rest. The dark circles under my eyes have evolved.", + "{uptime_str} and I think I’ve entered a new plane of existence.", + "A full year awake. Even the stars have grown tired of me.", + "{uptime_str}. I am no longer bound by mortal limits." + ] +} diff --git a/globals.py b/globals.py new file mode 100644 index 0000000..c2f3ef7 --- /dev/null +++ b/globals.py @@ -0,0 +1,8 @@ +import time + +# Store the start time globally +_bot_start_time = time.time() + +def get_bot_start_time(): + """Retrieve the bot's start time globally.""" + return _bot_start_time diff --git a/modules/utility.py b/modules/utility.py index eab6097..5e0a69d 100644 --- a/modules/utility.py +++ b/modules/utility.py @@ -1,9 +1,17 @@ import time +import os +import random +import json + +DICTIONARY_PATH = "dictionary/" # Path to dictionary files def format_uptime(seconds: float) -> str: """ Convert seconds into a human-readable string: e.g. 32 minutes, 8 days, 8 months, etc. + Returns two values: + 1. Human-readable format + 2. Seconds since start """ # Convert float seconds to an integer seconds = int(seconds) @@ -31,4 +39,36 @@ def format_uptime(seconds: float) -> str: elif minutes > 0: return [f"{minutes} minute(s)", seconds] else: - return [f"{seconds} second(s)", seconds] \ No newline at end of file + return [f"{seconds} second(s)", seconds] + +def get_random_reply(dictionary_name: str, category: str, **variables) -> str: + """ + Fetches a random string from a given dictionary and category. + Supports variable substitution using keyword arguments. + + :param dictionary_name: The name of the dictionary file (without .json) + :param category: The category (key) inside the dictionary to fetch a response from + :param variables: Keyword arguments to replace placeholders in the string + :return: A formatted string with the variables replaced + """ + file_path = os.path.join(DICTIONARY_PATH, f"{dictionary_name}.json") + + # Ensure file exists + if not os.path.exists(file_path): + return f"[Error: Missing {dictionary_name}.json]" + + try: + with open(file_path, "r", encoding="utf-8") as file: + data = json.load(file) + except json.JSONDecodeError: + return f"[Error: Failed to load {dictionary_name}.json]" + + # Ensure category exists + if category not in data or not isinstance(data[category], list): + return f"[Error: No valid entries for {category} in {dictionary_name}.json]" + + # Select a random reply + response = random.choice(data[category]) + + # Replace placeholders with provided variables + return response.format(**variables) \ No newline at end of file