diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..7baa6f9 --- /dev/null +++ b/.env.example @@ -0,0 +1 @@ +DISCORD_BOT_TOKEN="" \ No newline at end of file diff --git a/assets/cogs/cogmanager.py b/assets/cogs/cogmanager.py index 017f021..8c13e36 100644 --- a/assets/cogs/cogmanager.py +++ b/assets/cogs/cogmanager.py @@ -1,6 +1,11 @@ import discord from discord.ext import commands -from modules.globalvars import ownerid +import discord.ext +import discord.ext.commands +from modules.settings import Settings as SettingsManager +settings_manager = SettingsManager() +settings = settings_manager.settings + COG_PREFIX = "assets.cogs." @@ -9,10 +14,34 @@ class CogManager(commands.Cog): self.bot = bot @commands.command() - async def load(self, ctx, cog_name: str = None): - if ctx.author.id != ownerid: + async def enable(self, ctx, cog_name: str): + if ctx.author.id not in settings["bot"]["owner_ids"]: await ctx.send("You do not have permission to use this command.") return + + try: + await self.bot.load_extension(COG_PREFIX + cog_name) + await ctx.send(f"Loaded cog `{cog_name}` successfully.") + settings["bot"]["enabled_cogs"].append(cog_name) + settings_manager.commit() + + except Exception as e: + await ctx.send(f"Error enabling cog `{cog_name}`: {e}") + + + @commands.command() + async def load(self, ctx, cog_name: str | None = None): + if ctx.author.id not in settings["bot"]["owner_ids"]: + await ctx.send("You do not have permission to use this command.") + return + + if cog_name is None: + await ctx.send("Give cog_name") + return + + if cog_name[:-3] not in settings["bot"]["enabled_cogs"]: + await ctx.send("Please enable the cog first!") + return if cog_name is None: await ctx.send("Please provide the cog name to load.") return @@ -23,8 +52,8 @@ class CogManager(commands.Cog): await ctx.send(f"Error loading cog `{cog_name}`: {e}") @commands.command() - async def unload(self, ctx, cog_name: str = None): - if ctx.author.id != ownerid: + async def unload(self, ctx, cog_name: str | None = None): + if ctx.author.id not in settings["bot"]["owner_ids"]: await ctx.send("You do not have permission to use this command.") return if cog_name is None: @@ -37,13 +66,34 @@ class CogManager(commands.Cog): await ctx.send(f"Error unloading cog `{cog_name}`: {e}") @commands.command() - async def reload(self, ctx, cog_name: str = None): - if ctx.author.id != ownerid: + async def disable(self, ctx, cog_name: str | None = None): + if ctx.author.id not in settings["bot"]["owner_ids"]: + await ctx.send("You do not have permission to use this command.") + return + if cog_name is None: + await ctx.send("Please provide the cog name to disable.") + return + try: + await self.bot.unload_extension(COG_PREFIX + cog_name) + await ctx.send(f"Unloaded cog `{cog_name}` successfully.") + settings["bot"]["enabled_cogs"].remove(cog_name) + settings_manager.commit() + except Exception as e: + await ctx.send(f"Error unloading cog `{cog_name}`: {e}") + + + @commands.command() + async def reload(self, ctx, cog_name: str | None = None): + if ctx.author.id not in settings["bot"]["owner_ids"]: await ctx.send("You do not have permission to use this command.") return if cog_name is None: await ctx.send("Please provide the cog name to reload.") return + + if cog_name[:-3] not in settings["bot"]["enabled_cogs"]: + await ctx.send("Please enable the cog first!") + return try: await self.bot.unload_extension(COG_PREFIX + cog_name) await self.bot.load_extension(COG_PREFIX + cog_name) diff --git a/assets/cogs/filesharing.py b/assets/cogs/filesharing.py index 169aa3f..fe7803c 100644 --- a/assets/cogs/filesharing.py +++ b/assets/cogs/filesharing.py @@ -1,9 +1,12 @@ import discord import discord.context_managers from discord.ext import commands -from modules.globalvars import ownerid import logging from typing import Literal, get_args, cast +from modules.settings import Settings as SettingsManager +settings_manager = SettingsManager() +settings = settings_manager.settings + logger = logging.getLogger("goober") @@ -22,10 +25,10 @@ class FileSync(commands.Cog): await ctx.send("Invalid mode, use 's' or 'r'.") return - self.mode: AvailableModes = cast(AvailableModes, mode.lower()) + self.mode = cast(AvailableModes, mode.lower()) self.peer_id = peer.id - if ctx.author.id != ownerid: + if ctx.author.id not in settings["bot"]["owner_ids"]: await ctx.send("You don't have permission to execute this command.") return diff --git a/assets/cogs/fuckup.py b/assets/cogs/fuckup.py index 1dbc4d0..0f79066 100644 --- a/assets/cogs/fuckup.py +++ b/assets/cogs/fuckup.py @@ -1,9 +1,9 @@ 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 +import modules.keys as k async def deepfryimage(path): with Image.open(path).convert("RGB") as im: @@ -66,7 +66,7 @@ class whami(commands.Cog): else: fallback_image = get_random_asset_image() if fallback_image is None: - await ctx.reply(_('no_image_available')) + await ctx.reply(k.no_image_available()) return temp_input = tempfile.mktemp(suffix=os.path.splitext(fallback_image)[1]) shutil.copy(fallback_image, temp_input) @@ -74,7 +74,7 @@ class whami(commands.Cog): else: fallback_image = get_random_asset_image() if fallback_image is None: - await ctx.reply(_('no_image_available')) + await ctx.reply(k.no_image_available()) return temp_input = tempfile.mktemp(suffix=os.path.splitext(fallback_image)[1]) shutil.copy(fallback_image, temp_input) @@ -85,7 +85,7 @@ class whami(commands.Cog): 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')) + await ctx.reply(k.failed_generate_image()) return deepfried_path = await deepfryimage(output_path) diff --git a/assets/cogs/pulse.py b/assets/cogs/pulse.py index f717221..a41b902 100644 --- a/assets/cogs/pulse.py +++ b/assets/cogs/pulse.py @@ -2,7 +2,10 @@ from discord.ext import commands import discord from collections import defaultdict, Counter import datetime -from modules.globalvars import ownerid +from modules.settings import Settings as SettingsManager +settings_manager = SettingsManager() +settings = settings_manager.settings + class StatsCog(commands.Cog): def __init__(self, bot): self.bot = bot @@ -31,7 +34,7 @@ class StatsCog(commands.Cog): @commands.command() async def spyware(self, ctx): - if ctx.author.id != ownerid: + if ctx.author.id not in settings["bot"]["owner_ids"]: return uptime = datetime.datetime.utcnow() - self.start_time hours_elapsed = max((uptime.total_seconds() / 3600), 1) diff --git a/assets/cogs/tf.py.disabled b/assets/cogs/tf.py similarity index 93% rename from assets/cogs/tf.py.disabled rename to assets/cogs/tf.py index 28609e6..0fbee78 100644 --- a/assets/cogs/tf.py.disabled +++ b/assets/cogs/tf.py @@ -14,12 +14,12 @@ MODEL_MATCH_STRING = r"[0-9]{2}_[0-9]{2}_[0-9]{4}-[0-9]{2}_[0-9]{2}" try: import tensorflow as tf - from tensorflow import keras - from tensorflow.keras.preprocessing.text import Tokenizer - from tensorflow.keras.preprocessing.sequence import pad_sequences - from tensorflow.keras.models import Sequential, load_model - from tensorflow.keras.layers import Embedding, LSTM, Dense - from tensorflow.keras.backend import clear_session + import keras + from keras.preprocessing.text import Tokenizer + from keras.preprocessing.sequence import pad_sequences + from keras.models import Sequential, load_model + from keras.layers import Embedding, LSTM, Dense + from keras.backend import clear_session if tf.config.list_physical_devices('GPU'): print("Using GPU acceleration") diff --git a/assets/cogs/webscraper.py.disabled b/assets/cogs/webscraper.py similarity index 93% rename from assets/cogs/webscraper.py.disabled rename to assets/cogs/webscraper.py index 351e2e8..9547790 100644 --- a/assets/cogs/webscraper.py.disabled +++ b/assets/cogs/webscraper.py @@ -5,7 +5,10 @@ from bs4 import BeautifulSoup import json import asyncio from urllib.parse import urljoin -from modules.globalvars import ownerid +from modules.settings import Settings as SettingsManager +settings_manager = SettingsManager() +settings = settings_manager.settings + class WebScraper(commands.Cog): def __init__(self, bot): self.bot = bot @@ -81,7 +84,7 @@ class WebScraper(commands.Cog): @commands.command() async def start_scrape(self, ctx, start_url: str): """Command to start the scraping process.""" - if ctx.author.id != ownerid: + if ctx.author.id not in settings["bot"]["owner_ids"]: await ctx.send("You do not have permission to use this command.") return @@ -99,7 +102,7 @@ class WebScraper(commands.Cog): @commands.command() async def undo_scrape(self, ctx): """Command to undo the last scrape.""" - if ctx.author.id != ownerid: + if ctx.author.id not in settings["bot"]["owner_ids"]: await ctx.send("You do not have permission to use this command.") return diff --git a/assets/cogs/webserver.py.disabled b/assets/cogs/webserver.py similarity index 99% rename from assets/cogs/webserver.py.disabled rename to assets/cogs/webserver.py index 110c20d..70d8296 100644 --- a/assets/cogs/webserver.py.disabled +++ b/assets/cogs/webserver.py @@ -99,6 +99,9 @@ class GooberWeb(commands.Cog): print("Goober web server started on port 8080") async def stop_web_server(self): + if self.site is None or self.runner is None: + return + await self.site.stop() await self.runner.cleanup() print("Web server stopped") diff --git a/assets/locales/en.json b/assets/locales/en.json index 61f4778..a8ae545 100644 --- a/assets/locales/en.json +++ b/assets/locales/en.json @@ -131,6 +131,12 @@ "command_stats_embed_field2name": "Version", "command_stats_embed_field2value": "Local: {local_version} \nLatest: {latest_version}", "command_stats_embed_field3name": "Variable Info", - "command_stats_embed_field3value": "Name: {NAME} \nPrefix: {PREFIX} \nOwner ID: {ownerid}\nPing line: {PING_LINE} \nMemory Sharing Enabled: {showmemenabled} \nUser Training Enabled: {USERTRAIN_ENABLED}\nSong: {song} \nSplashtext: ```{splashtext}```" + "command_stats_embed_field3value": "Name: {NAME} \nPrefix: {PREFIX} \nOwner ID: {ownerid}\nPing line: {PING_LINE} \nMemory Sharing Enabled: {showmemenabled} \nUser Training Enabled: {USERTRAIN_ENABLED}\nSong: {song} \nSplashtext: ```{splashtext}```", + "no_image_available": "No images available!", + "failed_generate_image": "Failed to generate an image", + "markov_model_not_found": "Markov model not found!", + "blacklisted": "blacklisted", + "blacklisted_user": "Blacklisted user", + "edit_fail": "Failed to edit message" } diff --git a/assets/locales/fi.json b/assets/locales/fi.json index 93141cc..7b16005 100644 --- a/assets/locales/fi.json +++ b/assets/locales/fi.json @@ -102,7 +102,7 @@ "command_markov_retrain": "Uudelleenkoulutetaan markov-mallia... Odota.", "command_markov_memory_not_found": "Virhe: muistitiedostoa ei löytynyt!", "command_markov_memory_is_corrupt": "Virhe: muistitiedosto on korruptoitu!", - "command_markov_retraining": "Käsitellään {processed_data}/{data_size} datapisteestä...", + "command_markov_retraining": "Käsitellään {processed_data}/{data_size} datapistettä...", "command_markov_retrain_successful": "Markov-malli koulutettiin uudestaan {data_size} datapisteellä!", "command_desc_talk":"puhuu ja sillei", "command_talk_insufficent_text": "Minun pitää oppia lisää viesteistä ennen kun puhun.", @@ -131,5 +131,6 @@ "command_stats_embed_field2value": "Paikallinen: {local_version} \nUusin: {latest_version}", "command_stats_embed_field3name": "Muuttajainformaatio", "command_stats_embed_field3value": "Nimi: {NAME} \nEtuliite: {PREFIX} \nOmistajan ID: {ownerid}\nPing-linja: {PING_LINE} \nMuistin jako päällä: {showmemenabled} \nOppiminen käyttäjistä: {USERTRAIN_ENABLED}\nLaulu: {song} \nRoisketeksti: ```{splashtext}```" + } diff --git a/bot.py b/bot.py index 74cf0b7..f1a0a73 100644 --- a/bot.py +++ b/bot.py @@ -10,12 +10,22 @@ import shutil import uuid import asyncio import sys -from typing import List, Dict, Set, Optional, Tuple, Any, Union, Callable, Coroutine, TypeVar, Type +from typing import List, Dict, Literal, Set, Optional, Tuple, Any, TypedDict, Union, Callable, Coroutine, TypeVar, Type import logging from modules.globalvars import * from modules.prestartchecks import start_checks from modules.logger import GooberFormatter +import modules.keys as k +from modules import key_compiler import logging +from watchdog.observers import Observer +from watchdog.events import FileSystemEventHandler +from modules.settings import Settings as SettingsManager + +def build_keys(): + key_compiler.build_result("en", "assets/locales", types=True, output_path="modules/keys.py", generate_comments=True) + +build_keys() logger = logging.getLogger("goober") logger.setLevel(logging.DEBUG) @@ -31,8 +41,15 @@ file_handler.setFormatter(GooberFormatter(colors=False)) logger.addHandler(console_handler) logger.addHandler(file_handler) -# Print splash text and check for updates -print(splashtext) # Print splash text (from modules/globalvars.py) +settings_manager = SettingsManager() +settings = settings_manager.settings + +splash_text: str = "" + +with open(settings["splash_text_loc"], "r", encoding="UTF-8") as f: + splash_text = "".join(f.readlines()) + print(splash_text) + start_checks() import requests @@ -45,7 +62,6 @@ from discord.abc import Messageable from better_profanity import profanity from discord.ext import commands -from modules.volta.main import _, set_language from modules.markovmemory import * from modules.version import * from modules.sentenceprocessing import * @@ -60,8 +76,18 @@ T = TypeVar('T') MessageContext = Union[commands.Context, discord.Interaction] MessageReference = Union[Message, discord.WebhookMessage] +class MessageMetadata(TypedDict): + user_id: str + user_name: str + guild_id: str | Literal["DM"] + guild_name: str | Literal["DM"] + channel_id: str + channel_name: str + message: str + timestamp: float + # Constants with type hints -positive_gifs: List[str] = os.getenv("POSITIVE_GIFS", "").split(',') +positive_gifs: List[str] = settings["bot"]["misc"]["positive_gifs"] currenthash: str = "" launched: bool = False slash_commands_enabled: bool = False @@ -70,41 +96,48 @@ slash_commands_enabled: bool = False intents: discord.Intents = discord.Intents.default() intents.messages = True intents.message_content = True + bot: commands.Bot = commands.Bot( - command_prefix=PREFIX, + command_prefix=settings["bot"]["prefix"], intents=intents, allowed_mentions=discord.AllowedMentions(everyone=False, roles=False, users=False, replied_user=True) ) # Load memory and Markov model for text generation -memory: List[str] = load_memory() +memory: List[str | Dict[Literal["_meta"], MessageMetadata]] = load_memory() markov_model: Optional[markovify.Text] = load_markov_model() if not markov_model: - logger.error(_('markov_model_not_found')) + logger.error(k.markov_model_not_found()) memory = load_memory() markov_model = train_markov_model(memory) generated_sentences: Set[str] = set() used_words: Set[str] = set() -async def load_cogs_from_folder(bot, folder_name="assets/cogs"): - for filename in os.listdir(folder_name): - if filename.endswith(".py") and not filename.startswith("_"): - cog_name = filename[:-3] - module_path = folder_name.replace("/", ".").replace("\\", ".") + f".{cog_name}" - try: - await bot.load_extension(module_path) - logger.info(f"{(_('loaded_cog'))} {cog_name}") - except Exception as e: - logger.error(f"{(_('cog_fail'))} {cog_name} {e}") - traceback.print_exc() +async def load_cogs_from_folder(bot: commands.Bot, folder_name="assets/cogs"): + for filename in [file for file in os.listdir(folder_name) if file.endswith(".py")]: + cog_name:str = filename[:-3] + print(cog_name) + + if cog_name not in settings["bot"]["enabled_cogs"]: + logger.debug(f"Skipping cog {cog_name} (not in enabled cogs)") + continue + + module_path = folder_name.replace("/", ".").replace("\\", ".") + f".{cog_name}" + + try: + await bot.load_extension(module_path) + logger.info(f"{k.loaded_cog()} {cog_name}") + except Exception as e: + logger.error(f"{k.cog_fail()} {cog_name} {e}") + traceback.print_exc() async def send_alive_ping_periodically() -> None: while True: try: - requests.post(f"{VERSION_URL}/aliveping", json={"name": NAME}) + requests.post(f"{VERSION_URL}/aliveping", json={"name": settings["name"]}) except Exception as e: - logger.error(f"{(_('error_sending_alive_ping'))}{RESET} {e}") + logger.error(f"{k.error_sending_alive_ping(e)}{RESET} {e}") await asyncio.sleep(60) # Event: Called when the bot is ready @@ -121,9 +154,9 @@ async def on_ready() -> None: await load_cogs_from_folder(bot) try: synced: List[discord.app_commands.AppCommand] = await bot.tree.sync() - logger.info(f"{_('synced_commands')} {len(synced)} {(_('synced_commands2'))}") + logger.info(f"{k.synced_commands()} {len(synced)} {k.synced_commands2()}") slash_commands_enabled = True - logger.info(f"{(_('started')).format(name=NAME)}") + logger.info(k.started(settings["name"])) bot.loop.create_task(send_alive_ping_periodically()) except discord.errors.Forbidden as perm_error: @@ -131,13 +164,13 @@ async def on_ready() -> None: logger.error("Make sure the bot has the 'applications.commands' scope and is invited with the correct permissions.") quit() except Exception as e: - logger.error(f"{_('fail_commands_sync')} {e}") + logger.error(f"{k.fail_commands_sync()} {e}") traceback.print_exc() quit() - if not song: + if not settings["bot"]["misc"]["active_song"]: return - await bot.change_presence(activity=discord.Activity(type=discord.ActivityType.listening, name=f"{song}")) + await bot.change_presence(activity=discord.Activity(type=discord.ActivityType.listening, name=settings["bot"]["misc"]["active_song"])) launched = True @bot.event @@ -157,41 +190,48 @@ async def on_command_error(ctx: commands.Context, error: commands.CommandError) ) # Command: Retrain the Markov model from memory -@bot.hybrid_command(description=f"{(_('command_desc_retrain'))}") +@bot.hybrid_command(description=f"{k.command_desc_retrain()}") async def retrain(ctx: commands.Context) -> None: - if ctx.author.id != ownerid: + global markov_model + + if ctx.author.id not in settings["bot"]["owner_ids"]: + return + + message_ref: discord.Message | None = await send_message(ctx, f"{k.command_markov_retrain()}") + if message_ref is None: + logger.error("Failed to send message!") return - message_ref: MessageReference = await send_message(ctx, f"{(_('command_markov_retrain'))}") try: - with open(MEMORY_FILE, 'r') as f: + with open(settings["bot"]["active_memory"], 'r') as f: memory: List[str] = json.load(f) except FileNotFoundError: - await send_message(ctx, f"{(_('command_markov_memory_not_found'))}") + await send_message(ctx, f"{k.command_markov_memory_not_found()}") return except json.JSONDecodeError: - await send_message(ctx, f"{(_('command_markov_memory_is_corrupt'))}") + await send_message(ctx, f"{k.command_markov_memory_is_corrupt()}") return - - data_size: int = len(memory) - processed_data: int = 0 - processing_message_ref: MessageReference = await send_message(ctx, f"{(_('command_markov_retraining')).format(processed_data=processed_data, data_size=data_size)}") - start_time: float = time.time() - - for i, data in enumerate(memory): - processed_data += 1 - global markov_model + data_size: int = len(memory) + + processing_message_ref: discord.Message | None = await send_message(ctx, f"{k.command_markov_retraining(data_size)}") + if processing_message_ref is None: + logger.error("Couldnt find message processing message!") + + start_time: float = time.time() + markov_model = train_markov_model(memory) save_markov_model(markov_model) - await send_message(ctx, f"{_('command_markov_retrain_successful').format(data_size=data_size)}", edit=True, message_reference=processing_message_ref) + logger.debug(f"Completed retraining in {round(time.time() - start_time,3)}s") + + await send_message(ctx, f"{k.command_markov_retrain_successful(data_size)}", edit=True, message_reference=processing_message_ref) # Command: Generate a sentence using the Markov model -@bot.hybrid_command(description=f"{(_('command_desc_talk'))}") +@bot.hybrid_command(description=f"{k.command_desc_talk()}") async def talk(ctx: commands.Context, sentence_size: int = 5) -> None: if not markov_model: - await send_message(ctx, f"{(_('command_talk_insufficent_text'))}") + await send_message(ctx, f"{k.command_talk_insufficent_text()}") return response: Optional[str] = None @@ -218,65 +258,18 @@ async def talk(ctx: commands.Context, sentence_size: int = 5) -> None: else: combined_message: str = coherent_response logger.info(combined_message) + os.environ['gooberlatestgen'] = combined_message await send_message(ctx, combined_message) else: - await send_message(ctx, f"{(_('command_talk_generation_fail'))}") + await send_message(ctx, f"{k.command_talk_generation_fail()}") -# Command: Generate an image -@bot.hybrid_command(description=f"{(_('command_desc_help'))}") -async def impact(ctx: commands.Context) -> None: - assets_folder: str = "assets/images" - temp_input: Optional[str] = None - - def get_random_asset_image() -> Optional[str]: - files: List[str] = [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: discord.Attachment = ctx.message.attachments[0] - if attachment.content_type and attachment.content_type.startswith("image/"): - ext: str = os.path.splitext(attachment.filename)[1] - temp_input = f"tempy{ext}" - await attachment.save(temp_input) - input_path: str = temp_input - else: - fallback_image: Optional[str] = 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: Optional[str] = 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 - - await ctx.send(file=discord.File(output_path)) - - if temp_input and os.path.exists(temp_input): - os.remove(temp_input) # New demotivator command @bot.hybrid_command(description="Generate a demotivator poster with two lines of text") async def demotivator(ctx: commands.Context) -> None: assets_folder: str = "assets/images" - temp_input: Optional[str] = None + temp_input: str | None = None def get_random_asset_image() -> Optional[str]: files: List[str] = [f for f in os.listdir(assets_folder) if f.lower().endswith(('.png', '.jpg', '.jpeg', '.webp'))] @@ -289,12 +282,13 @@ async def demotivator(ctx: commands.Context) -> None: if attachment.content_type and attachment.content_type.startswith("image/"): ext: str = os.path.splitext(attachment.filename)[1] temp_input = f"tempy{ext}" - await attachment.save(temp_input) + with open(temp_input, "wb") as f: + await attachment.save(f) input_path: str = temp_input else: fallback_image: Optional[str] = get_random_asset_image() if fallback_image is None: - await ctx.reply(_('no_image_available')) + await ctx.reply(k.no_image_available()) return temp_input = tempfile.mktemp(suffix=os.path.splitext(fallback_image)[1]) shutil.copy(fallback_image, temp_input) @@ -302,7 +296,7 @@ async def demotivator(ctx: commands.Context) -> None: else: fallback_image = get_random_asset_image() if fallback_image is None: - await ctx.reply(_('no_image_available')) + await ctx.reply(k.no_image_available()) return temp_input = tempfile.mktemp(suffix=os.path.splitext(fallback_image)[1]) shutil.copy(fallback_image, temp_input) @@ -323,42 +317,43 @@ async def demotivator(ctx: commands.Context) -> None: bot.remove_command('help') # Command: Show help information -@bot.hybrid_command(description=f"{(_('command_desc_help'))}") +@bot.hybrid_command(description=f"{k.command_desc_help()}") async def help(ctx: commands.Context) -> None: embed: discord.Embed = discord.Embed( - title=f"{(_('command_help_embed_title'))}", - description=f"{(_('command_help_embed_desc'))}", + title=f"{k.command_help_embed_title()}", + description=f"{k.command_help_embed_desc()}", color=Colour(0x000000) ) command_categories: Dict[str, List[str]] = { - f"{(_('command_help_categories_general'))}": ["mem", "talk", "about", "ping", "impact", "demotivator", "help"], - f"{(_('command_help_categories_admin'))}": ["stats", "retrain", "setlanguage"] + f"{k.command_help_categories_general()}": ["mem", "talk", "about", "ping", "impact", "demotivator", "help"], + f"{k.command_help_categories_admin()}": ["stats", "retrain", "setlanguage"] } custom_commands: List[str] = [] for cog_name, cog in bot.cogs.items(): for command in cog.get_commands(): - if command.name not in command_categories[f"{(_('command_help_categories_general'))}"] and command.name not in command_categories[f"{(_('command_help_categories_admin'))}"]: + if command.name not in command_categories[f"{k.command_help_categories_general()}"] and command.name not in command_categories[f"{k.command_help_categories_admin()}"]: custom_commands.append(command.name) if custom_commands: - embed.add_field(name=f"{(_('command_help_categories_custom'))}", value="\n".join([f"{PREFIX}{command}" for command in custom_commands]), inline=False) + embed.add_field(name=f"{k.command_help_categories_custom()}", value="\n".join([f"{settings["bot"]["prefix"]}{command}" for command in custom_commands]), inline=False) for category, commands_list in command_categories.items(): - commands_in_category: str = "\n".join([f"{PREFIX}{command}" for command in commands_list]) + commands_in_category: str = "\n".join([f"{settings["bot"]["prefix"]}{command}" for command in commands_list]) embed.add_field(name=category, value=commands_in_category, inline=False) await send_message(ctx, embed=embed) -@bot.hybrid_command(description=f"{(_('command_desc_setlang'))}") +@bot.hybrid_command(description=f"{k.command_desc_setlang()}") @app_commands.describe(locale="Choose your language") async def setlanguage(ctx: commands.Context, locale: str) -> None: - if ctx.author.id != ownerid: + if ctx.author.id not in settings["bot"]["owner_ids"]: await ctx.send(":thumbsdown:") return + await ctx.defer() - set_language(locale) + k.change_language(locale) await ctx.send(":thumbsup:") # Event: Called on every message @@ -369,25 +364,32 @@ async def on_message(message: discord.Message) -> None: if message.author.bot: return - if str(message.author.id) in BLACKLISTED_USERS: + if str(message.author.id) in settings["bot"]["blacklisted_users"]: return - if message.content.startswith((f"{PREFIX}talk", f"{PREFIX}mem", f"{PREFIX}help", f"{PREFIX}stats", f"{PREFIX}")): - logger.info(f"{(_('command_ran')).format(message=message)}") + + commands = [settings["bot"]["prefix"] + command.name for command in bot.tree.get_commands()] + + if message.content.startswith(tuple(commands)): + logger.info(f"{k.command_ran(message.author.name, message.content)}") await bot.process_commands(message) return - if profanity.contains_profanity(message.content): + if profanity.contains_profanity(message.content) and settings["bot"]["misc"]["block_profanity"]: return if message.content: - if not USERTRAIN_ENABLED: + if not settings["bot"]["user_training"]: return + formatted_message: str = append_mentions_to_18digit_integer(message.content) cleaned_message: str = preprocess_message(formatted_message) if cleaned_message: memory.append(cleaned_message) - message_metadata = { + + + + message_metadata: MessageMetadata = { "user_id": str(message.author.id), "user_name": str(message.author), "guild_id": str(message.guild.id) if message.guild else "DM", @@ -409,7 +411,7 @@ async def on_message(message: discord.Message) -> None: sentiment_score = is_positive(message.content) # doesnt work but im scared to change the logic now please ignore if sentiment_score > 0.8: - if REACT != "True": + if not settings["bot"]["react_to_messages"]: return emoji = random.choice(EMOJIS) try: @@ -422,27 +424,27 @@ async def on_message(message: discord.Message) -> None: # Event: Called on every interaction (slash command, etc.) @bot.event async def on_interaction(interaction: discord.Interaction) -> None: - logger.info(f"{(_('command_ran_s')).format(interaction=interaction)}{interaction.data['name']}") + logger.info(f"{k.command_ran_s(interaction.user.name)} {interaction.user.name}") # Global check: Block blacklisted users from running commands @bot.check async def block_blacklisted(ctx: commands.Context) -> bool: - if str(ctx.author.id) in BLACKLISTED_USERS: + if str(ctx.author.id) in settings["bot"]["blacklisted_users"]: try: if isinstance(ctx, discord.Interaction): if not ctx.response.is_done(): - await ctx.response.send_message(_('blacklisted'), ephemeral=True) + await ctx.response.send_message(k.blacklisted(), ephemeral=True) else: - await ctx.followup.send(_('blacklisted'), ephemeral=True) + await ctx.followup.send(k.blacklisted(), ephemeral=True) else: - await ctx.send(_('blacklisted_user'), ephemeral=True) + await ctx.send(k.blacklisted_user(), ephemeral=True) except: pass return False return True # Command: Show bot latency -@bot.hybrid_command(description=f"{(_('command_desc_ping'))}") +@bot.hybrid_command(description=f"{k.command_desc_ping()}") async def ping(ctx: commands.Context) -> None: await ctx.defer() latency: int = round(bot.latency * 1000) @@ -450,35 +452,44 @@ async def ping(ctx: commands.Context) -> None: LOLembed: discord.Embed = discord.Embed( title="Pong!!", description=( - f"{PING_LINE}\n" - f"`{(_('command_ping_embed_desc'))}: {latency}ms`\n" + settings["bot"]["misc"]["ping_line"], + f"`{k.command_ping_embed_desc()}: {latency}ms`\n" ), color=Colour(0x000000) ) - LOLembed.set_footer(text=f"{(_('command_ping_footer'))} {ctx.author.name}", icon_url=ctx.author.avatar.url) + LOLembed.set_footer(text=f"{k.command_ping_footer()} {ctx.author.name}", icon_url=ctx.author.display_avatar.url) await ctx.send(embed=LOLembed) # Command: Show about information -@bot.hybrid_command(description=f"{(_('command_about_desc'))}") +@bot.hybrid_command(description=f"{k.command_about_desc()}") async def about(ctx: commands.Context) -> None: print("-----------------------------------\n\n") - latest_version: str = check_for_update() + latest_version: str = str(check_for_update()) print("-----------------------------------") - embed: discord.Embed = discord.Embed(title=f"{(_('command_about_embed_title'))}", description="", color=Colour(0x000000)) - embed.add_field(name=f"{(_('command_about_embed_field1'))}", value=f"{NAME}", inline=False) - embed.add_field(name=f"{(_('command_about_embed_field2name'))}", value=f"{(_('command_about_embed_field2value')).format(local_version=local_version, latest_version=latest_version)}", inline=False) - embed.add_field(name=f"Github", value=f"https://github.com/gooberinc/goober") + embed: discord.Embed = discord.Embed(title=f"{k.command_about_embed_title()}", description="", color=Colour(0x000000)) + + embed.add_field(name=k.command_about_embed_field1(), value=f"{settings["name"]}", inline=False) + + embed.add_field( + name=k.command_about_embed_field2name(), + value=k.command_about_embed_field2value( + local_version=local_version, latest_version=latest_version + ), + inline=False + ) + + embed.add_field(name="Github", value=f"https://github.com/gooberinc/goober") await send_message(ctx, embed=embed) # Command: Show bot statistics (admin only) @bot.hybrid_command(description="stats") async def stats(ctx: commands.Context) -> None: - if ctx.author.id != ownerid: + if ctx.author.id not in settings["bot"]["owner_ids"]: return print("-----------------------------------\n\n") - latest_version: str = check_for_update() + latest_version: str = str(check_for_update()) print("-----------------------------------") memory_file: str = 'memory.json' file_size: int = os.path.getsize(memory_file) @@ -486,18 +497,24 @@ async def stats(ctx: commands.Context) -> None: with open(memory_file, 'r') as file: line_count: int = sum(1 for _ in file) - embed: discord.Embed = discord.Embed(title=f"{(_('command_stats_embed_title'))}", description=f"{(_('command_stats_embed_desc'))}", color=Colour(0x000000)) - embed.add_field(name=f"{(_('command_stats_embed_field1name'))}", value=f"{(_('command_stats_embed_field1value')).format(file_size=file_size, line_count=line_count)}", inline=False) - embed.add_field(name=f"{(_('command_stats_embed_field2name'))}", value=f"{(_('command_stats_embed_field2value')).format(local_version=local_version, latest_version=latest_version)}", inline=False) - embed.add_field(name=f"{(_('command_stats_embed_field3name'))}", value=f"{(_('command_stats_embed_field3value')).format(NAME=NAME, PREFIX=PREFIX, ownerid=ownerid, PING_LINE=PING_LINE, showmemenabled=showmemenabled, USERTRAIN_ENABLED=USERTRAIN_ENABLED, song=song, splashtext=splashtext)}", inline=False) + embed: discord.Embed = discord.Embed(title=f"{k.command_stats_embed_title()}", description=f"{k.command_stats_embed_desc()}", color=Colour(0x000000)) + embed.add_field(name=f"{k.command_stats_embed_field1name()}", value=f"{k.command_stats_embed_field1value(file_size=file_size, line_count=line_count)}", inline=False) + embed.add_field(name=f"{k.command_stats_embed_field2name()}", value=f"{k.command_stats_embed_field2value(local_version=local_version, latest_version=latest_version)}", inline=False) + embed.add_field(name=f"{k.command_stats_embed_field3name()}", value=f"{k.command_stats_embed_field3value( + NAME=settings["name"], PREFIX=settings["bot"]["prefix"], ownerid=settings["bot"]["owner_ids"][0], + PING_LINE=settings["bot"]["misc"]["ping_line"], showmemenabled=settings["bot"]["allow_show_mem_command"], + USERTRAIN_ENABLED=settings["bot"]["user_training"], song=settings["bot"]["misc"]["active_song"], + splashtext=splash_text + )}", inline=False) await send_message(ctx, embed=embed) # Command: Upload memory.json to litterbox.catbox.moe and return the link @bot.hybrid_command() async def mem(ctx: commands.Context) -> None: - if showmemenabled != "true": + if not settings["bot"]["allow_show_mem_command"]: return + command: str = """curl -F "reqtype=fileupload" -F "time=1h" -F "fileToUpload=@memory.json" https://litterbox.catbox.moe/resources/internals/api.php""" memorylitter: subprocess.CompletedProcess = subprocess.run(command, shell=True, capture_output=True, text=True) logger.debug(memorylitter) @@ -509,5 +526,36 @@ def improve_sentence_coherence(sentence: str) -> str: sentence = sentence.replace(" i ", " I ") return sentence + +class OnMyWatch: + watchDirectory = "assets/locales" + + def __init__(self): + self.observer = Observer() + + def run(self): + event_handler = Handler() + self.observer.schedule(event_handler, self.watchDirectory, recursive = True) + self.observer.start() + try: + while True: + time.sleep(5) + except: + self.observer.stop() + print("Observer Stopped") + + self.observer.join() + + +class Handler(FileSystemEventHandler): + def on_any_event(self, event): + if event.is_directory: + return None + + elif event.event_type == 'modified': + build_keys() + + + # Start the bot -bot.run(TOKEN) \ No newline at end of file +bot.run(os.environ.get("DISCORD_BOT_TOKEN", "")) \ No newline at end of file diff --git a/modules/globalvars.py b/modules/globalvars.py index 2281388..5748d6c 100644 --- a/modules/globalvars.py +++ b/modules/globalvars.py @@ -23,37 +23,38 @@ YELLOW = f"{ANSI}33m" PURPLE = f"{ANSI}35m" DEBUG = f"{ANSI}1;30m" RESET = f"{ANSI}0m" + VERSION_URL = "https://raw.githubusercontent.com/gooberinc/version/main" UPDATE_URL = VERSION_URL+"/latest_version.json" print(UPDATE_URL) LOCAL_VERSION_FILE = "current_version.txt" -TOKEN = os.getenv("DISCORDBOTTOKEN", "0") -PREFIX = os.getenv("BOTPREFIX", "g.") -PING_LINE = os.getenv("PINGLINE") -CHECKS_DISABLED = os.getenv("CHECKSDISABLED") -LOCALE = os.getenv("LOCALE", "en") -gooberTOKEN = os.getenv("GOOBERTOKEN") -splashtext = os.getenv("SPLASHTEXT") -ownerid = int(os.getenv("OWNERID", "0")) -showmemenabled = os.getenv("SHOWMEMENABLED") -BLACKLISTED_USERS = os.getenv("BLACKLISTEDUSERS", "").split(",") -USERTRAIN_ENABLED = os.getenv("USERTRAINENABLED", "true").lower() == "true" -NAME = os.getenv("NAME") -MEMORY_FILE = "memory.json" -MEMORY_LOADED_FILE = "MEMORY_LOADED" # is this still even used?? okay just checked its used in the markov module -ALIVEPING = os.getenv("ALIVEPING") -AUTOUPDATE = os.getenv("AUTOUPDATE") + +# TOKEN = os.getenv("DISCORDBOTTOKEN", "0") +# PREFIX = os.getenv("BOTPREFIX", "g.") +# PING_LINE = os.getenv("PINGLINE") +# CHECKS_DISABLED = os.getenv("CHECKSDISABLED") +# LOCALE = os.getenv("LOCALE", "en") +# BLACKLISTED_USERS = os.getenv("BLACKLISTEDUSERS", "").split(",") +# USERTRAIN_ENABLED = os.getenv("USERTRAINENABLED", "true").lower() == "true" +# NAME = os.getenv("NAME") +# MEMORY_FILE = "memory.json" +# MEMORY_LOADED_FILE = "MEMORY_LOADED" # is this still even used?? okay just checked its used in the markov module +# ALIVEPING = os.getenv("ALIVEPING") +# AUTOUPDATE = os.getenv("AUTOUPDATE") +# REACT = os.getenv("REACT") + +# gooberTOKEN = os.getenv("GOOBERTOKEN") +# splashtext = os.getenv("SPLASHTEXT") +# ownerid = int(os.getenv("OWNERID", "0")) +# showmemenabled = os.getenv("SHOWMEMENABLED") + + # IGNOREWARNING = False # is this either??? i don't think so? -song = os.getenv("song") +# song = os.getenv("song") 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.3" os.environ['gooberlocal_version'] = local_version -REACT = os.getenv("REACT") -if get_git_branch() == "dev": - beta = True - # this makes goober think its a beta version, so it will not update to the latest stable version or run any version checks -else: - beta = False \ No newline at end of file +beta = get_git_branch() == "dev" diff --git a/modules/key_compiler.py b/modules/key_compiler.py new file mode 100644 index 0000000..6abac8f --- /dev/null +++ b/modules/key_compiler.py @@ -0,0 +1,191 @@ +# The MIT License (MIT) + +# Copyright (c) 2025 ctih1 + +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: + +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. + +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +import os +from typing import Dict, List, Literal +import json +import sys +import logging +import time + +NOTICE = """ +# This file was automatically created from localization JSON files. +# DO NOT EDIT THIS FILE DIRECTLY. If you want to edit a translation, please use the language's JSON file. +""" + + +logging.basicConfig( + level=logging.DEBUG, + format="%(levelname)s: [%(filename)s:%(funcName)s] %(message)s", + datefmt="%d/%m/%Y %H.%M.%S", + stream=sys.stdout, +) + +logger = logging.getLogger("kaannos") + +class LanguageCollector: + def __init__(self, language_dir: str) -> None: + self.path: str = language_dir + self.languages: Dict[str, Dict[str,str]] = {} + + for file in os.listdir(self.path): + if not file.endswith(".json") or len(file) > 7: + logger.debug(f"Skipping {file}") + continue + + locale: str = file.split(".json")[0] + logger.info(f"Discovered {file}") + with open(os.path.join(self.path, file), "r", encoding="UTF-8") as f: + keys: Dict[str,str] = json.load(f) + self.languages[locale] = keys + + print(self.languages) + self.find_missing_keys() + + + def find_missing_keys(self) -> None: + primary_language_keys: Dict[str, str] = self.languages["en"] + + for key in primary_language_keys: + for language in self.languages: + if key not in self.languages[language]: + logger.warning(f"Key {key} missing from {language}") + + for language in self.languages: + for key in self.languages[language]: + if key not in primary_language_keys: + logger.warning(f"Leftover key {key} found from {language}") + +class Script: + def __init__(self) -> None: + self.script: str = "" + + def add_line(self, content, indent: int=0, newline: bool = True) -> None: + self.script += f"{'\t' * indent}{content}{'\n' if newline else ''}" + +def process_name(key: str) -> str: + return key.replace(" ", "_").replace(":","").lower() + +def find_args(string: str) -> List[str]: + variable_open: bool = False + temp_content: str = "" + + variables: List[str] = [] + for char in string: + if variable_open: + if char == "}": + variable_open = False + variables.append(temp_content) + temp_content = "" + continue + + if char == "{": + raise SyntaxError("Variable already open!") + + temp_content += char + + else: + if char == "}": + raise SyntaxError("Trying to close a nonexistant variable") + + if char == "{": + variable_open = True + + return variables + +def convert_args(inp: str, vars: List[str], mode: Literal["brackets", "none"] = "brackets") -> str: + replacements = { + ".": "_", + ",": "_" + } + + for var in vars: + cleaned_var = var + for key, val in replacements.items(): + cleaned_var = cleaned_var.replace(key, val) + + if mode == "none": + inp = inp.replace(f"{var}", f"{cleaned_var}") + else: + inp = inp.replace(f"{{{var}}}", f"{{{cleaned_var}}}") + + return inp + + + +class GenerateScript: + def __init__(self, primary_lang:str, language_data: Dict[str, Dict[str,str]], use_typing: bool = True, output_path: str = "out.py", generate_comments: bool = True): + self.data = language_data + self.primary = primary_lang + self.script = Script() + self.uses_typing: bool = use_typing + self.output = output_path + self.generate_comments = generate_comments + + def create(self): + # I really don't like this implementation but also it works + self.script.add_line(NOTICE) + if self.uses_typing: + self.script.add_line("from typing import Literal, List") + self.script.add_line(f"Language=Literal{list(self.data.keys())}") + self.script.add_line(f"languages: List[Language] = {list(self.data.keys())}") + self.script.add_line(f"default_lang: Language | str='{self.primary}'") + self.script.add_line("def change_language(new_lang: Language | str) -> None: global default_lang; default_lang = new_lang") + else: + self.script.add_line(f"languages = {list(self.data.keys())}") + self.script.add_line(f"default_lang='{self.primary}'") + self.script.add_line("def change_language(new_lang): global default_lang; default_lang = new_lang") + + + self.primary_data = self.data[self.primary] + + for key in self.primary_data: + args = find_args(self.primary_data[key]) + + self.script.add_line(f"def {process_name(key)}({convert_args(','.join([*args, "lang:str|None=None" if self.uses_typing else "lang"]), args, "none")}):") + if self.generate_comments: + self.script.add_line('"""', 1) + self.script.add_line("### Locales", 1) + for language in self.data: + self.script.add_line(f'- {language.capitalize()}: **{self.data[language].get(key, self.primary_data[key])}**', 1) + self.script.add_line('"""', 1) + self.script.add_line("if not lang: lang=default_lang", 1) + for language in self.data: + formatted_map = "{" + for arg in args: + formatted_map += f'"{convert_args(arg, args, "none")}": {convert_args(arg, args, "none")},' + formatted_map = formatted_map[:-1] + "}" + self.script.add_line(f"""if lang == '{language}': return {convert_args(json.dumps( + self.data[language].get(key,self.primary_data[key]), + ensure_ascii=False + ), args)}{f'.format_map({formatted_map})' if len(args) > 0 else ''}""", 1) + + self.script.add_line("else: raise ValueError(f'Invalid language {lang}')", 1) + with open(self.output, "w", encoding="UTF-8") as f: + f.write(self.script.script) + + +def build_result(primary_lang: str, locale_dir: str, types: bool, output_path: str, generate_comments: bool = True): + start = time.time() + lc = LanguageCollector(locale_dir) + GenerateScript(primary_lang, lc.languages, types, output_path, generate_comments).create() + logger.info(f"Done in {time.time() - start}s") \ No newline at end of file diff --git a/modules/keys.py b/modules/keys.py new file mode 100644 index 0000000..a95d41c --- /dev/null +++ b/modules/keys.py @@ -0,0 +1,2306 @@ + +# This file was automatically created from localization JSON files. +# DO NOT EDIT THIS FILE DIRECTLY. If you want to edit a translation, please use the language's JSON file. + +from typing import Literal, List +Language=Literal['en', 'es', 'fi', 'fr', 'it'] +languages: List[Language] = ['en', 'es', 'fi', 'fr', 'it'] +default_lang: Language | str='en' +def change_language(new_lang: Language | str) -> None: global default_lang; default_lang = new_lang +def memory_file_valid(lang:str|None=None): + """ + ### Locales + - En: **The memory.json file is valid!** + - Es: **The memory.json file is valid!** + - Fi: **memory.json on toimiva!** + - Fr: **The memory.json file is valid!** + - It: **Il file JSON è valido!** + """ + if not lang: lang=default_lang + if lang == 'en': return "The memory.json file is valid!" + if lang == 'es': return "The memory.json file is valid!" + if lang == 'fi': return "memory.json on toimiva!" + if lang == 'fr': return "The memory.json file is valid!" + if lang == 'it': return "Il file JSON è valido!" + else: raise ValueError(f'Invalid language {lang}') +def file_aint_uft8(lang:str|None=None): + """ + ### Locales + - En: **File is not valid UTF-8 text. Might be binary or corrupted.** + - Es: **File is not valid UTF-8 text. Might be binary or corrupted.** + - Fi: **Tiedosto ei ole UTF-8 tekstiä. Saattaa olla binääriä tai korruptoitunut.** + - Fr: **File is not valid UTF-8 text. Might be binary or corrupted.** + - It: **File is not valid UTF-8 text. Might be binary or corrupted.** + """ + if not lang: lang=default_lang + if lang == 'en': return "File is not valid UTF-8 text. Might be binary or corrupted." + if lang == 'es': return "File is not valid UTF-8 text. Might be binary or corrupted." + if lang == 'fi': return "Tiedosto ei ole UTF-8 tekstiä. Saattaa olla binääriä tai korruptoitunut." + if lang == 'fr': return "File is not valid UTF-8 text. Might be binary or corrupted." + if lang == 'it': return "File is not valid UTF-8 text. Might be binary or corrupted." + else: raise ValueError(f'Invalid language {lang}') +def psutil_not_installed(lang:str|None=None): + """ + ### Locales + - En: **Memory check skipped.** + - Es: **Memory check skipped.** + - Fi: **Memory check skipped.** + - Fr: **Memory check skipped.** + - It: **Controllo memoria saltato.** + """ + if not lang: lang=default_lang + if lang == 'en': return "Memory check skipped." + if lang == 'es': return "Memory check skipped." + if lang == 'fi': return "Memory check skipped." + if lang == 'fr': return "Memory check skipped." + if lang == 'it': return "Controllo memoria saltato." + else: raise ValueError(f'Invalid language {lang}') +def not_cloned(lang:str|None=None): + """ + ### Locales + - En: **Goober is not cloned! Please clone it from GitHub.** + - Es: **Goober is not cloned! Please clone it from GitHub.** + - Fi: **Goober is not cloned! Please clone it from GitHub.** + - Fr: **Goober is not cloned! Please clone it from GitHub.** + - It: **Goober non è stato clonato! Clonalo da GitHub.** + """ + if not lang: lang=default_lang + if lang == 'en': return "Goober is not cloned! Please clone it from GitHub." + if lang == 'es': return "Goober is not cloned! Please clone it from GitHub." + if lang == 'fi': return "Goober is not cloned! Please clone it from GitHub." + if lang == 'fr': return "Goober is not cloned! Please clone it from GitHub." + if lang == 'it': return "Goober non è stato clonato! Clonalo da GitHub." + else: raise ValueError(f'Invalid language {lang}') +def checks_disabled(lang:str|None=None): + """ + ### Locales + - En: **Checks are disabled!** + - Es: **Checks are disabled!** + - Fi: **Tarkistukset on poistettu käytöstä!** + - Fr: **Les vérifications sont désactivées !** + - It: **I controlli sono disabilitati!** + """ + if not lang: lang=default_lang + if lang == 'en': return "Checks are disabled!" + if lang == 'es': return "Checks are disabled!" + if lang == 'fi': return "Tarkistukset on poistettu käytöstä!" + if lang == 'fr': return "Les vérifications sont désactivées !" + if lang == 'it': return "I controlli sono disabilitati!" + else: raise ValueError(f'Invalid language {lang}') +def unhandled_exception(lang:str|None=None): + """ + ### Locales + - En: **An unhandled exception occurred. Please report this issue on GitHub.** + - Es: **An unhandled exception occurred. Please report this issue on GitHub.** + - Fi: **Käsittelemätön virhe tapahtui. Ilmoita tästä GitHubissa.** + - Fr: **Une exception non gérée est survenue. Merci de rapporter ce problème sur GitHub.** + - It: **Si è verificata un'eccezione non gestita. Segnala questo problema su GitHub, per favore.** + """ + if not lang: lang=default_lang + if lang == 'en': return "An unhandled exception occurred. Please report this issue on GitHub." + if lang == 'es': return "An unhandled exception occurred. Please report this issue on GitHub." + if lang == 'fi': return "Käsittelemätön virhe tapahtui. Ilmoita tästä GitHubissa." + if lang == 'fr': return "Une exception non gérée est survenue. Merci de rapporter ce problème sur GitHub." + if lang == 'it': return "Si è verificata un'eccezione non gestita. Segnala questo problema su GitHub, per favore." + else: raise ValueError(f'Invalid language {lang}') +def active_users(lang:str|None=None): + """ + ### Locales + - En: **Active users:** + - Es: **Active users:** + - Fi: **Aktiiviset käyttäjät:** + - Fr: **Utilisateurs actifs :** + - It: **Utenti attivi:** + """ + if not lang: lang=default_lang + if lang == 'en': return "Active users:" + if lang == 'es': return "Active users:" + if lang == 'fi': return "Aktiiviset käyttäjät:" + if lang == 'fr': return "Utilisateurs actifs :" + if lang == 'it': return "Utenti attivi:" + else: raise ValueError(f'Invalid language {lang}') +def spacy_initialized(lang:str|None=None): + """ + ### Locales + - En: **spaCy and spacytextblob are ready.** + - Es: **spaCy and spacytextblob are ready.** + - Fi: **spaCy ja spacytextblob ovat valmiita.** + - Fr: **spaCy et spacytextblob sont prêts.** + - It: **spaCy e spacytextblob sono pronti.** + """ + if not lang: lang=default_lang + if lang == 'en': return "spaCy and spacytextblob are ready." + if lang == 'es': return "spaCy and spacytextblob are ready." + if lang == 'fi': return "spaCy ja spacytextblob ovat valmiita." + if lang == 'fr': return "spaCy et spacytextblob sont prêts." + if lang == 'it': return "spaCy e spacytextblob sono pronti." + else: raise ValueError(f'Invalid language {lang}') +def spacy_model_not_found(lang:str|None=None): + """ + ### Locales + - En: **The spaCy model was not found! Downloading it....`** + - Es: **The spaCy model was not found! Downloading it....`** + - Fi: **spaCy mallia ei löytynyt! Ladataan se....`** + - Fr: **Le modèle spaCy est introuvable ! Téléchargement en cours...** + - It: **Il modello spaCy non è stato trovato! Lo sto scaricando...** + """ + if not lang: lang=default_lang + if lang == 'en': return "The spaCy model was not found! Downloading it....`" + if lang == 'es': return "The spaCy model was not found! Downloading it....`" + if lang == 'fi': return "spaCy mallia ei löytynyt! Ladataan se....`" + if lang == 'fr': return "Le modèle spaCy est introuvable ! Téléchargement en cours..." + if lang == 'it': return "Il modello spaCy non è stato trovato! Lo sto scaricando..." + else: raise ValueError(f'Invalid language {lang}') +def env_file_not_found(lang:str|None=None): + """ + ### Locales + - En: **The .env file was not found! Please create one with the required variables.** + - Es: **The .env file was not found! Please create one with the required variables.** + - Fi: **.env-tiedostoa ei löytnyt! Luo tiedosto jossa on tarvittavat muuttujat** + - Fr: **Le fichier .env est introuvable ! Créez-en un avec les variables nécessaires.** + - It: **Il file .env non è stato trovato! Crea un file con le variabili richieste.** + """ + if not lang: lang=default_lang + if lang == 'en': return "The .env file was not found! Please create one with the required variables." + if lang == 'es': return "The .env file was not found! Please create one with the required variables." + if lang == 'fi': return ".env-tiedostoa ei löytnyt! Luo tiedosto jossa on tarvittavat muuttujat" + if lang == 'fr': return "Le fichier .env est introuvable ! Créez-en un avec les variables nécessaires." + if lang == 'it': return "Il file .env non è stato trovato! Crea un file con le variabili richieste." + else: raise ValueError(f'Invalid language {lang}') +def error_fetching_active_users(error,lang:str|None=None): + """ + ### Locales + - En: **Error fetching active users: {error}** + - Es: **Error fetching active users: {error}** + - Fi: **Aktiivisten käyttäjien hankkimisessa tapahtui ongelma: {error}** + - Fr: **Erreur lors de la récupération des utilisateurs actifs : {error}** + - It: **Errore nel recupero degli utenti attivi: {error}** + """ + if not lang: lang=default_lang + if lang == 'en': return "Error fetching active users: {error}".format_map({"error": error}) + if lang == 'es': return "Error fetching active users: {error}".format_map({"error": error}) + if lang == 'fi': return "Aktiivisten käyttäjien hankkimisessa tapahtui ongelma: {error}".format_map({"error": error}) + if lang == 'fr': return "Erreur lors de la récupération des utilisateurs actifs : {error}".format_map({"error": error}) + if lang == 'it': return "Errore nel recupero degli utenti attivi: {error}".format_map({"error": error}) + else: raise ValueError(f'Invalid language {lang}') +def error_sending_alive_ping(error,lang:str|None=None): + """ + ### Locales + - En: **Error sending alive ping: {error}** + - Es: **Error sending alive ping: {error}** + - Fi: **Pingin lähettäminen goober centraliin epäonnistui: {error}** + - Fr: **Erreur lors de l’envoi du ping actif : {error}** + - It: **Errore nell'invio di aliveping:** + """ + if not lang: lang=default_lang + if lang == 'en': return "Error sending alive ping: {error}".format_map({"error": error}) + if lang == 'es': return "Error sending alive ping: {error}".format_map({"error": error}) + if lang == 'fi': return "Pingin lähettäminen goober centraliin epäonnistui: {error}".format_map({"error": error}) + if lang == 'fr': return "Erreur lors de l’envoi du ping actif : {error}".format_map({"error": error}) + if lang == 'it': return "Errore nell'invio di aliveping:".format_map({"error": error}) + else: raise ValueError(f'Invalid language {lang}') +def already_started(lang:str|None=None): + """ + ### Locales + - En: **I've already started! I'm not updating...** + - Es: **I've already started! I'm not updating...** + - Fi: **Olen jo käynnistynyt! Ei päivitetä...** + - Fr: **J’ai déjà démarré ! Je ne me mets pas à jour...** + - It: **Sono già avviato! Non aggiorno...** + """ + if not lang: lang=default_lang + if lang == 'en': return "I've already started! I'm not updating..." + if lang == 'es': return "I've already started! I'm not updating..." + if lang == 'fi': return "Olen jo käynnistynyt! Ei päivitetä..." + if lang == 'fr': return "J’ai déjà démarré ! Je ne me mets pas à jour..." + if lang == 'it': return "Sono già avviato! Non aggiorno..." + else: raise ValueError(f'Invalid language {lang}') +def please_restart(lang:str|None=None): + """ + ### Locales + - En: **Please Restart goober!** + - Es: **Please Restart goober!** + - Fi: **Käynnistä uudelleen, hölmö!** + - Fr: **Redémarre, stp !** + - It: **Riavvia goober!** + """ + if not lang: lang=default_lang + if lang == 'en': return "Please Restart goober!" + if lang == 'es': return "Please Restart goober!" + if lang == 'fi': return "Käynnistä uudelleen, hölmö!" + if lang == 'fr': return "Redémarre, stp !" + if lang == 'it': return "Riavvia goober!" + else: raise ValueError(f'Invalid language {lang}') +def local_ahead(remote,branch,lang:str|None=None): + """ + ### Locales + - En: **Local {remote}/{branch} is ahead and/or up to par. Not Updating...** + - Es: **Local {remote}/{branch} is ahead and/or up to par. Not Updating...** + - Fi: **Paikallinen {remote}/{branch} on edellä ja/tai ajan tasalla. Ohitetaan päivitys...** + - Fr: **Local {remote}/{branch} est en avance ou à jour. Pas de mise à jour...** + - It: **Il ramo locale {remote}/{branch} è aggiornato o avanti. Nessun aggiornamento...** + """ + if not lang: lang=default_lang + if lang == 'en': return "Local {remote}/{branch} is ahead and/or up to par. Not Updating...".format_map({"remote": remote,"branch": branch}) + if lang == 'es': return "Local {remote}/{branch} is ahead and/or up to par. Not Updating...".format_map({"remote": remote,"branch": branch}) + if lang == 'fi': return "Paikallinen {remote}/{branch} on edellä ja/tai ajan tasalla. Ohitetaan päivitys...".format_map({"remote": remote,"branch": branch}) + if lang == 'fr': return "Local {remote}/{branch} est en avance ou à jour. Pas de mise à jour...".format_map({"remote": remote,"branch": branch}) + if lang == 'it': return "Il ramo locale {remote}/{branch} è aggiornato o avanti. Nessun aggiornamento...".format_map({"remote": remote,"branch": branch}) + else: raise ValueError(f'Invalid language {lang}') +def remote_ahead(remote,branch,lang:str|None=None): + """ + ### Locales + - En: **Remote {remote}/{branch} is ahead. Updating...** + - Es: **Remote {remote}/{branch} is ahead. Updating...** + - Fi: **Etärepositorio {remote}/{branch} on edellä. Päivitetään...** + - Fr: **Remote {remote}/{branch} est en avance. Mise à jour en cours...** + - It: **Il ramo remoto {remote}/{branch} è avanti. Aggiornamento in corso...** + """ + if not lang: lang=default_lang + if lang == 'en': return "Remote {remote}/{branch} is ahead. Updating...".format_map({"remote": remote,"branch": branch}) + if lang == 'es': return "Remote {remote}/{branch} is ahead. Updating...".format_map({"remote": remote,"branch": branch}) + if lang == 'fi': return "Etärepositorio {remote}/{branch} on edellä. Päivitetään...".format_map({"remote": remote,"branch": branch}) + if lang == 'fr': return "Remote {remote}/{branch} est en avance. Mise à jour en cours...".format_map({"remote": remote,"branch": branch}) + if lang == 'it': return "Il ramo remoto {remote}/{branch} è avanti. Aggiornamento in corso...".format_map({"remote": remote,"branch": branch}) + else: raise ValueError(f'Invalid language {lang}') +def cant_find_local_version(lang:str|None=None): + """ + ### Locales + - En: **I can't find the local_version variable! Or it's been tampered with and it's not an integer!** + - Es: **I can't find the local_version variable! Or it's been tampered with and it's not an integer!** + - Fi: **Muuttujaa local_version ei löytynyt, tai sitä on muokattu eikä ole kokonaisluku!** + - Fr: **Je ne trouve pas la variable local_version ! Ou elle a été modifiée et ce n’est pas un entier !** + - It: **Impossibile trovare la variabile local_version! O è stata manomessa e non è un intero!** + """ + if not lang: lang=default_lang + if lang == 'en': return "I can't find the local_version variable! Or it's been tampered with and it's not an integer!" + if lang == 'es': return "I can't find the local_version variable! Or it's been tampered with and it's not an integer!" + if lang == 'fi': return "Muuttujaa local_version ei löytynyt, tai sitä on muokattu eikä ole kokonaisluku!" + if lang == 'fr': return "Je ne trouve pas la variable local_version ! Ou elle a été modifiée et ce n’est pas un entier !" + if lang == 'it': return "Impossibile trovare la variabile local_version! O è stata manomessa e non è un intero!" + else: raise ValueError(f'Invalid language {lang}') +def running_prestart_checks(lang:str|None=None): + """ + ### Locales + - En: **Running pre-start checks...** + - Es: **Running pre-start checks...** + - Fi: **Suoritetaan esikäynnistystarkistuksia...** + - Fr: **Exécution des vérifications préalables au démarrage...** + - It: **Esecuzione dei controlli pre-avvio...** + """ + if not lang: lang=default_lang + if lang == 'en': return "Running pre-start checks..." + if lang == 'es': return "Running pre-start checks..." + if lang == 'fi': return "Suoritetaan esikäynnistystarkistuksia..." + if lang == 'fr': return "Exécution des vérifications préalables au démarrage..." + if lang == 'it': return "Esecuzione dei controlli pre-avvio..." + else: raise ValueError(f'Invalid language {lang}') +def continuing_in_seconds(seconds,lang:str|None=None): + """ + ### Locales + - En: **Continuing in {seconds} seconds... Press any key to skip.** + - Es: **Continuing in {seconds} seconds... Press any key to skip.** + - Fi: **Jatketaan {seconds} sekunnin kuluttua... Paina mitä tahansa näppäintä ohittaaksesi.** + - Fr: **Reprise dans {seconds} secondes... Appuie sur une touche pour passer.** + - It: **Continuo tra {seconds} secondi... Premi un tasto per saltare.** + """ + if not lang: lang=default_lang + if lang == 'en': return "Continuing in {seconds} seconds... Press any key to skip.".format_map({"seconds": seconds}) + if lang == 'es': return "Continuing in {seconds} seconds... Press any key to skip.".format_map({"seconds": seconds}) + if lang == 'fi': return "Jatketaan {seconds} sekunnin kuluttua... Paina mitä tahansa näppäintä ohittaaksesi.".format_map({"seconds": seconds}) + if lang == 'fr': return "Reprise dans {seconds} secondes... Appuie sur une touche pour passer.".format_map({"seconds": seconds}) + if lang == 'it': return "Continuo tra {seconds} secondi... Premi un tasto per saltare.".format_map({"seconds": seconds}) + else: raise ValueError(f'Invalid language {lang}') +def missing_requests_psutil(lang:str|None=None): + """ + ### Locales + - En: **Missing requests and psutil! Please install them using pip: `pip install requests psutil`** + - Es: **Missing requests and psutil! Please install them using pip: `pip install requests psutil`** + - Fi: **Kirjastot requests ja psutil puuttuvat! Asenna ne komennolla: `pip install requests psutil`** + - Fr: **requests et psutil manquants ! Installe-les avec pip : `pip install requests psutil`** + - It: **Mancano requests e psutil! Installali con pip: `pip install requests psutil`** + """ + if not lang: lang=default_lang + if lang == 'en': return "Missing requests and psutil! Please install them using pip: `pip install requests psutil`" + if lang == 'es': return "Missing requests and psutil! Please install them using pip: `pip install requests psutil`" + if lang == 'fi': return "Kirjastot requests ja psutil puuttuvat! Asenna ne komennolla: `pip install requests psutil`" + if lang == 'fr': return "requests et psutil manquants ! Installe-les avec pip : `pip install requests psutil`" + if lang == 'it': return "Mancano requests e psutil! Installali con pip: `pip install requests psutil`" + else: raise ValueError(f'Invalid language {lang}') +def requirements_not_found(path,lang:str|None=None): + """ + ### Locales + - En: **requirements.txt not found at {path} was it tampered with?** + - Es: **requirements.txt not found at {path} was it tampered with?** + - Fi: **Tiedostoa requirements.txt ei löytynyt polusta {path} – onko sitä muokattu?** + - Fr: **requirements.txt introuvable à {path}, a-t-il été modifié ?** + - It: **requirements.txt non trovato in {path} è stato manomesso?** + """ + if not lang: lang=default_lang + if lang == 'en': return "requirements.txt not found at {path} was it tampered with?".format_map({"path": path}) + if lang == 'es': return "requirements.txt not found at {path} was it tampered with?".format_map({"path": path}) + if lang == 'fi': return "Tiedostoa requirements.txt ei löytynyt polusta {path} – onko sitä muokattu?".format_map({"path": path}) + if lang == 'fr': return "requirements.txt introuvable à {path}, a-t-il été modifié ?".format_map({"path": path}) + if lang == 'it': return "requirements.txt non trovato in {path} è stato manomesso?".format_map({"path": path}) + else: raise ValueError(f'Invalid language {lang}') +def warning_failed_parse_imports(filename,error,lang:str|None=None): + """ + ### Locales + - En: **Warning: Failed to parse imports from {filename}: {error}** + - Es: **Warning: Failed to parse imports from {filename}: {error}** + - Fi: **Varoitus: tuontien jäsentäminen epäonnistui tiedostossa {filename}: {error}** + - Fr: **Avertissement : Échec du parsing des imports depuis {filename} : {error}** + - It: **Attenzione: impossibile analizzare le importazioni da {filename}: {error}** + """ + if not lang: lang=default_lang + if lang == 'en': return "Warning: Failed to parse imports from {filename}: {error}".format_map({"filename": filename,"error": error}) + if lang == 'es': return "Warning: Failed to parse imports from {filename}: {error}".format_map({"filename": filename,"error": error}) + if lang == 'fi': return "Varoitus: tuontien jäsentäminen epäonnistui tiedostossa {filename}: {error}".format_map({"filename": filename,"error": error}) + if lang == 'fr': return "Avertissement : Échec du parsing des imports depuis {filename} : {error}".format_map({"filename": filename,"error": error}) + if lang == 'it': return "Attenzione: impossibile analizzare le importazioni da {filename}: {error}".format_map({"filename": filename,"error": error}) + else: raise ValueError(f'Invalid language {lang}') +def cogs_dir_not_found(path,lang:str|None=None): + """ + ### Locales + - En: **Cogs directory not found at {path}, skipping scan.** + - Es: **Cogs directory not found at {path}, skipping scan.** + - Fi: **Cogs-kansiota ei löytynyt polusta {path}, ohitetaan tarkistus.** + - Fr: **Répertoire des cogs introuvable à {path}, scan ignoré.** + - It: **Cartella cogs non trovata in {path}, scansione saltata.** + """ + if not lang: lang=default_lang + if lang == 'en': return "Cogs directory not found at {path}, skipping scan.".format_map({"path": path}) + if lang == 'es': return "Cogs directory not found at {path}, skipping scan.".format_map({"path": path}) + if lang == 'fi': return "Cogs-kansiota ei löytynyt polusta {path}, ohitetaan tarkistus.".format_map({"path": path}) + if lang == 'fr': return "Répertoire des cogs introuvable à {path}, scan ignoré.".format_map({"path": path}) + if lang == 'it': return "Cartella cogs non trovata in {path}, scansione saltata.".format_map({"path": path}) + else: raise ValueError(f'Invalid language {lang}') +def std_lib_local_skipped(package,lang:str|None=None): + """ + ### Locales + - En: **STD LIB / LOCAL {package} (skipped check)** + - Es: **STD LIB / LOCAL {package} (skipped check)** + - Fi: **STD LIB / PAIKALLINEN {package} (tarkistus ohitettu)** + - Fr: **LIB STD / LOCAL {package} (vérification sautée)** + - It: **LIB STD / LOCALE {package} (controllo saltato)** + """ + if not lang: lang=default_lang + if lang == 'en': return "STD LIB / LOCAL {package} (skipped check)".format_map({"package": package}) + if lang == 'es': return "STD LIB / LOCAL {package} (skipped check)".format_map({"package": package}) + if lang == 'fi': return "STD LIB / PAIKALLINEN {package} (tarkistus ohitettu)".format_map({"package": package}) + if lang == 'fr': return "LIB STD / LOCAL {package} (vérification sautée)".format_map({"package": package}) + if lang == 'it': return "LIB STD / LOCALE {package} (controllo saltato)".format_map({"package": package}) + else: raise ValueError(f'Invalid language {lang}') +def ok_installed(lang:str|None=None): + """ + ### Locales + - En: **OK** + - Es: **OK** + - Fi: **OK** + - Fr: **OK** + - It: **OK** + """ + if not lang: lang=default_lang + if lang == 'en': return "OK" + if lang == 'es': return "OK" + if lang == 'fi': return "OK" + if lang == 'fr': return "OK" + if lang == 'it': return "OK" + else: raise ValueError(f'Invalid language {lang}') +def missing_package(lang:str|None=None): + """ + ### Locales + - En: **MISSING** + - Es: **MISSING** + - Fi: **PUUTTUU** + - Fr: **MANQUANT** + - It: **REQUISITO MANCANTE** + """ + if not lang: lang=default_lang + if lang == 'en': return "MISSING" + if lang == 'es': return "MISSING" + if lang == 'fi': return "PUUTTUU" + if lang == 'fr': return "MANQUANT" + if lang == 'it': return "REQUISITO MANCANTE" + else: raise ValueError(f'Invalid language {lang}') +def missing_package2(lang:str|None=None): + """ + ### Locales + - En: **is not installed** + - Es: **is not installed** + - Fi: **ei ole asennettu** + - Fr: **n’est pas installé** + - It: **non è installato** + """ + if not lang: lang=default_lang + if lang == 'en': return "is not installed" + if lang == 'es': return "is not installed" + if lang == 'fi': return "ei ole asennettu" + if lang == 'fr': return "n’est pas installé" + if lang == 'it': return "non è installato" + else: raise ValueError(f'Invalid language {lang}') +def missing_packages_detected(lang:str|None=None): + """ + ### Locales + - En: **Missing packages detected:** + - Es: **Missing packages detected:** + - Fi: **Puuttuvia kirjastoja havaittu:** + - Fr: **Packages manquants détectés :** + - It: **Pacchetti mancanti rilevati:** + """ + if not lang: lang=default_lang + if lang == 'en': return "Missing packages detected:" + if lang == 'es': return "Missing packages detected:" + if lang == 'fi': return "Puuttuvia kirjastoja havaittu:" + if lang == 'fr': return "Packages manquants détectés :" + if lang == 'it': return "Pacchetti mancanti rilevati:" + else: raise ValueError(f'Invalid language {lang}') +def telling_goober_central(url,lang:str|None=None): + """ + ### Locales + - En: **Telling goober central at {url}** + - Es: **Telling goober central at {url}** + - Fi: **Ilmoitetaan goober-centralille osoitteessa {url}** + - Fr: **Envoi à goober central à {url}** + - It: **Segnalazione a goober central su {url}** + """ + if not lang: lang=default_lang + if lang == 'en': return "Telling goober central at {url}".format_map({"url": url}) + if lang == 'es': return "Telling goober central at {url}".format_map({"url": url}) + if lang == 'fi': return "Ilmoitetaan goober-centralille osoitteessa {url}".format_map({"url": url}) + if lang == 'fr': return "Envoi à goober central à {url}".format_map({"url": url}) + if lang == 'it': return "Segnalazione a goober central su {url}".format_map({"url": url}) + else: raise ValueError(f'Invalid language {lang}') +def failed_to_contact(url,error,lang:str|None=None): + """ + ### Locales + - En: **Failed to contact {url}: {error}** + - Es: **Failed to contact {url}: {error}** + - Fi: **Yhteyden muodostus epäonnistui osoitteeseen {url}: {error}** + - Fr: **Impossible de contacter {url} : {error}** + - It: **Impossibile contattare {url}: {error}** + """ + if not lang: lang=default_lang + if lang == 'en': return "Failed to contact {url}: {error}".format_map({"url": url,"error": error}) + if lang == 'es': return "Failed to contact {url}: {error}".format_map({"url": url,"error": error}) + if lang == 'fi': return "Yhteyden muodostus epäonnistui osoitteeseen {url}: {error}".format_map({"url": url,"error": error}) + if lang == 'fr': return "Impossible de contacter {url} : {error}".format_map({"url": url,"error": error}) + if lang == 'it': return "Impossibile contattare {url}: {error}".format_map({"url": url,"error": error}) + else: raise ValueError(f'Invalid language {lang}') +def all_requirements_satisfied(lang:str|None=None): + """ + ### Locales + - En: **All requirements are satisfied.** + - Es: **All requirements are satisfied.** + - Fi: **Kaikki vaatimukset täyttyvät.** + - Fr: **Toutes les dépendances sont satisfaites.** + - It: **Tutti i requisiti sono soddisfatti.** + """ + if not lang: lang=default_lang + if lang == 'en': return "All requirements are satisfied." + if lang == 'es': return "All requirements are satisfied." + if lang == 'fi': return "Kaikki vaatimukset täyttyvät." + if lang == 'fr': return "Toutes les dépendances sont satisfaites." + if lang == 'it': return "Tutti i requisiti sono soddisfatti." + else: raise ValueError(f'Invalid language {lang}') +def ping_to(host,latency,lang:str|None=None): + """ + ### Locales + - En: **Ping to {host}: {latency} ms** + - Es: **Ping to {host}: {latency} ms** + - Fi: **Ping osoitteeseen {host}: {latency} ms** + - Fr: **Ping vers {host} : {latency} ms** + - It: **Ping a {host}: {latency} ms** + """ + if not lang: lang=default_lang + if lang == 'en': return "Ping to {host}: {latency} ms".format_map({"host": host,"latency": latency}) + if lang == 'es': return "Ping to {host}: {latency} ms".format_map({"host": host,"latency": latency}) + if lang == 'fi': return "Ping osoitteeseen {host}: {latency} ms".format_map({"host": host,"latency": latency}) + if lang == 'fr': return "Ping vers {host} : {latency} ms".format_map({"host": host,"latency": latency}) + if lang == 'it': return "Ping a {host}: {latency} ms".format_map({"host": host,"latency": latency}) + else: raise ValueError(f'Invalid language {lang}') +def high_latency(lang:str|None=None): + """ + ### Locales + - En: **High latency detected! You may experience delays in response times.** + - Es: **High latency detected! You may experience delays in response times.** + - Fi: **Korkea viive havaittu! Vastaukset saattavat hidastua.** + - Fr: **Latence élevée détectée ! Tu pourrais avoir des délais de réponse.** + - It: **Latenza elevata rilevata! Potresti riscontrare ritardi nelle risposte.** + """ + if not lang: lang=default_lang + if lang == 'en': return "High latency detected! You may experience delays in response times." + if lang == 'es': return "High latency detected! You may experience delays in response times." + if lang == 'fi': return "Korkea viive havaittu! Vastaukset saattavat hidastua." + if lang == 'fr': return "Latence élevée détectée ! Tu pourrais avoir des délais de réponse." + if lang == 'it': return "Latenza elevata rilevata! Potresti riscontrare ritardi nelle risposte." + else: raise ValueError(f'Invalid language {lang}') +def could_not_parse_latency(lang:str|None=None): + """ + ### Locales + - En: **Could not parse latency.** + - Es: **Could not parse latency.** + - Fi: **Viivettä ei voitu tulkita.** + - Fr: **Impossible d’analyser la latence.** + - It: **Impossibile analizzare la latenza.** + """ + if not lang: lang=default_lang + if lang == 'en': return "Could not parse latency." + if lang == 'es': return "Could not parse latency." + if lang == 'fi': return "Viivettä ei voitu tulkita." + if lang == 'fr': return "Impossible d’analyser la latence." + if lang == 'it': return "Impossibile analizzare la latenza." + else: raise ValueError(f'Invalid language {lang}') +def ping_failed(host,lang:str|None=None): + """ + ### Locales + - En: **Ping to {host} failed.** + - Es: **Ping to {host} failed.** + - Fi: **Ping osoitteeseen {host} epäonnistui.** + - Fr: **Ping vers {host} échoué.** + - It: **Ping a {host} fallito.** + """ + if not lang: lang=default_lang + if lang == 'en': return "Ping to {host} failed.".format_map({"host": host}) + if lang == 'es': return "Ping to {host} failed.".format_map({"host": host}) + if lang == 'fi': return "Ping osoitteeseen {host} epäonnistui.".format_map({"host": host}) + if lang == 'fr': return "Ping vers {host} échoué.".format_map({"host": host}) + if lang == 'it': return "Ping a {host} fallito.".format_map({"host": host}) + else: raise ValueError(f'Invalid language {lang}') +def error_running_ping(error,lang:str|None=None): + """ + ### Locales + - En: **Error running ping: {error}** + - Es: **Error running ping: {error}** + - Fi: **Virhe ping-komennon suorittamisessa: {error}** + - Fr: **Erreur lors du ping : {error}** + - It: **Errore durante l'esecuzione del ping: {error}** + """ + if not lang: lang=default_lang + if lang == 'en': return "Error running ping: {error}".format_map({"error": error}) + if lang == 'es': return "Error running ping: {error}".format_map({"error": error}) + if lang == 'fi': return "Virhe ping-komennon suorittamisessa: {error}".format_map({"error": error}) + if lang == 'fr': return "Erreur lors du ping : {error}".format_map({"error": error}) + if lang == 'it': return "Errore durante l'esecuzione del ping: {error}".format_map({"error": error}) + else: raise ValueError(f'Invalid language {lang}') +def memory_usage(used,total,percent,lang:str|None=None): + """ + ### Locales + - En: **Memory Usage: {used} GB / {total} GB ({percent}%)** + - Es: **Memory Usage: {used} GB / {total} GB ({percent}%)** + - Fi: **Muistin käyttö: {used} Gt / {total} Gt ({percent}%)** + - Fr: **Utilisation mémoire : {used} Go / {total} Go ({percent}%)** + - It: **Utilizzo memoria: {used} GB / {total} GB ({percent}%)** + """ + if not lang: lang=default_lang + if lang == 'en': return "Memory Usage: {used} GB / {total} GB ({percent}%)".format_map({"used": used,"total": total,"percent": percent}) + if lang == 'es': return "Memory Usage: {used} GB / {total} GB ({percent}%)".format_map({"used": used,"total": total,"percent": percent}) + if lang == 'fi': return "Muistin käyttö: {used} Gt / {total} Gt ({percent}%)".format_map({"used": used,"total": total,"percent": percent}) + if lang == 'fr': return "Utilisation mémoire : {used} Go / {total} Go ({percent}%)".format_map({"used": used,"total": total,"percent": percent}) + if lang == 'it': return "Utilizzo memoria: {used} GB / {total} GB ({percent}%)".format_map({"used": used,"total": total,"percent": percent}) + else: raise ValueError(f'Invalid language {lang}') +def memory_above_90(percent,lang:str|None=None): + """ + ### Locales + - En: **Memory usage is above 90% ({percent}%). Consider freeing up memory.** + - Es: **Memory usage is above 90% ({percent}%). Consider freeing up memory.** + - Fi: **Muistin käyttö ylittää 90 % ({percent}%). Harkitse muistin vapauttamista.** + - Fr: **Usage mémoire au-dessus de 90% ({percent}%). Pense à libérer de la mémoire.** + - It: **Utilizzo memoria sopra il 90% ({percent}%). Considera di liberare memoria.** + """ + if not lang: lang=default_lang + if lang == 'en': return "Memory usage is above 90% ({percent}%). Consider freeing up memory.".format_map({"percent": percent}) + if lang == 'es': return "Memory usage is above 90% ({percent}%). Consider freeing up memory.".format_map({"percent": percent}) + if lang == 'fi': return "Muistin käyttö ylittää 90 % ({percent}%). Harkitse muistin vapauttamista.".format_map({"percent": percent}) + if lang == 'fr': return "Usage mémoire au-dessus de 90% ({percent}%). Pense à libérer de la mémoire.".format_map({"percent": percent}) + if lang == 'it': return "Utilizzo memoria sopra il 90% ({percent}%). Considera di liberare memoria.".format_map({"percent": percent}) + else: raise ValueError(f'Invalid language {lang}') +def total_memory(total,lang:str|None=None): + """ + ### Locales + - En: **Total Memory: {total} GB** + - Es: **Total Memory: {total} GB** + - Fi: **Kokonaismuisti: {total} Gt** + - Fr: **Mémoire totale : {total} Go** + - It: **Memoria totale: {total} GB** + """ + if not lang: lang=default_lang + if lang == 'en': return "Total Memory: {total} GB".format_map({"total": total}) + if lang == 'es': return "Total Memory: {total} GB".format_map({"total": total}) + if lang == 'fi': return "Kokonaismuisti: {total} Gt".format_map({"total": total}) + if lang == 'fr': return "Mémoire totale : {total} Go".format_map({"total": total}) + if lang == 'it': return "Memoria totale: {total} GB".format_map({"total": total}) + else: raise ValueError(f'Invalid language {lang}') +def used_memory(used,lang:str|None=None): + """ + ### Locales + - En: **Used Memory: {used} GB** + - Es: **Used Memory: {used} GB** + - Fi: **Käytetty muisti: {used} Gt** + - Fr: **Mémoire utilisée : {used} Go** + - It: **Memoria usata: {used} GB** + """ + if not lang: lang=default_lang + if lang == 'en': return "Used Memory: {used} GB".format_map({"used": used}) + if lang == 'es': return "Used Memory: {used} GB".format_map({"used": used}) + if lang == 'fi': return "Käytetty muisti: {used} Gt".format_map({"used": used}) + if lang == 'fr': return "Mémoire utilisée : {used} Go".format_map({"used": used}) + if lang == 'it': return "Memoria usata: {used} GB".format_map({"used": used}) + else: raise ValueError(f'Invalid language {lang}') +def low_free_memory(free,lang:str|None=None): + """ + ### Locales + - En: **Low free memory detected! Only {free} GB available.** + - Es: **Low free memory detected! Only {free} GB available.** + - Fi: **Vapaa muisti vähissä! Vain {free} Gt jäljellä.** + - Fr: **Mémoire libre faible détectée ! Seulement {free} Go disponibles.** + - It: **Poca memoria libera! Solo {free} GB disponibili.** + """ + if not lang: lang=default_lang + if lang == 'en': return "Low free memory detected! Only {free} GB available.".format_map({"free": free}) + if lang == 'es': return "Low free memory detected! Only {free} GB available.".format_map({"free": free}) + if lang == 'fi': return "Vapaa muisti vähissä! Vain {free} Gt jäljellä.".format_map({"free": free}) + if lang == 'fr': return "Mémoire libre faible détectée ! Seulement {free} Go disponibles.".format_map({"free": free}) + if lang == 'it': return "Poca memoria libera! Solo {free} GB disponibili.".format_map({"free": free}) + else: raise ValueError(f'Invalid language {lang}') +def measuring_cpu(lang:str|None=None): + """ + ### Locales + - En: **Measuring CPU usage per core...** + - Es: **Measuring CPU usage per core...** + - Fi: **Mitataan suorittimen käyttöä ytimittäin...** + - Fr: **Mesure de l’usage CPU par cœur...** + - It: **Misurazione utilizzo CPU per core...** + """ + if not lang: lang=default_lang + if lang == 'en': return "Measuring CPU usage per core..." + if lang == 'es': return "Measuring CPU usage per core..." + if lang == 'fi': return "Mitataan suorittimen käyttöä ytimittäin..." + if lang == 'fr': return "Mesure de l’usage CPU par cœur..." + if lang == 'it': return "Misurazione utilizzo CPU per core..." + else: raise ValueError(f'Invalid language {lang}') +def core_usage(idx,bar,usage,lang:str|None=None): + """ + ### Locales + - En: **Core {idx}: [{bar}] {usage}%** + - Es: **Core {idx}: [{bar}] {usage}%** + - Fi: **Ydin {idx}: [{bar}] {usage}%** + - Fr: **Cœur {idx} : [{bar}] {usage}%** + - It: **Core {idx}: [{bar}] {usage}%** + """ + if not lang: lang=default_lang + if lang == 'en': return "Core {idx}: [{bar}] {usage}%".format_map({"idx": idx,"bar": bar,"usage": usage}) + if lang == 'es': return "Core {idx}: [{bar}] {usage}%".format_map({"idx": idx,"bar": bar,"usage": usage}) + if lang == 'fi': return "Ydin {idx}: [{bar}] {usage}%".format_map({"idx": idx,"bar": bar,"usage": usage}) + if lang == 'fr': return "Cœur {idx} : [{bar}] {usage}%".format_map({"idx": idx,"bar": bar,"usage": usage}) + if lang == 'it': return "Core {idx}: [{bar}] {usage}%".format_map({"idx": idx,"bar": bar,"usage": usage}) + else: raise ValueError(f'Invalid language {lang}') +def total_cpu_usage(usage,lang:str|None=None): + """ + ### Locales + - En: **Total CPU Usage: {usage}%** + - Es: **Total CPU Usage: {usage}%** + - Fi: **Kokonaisprosessorin käyttö: {usage}%** + - Fr: **Usage total CPU : {usage}%** + - It: **Utilizzo totale CPU: {usage}%** + """ + if not lang: lang=default_lang + if lang == 'en': return "Total CPU Usage: {usage}%".format_map({"usage": usage}) + if lang == 'es': return "Total CPU Usage: {usage}%".format_map({"usage": usage}) + if lang == 'fi': return "Kokonaisprosessorin käyttö: {usage}%".format_map({"usage": usage}) + if lang == 'fr': return "Usage total CPU : {usage}%".format_map({"usage": usage}) + if lang == 'it': return "Utilizzo totale CPU: {usage}%".format_map({"usage": usage}) + else: raise ValueError(f'Invalid language {lang}') +def high_avg_cpu(usage,lang:str|None=None): + """ + ### Locales + - En: **High average CPU usage: {usage}%** + - Es: **High average CPU usage: {usage}%** + - Fi: **Korkea keskimääräinen prosessorin käyttö: {usage}%** + - Fr: **Moyenne CPU élevée : {usage}%** + - It: **Utilizzo medio CPU elevato: {usage}%** + """ + if not lang: lang=default_lang + if lang == 'en': return "High average CPU usage: {usage}%".format_map({"usage": usage}) + if lang == 'es': return "High average CPU usage: {usage}%".format_map({"usage": usage}) + if lang == 'fi': return "Korkea keskimääräinen prosessorin käyttö: {usage}%".format_map({"usage": usage}) + if lang == 'fr': return "Moyenne CPU élevée : {usage}%".format_map({"usage": usage}) + if lang == 'it': return "Utilizzo medio CPU elevato: {usage}%".format_map({"usage": usage}) + else: raise ValueError(f'Invalid language {lang}') +def really_high_cpu(lang:str|None=None): + """ + ### Locales + - En: **Really high CPU load! System may throttle or hang.** + - Es: **Really high CPU load! System may throttle or hang.** + - Fi: **Erittäin korkea prosessorikuorma! Järjestelmä saattaa hidastua tai jumittua.** + - Fr: **Charge CPU vraiment élevée ! Le système pourrait ralentir ou planter.** + - It: **Carico CPU molto alto! Il sistema potrebbe rallentare o bloccarsi.** + """ + if not lang: lang=default_lang + if lang == 'en': return "Really high CPU load! System may throttle or hang." + if lang == 'es': return "Really high CPU load! System may throttle or hang." + if lang == 'fi': return "Erittäin korkea prosessorikuorma! Järjestelmä saattaa hidastua tai jumittua." + if lang == 'fr': return "Charge CPU vraiment élevée ! Le système pourrait ralentir ou planter." + if lang == 'it': return "Carico CPU molto alto! Il sistema potrebbe rallentare o bloccarsi." + else: raise ValueError(f'Invalid language {lang}') +def memory_file(size,lang:str|None=None): + """ + ### Locales + - En: **Memory file: {size} MB** + - Es: **Memory file: {size} MB** + - Fi: **Muistitiedosto: {size} Mt** + - Fr: **Fichier mémoire : {size} Mo** + - It: **File memoria: {size} MB** + """ + if not lang: lang=default_lang + if lang == 'en': return "Memory file: {size} MB".format_map({"size": size}) + if lang == 'es': return "Memory file: {size} MB".format_map({"size": size}) + if lang == 'fi': return "Muistitiedosto: {size} Mt".format_map({"size": size}) + if lang == 'fr': return "Fichier mémoire : {size} Mo".format_map({"size": size}) + if lang == 'it': return "File memoria: {size} MB".format_map({"size": size}) + else: raise ValueError(f'Invalid language {lang}') +def memory_file_large(lang:str|None=None): + """ + ### Locales + - En: **Memory file is 1GB or higher, consider clearing it to free up space.** + - Es: **Memory file is 1GB or higher, consider clearing it to free up space.** + - Fi: **Muistitiedosto on enemmän kuin 1 Gt – harkitse sen tyhjentämistä tilan vapauttamiseksi.** + - Fr: **Fichier mémoire de 1 Go ou plus, pense à le nettoyer pour libérer de l’espace.** + - It: **Il file di memoria è 1GB o più, valuta di svuotarlo.** + """ + if not lang: lang=default_lang + if lang == 'en': return "Memory file is 1GB or higher, consider clearing it to free up space." + if lang == 'es': return "Memory file is 1GB or higher, consider clearing it to free up space." + if lang == 'fi': return "Muistitiedosto on enemmän kuin 1 Gt – harkitse sen tyhjentämistä tilan vapauttamiseksi." + if lang == 'fr': return "Fichier mémoire de 1 Go ou plus, pense à le nettoyer pour libérer de l’espace." + if lang == 'it': return "Il file di memoria è 1GB o più, valuta di svuotarlo." + else: raise ValueError(f'Invalid language {lang}') +def memory_file_corrupted(error,lang:str|None=None): + """ + ### Locales + - En: **Memory file is corrupted! JSON decode error: {error}** + - Es: **Memory file is corrupted! JSON decode error: {error}** + - Fi: **Muistitiedosto on vioittunut! JSON purkuvirhe: {error}** + - Fr: **Fichier mémoire corrompu ! Erreur JSON : {error}** + - It: **File memoria corrotto! Errore JSON decode: {error}** + """ + if not lang: lang=default_lang + if lang == 'en': return "Memory file is corrupted! JSON decode error: {error}".format_map({"error": error}) + if lang == 'es': return "Memory file is corrupted! JSON decode error: {error}".format_map({"error": error}) + if lang == 'fi': return "Muistitiedosto on vioittunut! JSON purkuvirhe: {error}".format_map({"error": error}) + if lang == 'fr': return "Fichier mémoire corrompu ! Erreur JSON : {error}".format_map({"error": error}) + if lang == 'it': return "File memoria corrotto! Errore JSON decode: {error}".format_map({"error": error}) + else: raise ValueError(f'Invalid language {lang}') +def consider_backup_memory(lang:str|None=None): + """ + ### Locales + - En: **Consider backing up and recreating the memory file.** + - Es: **Consider backing up and recreating the memory file.** + - Fi: **Harkitse muistitiedoston varmuuskopioimista ja uudelleenluontia.** + - Fr: **Pense à sauvegarder et recréer le fichier mémoire.** + - It: **Valuta di fare un backup e ricreare il file di memoria.** + """ + if not lang: lang=default_lang + if lang == 'en': return "Consider backing up and recreating the memory file." + if lang == 'es': return "Consider backing up and recreating the memory file." + if lang == 'fi': return "Harkitse muistitiedoston varmuuskopioimista ja uudelleenluontia." + if lang == 'fr': return "Pense à sauvegarder et recréer le fichier mémoire." + if lang == 'it': return "Valuta di fare un backup e ricreare il file di memoria." + else: raise ValueError(f'Invalid language {lang}') +def memory_file_encoding(error,lang:str|None=None): + """ + ### Locales + - En: **Memory file has encoding issues: {error}** + - Es: **Memory file has encoding issues: {error}** + - Fi: **Muistitiedostossa on koodausongelmia: {error}** + - Fr: **Problèmes d’encodage du fichier mémoire : {error}** + - It: **Problemi di codifica nel file memoria: {error}** + """ + if not lang: lang=default_lang + if lang == 'en': return "Memory file has encoding issues: {error}".format_map({"error": error}) + if lang == 'es': return "Memory file has encoding issues: {error}".format_map({"error": error}) + if lang == 'fi': return "Muistitiedostossa on koodausongelmia: {error}".format_map({"error": error}) + if lang == 'fr': return "Problèmes d’encodage du fichier mémoire : {error}".format_map({"error": error}) + if lang == 'it': return "Problemi di codifica nel file memoria: {error}".format_map({"error": error}) + else: raise ValueError(f'Invalid language {lang}') +def error_reading_memory(error,lang:str|None=None): + """ + ### Locales + - En: **Error reading memory file: {error}** + - Es: **Error reading memory file: {error}** + - Fi: **Virhe muistitiedoston lukemisessa: {error}** + - Fr: **Erreur lecture fichier mémoire : {error}** + - It: **Errore nella lettura del file memoria: {error}** + """ + if not lang: lang=default_lang + if lang == 'en': return "Error reading memory file: {error}".format_map({"error": error}) + if lang == 'es': return "Error reading memory file: {error}".format_map({"error": error}) + if lang == 'fi': return "Virhe muistitiedoston lukemisessa: {error}".format_map({"error": error}) + if lang == 'fr': return "Erreur lecture fichier mémoire : {error}".format_map({"error": error}) + if lang == 'it': return "Errore nella lettura del file memoria: {error}".format_map({"error": error}) + else: raise ValueError(f'Invalid language {lang}') +def memory_file_not_found(lang:str|None=None): + """ + ### Locales + - En: **Memory file not found.** + - Es: **Memory file not found.** + - Fi: **Muistitiedostoa ei löytynyt.** + - Fr: **Fichier mémoire introuvable.** + - It: **File memoria non trovato.** + """ + if not lang: lang=default_lang + if lang == 'en': return "Memory file not found." + if lang == 'es': return "Memory file not found." + if lang == 'fi': return "Muistitiedostoa ei löytynyt." + if lang == 'fr': return "Fichier mémoire introuvable." + if lang == 'it': return "File memoria non trovato." + else: raise ValueError(f'Invalid language {lang}') +def modification_warning(lang:str|None=None): + """ + ### Locales + - En: **Goober has been modified! Any changes will be lost in an update!** + - Es: **Goober ha sido modificado! Se omiten las comprobaciones del servidor por completo...** + - Fi: **Gooberia on muokattu! Ohitetaan palvelimen tarkistus kokonaan...** + - Fr: **Goober a été modifié ! Toutes les modifications seront perdues lors d'une mise à jour !** + - It: **Goober è stato modificato! Verifiche del server saltate completamente...** + """ + if not lang: lang=default_lang + if lang == 'en': return "Goober has been modified! Any changes will be lost in an update!" + if lang == 'es': return "Goober ha sido modificado! Se omiten las comprobaciones del servidor por completo..." + if lang == 'fi': return "Gooberia on muokattu! Ohitetaan palvelimen tarkistus kokonaan..." + if lang == 'fr': return "Goober a été modifié ! Toutes les modifications seront perdues lors d'une mise à jour !" + if lang == 'it': return "Goober è stato modificato! Verifiche del server saltate completamente..." + else: raise ValueError(f'Invalid language {lang}') +def reported_version(lang:str|None=None): + """ + ### Locales + - En: **Reported Version:** + - Es: **Version reportada:** + - Fi: **Ilmoitettu versio:** + - Fr: **Version rapportée :** + - It: **Versione segnalata:** + """ + if not lang: lang=default_lang + if lang == 'en': return "Reported Version:" + if lang == 'es': return "Version reportada:" + if lang == 'fi': return "Ilmoitettu versio:" + if lang == 'fr': return "Version rapportée :" + if lang == 'it': return "Versione segnalata:" + else: raise ValueError(f'Invalid language {lang}') +def current_hash(lang:str|None=None): + """ + ### Locales + - En: **Current Hash:** + - Es: **Hash actual:** + - Fi: **Tämänhetkinen hash:** + - Fr: **Hachage actuel :** + - It: **Hash attuale:** + """ + if not lang: lang=default_lang + if lang == 'en': return "Current Hash:" + if lang == 'es': return "Hash actual:" + if lang == 'fi': return "Tämänhetkinen hash:" + if lang == 'fr': return "Hachage actuel :" + if lang == 'it': return "Hash attuale:" + else: raise ValueError(f'Invalid language {lang}') +def not_found(lang:str|None=None): + """ + ### Locales + - En: **is not found!** + - Es: **no existe!** + - Fi: **ei löytynyt!** + - Fr: **n'est pas trouvé !** + - It: **non trovato!** + """ + if not lang: lang=default_lang + if lang == 'en': return "is not found!" + if lang == 'es': return "no existe!" + if lang == 'fi': return "ei löytynyt!" + if lang == 'fr': return "n'est pas trouvé !" + if lang == 'it': return "non trovato!" + else: raise ValueError(f'Invalid language {lang}') +def version_error(lang:str|None=None): + """ + ### Locales + - En: **Unable to fetch version info. Status code** + - Es: **No se puede obtener la informacion de la version. Codigo de estado** + - Fi: **Versiotietojen saanti epäonnistui.. Tilakoodi:** + - Fr: **Impossible de récupérer les informations de version. Code d'état** + - It: **Impossibile recuperare le informazioni sulla versione. Codice di stato** + """ + if not lang: lang=default_lang + if lang == 'en': return "Unable to fetch version info. Status code" + if lang == 'es': return "No se puede obtener la informacion de la version. Codigo de estado" + if lang == 'fi': return "Versiotietojen saanti epäonnistui.. Tilakoodi:" + if lang == 'fr': return "Impossible de récupérer les informations de version. Code d'état" + if lang == 'it': return "Impossibile recuperare le informazioni sulla versione. Codice di stato" + else: raise ValueError(f'Invalid language {lang}') +def loaded_cog(lang:str|None=None): + """ + ### Locales + - En: **Loaded cog:** + - Es: **Engranaje cog:** + - Fi: **Ladatut cogit:** + - Fr: **Cog chargé :** + - It: **Cog caricato:** + """ + if not lang: lang=default_lang + if lang == 'en': return "Loaded cog:" + if lang == 'es': return "Engranaje cog:" + if lang == 'fi': return "Ladatut cogit:" + if lang == 'fr': return "Cog chargé :" + if lang == 'it': return "Cog caricato:" + else: raise ValueError(f'Invalid language {lang}') +def loaded_cog2(lang:str|None=None): + """ + ### Locales + - En: **Loaded module:** + - Es: **Loaded module:** + - Fi: **Ladattiin moduuli:** + - Fr: **Module chargé :** + - It: **Module caricato:** + """ + if not lang: lang=default_lang + if lang == 'en': return "Loaded module:" + if lang == 'es': return "Loaded module:" + if lang == 'fi': return "Ladattiin moduuli:" + if lang == 'fr': return "Module chargé :" + if lang == 'it': return "Module caricato:" + else: raise ValueError(f'Invalid language {lang}') +def cog_fail(lang:str|None=None): + """ + ### Locales + - En: **Failed to load cog:** + - Es: **No se pudo cargar el cog:** + - Fi: **Cogin lataus epäonnistui kohteelle:** + - Fr: **Échec du chargement du cog :** + - It: **Impossibile caricare il cog:** + """ + if not lang: lang=default_lang + if lang == 'en': return "Failed to load cog:" + if lang == 'es': return "No se pudo cargar el cog:" + if lang == 'fi': return "Cogin lataus epäonnistui kohteelle:" + if lang == 'fr': return "Échec du chargement du cog :" + if lang == 'it': return "Impossibile caricare il cog:" + else: raise ValueError(f'Invalid language {lang}') +def cog_fail2(lang:str|None=None): + """ + ### Locales + - En: **Failed to load module:** + - Es: **Failed to load module:** + - Fi: **Moduulin lataaminen epäonnistui:** + - Fr: **Échec du chargement du module :** + - It: **Impossibile caricare il module:** + """ + if not lang: lang=default_lang + if lang == 'en': return "Failed to load module:" + if lang == 'es': return "Failed to load module:" + if lang == 'fi': return "Moduulin lataaminen epäonnistui:" + if lang == 'fr': return "Échec du chargement du module :" + if lang == 'it': return "Impossibile caricare il module:" + else: raise ValueError(f'Invalid language {lang}') +def no_model(lang:str|None=None): + """ + ### Locales + - En: **No saved Markov model found. Starting from scratch.** + - Es: **No se encontro ningún modelo de Markov guardado. Empezando desde cero.** + - Fi: **Olemassaolevaa markov-mallia ei löydetty. Aloitetaan alusta.** + - Fr: **Aucun modèle Markov sauvegardé trouvé. Démarrage à partir de zéro.** + - It: **Nessun modello Markov salvato trovato. Iniziamo da zero.** + """ + if not lang: lang=default_lang + if lang == 'en': return "No saved Markov model found. Starting from scratch." + if lang == 'es': return "No se encontro ningún modelo de Markov guardado. Empezando desde cero." + if lang == 'fi': return "Olemassaolevaa markov-mallia ei löydetty. Aloitetaan alusta." + if lang == 'fr': return "Aucun modèle Markov sauvegardé trouvé. Démarrage à partir de zéro." + if lang == 'it': return "Nessun modello Markov salvato trovato. Iniziamo da zero." + else: raise ValueError(f'Invalid language {lang}') +def folder_created(folder_name,lang:str|None=None): + """ + ### Locales + - En: **Folder '{folder_name}' created.** + - Es: **Directorio '{folder_name}' creado.** + - Fi: **Kansio '{folder_name}' luotu.** + - Fr: **Dossier '{folder_name}' créé.** + - It: **Cartella '{folder_name}' creata.** + """ + if not lang: lang=default_lang + if lang == 'en': return "Folder '{folder_name}' created.".format_map({"folder_name": folder_name}) + if lang == 'es': return "Directorio '{folder_name}' creado.".format_map({"folder_name": folder_name}) + if lang == 'fi': return "Kansio '{folder_name}' luotu.".format_map({"folder_name": folder_name}) + if lang == 'fr': return "Dossier '{folder_name}' créé.".format_map({"folder_name": folder_name}) + if lang == 'it': return "Cartella '{folder_name}' creata.".format_map({"folder_name": folder_name}) + else: raise ValueError(f'Invalid language {lang}') +def folder_exists(folder_name,lang:str|None=None): + """ + ### Locales + - En: **Folder '{folder_name}' already exists. skipping...** + - Es: **El directorio '{folder_name}' ya existe. Se omite...** + - Fi: **Kansio '{folder_name}' on jo olemassa...** + - Fr: **Le dossier '{folder_name}' existe déjà. Ignorons...** + - It: **La cartella '{folder_name}' esiste già. Saltando...** + """ + if not lang: lang=default_lang + if lang == 'en': return "Folder '{folder_name}' already exists. skipping...".format_map({"folder_name": folder_name}) + if lang == 'es': return "El directorio '{folder_name}' ya existe. Se omite...".format_map({"folder_name": folder_name}) + if lang == 'fi': return "Kansio '{folder_name}' on jo olemassa...".format_map({"folder_name": folder_name}) + if lang == 'fr': return "Le dossier '{folder_name}' existe déjà. Ignorons...".format_map({"folder_name": folder_name}) + if lang == 'it': return "La cartella '{folder_name}' esiste già. Saltando...".format_map({"folder_name": folder_name}) + else: raise ValueError(f'Invalid language {lang}') +def logged_in(lang:str|None=None): + """ + ### Locales + - En: **Logged in as** + - Es: **Inicio sesion como** + - Fi: **Kirjauduttiin sisään käyttäjänä** + - Fr: **Connecté en tant que** + - It: **Accesso effettuato come** + """ + if not lang: lang=default_lang + if lang == 'en': return "Logged in as" + if lang == 'es': return "Inicio sesion como" + if lang == 'fi': return "Kirjauduttiin sisään käyttäjänä" + if lang == 'fr': return "Connecté en tant que" + if lang == 'it': return "Accesso effettuato come" + else: raise ValueError(f'Invalid language {lang}') +def synced_commands(lang:str|None=None): + """ + ### Locales + - En: **Synced** + - Es: **Sincronizado** + - Fi: **Synkronoitiin** + - Fr: **Synchronisé** + - It: **Sincronizzati** + """ + if not lang: lang=default_lang + if lang == 'en': return "Synced" + if lang == 'es': return "Sincronizado" + if lang == 'fi': return "Synkronoitiin" + if lang == 'fr': return "Synchronisé" + if lang == 'it': return "Sincronizzati" + else: raise ValueError(f'Invalid language {lang}') +def synced_commands2(lang:str|None=None): + """ + ### Locales + - En: **commands!** + - Es: **comandos!** + - Fi: **komennot!** + - Fr: **commandes !** + - It: **comandi!** + """ + if not lang: lang=default_lang + if lang == 'en': return "commands!" + if lang == 'es': return "comandos!" + if lang == 'fi': return "komennot!" + if lang == 'fr': return "commandes !" + if lang == 'it': return "comandi!" + else: raise ValueError(f'Invalid language {lang}') +def fail_commands_sync(lang:str|None=None): + """ + ### Locales + - En: **Failed to sync commands:** + - Es: **Error al sincronizar comandos:** + - Fi: **Komentojen synkronointi epäonnistui:** + - Fr: **Échec de la synchronisation des commandes :** + - It: **Impossibile sincronizzare i comandi:** + """ + if not lang: lang=default_lang + if lang == 'en': return "Failed to sync commands:" + if lang == 'es': return "Error al sincronizar comandos:" + if lang == 'fi': return "Komentojen synkronointi epäonnistui:" + if lang == 'fr': return "Échec de la synchronisation des commandes :" + if lang == 'it': return "Impossibile sincronizzare i comandi:" + else: raise ValueError(f'Invalid language {lang}') +def started(name,lang:str|None=None): + """ + ### Locales + - En: **{name} has started! +You're the star of the show now baby!** + - Es: **{name} ha empezado!** + - Fi: **{name} on käynnistynyt! +Olet nyt sarjan tähti, beibi!** + - Fr: **{name} a démarré !** + - It: **{name} è stato avviato! +Il palco è tuo!** + """ + if not lang: lang=default_lang + if lang == 'en': return "{name} has started!\nYou're the star of the show now baby!".format_map({"name": name}) + if lang == 'es': return "{name} ha empezado!".format_map({"name": name}) + if lang == 'fi': return "{name} on käynnistynyt!\nOlet nyt sarjan tähti, beibi!".format_map({"name": name}) + if lang == 'fr': return "{name} a démarré !".format_map({"name": name}) + if lang == 'it': return "{name} è stato avviato!\nIl palco è tuo!".format_map({"name": name}) + else: raise ValueError(f'Invalid language {lang}') +def name_check(lang:str|None=None): + """ + ### Locales + - En: **Error checking name availability:** + - Es: **Error al comprobar la disponibilidad del nombre:** + - Fi: **Nimen saatavuuden tarkistus epäonnistui:** + - Fr: **Erreur lors de la vérification de la disponibilité du nom :** + - It: **Errore nel controllo disponibilità del nome:** + """ + if not lang: lang=default_lang + if lang == 'en': return "Error checking name availability:" + if lang == 'es': return "Error al comprobar la disponibilidad del nombre:" + if lang == 'fi': return "Nimen saatavuuden tarkistus epäonnistui:" + if lang == 'fr': return "Erreur lors de la vérification de la disponibilité du nom :" + if lang == 'it': return "Errore nel controllo disponibilità del nome:" + else: raise ValueError(f'Invalid language {lang}') +def name_taken(lang:str|None=None): + """ + ### Locales + - En: **Name is already taken. Please choose a different name.** + - Es: **El nombre ya está en uso. Elija otro.** + - Fi: **Nimi on jo käytössä. Valitse toinen nimi.** + - Fr: **Le nom est déjà pris. Veuillez choisir un autre nom.** + - It: **Il nome è già preso. Scegli un nome diverso.** + """ + if not lang: lang=default_lang + if lang == 'en': return "Name is already taken. Please choose a different name." + if lang == 'es': return "El nombre ya está en uso. Elija otro." + if lang == 'fi': return "Nimi on jo käytössä. Valitse toinen nimi." + if lang == 'fr': return "Le nom est déjà pris. Veuillez choisir un autre nom." + if lang == 'it': return "Il nome è già preso. Scegli un nome diverso." + else: raise ValueError(f'Invalid language {lang}') +def name_check2(lang:str|None=None): + """ + ### Locales + - En: **Error during name availability check:** + - Es: **Error durante la comprobacion de disponibilidad del nombre:** + - Fi: **Virhe tapahtui nimen saatavuuden tarkistamisessa:** + - Fr: **Erreur lors de la vérification de la disponibilité du nom :** + - It: **Errore durante il controllo della disponibilità del nome:** + """ + if not lang: lang=default_lang + if lang == 'en': return "Error during name availability check:" + if lang == 'es': return "Error durante la comprobacion de disponibilidad del nombre:" + if lang == 'fi': return "Virhe tapahtui nimen saatavuuden tarkistamisessa:" + if lang == 'fr': return "Erreur lors de la vérification de la disponibilité du nom :" + if lang == 'it': return "Errore durante il controllo della disponibilità del nome:" + else: raise ValueError(f'Invalid language {lang}') +def add_token(token,lang:str|None=None): + """ + ### Locales + - En: **Token: {token} +Please add this token to your .env file as** + - Es: **Token: {token} +Agregue este token a su archivo .env como** + - Fi: **Token: {token} +Lisää tämä .env-tiedostoosi nimellä** + - Fr: **Token : {token} +Veuillez ajouter ce token à votre fichier .env comme** + - It: **Token: {token} +Aggiungi questo token al tuo file .env come** + """ + if not lang: lang=default_lang + if lang == 'en': return "Token: {token}\nPlease add this token to your .env file as".format_map({"token": token}) + if lang == 'es': return "Token: {token}\nAgregue este token a su archivo .env como".format_map({"token": token}) + if lang == 'fi': return "Token: {token}\nLisää tämä .env-tiedostoosi nimellä".format_map({"token": token}) + if lang == 'fr': return "Token : {token}\nVeuillez ajouter ce token à votre fichier .env comme".format_map({"token": token}) + if lang == 'it': return "Token: {token}\nAggiungi questo token al tuo file .env come".format_map({"token": token}) + else: raise ValueError(f'Invalid language {lang}') +def token_exists(lang:str|None=None): + """ + ### Locales + - En: **Token already exists in .env. Continuing with the existing token.** + - Es: **Hay un token en el archivo .env. Continue con el token existente.** + - Fi: **Token on jo olemassa .env-tiedostossa. Jatketaan määritetyllä tokenilla.** + - Fr: **Le token existe déjà dans .env. Utilisation du token existant.** + - It: **Il token esiste già in .env. Continuando con il token esistente.** + """ + if not lang: lang=default_lang + if lang == 'en': return "Token already exists in .env. Continuing with the existing token." + if lang == 'es': return "Hay un token en el archivo .env. Continue con el token existente." + if lang == 'fi': return "Token on jo olemassa .env-tiedostossa. Jatketaan määritetyllä tokenilla." + if lang == 'fr': return "Le token existe déjà dans .env. Utilisation du token existant." + if lang == 'it': return "Il token esiste già in .env. Continuando con il token esistente." + else: raise ValueError(f'Invalid language {lang}') +def registration_error(lang:str|None=None): + """ + ### Locales + - En: **Error during registration:** + - Es: **Error durante el registro:** + - Fi: **Virhe rekisteröinnissä:** + - Fr: **Erreur lors de l'enregistrement :** + - It: **Errore durante la registrazione:** + """ + if not lang: lang=default_lang + if lang == 'en': return "Error during registration:" + if lang == 'es': return "Error durante el registro:" + if lang == 'fi': return "Virhe rekisteröinnissä:" + if lang == 'fr': return "Erreur lors de l'enregistrement :" + if lang == 'it': return "Errore durante la registrazione:" + else: raise ValueError(f'Invalid language {lang}') +def version_backup(lang:str|None=None): + """ + ### Locales + - En: **Backup created:** + - Es: **Copia de seguridad creada:** + - Fi: **Varmuuskopio luotu:** + - Fr: **Sauvegarde créée :** + - It: **Backup creato:** + """ + if not lang: lang=default_lang + if lang == 'en': return "Backup created:" + if lang == 'es': return "Copia de seguridad creada:" + if lang == 'fi': return "Varmuuskopio luotu:" + if lang == 'fr': return "Sauvegarde créée :" + if lang == 'it': return "Backup creato:" + else: raise ValueError(f'Invalid language {lang}') +def backup_error(LOCAL_VERSION_FILE,lang:str|None=None): + """ + ### Locales + - En: **Error: {LOCAL_VERSION_FILE} not found for backup.** + - Es: **Error: {LOCAL_VERSION_FILE} no encontrado para la copia de seguridad.** + - Fi: **Virhe: {LOCAL_VERSION_FILE}-tiedostoa ei löytynyt varmuuskopiota varten.** + - Fr: **Erreur : {LOCAL_VERSION_FILE} introuvable pour la sauvegarde.** + - It: **Errore: {LOCAL_VERSION_FILE} non trovato per il backup.** + """ + if not lang: lang=default_lang + if lang == 'en': return "Error: {LOCAL_VERSION_FILE} not found for backup.".format_map({"LOCAL_VERSION_FILE": LOCAL_VERSION_FILE}) + if lang == 'es': return "Error: {LOCAL_VERSION_FILE} no encontrado para la copia de seguridad.".format_map({"LOCAL_VERSION_FILE": LOCAL_VERSION_FILE}) + if lang == 'fi': return "Virhe: {LOCAL_VERSION_FILE}-tiedostoa ei löytynyt varmuuskopiota varten.".format_map({"LOCAL_VERSION_FILE": LOCAL_VERSION_FILE}) + if lang == 'fr': return "Erreur : {LOCAL_VERSION_FILE} introuvable pour la sauvegarde.".format_map({"LOCAL_VERSION_FILE": LOCAL_VERSION_FILE}) + if lang == 'it': return "Errore: {LOCAL_VERSION_FILE} non trovato per il backup.".format_map({"LOCAL_VERSION_FILE": LOCAL_VERSION_FILE}) + else: raise ValueError(f'Invalid language {lang}') +def model_loaded(lang:str|None=None): + """ + ### Locales + - En: **Markov model loaded from** + - Es: **Modelo de Markov cargado desde** + - Fi: **Markov-malli ladattu** + - Fr: **Modèle Markov chargé depuis** + - It: **Modello Markov caricato da** + """ + if not lang: lang=default_lang + if lang == 'en': return "Markov model loaded from" + if lang == 'es': return "Modelo de Markov cargado desde" + if lang == 'fi': return "Markov-malli ladattu" + if lang == 'fr': return "Modèle Markov chargé depuis" + if lang == 'it': return "Modello Markov caricato da" + else: raise ValueError(f'Invalid language {lang}') +def fetch_update_fail(lang:str|None=None): + """ + ### Locales + - En: **Could not fetch update information.** + - Es: **No se pudo obtener la informacion de actualizacion.** + - Fi: **Päivitystietojen hankkiminen epäonnistui.** + - Fr: **Impossible de récupérer les informations de mise à jour.** + - It: **Impossibile recuperare le informazioni sull'aggiornamento.** + """ + if not lang: lang=default_lang + if lang == 'en': return "Could not fetch update information." + if lang == 'es': return "No se pudo obtener la informacion de actualizacion." + if lang == 'fi': return "Päivitystietojen hankkiminen epäonnistui." + if lang == 'fr': return "Impossible de récupérer les informations de mise à jour." + if lang == 'it': return "Impossibile recuperare le informazioni sull'aggiornamento." + else: raise ValueError(f'Invalid language {lang}') +def invalid_server(lang:str|None=None): + """ + ### Locales + - En: **Error: Invalid version information received from server.** + - Es: **Error: Se recibio informacion de version no valida del servidor.** + - Fi: **Virhe: Palvelin antoi virheellisen versiotietoraportin.** + - Fr: **Erreur : Informations de version invalides reçues du serveur.** + - It: **Errore: informazioni sulla versione non valide ricevute dal server.** + """ + if not lang: lang=default_lang + if lang == 'en': return "Error: Invalid version information received from server." + if lang == 'es': return "Error: Se recibio informacion de version no valida del servidor." + if lang == 'fi': return "Virhe: Palvelin antoi virheellisen versiotietoraportin." + if lang == 'fr': return "Erreur : Informations de version invalides reçues du serveur." + if lang == 'it': return "Errore: informazioni sulla versione non valide ricevute dal server." + else: raise ValueError(f'Invalid language {lang}') +def goober_server_alert(lang:str|None=None): + """ + ### Locales + - En: **Alert from goober central! +** + - Es: **Alert from goober central! +** + - Fi: **Viesti goober centralista! +** + - Fr: **Alerte du serveur Goober central ! +** + - It: **Avviso da goober central! +** + """ + if not lang: lang=default_lang + if lang == 'en': return "Alert from goober central!\n" + if lang == 'es': return "Alert from goober central!\n" + if lang == 'fi': return "Viesti goober centralista!\n" + if lang == 'fr': return "Alerte du serveur Goober central !\n" + if lang == 'it': return "Avviso da goober central!\n" + else: raise ValueError(f'Invalid language {lang}') +def new_version(latest_version,local_version,lang:str|None=None): + """ + ### Locales + - En: **New version available: {latest_version} (Current: {local_version})** + - Es: **Nueva version disponible: {latest_version} (Version actual: {local_version})** + - Fi: **Uusi versio saatavilla: {latest_version} (Tämänhetkinen: {local_version})** + - Fr: **Nouvelle version disponible : {latest_version} (Actuelle : {local_version})** + - It: **Nuova versione disponibile: {latest_version} (Attuale: {local_version})** + """ + if not lang: lang=default_lang + if lang == 'en': return "New version available: {latest_version} (Current: {local_version})".format_map({"latest_version": latest_version,"local_version": local_version}) + if lang == 'es': return "Nueva version disponible: {latest_version} (Version actual: {local_version})".format_map({"latest_version": latest_version,"local_version": local_version}) + if lang == 'fi': return "Uusi versio saatavilla: {latest_version} (Tämänhetkinen: {local_version})".format_map({"latest_version": latest_version,"local_version": local_version}) + if lang == 'fr': return "Nouvelle version disponible : {latest_version} (Actuelle : {local_version})".format_map({"latest_version": latest_version,"local_version": local_version}) + if lang == 'it': return "Nuova versione disponibile: {latest_version} (Attuale: {local_version})".format_map({"latest_version": latest_version,"local_version": local_version}) + else: raise ValueError(f'Invalid language {lang}') +def changelog(VERSION_URL,lang:str|None=None): + """ + ### Locales + - En: **Check {VERSION_URL}/goob/changes.txt to check out the changelog + +** + - Es: **Consulte {VERSION_URL}/goob/changes.txt para ver el registro de cambios + +** + - Fi: **Mene osoitteeseen {VERSION_URL}/goob/changes.txt katsotakseen muutoslokin + +** + - Fr: **Consultez {VERSION_URL}/goob/changes.txt pour voir les modifications + +** + - It: **Controlla {VERSION_URL}/goob/changes.txt per vedere il changelog + +** + """ + if not lang: lang=default_lang + if lang == 'en': return "Check {VERSION_URL}/goob/changes.txt to check out the changelog\n\n".format_map({"VERSION_URL": VERSION_URL}) + if lang == 'es': return "Consulte {VERSION_URL}/goob/changes.txt para ver el registro de cambios\n\n".format_map({"VERSION_URL": VERSION_URL}) + if lang == 'fi': return "Mene osoitteeseen {VERSION_URL}/goob/changes.txt katsotakseen muutoslokin\n\n".format_map({"VERSION_URL": VERSION_URL}) + if lang == 'fr': return "Consultez {VERSION_URL}/goob/changes.txt pour voir les modifications\n\n".format_map({"VERSION_URL": VERSION_URL}) + if lang == 'it': return "Controlla {VERSION_URL}/goob/changes.txt per vedere il changelog\n\n".format_map({"VERSION_URL": VERSION_URL}) + else: raise ValueError(f'Invalid language {lang}') +def invalid_version(local_version,lang:str|None=None): + """ + ### Locales + - En: **The version: {local_version} isnt valid!** + - Es: **La version: {local_version} no es valida!** + - Fi: **Versio: {local_version} on virheellinen!** + - Fr: **La version : {local_version} n'est pas valide !** + - It: **La versione: {local_version} non è valida!** + """ + if not lang: lang=default_lang + if lang == 'en': return "The version: {local_version} isnt valid!".format_map({"local_version": local_version}) + if lang == 'es': return "La version: {local_version} no es valida!".format_map({"local_version": local_version}) + if lang == 'fi': return "Versio: {local_version} on virheellinen!".format_map({"local_version": local_version}) + if lang == 'fr': return "La version : {local_version} n'est pas valide !".format_map({"local_version": local_version}) + if lang == 'it': return "La versione: {local_version} non è valida!".format_map({"local_version": local_version}) + else: raise ValueError(f'Invalid language {lang}') +def invalid_version2(lang:str|None=None): + """ + ### Locales + - En: **If this is intended then ignore this message, else press Y to pull a valid version from the server regardless of the version of goober currently running** + - Es: **Si esto es lo que pretende, ignore este mensaje; si no, haga clic en Y en su teclado para descargar una version valida del servidor, independientemente de la version que se este ejecutando actualmente.** + - Fi: **Jos tämä on tahallista, voit jättää tämän viestin huomiotta. Jos tämä ei ole tahallista, paina Y-näppäintä hankkiaksesi kelvollisen version, riippumatta Gooberin tämänhetkisestä versiosta.** + - Fr: **Si c'est intentionnel, ignorez ce message. Sinon, appuyez sur Y pour récupérer une version valide depuis le serveur, quelle que soit la version actuelle de Goober.** + - It: **Se è intenzionale ignora questo messaggio, altrimenti premi Y per scaricare una versione valida dal server indipendentemente dalla versione attuale di goober** + """ + if not lang: lang=default_lang + if lang == 'en': return "If this is intended then ignore this message, else press Y to pull a valid version from the server regardless of the version of goober currently running" + if lang == 'es': return "Si esto es lo que pretende, ignore este mensaje; si no, haga clic en Y en su teclado para descargar una version valida del servidor, independientemente de la version que se este ejecutando actualmente." + if lang == 'fi': return "Jos tämä on tahallista, voit jättää tämän viestin huomiotta. Jos tämä ei ole tahallista, paina Y-näppäintä hankkiaksesi kelvollisen version, riippumatta Gooberin tämänhetkisestä versiosta." + if lang == 'fr': return "Si c'est intentionnel, ignorez ce message. Sinon, appuyez sur Y pour récupérer une version valide depuis le serveur, quelle que soit la version actuelle de Goober." + if lang == 'it': return "Se è intenzionale ignora questo messaggio, altrimenti premi Y per scaricare una versione valida dal server indipendentemente dalla versione attuale di goober" + else: raise ValueError(f'Invalid language {lang}') +def invalid_version3(lang:str|None=None): + """ + ### Locales + - En: **The current version will be backed up to current_version.bak..** + - Es: **La version actual se copiara a current_version.bak..** + - Fi: **Tämänhetkinen versio varmuuskopioidaan kohteeseen current_version.bak..** + - Fr: **La version actuelle sera sauvegardée dans current_version.bak..** + - It: **La versione attuale sarà salvata come current_version.bak..** + """ + if not lang: lang=default_lang + if lang == 'en': return "The current version will be backed up to current_version.bak.." + if lang == 'es': return "La version actual se copiara a current_version.bak.." + if lang == 'fi': return "Tämänhetkinen versio varmuuskopioidaan kohteeseen current_version.bak.." + if lang == 'fr': return "La version actuelle sera sauvegardée dans current_version.bak.." + if lang == 'it': return "La versione attuale sarà salvata come current_version.bak.." + else: raise ValueError(f'Invalid language {lang}') +def input(lang:str|None=None): + """ + ### Locales + - En: **(Y or any other key to ignore....)** + - Es: **(Y o cualquier otra tecla para ignorar....)** + - Fi: **(Y:tä tai mitä vaan muuta näppäintä jättää tämän huomioimatta....)** + - Fr: **(Y ou toute autre touche pour ignorer...)** + - It: **(Y o qualsiasi altro tasto per ignorare....)** + """ + if not lang: lang=default_lang + if lang == 'en': return "(Y or any other key to ignore....)" + if lang == 'es': return "(Y o cualquier otra tecla para ignorar....)" + if lang == 'fi': return "(Y:tä tai mitä vaan muuta näppäintä jättää tämän huomioimatta....)" + if lang == 'fr': return "(Y ou toute autre touche pour ignorer...)" + if lang == 'it': return "(Y o qualsiasi altro tasto per ignorare....)" + else: raise ValueError(f'Invalid language {lang}') +def modification_ignored(lang:str|None=None): + """ + ### Locales + - En: **You've modified** + - Es: **Has modificado** + - Fi: **Olet muokannut** + - Fr: **Vous avez modifié** + - It: **Hai modificato** + """ + if not lang: lang=default_lang + if lang == 'en': return "You've modified" + if lang == 'es': return "Has modificado" + if lang == 'fi': return "Olet muokannut" + if lang == 'fr': return "Vous avez modifié" + if lang == 'it': return "Hai modificato" + else: raise ValueError(f'Invalid language {lang}') +def modification_ignored2(lang:str|None=None): + """ + ### Locales + - En: **IGNOREWARNING is set to false..** + - Es: **IGNOREWARNING es falso** + - Fi: **IGNOREWARNING on asetettu false:ksi..** + - Fr: **IGNOREWARNING est désactivé..** + - It: **IGNOREWARNING è impostato su false..** + """ + if not lang: lang=default_lang + if lang == 'en': return "IGNOREWARNING is set to false.." + if lang == 'es': return "IGNOREWARNING es falso" + if lang == 'fi': return "IGNOREWARNING on asetettu false:ksi.." + if lang == 'fr': return "IGNOREWARNING est désactivé.." + if lang == 'it': return "IGNOREWARNING è impostato su false.." + else: raise ValueError(f'Invalid language {lang}') +def latest_version(lang:str|None=None): + """ + ### Locales + - En: **You're using the latest version:** + - Es: **Usando la ultima version:** + - Fi: **Käytät uusinta versiota:** + - Fr: **Vous utilisez la dernière version :** + - It: **Stai utilizzando l'ultima versione:** + """ + if not lang: lang=default_lang + if lang == 'en': return "You're using the latest version:" + if lang == 'es': return "Usando la ultima version:" + if lang == 'fi': return "Käytät uusinta versiota:" + if lang == 'fr': return "Vous utilisez la dernière version :" + if lang == 'it': return "Stai utilizzando l'ultima versione:" + else: raise ValueError(f'Invalid language {lang}') +def latest_version2(VERSION_URL,lang:str|None=None): + """ + ### Locales + - En: **Check {VERSION_URL}/goob/changes.txt to check out the changelog** + - Es: **Consulte {VERSION_URL}/goob/changes.txt para ver el registro de cambios** + - Fi: **Tarkista {VERSION_URL}/goob/changes.txt katsotakseen muutosloki** + - Fr: **Consultez {VERSION_URL}/goob/changes.txt pour voir les modifications** + - It: **Controlla {VERSION_URL}/goob/changes.txt per vedere il changelog** + """ + if not lang: lang=default_lang + if lang == 'en': return "Check {VERSION_URL}/goob/changes.txt to check out the changelog".format_map({"VERSION_URL": VERSION_URL}) + if lang == 'es': return "Consulte {VERSION_URL}/goob/changes.txt para ver el registro de cambios".format_map({"VERSION_URL": VERSION_URL}) + if lang == 'fi': return "Tarkista {VERSION_URL}/goob/changes.txt katsotakseen muutosloki".format_map({"VERSION_URL": VERSION_URL}) + if lang == 'fr': return "Consultez {VERSION_URL}/goob/changes.txt pour voir les modifications".format_map({"VERSION_URL": VERSION_URL}) + if lang == 'it': return "Controlla {VERSION_URL}/goob/changes.txt per vedere il changelog".format_map({"VERSION_URL": VERSION_URL}) + else: raise ValueError(f'Invalid language {lang}') +def pinging_disabled(lang:str|None=None): + """ + ### Locales + - En: **Pinging is disabled! Not telling the server im on...** + - Es: **El ping esta deshabilitado** + - Fi: **Pingaus on poistettu käytöstä! En kerro palvelimelle, että olen päällä...** + - Fr: **Le ping est désactivé ! Je ne préviens pas le serveur que je suis en ligne...** + - It: **Il ping è disabilitato! Non dico al server che sono online...** + """ + if not lang: lang=default_lang + if lang == 'en': return "Pinging is disabled! Not telling the server im on..." + if lang == 'es': return "El ping esta deshabilitado" + if lang == 'fi': return "Pingaus on poistettu käytöstä! En kerro palvelimelle, että olen päällä..." + if lang == 'fr': return "Le ping est désactivé ! Je ne préviens pas le serveur que je suis en ligne..." + if lang == 'it': return "Il ping è disabilitato! Non dico al server che sono online..." + else: raise ValueError(f'Invalid language {lang}') +def goober_ping_success(NAME,lang:str|None=None): + """ + ### Locales + - En: **Logged into goober central as {NAME}** + - Es: **Envie ping a Goober Central!** + - Fi: **Lähetettiin olemassaolo ping goober centraliin!** + - Fr: **Connecté à Goober central en tant que {NAME}** + - It: **Accesso a goober central come {NAME}** + """ + if not lang: lang=default_lang + if lang == 'en': return "Logged into goober central as {NAME}".format_map({"NAME": NAME}) + if lang == 'es': return "Envie ping a Goober Central!".format_map({"NAME": NAME}) + if lang == 'fi': return "Lähetettiin olemassaolo ping goober centraliin!".format_map({"NAME": NAME}) + if lang == 'fr': return "Connecté à Goober central en tant que {NAME}".format_map({"NAME": NAME}) + if lang == 'it': return "Accesso a goober central come {NAME}".format_map({"NAME": NAME}) + else: raise ValueError(f'Invalid language {lang}') +def goober_ping_fail(lang:str|None=None): + """ + ### Locales + - En: **Failed to send data. Server returned status code:** + - Es: **Error al enviar datos. El servidor devolvio el codigo de estado:** + - Fi: **Tiedon lähetys epäonnistui. Palvelin antoi tilakoodin:** + - Fr: **Échec de l'envoi des données. Le serveur a retourné le code d'état :** + - It: **Impossibile inviare i dati. Il server ha restituito il codice di stato:** + """ + if not lang: lang=default_lang + if lang == 'en': return "Failed to send data. Server returned status code:" + if lang == 'es': return "Error al enviar datos. El servidor devolvio el codigo de estado:" + if lang == 'fi': return "Tiedon lähetys epäonnistui. Palvelin antoi tilakoodin:" + if lang == 'fr': return "Échec de l'envoi des données. Le serveur a retourné le code d'état :" + if lang == 'it': return "Impossibile inviare i dati. Il server ha restituito il codice di stato:" + else: raise ValueError(f'Invalid language {lang}') +def goober_ping_fail2(lang:str|None=None): + """ + ### Locales + - En: **An error occurred while sending data:** + - Es: **Se produjo un error al enviar los datos:** + - Fi: **Tiedon lähettämisen aikana tapahtui virhe:** + - Fr: **Une erreur est survenue lors de l'envoi des données :** + - It: **Si è verificato un errore durante l'invio dei dati:** + """ + if not lang: lang=default_lang + if lang == 'en': return "An error occurred while sending data:" + if lang == 'es': return "Se produjo un error al enviar los datos:" + if lang == 'fi': return "Tiedon lähettämisen aikana tapahtui virhe:" + if lang == 'fr': return "Une erreur est survenue lors de l'envoi des données :" + if lang == 'it': return "Si è verificato un errore durante l'invio dei dati:" + else: raise ValueError(f'Invalid language {lang}') +def sentence_positivity(lang:str|None=None): + """ + ### Locales + - En: **Positivity of sentence is:** + - Es: **La positividad de la sentencia es:** + - Fi: **Lauseen positiivisuus on:** + - Fr: **La positivité de la phrase est :** + - It: **La positività della frase è:** + """ + if not lang: lang=default_lang + if lang == 'en': return "Positivity of sentence is:" + if lang == 'es': return "La positividad de la sentencia es:" + if lang == 'fi': return "Lauseen positiivisuus on:" + if lang == 'fr': return "La positivité de la phrase est :" + if lang == 'it': return "La positività della frase è:" + else: raise ValueError(f'Invalid language {lang}') +def command_edit_fail(lang:str|None=None): + """ + ### Locales + - En: **Failed to edit message:** + - Es: **No se pudo editar el mensaje:** + - Fi: **Viestin muokkaus epäonnistui:** + - Fr: **Échec de la modification du message :** + - It: **Impossibile modificare il messaggio:** + """ + if not lang: lang=default_lang + if lang == 'en': return "Failed to edit message:" + if lang == 'es': return "No se pudo editar el mensaje:" + if lang == 'fi': return "Viestin muokkaus epäonnistui:" + if lang == 'fr': return "Échec de la modification du message :" + if lang == 'it': return "Impossibile modificare il messaggio:" + else: raise ValueError(f'Invalid language {lang}') +def command_desc_retrain(lang:str|None=None): + """ + ### Locales + - En: **Retrains the Markov model manually.** + - Es: **Vuelve a entrenar el modelo de Markov manualmente.** + - Fi: **Uudelleenkouluttaa markov-mallin manuaalisesti.** + - Fr: **Réentraîne manuellement le modèle Markov.** + - It: **Rafforza manualmente il modello Markov.** + """ + if not lang: lang=default_lang + if lang == 'en': return "Retrains the Markov model manually." + if lang == 'es': return "Vuelve a entrenar el modelo de Markov manualmente." + if lang == 'fi': return "Uudelleenkouluttaa markov-mallin manuaalisesti." + if lang == 'fr': return "Réentraîne manuellement le modèle Markov." + if lang == 'it': return "Rafforza manualmente il modello Markov." + else: raise ValueError(f'Invalid language {lang}') +def command_markov_retrain(lang:str|None=None): + """ + ### Locales + - En: **Retraining the Markov model... Please wait.** + - Es: **Reentrenando el modelo de Markov... Por favor espere** + - Fi: **Uudelleenkoulutetaan markov-mallia... Odota.** + - Fr: **Réentraînement du modèle Markov... Veuillez patienter.** + - It: **Rafforzamento del modello Markov in corso... Attendere.** + """ + if not lang: lang=default_lang + if lang == 'en': return "Retraining the Markov model... Please wait." + if lang == 'es': return "Reentrenando el modelo de Markov... Por favor espere" + if lang == 'fi': return "Uudelleenkoulutetaan markov-mallia... Odota." + if lang == 'fr': return "Réentraînement du modèle Markov... Veuillez patienter." + if lang == 'it': return "Rafforzamento del modello Markov in corso... Attendere." + else: raise ValueError(f'Invalid language {lang}') +def command_markov_memory_not_found(lang:str|None=None): + """ + ### Locales + - En: **Error: memory file not found!** + - Es: **Error: no hay archivo de memoria!** + - Fi: **Virhe: muistitiedostoa ei löytynyt!** + - Fr: **Erreur : fichier de mémoire introuvable !** + - It: **Errore: file di memoria non trovato!** + """ + if not lang: lang=default_lang + if lang == 'en': return "Error: memory file not found!" + if lang == 'es': return "Error: no hay archivo de memoria!" + if lang == 'fi': return "Virhe: muistitiedostoa ei löytynyt!" + if lang == 'fr': return "Erreur : fichier de mémoire introuvable !" + if lang == 'it': return "Errore: file di memoria non trovato!" + else: raise ValueError(f'Invalid language {lang}') +def command_markov_memory_is_corrupt(lang:str|None=None): + """ + ### Locales + - En: **Error: memory file is corrupt!** + - Es: **Error: el archivo de memoria esta danado!** + - Fi: **Virhe: muistitiedosto on korruptoitu!** + - Fr: **Erreur : le fichier de mémoire est corrompu !** + - It: **Errore: file di memoria corrotto!** + """ + if not lang: lang=default_lang + if lang == 'en': return "Error: memory file is corrupt!" + if lang == 'es': return "Error: el archivo de memoria esta danado!" + if lang == 'fi': return "Virhe: muistitiedosto on korruptoitu!" + if lang == 'fr': return "Erreur : le fichier de mémoire est corrompu !" + if lang == 'it': return "Errore: file di memoria corrotto!" + else: raise ValueError(f'Invalid language {lang}') +def command_markov_retraining(data_size,lang:str|None=None): + """ + ### Locales + - En: **Processing {data_size} data points...** + - Es: **Procesando {processed_data}/{data_size} puntos de datos...** + - Fi: **Käsitellään {processed_data}/{data_size} datapistettä...** + - Fr: **Traitement de {processed_data}/{data_size} points de données...** + - It: **Elaborazione di {data_size} punti dati...** + """ + if not lang: lang=default_lang + if lang == 'en': return "Processing {data_size} data points...".format_map({"data_size": data_size}) + if lang == 'es': return "Procesando {processed_data}/{data_size} puntos de datos...".format_map({"data_size": data_size}) + if lang == 'fi': return "Käsitellään {processed_data}/{data_size} datapistettä...".format_map({"data_size": data_size}) + if lang == 'fr': return "Traitement de {processed_data}/{data_size} points de données...".format_map({"data_size": data_size}) + if lang == 'it': return "Elaborazione di {data_size} punti dati...".format_map({"data_size": data_size}) + else: raise ValueError(f'Invalid language {lang}') +def command_markov_retrain_successful(data_size,lang:str|None=None): + """ + ### Locales + - En: **Markov model retrained successfully using {data_size} data points!** + - Es: **Modelo de Markov reentrenado exitosamente usando {data_size} puntos de datos!** + - Fi: **Markov-malli koulutettiin uudestaan {data_size} datapisteellä!** + - Fr: **Modèle Markov réentraîné avec succès en utilisant {data_size} points de données !** + - It: **Modello Markov rafforzato con successo utilizzando {data_size} punti dati!** + """ + if not lang: lang=default_lang + if lang == 'en': return "Markov model retrained successfully using {data_size} data points!".format_map({"data_size": data_size}) + if lang == 'es': return "Modelo de Markov reentrenado exitosamente usando {data_size} puntos de datos!".format_map({"data_size": data_size}) + if lang == 'fi': return "Markov-malli koulutettiin uudestaan {data_size} datapisteellä!".format_map({"data_size": data_size}) + if lang == 'fr': return "Modèle Markov réentraîné avec succès en utilisant {data_size} points de données !".format_map({"data_size": data_size}) + if lang == 'it': return "Modello Markov rafforzato con successo utilizzando {data_size} punti dati!".format_map({"data_size": data_size}) + else: raise ValueError(f'Invalid language {lang}') +def command_desc_talk(lang:str|None=None): + """ + ### Locales + - En: **talks n like stuf** + - Es: **hace que el bot hable** + - Fi: **puhuu ja sillei** + - Fr: **parle et tout ça** + - It: **parla n come stuf** + """ + if not lang: lang=default_lang + if lang == 'en': return "talks n like stuf" + if lang == 'es': return "hace que el bot hable" + if lang == 'fi': return "puhuu ja sillei" + if lang == 'fr': return "parle et tout ça" + if lang == 'it': return "parla n come stuf" + else: raise ValueError(f'Invalid language {lang}') +def command_talk_insufficent_text(lang:str|None=None): + """ + ### Locales + - En: **I need to learn more from messages before I can talk.** + - Es: **Necesito aprender más sobre los mensajes antes de hablar.** + - Fi: **Minun pitää oppia lisää viesteistä ennen kun puhun.** + - Fr: **Je dois apprendre plus de messages avant de pouvoir parler.** + - It: **Ho bisogno di imparare di più dai messaggi prima di poter parlare.** + """ + if not lang: lang=default_lang + if lang == 'en': return "I need to learn more from messages before I can talk." + if lang == 'es': return "Necesito aprender más sobre los mensajes antes de hablar." + if lang == 'fi': return "Minun pitää oppia lisää viesteistä ennen kun puhun." + if lang == 'fr': return "Je dois apprendre plus de messages avant de pouvoir parler." + if lang == 'it': return "Ho bisogno di imparare di più dai messaggi prima di poter parlare." + else: raise ValueError(f'Invalid language {lang}') +def command_talk_generation_fail(lang:str|None=None): + """ + ### Locales + - En: **I have nothing to say right now!** + - Es: **No tengo nada que decir ahora!** + - Fi: **Minulla ei ole mitään sanottavaa!** + - Fr: **Je n'ai rien à dire pour le moment !** + - It: **Non ho nulla da dire in questo momento!** + """ + if not lang: lang=default_lang + if lang == 'en': return "I have nothing to say right now!" + if lang == 'es': return "No tengo nada que decir ahora!" + if lang == 'fi': return "Minulla ei ole mitään sanottavaa!" + if lang == 'fr': return "Je n'ai rien à dire pour le moment !" + if lang == 'it': return "Non ho nulla da dire in questo momento!" + else: raise ValueError(f'Invalid language {lang}') +def command_desc_help(lang:str|None=None): + """ + ### Locales + - En: **help** + - Es: **Ayuda** + - Fi: **auta** + - Fr: **aide** + - It: **aiuto** + """ + if not lang: lang=default_lang + if lang == 'en': return "help" + if lang == 'es': return "Ayuda" + if lang == 'fi': return "auta" + if lang == 'fr': return "aide" + if lang == 'it': return "aiuto" + else: raise ValueError(f'Invalid language {lang}') +def command_help_embed_title(lang:str|None=None): + """ + ### Locales + - En: **Bot Help** + - Es: **Ayuda del bot** + - Fi: **Botin apu** + - Fr: **Aide du bot** + - It: **Aiuto Bot** + """ + if not lang: lang=default_lang + if lang == 'en': return "Bot Help" + if lang == 'es': return "Ayuda del bot" + if lang == 'fi': return "Botin apu" + if lang == 'fr': return "Aide du bot" + if lang == 'it': return "Aiuto Bot" + else: raise ValueError(f'Invalid language {lang}') +def command_help_embed_desc(lang:str|None=None): + """ + ### Locales + - En: **List of commands grouped by category.** + - Es: **Lista de comandos agrupados por categoria** + - Fi: **Komennot ryhmitelty kategorioilla** + - Fr: **Liste des commandes regroupées par catégorie.** + - It: **Elenco dei comandi raggruppati per categoria.** + """ + if not lang: lang=default_lang + if lang == 'en': return "List of commands grouped by category." + if lang == 'es': return "Lista de comandos agrupados por categoria" + if lang == 'fi': return "Komennot ryhmitelty kategorioilla" + if lang == 'fr': return "Liste des commandes regroupées par catégorie." + if lang == 'it': return "Elenco dei comandi raggruppati per categoria." + else: raise ValueError(f'Invalid language {lang}') +def command_help_categories_general(lang:str|None=None): + """ + ### Locales + - En: **General** + - Es: **General** + - Fi: **Yleiset** + - Fr: **Général** + - It: **Generale** + """ + if not lang: lang=default_lang + if lang == 'en': return "General" + if lang == 'es': return "General" + if lang == 'fi': return "Yleiset" + if lang == 'fr': return "Général" + if lang == 'it': return "Generale" + else: raise ValueError(f'Invalid language {lang}') +def command_help_categories_admin(lang:str|None=None): + """ + ### Locales + - En: **Administration** + - Es: **Administracion** + - Fi: **Ylläpito** + - Fr: **Administration** + - It: **Amministrazione** + """ + if not lang: lang=default_lang + if lang == 'en': return "Administration" + if lang == 'es': return "Administracion" + if lang == 'fi': return "Ylläpito" + if lang == 'fr': return "Administration" + if lang == 'it': return "Amministrazione" + else: raise ValueError(f'Invalid language {lang}') +def command_help_categories_custom(lang:str|None=None): + """ + ### Locales + - En: **Custom Commands** + - Es: **Comandos personalizados** + - Fi: **Mukautetut komennot** + - Fr: **Commandes personnalisées** + - It: **Comandi personalizzati** + """ + if not lang: lang=default_lang + if lang == 'en': return "Custom Commands" + if lang == 'es': return "Comandos personalizados" + if lang == 'fi': return "Mukautetut komennot" + if lang == 'fr': return "Commandes personnalisées" + if lang == 'it': return "Comandi personalizzati" + else: raise ValueError(f'Invalid language {lang}') +def command_ran(message_author_name,message_content,lang:str|None=None): + """ + ### Locales + - En: **Info: {message.author.name} ran {message.content}** + - Es: **Informacion: {message.author.name} ejecuto {message.content}** + - Fi: **Tietoa: {message.author.name} suoritti {message.content}** + - Fr: **Info : {message.author.name} a exécuté {message.content}** + - It: **Info: {message.author.name} ha eseguito {message.content}** + """ + if not lang: lang=default_lang + if lang == 'en': return "Info: {message_author_name} ran {message_content}".format_map({"message_author_name": message_author_name,"message_content": message_content}) + if lang == 'es': return "Informacion: {message_author_name} ejecuto {message_content}".format_map({"message_author_name": message_author_name,"message_content": message_content}) + if lang == 'fi': return "Tietoa: {message_author_name} suoritti {message_content}".format_map({"message_author_name": message_author_name,"message_content": message_content}) + if lang == 'fr': return "Info : {message_author_name} a exécuté {message_content}".format_map({"message_author_name": message_author_name,"message_content": message_content}) + if lang == 'it': return "Info: {message_author_name} ha eseguito {message_content}".format_map({"message_author_name": message_author_name,"message_content": message_content}) + else: raise ValueError(f'Invalid language {lang}') +def command_ran_s(interaction_user,lang:str|None=None): + """ + ### Locales + - En: **Info: {interaction.user} ran ** + - Es: **Info: {interaction.user} ran ** + - Fi: **Info: {interaction.user} suoritti** + - Fr: **Info : {interaction.user} a exécuté ** + - It: **Info: {interaction.user} ha eseguito ** + """ + if not lang: lang=default_lang + if lang == 'en': return "Info: {interaction_user} ran ".format_map({"interaction_user": interaction_user}) + if lang == 'es': return "Info: {interaction_user} ran ".format_map({"interaction_user": interaction_user}) + if lang == 'fi': return "Info: {interaction_user} suoritti".format_map({"interaction_user": interaction_user}) + if lang == 'fr': return "Info : {interaction_user} a exécuté ".format_map({"interaction_user": interaction_user}) + if lang == 'it': return "Info: {interaction_user} ha eseguito ".format_map({"interaction_user": interaction_user}) + else: raise ValueError(f'Invalid language {lang}') +def command_desc_ping(lang:str|None=None): + """ + ### Locales + - En: **ping** + - Es: **ping** + - Fi: **ping** + - Fr: **ping** + - It: **ping** + """ + if not lang: lang=default_lang + if lang == 'en': return "ping" + if lang == 'es': return "ping" + if lang == 'fi': return "ping" + if lang == 'fr': return "ping" + if lang == 'it': return "ping" + else: raise ValueError(f'Invalid language {lang}') +def command_desc_setlang(lang:str|None=None): + """ + ### Locales + - En: **Set a new language for the bot (temporarily)** + - Es: **Set a new language for the bot (temporarily)** + - Fi: **Set a new language for the bot (temporarily)** + - Fr: **Set a new language for the bot (temporarily)** + - It: **Imposta una nuova lingua per il bot (temporaneamente)** + """ + if not lang: lang=default_lang + if lang == 'en': return "Set a new language for the bot (temporarily)" + if lang == 'es': return "Set a new language for the bot (temporarily)" + if lang == 'fi': return "Set a new language for the bot (temporarily)" + if lang == 'fr': return "Set a new language for the bot (temporarily)" + if lang == 'it': return "Imposta una nuova lingua per il bot (temporaneamente)" + else: raise ValueError(f'Invalid language {lang}') +def command_ping_embed_desc(lang:str|None=None): + """ + ### Locales + - En: **Bot Latency:** + - Es: **Latencia del bot:** + - Fi: **Botin viive:** + - Fr: **Latence du bot :** + - It: **Latenza del bot:** + """ + if not lang: lang=default_lang + if lang == 'en': return "Bot Latency:" + if lang == 'es': return "Latencia del bot:" + if lang == 'fi': return "Botin viive:" + if lang == 'fr': return "Latence du bot :" + if lang == 'it': return "Latenza del bot:" + else: raise ValueError(f'Invalid language {lang}') +def command_ping_footer(lang:str|None=None): + """ + ### Locales + - En: **Requested by** + - Es: **Solicitado por** + - Fi: **Pyytäjä: ** + - Fr: **Demandé par** + - It: **Richiesto da** + """ + if not lang: lang=default_lang + if lang == 'en': return "Requested by" + if lang == 'es': return "Solicitado por" + if lang == 'fi': return "Pyytäjä: " + if lang == 'fr': return "Demandé par" + if lang == 'it': return "Richiesto da" + else: raise ValueError(f'Invalid language {lang}') +def command_about_desc(lang:str|None=None): + """ + ### Locales + - En: **about** + - Es: **Acerca** + - Fi: **tietoa** + - Fr: **à propos** + - It: **informazioni** + """ + if not lang: lang=default_lang + if lang == 'en': return "about" + if lang == 'es': return "Acerca" + if lang == 'fi': return "tietoa" + if lang == 'fr': return "à propos" + if lang == 'it': return "informazioni" + else: raise ValueError(f'Invalid language {lang}') +def command_about_embed_title(lang:str|None=None): + """ + ### Locales + - En: **About me** + - Es: **Acerca de mi** + - Fi: **Tietoa minusta** + - Fr: **À propos de moi** + - It: **Informazioni su di me** + """ + if not lang: lang=default_lang + if lang == 'en': return "About me" + if lang == 'es': return "Acerca de mi" + if lang == 'fi': return "Tietoa minusta" + if lang == 'fr': return "À propos de moi" + if lang == 'it': return "Informazioni su di me" + else: raise ValueError(f'Invalid language {lang}') +def command_about_embed_field1(lang:str|None=None): + """ + ### Locales + - En: **Name** + - Es: **Nombre** + - Fi: **Nimi** + - Fr: **Nom** + - It: **Nome** + """ + if not lang: lang=default_lang + if lang == 'en': return "Name" + if lang == 'es': return "Nombre" + if lang == 'fi': return "Nimi" + if lang == 'fr': return "Nom" + if lang == 'it': return "Nome" + else: raise ValueError(f'Invalid language {lang}') +def command_about_embed_field2name(lang:str|None=None): + """ + ### Locales + - En: **Version** + - Es: **Version** + - Fi: **Versio** + - Fr: **Version** + - It: **Versione** + """ + if not lang: lang=default_lang + if lang == 'en': return "Version" + if lang == 'es': return "Version" + if lang == 'fi': return "Versio" + if lang == 'fr': return "Version" + if lang == 'it': return "Versione" + else: raise ValueError(f'Invalid language {lang}') +def command_about_embed_field2value(local_version,latest_version,lang:str|None=None): + """ + ### Locales + - En: **Local: {local_version} +Latest: {latest_version}** + - Es: **Version local: {local_version} +Ultima version: {latest_version}** + - Fi: **Paikallinen: {local_version} +Uusin: {latest_version}** + - Fr: **Locale : {local_version} +Dernière : {latest_version}** + - It: **Locale: {local_version} +Ultima: {latest_version}** + """ + if not lang: lang=default_lang + if lang == 'en': return "Local: {local_version} \nLatest: {latest_version}".format_map({"local_version": local_version,"latest_version": latest_version}) + if lang == 'es': return "Version local: {local_version} \nUltima version: {latest_version}".format_map({"local_version": local_version,"latest_version": latest_version}) + if lang == 'fi': return "Paikallinen: {local_version} \nUusin: {latest_version}".format_map({"local_version": local_version,"latest_version": latest_version}) + if lang == 'fr': return "Locale : {local_version} \nDernière : {latest_version}".format_map({"local_version": local_version,"latest_version": latest_version}) + if lang == 'it': return "Locale: {local_version} \nUltima: {latest_version}".format_map({"local_version": local_version,"latest_version": latest_version}) + else: raise ValueError(f'Invalid language {lang}') +def command_desc_stats(lang:str|None=None): + """ + ### Locales + - En: **stats** + - Es: **Estadistica** + - Fi: **statistiikat** + - Fr: **statistiques** + - It: **statistiche** + """ + if not lang: lang=default_lang + if lang == 'en': return "stats" + if lang == 'es': return "Estadistica" + if lang == 'fi': return "statistiikat" + if lang == 'fr': return "statistiques" + if lang == 'it': return "statistiche" + else: raise ValueError(f'Invalid language {lang}') +def command_stats_embed_title(lang:str|None=None): + """ + ### Locales + - En: **Bot stats** + - Es: **Estadisticas de bot** + - Fi: **Botin statistiikat** + - Fr: **Statistiques du bot** + - It: **Statistiche del bot** + """ + if not lang: lang=default_lang + if lang == 'en': return "Bot stats" + if lang == 'es': return "Estadisticas de bot" + if lang == 'fi': return "Botin statistiikat" + if lang == 'fr': return "Statistiques du bot" + if lang == 'it': return "Statistiche del bot" + else: raise ValueError(f'Invalid language {lang}') +def command_stats_embed_desc(lang:str|None=None): + """ + ### Locales + - En: **Data about the the bot's memory.** + - Es: **Datos sobre la memoria del bot** + - Fi: **Tietoa botin muistista.** + - Fr: **Données sur la mémoire du bot.** + - It: **Dati sulla memoria del bot.** + """ + if not lang: lang=default_lang + if lang == 'en': return "Data about the the bot's memory." + if lang == 'es': return "Datos sobre la memoria del bot" + if lang == 'fi': return "Tietoa botin muistista." + if lang == 'fr': return "Données sur la mémoire du bot." + if lang == 'it': return "Dati sulla memoria del bot." + else: raise ValueError(f'Invalid language {lang}') +def command_stats_embed_field1name(lang:str|None=None): + """ + ### Locales + - En: **File Stats** + - Es: **Estadisticas** + - Fi: **Tiedostostatistiikat** + - Fr: **Statistiques du fichier** + - It: **Statistiche del file** + """ + if not lang: lang=default_lang + if lang == 'en': return "File Stats" + if lang == 'es': return "Estadisticas" + if lang == 'fi': return "Tiedostostatistiikat" + if lang == 'fr': return "Statistiques du fichier" + if lang == 'it': return "Statistiche del file" + else: raise ValueError(f'Invalid language {lang}') +def command_stats_embed_field1value(file_size,line_count,lang:str|None=None): + """ + ### Locales + - En: **Size: {file_size} bytes +Lines: {line_count}** + - Es: **Tamano: {file_size} bytes +Lineas: {line_count}** + - Fi: **Koko: {file_size} tavua +Linjoja: {line_count}** + - Fr: **Taille : {file_size} octets +Lignes : {line_count}** + - It: **Dimensione: {file_size} byte +Linee: {line_count}** + """ + if not lang: lang=default_lang + if lang == 'en': return "Size: {file_size} bytes\nLines: {line_count}".format_map({"file_size": file_size,"line_count": line_count}) + if lang == 'es': return "Tamano: {file_size} bytes\nLineas: {line_count}".format_map({"file_size": file_size,"line_count": line_count}) + if lang == 'fi': return "Koko: {file_size} tavua\nLinjoja: {line_count}".format_map({"file_size": file_size,"line_count": line_count}) + if lang == 'fr': return "Taille : {file_size} octets\nLignes : {line_count}".format_map({"file_size": file_size,"line_count": line_count}) + if lang == 'it': return "Dimensione: {file_size} byte\nLinee: {line_count}".format_map({"file_size": file_size,"line_count": line_count}) + else: raise ValueError(f'Invalid language {lang}') +def command_stats_embed_field2name(lang:str|None=None): + """ + ### Locales + - En: **Version** + - Es: **Version** + - Fi: **Versio** + - Fr: **Version** + - It: **Versione** + """ + if not lang: lang=default_lang + if lang == 'en': return "Version" + if lang == 'es': return "Version" + if lang == 'fi': return "Versio" + if lang == 'fr': return "Version" + if lang == 'it': return "Versione" + else: raise ValueError(f'Invalid language {lang}') +def command_stats_embed_field2value(local_version,latest_version,lang:str|None=None): + """ + ### Locales + - En: **Local: {local_version} +Latest: {latest_version}** + - Es: **Version local: {local_version} +Ultima version: {latest_version}** + - Fi: **Paikallinen: {local_version} +Uusin: {latest_version}** + - Fr: **Locale : {local_version} +Dernière : {latest_version}** + - It: **Locale: {local_version} +Ultima: {latest_version}** + """ + if not lang: lang=default_lang + if lang == 'en': return "Local: {local_version} \nLatest: {latest_version}".format_map({"local_version": local_version,"latest_version": latest_version}) + if lang == 'es': return "Version local: {local_version} \nUltima version: {latest_version}".format_map({"local_version": local_version,"latest_version": latest_version}) + if lang == 'fi': return "Paikallinen: {local_version} \nUusin: {latest_version}".format_map({"local_version": local_version,"latest_version": latest_version}) + if lang == 'fr': return "Locale : {local_version} \nDernière : {latest_version}".format_map({"local_version": local_version,"latest_version": latest_version}) + if lang == 'it': return "Locale: {local_version} \nUltima: {latest_version}".format_map({"local_version": local_version,"latest_version": latest_version}) + else: raise ValueError(f'Invalid language {lang}') +def command_stats_embed_field3name(lang:str|None=None): + """ + ### Locales + - En: **Variable Info** + - Es: **informacion sobre las variables** + - Fi: **Muuttajainformaatio** + - Fr: **Informations variables** + - It: **Informazioni sulle variabili** + """ + if not lang: lang=default_lang + if lang == 'en': return "Variable Info" + if lang == 'es': return "informacion sobre las variables" + if lang == 'fi': return "Muuttajainformaatio" + if lang == 'fr': return "Informations variables" + if lang == 'it': return "Informazioni sulle variabili" + else: raise ValueError(f'Invalid language {lang}') +def command_stats_embed_field3value(NAME,PREFIX,ownerid,PING_LINE,showmemenabled,USERTRAIN_ENABLED,song,splashtext,lang:str|None=None): + """ + ### Locales + - En: **Name: {NAME} +Prefix: {PREFIX} +Owner ID: {ownerid} +Ping line: {PING_LINE} +Memory Sharing Enabled: {showmemenabled} +User Training Enabled: {USERTRAIN_ENABLED} +Song: {song} +Splashtext: ```{splashtext}```** + - Es: **Nombre: {NAME} +Prefijo: {PREFIX} +ID del propietario: {ownerid} +Linea de ping: {PING_LINE} +Compartir memoria habilitada: {showmemenabled} +Entrenamiento de usuario habilitado: {USERTRAIN_ENABLED} +Cancion: {song} +Texto de bienvenida: ```{splashtext}```** + - Fi: **Nimi: {NAME} +Etuliite: {PREFIX} +Omistajan ID: {ownerid} +Ping-linja: {PING_LINE} +Muistin jako päällä: {showmemenabled} +Oppiminen käyttäjistä: {USERTRAIN_ENABLED} +Laulu: {song} +Roisketeksti: ```{splashtext}```** + - Fr: **Nom : {NAME} +Préfixe : {PREFIX} +ID du propriétaire : {ownerid} +Ligne de ping : {PING_LINE} +Partage de mémoire activé : {showmemenabled} +Entraînement utilisateur activé : {USERTRAIN_ENABLED} +Chanson : {song} +Texte de démarrage : ```{splashtext}```** + - It: **Nome: {NAME} +Prefisso: {PREFIX} +ID Proprietario: {ownerid} +Linea ping: {PING_LINE} +Memoria Condivisa Abilitata: {showmemenabled} +Addestramento Utente Abilitato: {USERTRAIN_ENABLED} +Canzone: {song} +Splashtext: ```{splashtext}```** + """ + if not lang: lang=default_lang + if lang == 'en': return "Name: {NAME} \nPrefix: {PREFIX} \nOwner ID: {ownerid}\nPing line: {PING_LINE} \nMemory Sharing Enabled: {showmemenabled} \nUser Training Enabled: {USERTRAIN_ENABLED}\nSong: {song} \nSplashtext: ```{splashtext}```".format_map({"NAME": NAME,"PREFIX": PREFIX,"ownerid": ownerid,"PING_LINE": PING_LINE,"showmemenabled": showmemenabled,"USERTRAIN_ENABLED": USERTRAIN_ENABLED,"song": song,"splashtext": splashtext}) + if lang == 'es': return "Nombre: {NAME} \nPrefijo: {PREFIX} \nID del propietario: {ownerid}\nLinea de ping: {PING_LINE} \nCompartir memoria habilitada: {showmemenabled} \nEntrenamiento de usuario habilitado: {USERTRAIN_ENABLED} \nCancion: {song} \nTexto de bienvenida: ```{splashtext}```".format_map({"NAME": NAME,"PREFIX": PREFIX,"ownerid": ownerid,"PING_LINE": PING_LINE,"showmemenabled": showmemenabled,"USERTRAIN_ENABLED": USERTRAIN_ENABLED,"song": song,"splashtext": splashtext}) + if lang == 'fi': return "Nimi: {NAME} \nEtuliite: {PREFIX} \nOmistajan ID: {ownerid}\nPing-linja: {PING_LINE} \nMuistin jako päällä: {showmemenabled} \nOppiminen käyttäjistä: {USERTRAIN_ENABLED}\nLaulu: {song} \nRoisketeksti: ```{splashtext}```".format_map({"NAME": NAME,"PREFIX": PREFIX,"ownerid": ownerid,"PING_LINE": PING_LINE,"showmemenabled": showmemenabled,"USERTRAIN_ENABLED": USERTRAIN_ENABLED,"song": song,"splashtext": splashtext}) + if lang == 'fr': return "Nom : {NAME} \nPréfixe : {PREFIX} \nID du propriétaire : {ownerid}\nLigne de ping : {PING_LINE} \nPartage de mémoire activé : {showmemenabled} \nEntraînement utilisateur activé : {USERTRAIN_ENABLED} \nChanson : {song} \nTexte de démarrage : ```{splashtext}```".format_map({"NAME": NAME,"PREFIX": PREFIX,"ownerid": ownerid,"PING_LINE": PING_LINE,"showmemenabled": showmemenabled,"USERTRAIN_ENABLED": USERTRAIN_ENABLED,"song": song,"splashtext": splashtext}) + if lang == 'it': return "Nome: {NAME} \nPrefisso: {PREFIX} \nID Proprietario: {ownerid}\nLinea ping: {PING_LINE} \nMemoria Condivisa Abilitata: {showmemenabled} \nAddestramento Utente Abilitato: {USERTRAIN_ENABLED}\nCanzone: {song} \nSplashtext: ```{splashtext}```".format_map({"NAME": NAME,"PREFIX": PREFIX,"ownerid": ownerid,"PING_LINE": PING_LINE,"showmemenabled": showmemenabled,"USERTRAIN_ENABLED": USERTRAIN_ENABLED,"song": song,"splashtext": splashtext}) + else: raise ValueError(f'Invalid language {lang}') +def no_image_available(lang:str|None=None): + """ + ### Locales + - En: **No images available!** + - Es: **No images available!** + - Fi: **No images available!** + - Fr: **No images available!** + - It: **No images available!** + """ + if not lang: lang=default_lang + if lang == 'en': return "No images available!" + if lang == 'es': return "No images available!" + if lang == 'fi': return "No images available!" + if lang == 'fr': return "No images available!" + if lang == 'it': return "No images available!" + else: raise ValueError(f'Invalid language {lang}') +def failed_generate_image(lang:str|None=None): + """ + ### Locales + - En: **Failed to generate an image** + - Es: **Failed to generate an image** + - Fi: **Failed to generate an image** + - Fr: **Failed to generate an image** + - It: **Failed to generate an image** + """ + if not lang: lang=default_lang + if lang == 'en': return "Failed to generate an image" + if lang == 'es': return "Failed to generate an image" + if lang == 'fi': return "Failed to generate an image" + if lang == 'fr': return "Failed to generate an image" + if lang == 'it': return "Failed to generate an image" + else: raise ValueError(f'Invalid language {lang}') +def markov_model_not_found(lang:str|None=None): + """ + ### Locales + - En: **Markov model not found!** + - Es: **Markov model not found!** + - Fi: **Markov model not found!** + - Fr: **Markov model not found!** + - It: **Markov model not found!** + """ + if not lang: lang=default_lang + if lang == 'en': return "Markov model not found!" + if lang == 'es': return "Markov model not found!" + if lang == 'fi': return "Markov model not found!" + if lang == 'fr': return "Markov model not found!" + if lang == 'it': return "Markov model not found!" + else: raise ValueError(f'Invalid language {lang}') +def blacklisted(lang:str|None=None): + """ + ### Locales + - En: **blacklisted** + - Es: **blacklisted** + - Fi: **blacklisted** + - Fr: **blacklisted** + - It: **blacklisted** + """ + if not lang: lang=default_lang + if lang == 'en': return "blacklisted" + if lang == 'es': return "blacklisted" + if lang == 'fi': return "blacklisted" + if lang == 'fr': return "blacklisted" + if lang == 'it': return "blacklisted" + else: raise ValueError(f'Invalid language {lang}') +def blacklisted_user(lang:str|None=None): + """ + ### Locales + - En: **Blacklisted user** + - Es: **Blacklisted user** + - Fi: **Blacklisted user** + - Fr: **Blacklisted user** + - It: **Blacklisted user** + """ + if not lang: lang=default_lang + if lang == 'en': return "Blacklisted user" + if lang == 'es': return "Blacklisted user" + if lang == 'fi': return "Blacklisted user" + if lang == 'fr': return "Blacklisted user" + if lang == 'it': return "Blacklisted user" + else: raise ValueError(f'Invalid language {lang}') +def edit_fail(lang:str|None=None): + """ + ### Locales + - En: **Failed to edit message** + - Es: **Failed to edit message** + - Fi: **Failed to edit message** + - Fr: **Failed to edit message** + - It: **Failed to edit message** + """ + if not lang: lang=default_lang + if lang == 'en': return "Failed to edit message" + if lang == 'es': return "Failed to edit message" + if lang == 'fi': return "Failed to edit message" + if lang == 'fr': return "Failed to edit message" + if lang == 'it': return "Failed to edit message" + else: raise ValueError(f'Invalid language {lang}') diff --git a/modules/markovmemory.py b/modules/markovmemory.py index 3235035..3221b9d 100644 --- a/modules/markovmemory.py +++ b/modules/markovmemory.py @@ -3,8 +3,13 @@ import json import markovify import pickle from modules.globalvars import * -from modules.volta.main import _ import logging +import modules.keys as k +from modules.settings import Settings as SettingsManager +settings_manager = SettingsManager() +settings = settings_manager.settings + + logger = logging.getLogger("goober") # Get file size and line count for a given file path def get_file_info(file_path): @@ -22,7 +27,7 @@ def load_memory(): # Try to load data from MEMORY_FILE try: - with open(MEMORY_FILE, "r") as f: + with open(settings["bot"]["active_memory"], "r") as f: data = json.load(f) except FileNotFoundError: pass @@ -31,7 +36,7 @@ def load_memory(): # Save memory data to MEMORY_FILE def save_memory(memory): - with open(MEMORY_FILE, "w") as f: + with open(settings["bot"]["active_memory"], "w") as f: json.dump(memory, f, indent=4) def train_markov_model(memory, additional_data=None): @@ -57,8 +62,8 @@ def load_markov_model(filename='markov_model.pkl'): try: with open(filename, 'rb') as f: model = pickle.load(f) - logger.info(f"{_('model_loaded')} {filename}.{RESET}") + logger.info(f"{k.model_loaded()} {filename}.{RESET}") return model except FileNotFoundError: - logger.error(f"{filename} {_('not_found')}{RESET}") + logger.error(f"{filename} {k.not_found()}{RESET}") return None \ No newline at end of file diff --git a/modules/prestartchecks.py b/modules/prestartchecks.py index bb952f4..3948309 100644 --- a/modules/prestartchecks.py +++ b/modules/prestartchecks.py @@ -1,5 +1,4 @@ from modules.globalvars import * -from modules.volta.main import _, check_missing_translations import time import os import sys @@ -11,6 +10,11 @@ import re from spacy.util import is_package import importlib.metadata import logging +import modules.keys as k +from modules.settings import Settings as SettingsManager +settings_manager = SettingsManager() +settings = settings_manager.settings + logger = logging.getLogger("goober") @@ -21,7 +25,7 @@ try: import psutil except ImportError: psutilavaliable = False - logger.error(_('missing_requests_psutil')) + logger.error(k.missing_requests_psutil()) def check_for_model(): if is_package("en_core_web_sm"): @@ -34,7 +38,7 @@ def iscloned(): if os.path.exists(".git"): return True else: - logger.error(f"{_('not_cloned')}") + logger.error(f"{k.not_cloned()}") sys.exit(1) def get_stdlib_modules(): @@ -67,7 +71,7 @@ def check_requirements(): requirements_path = os.path.abspath(os.path.join(parent_dir, '..', 'requirements.txt')) if not os.path.exists(requirements_path): - logger.error(f"{(_('requirements_not_found')).format(path=requirements_path)}") + logger.error(f"{k.requirements_not_found(path=requirements_path)}") return with open(requirements_path, 'r') as f: @@ -85,24 +89,24 @@ def check_requirements(): for req in sorted(requirements): if req in STD_LIB_MODULES or req == 'modules': - print((_('std_lib_local_skipped')).format(package=req)) + print(k.std_lib_local_skipped(package=req)) continue check_name = req.lower() if check_name in installed_packages: - logger.info(f"{_('ok_installed').format(package=check_name)} {check_name}") + logger.info(f"{k.ok_installed()} {check_name}") else: - logger.error(f"{(_('missing_package')).format(package=check_name)} {check_name} {(_('missing_package2'))}") + logger.error(f"{k.missing_package()} {check_name} {k.missing_package2()}") missing.append(check_name) if missing: - logger.error(_('missing_packages_detected')) + logger.error(k.missing_packages_detected()) for pkg in missing: print(f" - {pkg}") sys.exit(1) else: - logger.info(_('all_requirements_satisfied')) + logger.info(k.all_requirements_satisfied()) def check_latency(): host = "1.1.1.1" @@ -132,16 +136,16 @@ def check_latency(): match = re.search(latency_pattern, result.stdout) if match: latency_ms = float(match.group(1)) - logger.info((_('ping_to')).format(host=host, latency=latency_ms)) + logger.info(k.ping_to(host=host, latency=latency_ms)) if latency_ms > 300: - logger.warning(f"{(_('high_latency'))}") + logger.warning(f"{k.high_latency()}") else: - logger.warning((_('could_not_parse_latency'))) + logger.warning(k.could_not_parse_latency()) else: print(result.stderr) - logger.error(f"{(_('ping_failed')).format(host=host)}{RESET}") + logger.error(f"{k.ping_failed(host=host)}{RESET}") except Exception as e: - logger.error((_('error_running_ping')).format(error=e)) + logger.error(k.error_running_ping(error=e)) def check_memory(): if psutilavaliable == False: @@ -152,48 +156,48 @@ def check_memory(): used_memory = memory_info.used / (1024 ** 3) free_memory = memory_info.available / (1024 ** 3) - logger.info((_('memory_usage')).format(used=used_memory, total=total_memory, percent=(used_memory / total_memory) * 100)) + logger.info(k.memory_usage(used=used_memory, total=total_memory, percent=(used_memory / total_memory) * 100)) if used_memory > total_memory * 0.9: - print(f"{YELLOW}{(_('memory_above_90')).format(percent=(used_memory / total_memory) * 100)}{RESET}") - logger.info((_('total_memory')).format(total=total_memory)) - logger.info((_('used_memory')).format(used=used_memory)) + print(f"{YELLOW}{k.memory_above_90(percent=(used_memory / total_memory) * 100)}{RESET}") + logger.info(k.total_memory(total=total_memory)) + logger.info(k.used_memory(used=used_memory)) if free_memory < 1: - logger.warning(f"{(_('low_free_memory')).format(free=free_memory)}") + logger.warning(f"{k.low_free_memory(free=free_memory)}") sys.exit(1) except ImportError: - logger.error(_('psutil_not_installed')) # todo: translate this into italian and put it in the translations "psutil is not installed. Memory check skipped." + logger.error(k.psutil_not_installed()) # todo: translate this into italian and put it in the translations "psutil is not installed. Memory check skipped." def check_cpu(): if psutilavaliable == False: return - logger.info((_('measuring_cpu'))) + logger.info(k.measuring_cpu()) cpu_per_core = psutil.cpu_percent(interval=1, percpu=True) # type: ignore total_cpu = sum(cpu_per_core) / len(cpu_per_core) - logger.info((_('total_cpu_usage')).format(usage=total_cpu)) + logger.info(k.total_cpu_usage(usage=total_cpu)) if total_cpu > 85: - logger.warning(f"{(_('high_avg_cpu')).format(usage=total_cpu)}") + logger.warning(f"{k.high_avg_cpu(usage=total_cpu)}") if total_cpu > 95: - logger.error(_('really_high_cpu')) + logger.error(k.really_high_cpu()) sys.exit(1) def check_memoryjson(): try: - logger.info((_('memory_file')).format(size=os.path.getsize(MEMORY_FILE) / (1024 ** 2))) - if os.path.getsize(MEMORY_FILE) > 1_073_741_824: - logger.warning(f"{(_('memory_file_large'))}") + logger.info(k.memory_file(size=os.path.getsize(settings["bot"]["active_memory"]) / (1024 ** 2))) + if os.path.getsize(settings["bot"]["active_memory"]) > 1_073_741_824: + logger.warning(f"{k.memory_file_large()}") try: - with open(MEMORY_FILE, 'r', encoding='utf-8') as f: + with open(settings["bot"]["active_memory"], 'r', encoding='utf-8') as f: json.load(f) except json.JSONDecodeError as e: - logger.error(f"{(_('memory_file_corrupted')).format(error=e)}") - logger.warning(f"{(_('consider_backup_memory'))}") + logger.error(f"{k.memory_file_corrupted(error=e)}") + logger.warning(f"{k.consider_backup_memory()}") except UnicodeDecodeError as e: - logger.error(f"{(_('memory_file_encoding')).format(error=e)}") - logger.warning(f"{(_('consider_backup_memory'))}") + logger.error(f"{k.memory_file_encoding(error=e)}") + logger.warning(f"{k.consider_backup_memory()}") except Exception as e: - logger.error(f"{(_('error_reading_memory')).format(error=e)}") + logger.error(f"{k.error_reading_memory(error=e)}") except FileNotFoundError: - logger(f"{(_('memory_file_not_found'))}") + logger.info(f"{k.memory_file_not_found()}") def presskey2skip(timeout): if os.name == 'nt': @@ -228,13 +232,13 @@ def presskey2skip(timeout): termios.tcsetattr(fd, termios.TCSADRAIN, old_settings) beta = beta def start_checks(): - if CHECKS_DISABLED == "True": - logger.warning(f"{(_('checks_disabled'))}") + if settings["disable_checks"]: + logger.warning(f"{k.checks_disabled()}") return - logger.info(_('running_prestart_checks')) + + logger.info(k.running_prestart_checks()) check_for_model() iscloned() - check_missing_translations() check_requirements() check_latency() check_memory() @@ -243,13 +247,15 @@ def start_checks(): if os.path.exists(".env"): pass else: - logger.warning(f"{(_('env_file_not_found'))}") + logger.warning(f"{k.env_file_not_found()}") sys.exit(1) if beta == True: logger.warning(f"this build isnt finished yet, some things might not work as expected") else: pass - logger.info(_('continuing_in_seconds').format(seconds=5)) + logger.info(k.continuing_in_seconds(seconds=5)) presskey2skip(timeout=5) os.system('cls' if os.name == 'nt' else 'clear') - print(splashtext) \ No newline at end of file + + with open(settings ["splash_text_loc"], "r") as f: + print("".join(f.readlines())) diff --git a/modules/sentenceprocessing.py b/modules/sentenceprocessing.py index 993ba90..4955dc9 100644 --- a/modules/sentenceprocessing.py +++ b/modules/sentenceprocessing.py @@ -1,10 +1,12 @@ import re +import discord.ext +import discord.ext.commands from modules.globalvars import * -from modules.volta.main import _ - import spacy from spacy.tokens import Doc from spacytextblob.spacytextblob import SpacyTextBlob +import discord +import modules.keys as k import logging logger = logging.getLogger("goober") @@ -14,12 +16,12 @@ def check_resources(): try: nlp = spacy.load("en_core_web_sm") except OSError: - logging.critical((_('spacy_model_not_found'))) - spacy.cli.download("en_core_web_sm") + logging.critical(k.spacy_model_not_found()) + spacy.cli.download("en_core_web_sm") # type: ignore nlp = spacy.load("en_core_web_sm") if "spacytextblob" not in nlp.pipe_names: nlp.add_pipe("spacytextblob") - logger.info((_('spacy_initialized'))) + logger.info(k.spacy_initialized()) check_resources() @@ -31,35 +33,37 @@ def is_positive(sentence): doc = nlp(sentence) sentiment_score = doc._.polarity # from spacytextblob - debug_message = f"{(_('sentence_positivity'))} {sentiment_score}{RESET}" + debug_message = f"{k.sentence_positivity()} {sentiment_score}{RESET}" logger.debug(debug_message) return sentiment_score > 0.6 # had to raise the bar because it kept saying "death to jews" was fine and it kept reacting to them -async def send_message(ctx, message=None, embed=None, file=None, edit=False, message_reference=None): +async def send_message(ctx: discord.ext.commands.Context, + message: str | None = None, + embed: discord.Embed | None = None, + file: discord.File | None = None, + edit: bool = False, + message_reference: discord.Message | None = None + ) -> discord.Message | None: + + sent_message: discord.Message | None = None + if edit and message_reference: try: await message_reference.edit(content=message, embed=embed) + return message_reference except Exception as e: - await ctx.send(f"{RED}{(_('edit_fail'))} {e}{RESET}") + await ctx.send(f"{k.edit_fail()} {e}") + return None + + if embed: + sent_message = await ctx.send(embed=embed, content=message) + elif file: + sent_message = await ctx.send(file=file, content=message) else: - if hasattr(ctx, "respond"): - sent_message = None - if embed: - sent_message = await ctx.respond(embed=embed, ephemeral=False) - elif message: - sent_message = await ctx.respond(message, ephemeral=False) - if file: - sent_message = await ctx.respond(file=file, ephemeral=False) - else: - sent_message = None - if embed: - sent_message = await ctx.send(embed=embed) - elif message: - sent_message = await ctx.send(message) - if file: - sent_message = await ctx.send(file=file) - return sent_message + sent_message = await ctx.send(content=message) + + return sent_message def append_mentions_to_18digit_integer(message): pattern = r'\b\d{18}\b' diff --git a/modules/settings.py b/modules/settings.py new file mode 100644 index 0000000..ecad665 --- /dev/null +++ b/modules/settings.py @@ -0,0 +1,58 @@ +import json +import os +from typing import List, Mapping, Any, TypedDict +from modules.keys import Language +import logging +import copy + +logger = logging.getLogger("goober") + +class MiscBotOptions(TypedDict): + ping_line: str + active_song: str + positive_gifs: List[str] + block_profanity: bool + +class BotSettings(TypedDict): + prefix: str + owner_ids: List[int] + blacklisted_users: List[int] + user_training: bool + allow_show_mem_command: bool + react_to_messages: bool + misc: MiscBotOptions + enabled_cogs: List[str] + active_memory: str + +class SettingsType(TypedDict): + bot: BotSettings + locale: Language + name: str + auto_update: bool + disable_checks: bool + splash_text_loc: str + +class Settings: + def __init__(self) -> None: + self.path: str = os.path.join(".", "settings", "settings.json") + + if not os.path.exists(self.path): + raise ValueError("settings.json file does not exist!") + + self.settings: SettingsType + self.original_settings: SettingsType + + with open(self.path, "r") as f: + self.__kv_store: dict = json.load(f) + + self.settings = SettingsType(self.__kv_store) # type: ignore + self.original_settings = copy.deepcopy(self.settings) + + def commit(self) -> None: + with open(self.path, "w") as f: + json.dump(self.settings, f, indent=4) + + self.original_settings = self.settings + + def discard(self) -> None: + self.settings = self.original_settings \ No newline at end of file diff --git a/modules/unhandledexception.py b/modules/unhandledexception.py index 9521e72..93ee70e 100644 --- a/modules/unhandledexception.py +++ b/modules/unhandledexception.py @@ -1,8 +1,14 @@ import sys import traceback import os -from modules.globalvars import RED, RESET, splashtext -from modules.volta.main import _ +from modules.settings import Settings as SettingsManager +import logging +from modules.globalvars import RED, RESET +import modules.keys as k + +settings_manager = SettingsManager() +settings = settings_manager.settings +logger = logging.getLogger("goober") def handle_exception(exc_type, exc_value, exc_traceback, *, context=None): os.system('cls' if os.name == 'nt' else 'clear') @@ -11,11 +17,13 @@ def handle_exception(exc_type, exc_value, exc_traceback, *, context=None): sys.__excepthook__(exc_type, exc_value, exc_traceback) return - print(splashtext) + with open(settings['splash_text_loc'], "r") as f: + print("".join(f.readlines())) + print(f"{RED}=====BEGINNING OF TRACEBACK====={RESET}") traceback.print_exception(exc_type, exc_value, exc_traceback) print(f"{RED}========END OF TRACEBACK========{RESET}") - print(f"{RED}{_('unhandled_exception')}{RESET}") + print(f"{RED}{k.unhandled_exception()}{RESET}") if context: diff --git a/modules/version.py b/modules/version.py index a5c1132..3b09cca 100644 --- a/modules/version.py +++ b/modules/version.py @@ -1,5 +1,3 @@ -from modules.volta.main import _ -from modules.globalvars import * import requests import subprocess import sys @@ -7,6 +5,13 @@ import logging import json import time import random +import modules.keys as k +from modules.globalvars import * +from modules.settings import Settings as SettingsManager + +settings_manager = SettingsManager() +settings = settings_manager.settings + logger = logging.getLogger("goober") launched = False @@ -24,18 +29,18 @@ def is_remote_ahead(branch='main', remote='origin'): # Automatically update the local repository if the remote is ahead def auto_update(branch='main', remote='origin'): if launched == True: - print(_("already_started")) + print(k.already_started()) return - if AUTOUPDATE != "True": + if settings["auto_update"] != "True": pass # Auto-update is disabled if is_remote_ahead(branch, remote): - print(_( "remote_ahead").format(remote=remote, branch=branch)) + logger.info(k.remote_ahead(remote, branch)) pull_result = run_cmd(f'git pull {remote} {branch}') logger.info(pull_result) - logger.info(_( "please_restart")) + logger.info(k.please_restart()) sys.exit(0) else: - logger.info(_( "local_ahead").format(remote=remote, branch=branch)) + logger.info(k.local_ahead(remote, branch)) def get_latest_version_info(): try: @@ -75,31 +80,34 @@ def check_for_update(): latest_version_info = get_latest_version_info() if not latest_version_info: - logger.error(f"{_('fetch_update_fail')}") - return None, None + logger.error(f"{k.fetch_update_fail()}") + return None latest_version = latest_version_info.get("version") os.environ['gooberlatest_version'] = latest_version download_url = latest_version_info.get("download_url") if not latest_version or not download_url: - logger.error(f"{RED}{_('invalid_server')}{RESET}") - return None, None + logger.error(k.invalid_server()) + return None + # Check if local_version is valid if local_version == "0.0.0" or None: - logger.error(f"{RED}{_('cant_find_local_version')}{RESET}") + logger.error(k.cant_find_local_version()) return # Compare local and latest versions + if local_version < latest_version: - logger.info(f"{YELLOW}{_('new_version').format(latest_version=latest_version, local_version=local_version)}{RESET}") - logger.info(f"{YELLOW}{_('changelog').format(VERSION_URL=VERSION_URL)}{RESET}") + logger.warning(k.new_version(latest_version=latest_version, local_version=local_version)) + logger.warning(k.changelog(VERSION_URL=VERSION_URL)) auto_update() + elif beta == True: logger.warning(f"You are running an \"unstable\" version of Goober, do not expect it to work properly.\nVersion {local_version}\nServer: {latest_version}{RESET}") elif local_version > latest_version: - logger.warning(f"{_('modification_warning')}") + logger.warning(f"{k.modification_warning()}") elif local_version == latest_version: - logger.info(f"{_('latest_version')} {local_version}") - logger.info(f"{_('latest_version2').format(VERSION_URL=VERSION_URL)}\n\n") + logger.info(f"{k.latest_version()} {local_version}") + logger.info(f"{k.latest_version2(VERSION_URL=VERSION_URL)}\n\n") launched = True return latest_version \ No newline at end of file diff --git a/replace_volta.py b/replace_volta.py new file mode 100644 index 0000000..2de6584 --- /dev/null +++ b/replace_volta.py @@ -0,0 +1,47 @@ +import os +import re + +folder_path = "." + +# Real trap regex 😮‍💨 — group(1)=key, group(2)=format args (optional) +pattern = re.compile( + r""" + (?