From 9fa18247e2311e0cb370b936175effa4818788fd Mon Sep 17 00:00:00 2001 From: WhatDidYouExpect <89535984+WhatDidYouExpect@users.noreply.github.com> Date: Wed, 16 Jul 2025 00:43:45 +0200 Subject: [PATCH 1/6] forgot to fix up the .env --- example.env | 2 -- 1 file changed, 2 deletions(-) diff --git a/example.env b/example.env index 03c30c6..6792699 100644 --- a/example.env +++ b/example.env @@ -5,11 +5,9 @@ BLACKLISTEDUSERS= OWNERID= USERTRAINENABLED="true" SHOWMEMENABLED="true" -NAME="gooberino goobs" LOCALE=fi ALIVEPING="True" AUTOUPDATE="True" -GOOBERTOKEN= SONG="Basket Case - Green Day" CHECKSDISABLED="Frue" REACT="True" From ed5f19ccf922c96b2534f62f5969b2f21dd16b87 Mon Sep 17 00:00:00 2001 From: WhatDidYouExpect <89535984+WhatDidYouExpect@users.noreply.github.com> Date: Wed, 16 Jul 2025 00:47:57 +0200 Subject: [PATCH 2/6] goodbye active users --- bot.py | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/bot.py b/bot.py index 437d777..4e53488 100644 --- a/bot.py +++ b/bot.py @@ -99,17 +99,6 @@ async def load_cogs_from_folder(bot, folder_name="assets/cogs"): logger.error(f"{(_('cog_fail'))} {cog_name} {e}") traceback.print_exc() -async def fetch_active_users() -> str: - try: - response: requests.Response = requests.get(f"{VERSION_URL}/active-users") - if response.status_code == 200: - return response.text.strip() - else: - return "?" - except Exception as e: - logger.e(f"{_('error_fetching_active_users')} {RESET} {e}") - return "?" - async def send_alive_ping_periodically() -> None: while True: try: @@ -134,9 +123,6 @@ async def on_ready() -> None: synced: List[discord.app_commands.AppCommand] = await bot.tree.sync() logger.info(f"{_('synced_commands')} {len(synced)} {(_('synced_commands2'))}") slash_commands_enabled = True - - active_users: str = await fetch_active_users() - logger.info(f"{(_('active_users:'))} {active_users}") logger.info(f"{(_('started')).format(name=NAME)}") bot.loop.create_task(send_alive_ping_periodically()) From 260b7e3360b400e234e0a1fe11bffa04c488da86 Mon Sep 17 00:00:00 2001 From: WhatDidYouExpect <89535984+WhatDidYouExpect@users.noreply.github.com> Date: Wed, 16 Jul 2025 00:48:15 +0200 Subject: [PATCH 3/6] dead --- assets/cogs/grabtemplate.py | 29 ----------------------------- 1 file changed, 29 deletions(-) delete mode 100644 assets/cogs/grabtemplate.py diff --git a/assets/cogs/grabtemplate.py b/assets/cogs/grabtemplate.py deleted file mode 100644 index 5a9d8a0..0000000 --- a/assets/cogs/grabtemplate.py +++ /dev/null @@ -1,29 +0,0 @@ -import discord -from discord.ext import commands -import os -import requests -import ast -from modules.globalvars import VERSION_URL - - -class grabTemplate(commands.Cog): - def __init__(self, bot): - self.bot = bot - - def download_json(): - response = requests.get(f"{VERSION_URL}/goob/template.json") - if response.status_code == 200: - if os.path.exists("memory.json"): - return - else: - userinput = input("Do you want to download the template json instead of starting from scratch?\n(Y/N)\n") - if userinput.lower() == "y": - with open("memory.json", "w", encoding="utf-8") as file: - file.write(response.text) - else: - print("Starting from scratch...") - elif response.status_code == 404: - print("File not found on goober central!!") - download_json() -async def setup(bot): - await bot.add_cog(grabTemplate(bot)) From 81b3abf287327773bd704e3cd9ace0de2bd2a530 Mon Sep 17 00:00:00 2001 From: WhatDidYouExpect <89535984+WhatDidYouExpect@users.noreply.github.com> Date: Wed, 16 Jul 2025 01:32:38 +0200 Subject: [PATCH 4/6] duct tape fix for cogmanager and tested using the image module inside of a cog --- assets/cogs/cogmanager.py | 11 +++-- assets/cogs/fuckup.py | 97 +++++++++++++++++++++++++++++++++++++++ modules/coghooks.py | 51 ++++++++++++++++++++ 3 files changed, 154 insertions(+), 5 deletions(-) create mode 100644 assets/cogs/fuckup.py create mode 100644 modules/coghooks.py diff --git a/assets/cogs/cogmanager.py b/assets/cogs/cogmanager.py index 3bddc5f..017f021 100644 --- a/assets/cogs/cogmanager.py +++ b/assets/cogs/cogmanager.py @@ -1,8 +1,9 @@ import discord from discord.ext import commands -import os from modules.globalvars import ownerid +COG_PREFIX = "assets.cogs." + class CogManager(commands.Cog): def __init__(self, bot): self.bot = bot @@ -16,7 +17,7 @@ class CogManager(commands.Cog): await ctx.send("Please provide the cog name to load.") return try: - await self.bot.load_extension(f"cogs.{cog_name}") + await self.bot.load_extension(COG_PREFIX + cog_name) await ctx.send(f"Loaded cog `{cog_name}` successfully.") except Exception as e: await ctx.send(f"Error loading cog `{cog_name}`: {e}") @@ -30,7 +31,7 @@ class CogManager(commands.Cog): await ctx.send("Please provide the cog name to unload.") return try: - await self.bot.unload_extension(f"cogs.{cog_name}") + await self.bot.unload_extension(COG_PREFIX + cog_name) await ctx.send(f"Unloaded cog `{cog_name}` successfully.") except Exception as e: await ctx.send(f"Error unloading cog `{cog_name}`: {e}") @@ -44,8 +45,8 @@ class CogManager(commands.Cog): await ctx.send("Please provide the cog name to reload.") return try: - await self.bot.unload_extension(f"cogs.{cog_name}") - await self.bot.load_extension(f"cogs.{cog_name}") + await self.bot.unload_extension(COG_PREFIX + cog_name) + await self.bot.load_extension(COG_PREFIX + cog_name) await ctx.send(f"Reloaded cog `{cog_name}` successfully.") except Exception as e: await ctx.send(f"Error reloading cog `{cog_name}`: {e}") diff --git a/assets/cogs/fuckup.py b/assets/cogs/fuckup.py new file mode 100644 index 0000000..0540f09 --- /dev/null +++ b/assets/cogs/fuckup.py @@ -0,0 +1,97 @@ +import discord +from discord.ext import commands +from modules.image import * +from PIL import Image, ImageEnhance, ImageFilter, ImageOps, ImageChops, ImageColor +import os, random, shutil, tempfile + +async def deepfryimage(path): + with Image.open(path).convert("RGB") as im: + # make it burn + for _ in range(3): + im = im.resize((int(im.width * 0.7), int(im.height * 0.7))) + im = im.resize((int(im.width * 1.5), int(im.height * 1.5))) + im = ImageEnhance.Contrast(im).enhance(random.uniform(5, 10)) + im = ImageEnhance.Sharpness(im).enhance(random.uniform(10, 50)) + im = ImageEnhance.Brightness(im).enhance(random.uniform(1.5, 3)) + r, g, b = im.split() + r = r.point(lambda i: min(255, i * random.uniform(1.2, 2.0))) + g = g.point(lambda i: min(255, i * random.uniform(0.5, 1.5))) + b = b.point(lambda i: min(255, i * random.uniform(0.5, 2.0))) + channels = [r, g, b] + random.shuffle(channels) + im = Image.merge("RGB", tuple(channels)) + overlay_color = tuple(random.randint(0, 255) for _ in range(3)) + overlay = Image.new("RGB", im.size, overlay_color) + im = ImageChops.add(im, overlay, scale=2.0, offset=random.randint(-64, 64)) + + im = im.filter(ImageFilter.EDGE_ENHANCE_MORE) + im = im.filter(ImageFilter.GaussianBlur(radius=random.uniform(0.5, 2))) + for _ in range(3): + tmp_path = tempfile.mktemp(suffix=".jpg") + im.save(tmp_path, format="JPEG", quality=random.randint(5, 15)) + im = Image.open(tmp_path) + if random.random() < 0.3: + im = ImageOps.posterize(im, bits=random.choice([2, 3, 4])) + if random.random() < 0.2: + im = ImageOps.invert(im) + out_path = tempfile.mktemp(suffix=".jpg") + im.save(out_path, format="JPEG", quality=5) + return out_path + + +class whami(commands.Cog): + def __init__(self, bot): + self.bot = bot + + + @commands.command() + async def fuckup(self, ctx): + assets_folder = "assets/images" + temp_input = None + + def get_random_asset_image(): + files = [f for f in os.listdir(assets_folder) if f.lower().endswith(('.png', '.jpg', '.jpeg', '.webp'))] + if not files: + return None + return os.path.join(assets_folder, random.choice(files)) + + if ctx.message.attachments: + attachment = ctx.message.attachments[0] + if attachment.content_type and attachment.content_type.startswith("image/"): + ext = os.path.splitext(attachment.filename)[1] + temp_input = f"tempy{ext}" + await attachment.save(temp_input) + input_path = temp_input + else: + fallback_image = get_random_asset_image() + if fallback_image is None: + await ctx.reply(_('no_image_available')) + return + temp_input = tempfile.mktemp(suffix=os.path.splitext(fallback_image)[1]) + shutil.copy(fallback_image, temp_input) + input_path = temp_input + else: + fallback_image = get_random_asset_image() + if fallback_image is None: + await ctx.reply(_('no_image_available')) + return + temp_input = tempfile.mktemp(suffix=os.path.splitext(fallback_image)[1]) + shutil.copy(fallback_image, temp_input) + input_path = temp_input + + output_path = await gen_meme(input_path) + + if output_path is None or not os.path.isfile(output_path): + if temp_input and os.path.exists(temp_input): + os.remove(temp_input) + await ctx.reply(_('failed_generate_image')) + return + + deepfried_path = await deepfryimage(output_path) + await ctx.send(file=discord.File(deepfried_path)) + + if temp_input and os.path.exists(temp_input): + os.remove(temp_input) + +async def setup(bot): + await bot.add_cog(whami(bot)) diff --git a/modules/coghooks.py b/modules/coghooks.py new file mode 100644 index 0000000..ab56339 --- /dev/null +++ b/modules/coghooks.py @@ -0,0 +1,51 @@ +import os +import importlib +import inspect +import sys + +_hooks = {} + +def register_hook(name, func): + if name not in _hooks: + _hooks[name] = [] + _hooks[name].append(func) + +async def call_hook(name, *args, **kwargs): + if name not in _hooks: + return + for func in _hooks[name]: + if callable(func): + if inspect.iscoroutinefunction(func): + await func(*args, **kwargs) + else: + func(*args, **kwargs) + +def register_all_functions_as_hooks(module): + """Register every function/coroutine function in the given module as a hook under its function name.""" + for name, obj in inspect.getmembers(module): + if inspect.isfunction(obj) or inspect.iscoroutinefunction(obj): + register_hook(name, obj) + +def _register_all_modules_functions(): + """Scan all python modules in this 'modules' folder (excluding this file) and register their functions.""" + # Calculate the path to the modules directory relative to this file + modules_dir = os.path.dirname(os.path.abspath(__file__)) + + # Current file name so we skip it + current_file = os.path.basename(__file__) + + # Ensure 'modules' is in sys.path for importlib to work + if modules_dir not in sys.path: + sys.path.insert(0, modules_dir) + + # List all python files except dunder files and this file + for filename in os.listdir(modules_dir): + if filename.endswith(".py") and not filename.startswith("__") and filename != current_file: + module_name = filename[:-3] # strip .py extension + try: + module = importlib.import_module(module_name) + register_all_functions_as_hooks(module) + except Exception as e: + print(f"[hooks] Failed to import {module_name}: {e}") + + From c19ee38c9af71465334cb6a8ef0347be110d3081 Mon Sep 17 00:00:00 2001 From: WhatDidYouExpect <89535984+WhatDidYouExpect@users.noreply.github.com> Date: Wed, 16 Jul 2025 11:02:25 +0200 Subject: [PATCH 5/6] cleaned some crap up and updated volta --- assets/cogs/fuckup.py | 1 + example.env | 1 - modules/volta/main.py | 58 ++++++++++++++++++++++++++++++++++++------- 3 files changed, 50 insertions(+), 10 deletions(-) diff --git a/assets/cogs/fuckup.py b/assets/cogs/fuckup.py index 0540f09..1dbc4d0 100644 --- a/assets/cogs/fuckup.py +++ b/assets/cogs/fuckup.py @@ -1,6 +1,7 @@ import discord from discord.ext import commands from modules.image import * +from modules.volta.main import _ from PIL import Image, ImageEnhance, ImageFilter, ImageOps, ImageChops, ImageColor import os, random, shutil, tempfile diff --git a/example.env b/example.env index 6792699..8913dff 100644 --- a/example.env +++ b/example.env @@ -6,7 +6,6 @@ OWNERID= USERTRAINENABLED="true" SHOWMEMENABLED="true" LOCALE=fi -ALIVEPING="True" AUTOUPDATE="True" SONG="Basket Case - Green Day" CHECKSDISABLED="Frue" diff --git a/modules/volta/main.py b/modules/volta/main.py index 03f5d4f..fb6a080 100644 --- a/modules/volta/main.py +++ b/modules/volta/main.py @@ -3,6 +3,7 @@ # For updates or contributions, visit: https://github.com/gooberinc/volta # Also, Note to self: Add more comments it needs more love import os +import locale import json import pathlib import threading @@ -16,8 +17,6 @@ YELLOW = f"{ANSI}33m" DEBUG = f"{ANSI}1;30m" RESET = f"{ANSI}0m" -load_dotenv() - LOCALE = os.getenv("LOCALE") module_dir = pathlib.Path(__file__).parent.parent working_dir = pathlib.Path.cwd() @@ -62,6 +61,37 @@ if working_dir != module_dir: translations = {} _file_mod_times = {} +import locale +import platform +import os +import sys + +def get_system_locale(): + system = platform.system() # fallback incase locale isnt set + if system == "Windows": + lang, _ = locale.getdefaultlocale() + return lang or os.getenv("LANG") + elif system == "Darwin": + try: + import subprocess + result = subprocess.run( + ["defaults", "read", "-g", "AppleLocale"], + stdout=subprocess.PIPE, + stderr=subprocess.DEVNULL, + text=True + ) + return result.stdout.strip() or locale.getdefaultlocale()[0] + except Exception: + return locale.getdefaultlocale()[0] + elif system == "Linux": + return ( + os.getenv("LC_ALL") or + os.getenv("LANG") or + locale.getdefaultlocale()[0] + ) + return locale.getdefaultlocale()[0] + + def load_translations(): global translations, _file_mod_times translations.clear() @@ -99,7 +129,9 @@ def reload_if_changed(): def set_language(lang: str): global LOCALE, ENGLISH_MISSING - if lang in translations: + if not LOCALE: + LOCALE = get_system_locale() + elif lang in translations: LOCALE = lang else: print(f"[VOLTA] {RED}Language '{lang}' not found, defaulting to 'en'{RESET}") @@ -141,19 +173,27 @@ def check_missing_translations(): else: print(f"[VOLTA] All translation keys present for locale: {LOCALE}") +printedsystemfallback = False def get_translation(lang: str, key: str): + global printedsystemfallback if ENGLISH_MISSING: return f"[VOLTA] {RED}No fallback available!{RESET}" + fallback_translations = translations.get(FALLBACK_LOCALE, {}) + sys_lang = get_system_locale().split("_")[0] if get_system_locale() else None + sys_translations = translations.get(sys_lang, {}) if sys_lang else {} lang_translations = translations.get(lang, {}) if key in lang_translations: return lang_translations[key] - else: - if key not in translations.get(FALLBACK_LOCALE, {}): - return f"[VOLTA] {YELLOW}Missing key: '{key}' in {FALLBACK_LOCALE}.json!{RESET}" - fallback = translations.get(FALLBACK_LOCALE, {}).get(key, key) - print(f"[VOLTA] {YELLOW}Missing key: '{key}' in language '{lang}', falling back to: '{fallback}' using {FALLBACK_LOCALE}.json{RESET}") # yeah probably print this - return fallback + if sys_lang and sys_lang != lang and key in sys_translations: + if not printedsystemfallback: + print(f"[VOLTA] {YELLOW}Falling back to system language {sys_lang}!{RESET}") + printedsystemfallback = True + return sys_translations[key] + if key in fallback_translations: + print(f"[VOLTA] {YELLOW}Missing key: '{key}' in '{lang}', falling back to fallback locale '{FALLBACK_LOCALE}'{RESET}") + return fallback_translations[key] + return f"[VOLTA] {YELLOW}Missing key: '{key}' in all locales!{RESET}" def _(key: str) -> str: return get_translation(LOCALE, key) From e333e9bba2009fe9a806a3d28a83d4931ff83928 Mon Sep 17 00:00:00 2001 From: WhatDidYouExpect <89535984+WhatDidYouExpect@users.noreply.github.com> Date: Wed, 16 Jul 2025 11:06:07 +0200 Subject: [PATCH 6/6] almost forgot to bump up the version by 1 --- modules/globalvars.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/globalvars.py b/modules/globalvars.py index 9f6e2e7..23e7e79 100644 --- a/modules/globalvars.py +++ b/modules/globalvars.py @@ -49,7 +49,7 @@ arch = platform.machine() slash_commands_enabled = True # 100% broken, its a newer enough version so its probably enabled by default.... fix this at somepoint or hard code it in goober central code launched = False latest_version = "0.0.0" -local_version = "2.3.1" +local_version = "2.3.2" os.environ['gooberlocal_version'] = local_version REACT = os.getenv("REACT") if get_git_branch() == "dev":