diff --git a/.gitignore b/.gitignore index ccdc725..078e8b0 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ memory.json memory.json venv/ output.png +.vscode/ \ No newline at end of file diff --git a/assets/images/crash2.png b/assets/images/crash2.png new file mode 100644 index 0000000..12f7616 Binary files /dev/null and b/assets/images/crash2.png differ diff --git a/assets/images/smashedphone.webp b/assets/images/smashedphone.webp new file mode 100644 index 0000000..845070f Binary files /dev/null and b/assets/images/smashedphone.webp differ diff --git a/assets/images/thisisfine.png b/assets/images/thisisfine.png new file mode 100644 index 0000000..41977dc Binary files /dev/null and b/assets/images/thisisfine.png differ diff --git a/bot.py b/bot.py index 4d65b2e..2edbed5 100644 --- a/bot.py +++ b/bot.py @@ -3,12 +3,9 @@ import re import json import time import random -import shutil import traceback import subprocess - - from modules.globalvars import * from modules.prestartchecks import start_checks @@ -17,21 +14,16 @@ print(splashtext) # Print splash text (from modules/globalvars.py) start_checks() import requests -import psutil import discord -from discord.ext import commands, tasks -from discord import app_commands +from discord.ext import commands from discord import Colour import nltk -from nltk.data import find -from nltk import download +import nltk.data from better_profanity import profanity - -from discord.ext import commands, tasks -from discord import app_commands +from discord.ext import commands from modules.central import ping_server from modules.translations import * @@ -54,10 +46,10 @@ def check_resources(): } for resource, path in resources.items(): try: - find(path) # find is from nltk.data + nltk.data.find(path) print(f"{resource} is already installed.") - except LookupError: - download(resource) # download is from nltk + except Exception: + nltk.download(str(resource)) check_resources() @@ -145,12 +137,6 @@ async def on_ready(): print(f"{RED}Permission error while syncing commands: {perm_error}{RESET}") print(f"{RED}Make sure the bot has the 'applications.commands' scope and is invited with the correct permissions.{RESET}") quit() - except Exception as e: - print(f"{RED}{get_translation(LOCALE, 'fail_commands_sync')} {e}{RESET}") - traceback.print_exc() - quit() - print(f"{GREEN}{get_translation(LOCALE, 'started').format(name=NAME)}{RESET}") - except Exception as e: print(f"{RED}{get_translation(LOCALE, 'fail_commands_sync')} {e}{RESET}") traceback.print_exc() @@ -161,7 +147,7 @@ async def on_ready(): launched = True # Load positive GIF URLs from environment variable -positive_gifs = os.getenv("POSITIVE_GIFS").split(',') +positive_gifs: list[str] = os.getenv("POSITIVE_GIFS", "").split(',') @bot.event async def on_command_error(ctx, error): @@ -295,7 +281,7 @@ async def help(ctx): # Event: Called on every message @bot.event async def on_message(message): - global memory, markov_model, last_random_talk_time + global memory, markov_model # Ignore bot messages if message.author.bot: @@ -396,7 +382,7 @@ async def stats(ctx): embed = discord.Embed(title=f"{get_translation(LOCALE, 'command_stats_embed_title')}", description=f"{get_translation(LOCALE, 'command_stats_embed_desc')}", color=Colour(0x000000)) embed.add_field(name=f"{get_translation(LOCALE, 'command_stats_embed_field1name')}", value=f"{get_translation(LOCALE, 'command_stats_embed_field1value').format(file_size=file_size, line_count=line_count)}", inline=False) embed.add_field(name=f"{get_translation(LOCALE, 'command_stats_embed_field2name')}", value=f"{get_translation(LOCALE, 'command_stats_embed_field2value').format(local_version=local_version, latest_version=latest_version)}", inline=False) - embed.add_field(name=f"{get_translation(LOCALE, 'command_stats_embed_field3name')}", value=f"{get_translation(LOCALE, 'command_stats_embed_field3value').format(NAME=NAME, PREFIX=PREFIX, ownerid=ownerid, cooldown_time=cooldown_time, PING_LINE=PING_LINE, showmemenabled=showmemenabled, USERTRAIN_ENABLED=USERTRAIN_ENABLED, last_random_talk_time=last_random_talk_time, song=song, splashtext=splashtext)}", inline=False) + embed.add_field(name=f"{get_translation(LOCALE, 'command_stats_embed_field3name')}", value=f"{get_translation(LOCALE, 'command_stats_embed_field3value').format(NAME=NAME, PREFIX=PREFIX, ownerid=ownerid, cooldown_time=cooldown_time, PING_LINE=PING_LINE, showmemenabled=showmemenabled, USERTRAIN_ENABLED=USERTRAIN_ENABLED, song=song, splashtext=splashtext)}", inline=False) await send_message(ctx, embed=embed) diff --git a/example.env b/example.env index 4a0e361..7339bf4 100644 --- a/example.env +++ b/example.env @@ -2,8 +2,6 @@ DISCORD_BOT_TOKEN=token BOT_PREFIX="g." PING_LINE="The Beretta fires fast and won't make you feel any better!" BLACKLISTED_USERS= -rnd_talk_channel1=1319593363997589614 -rnd_talk_channel2=1318263176134918246 cooldown=10800 hourlyspeak=1318263176134918246 ownerid=542701119948849163 @@ -15,7 +13,7 @@ ALIVEPING="true" AUTOUPDATE="True" gooberTOKEN= song="War Without Reason" -POSITIVE_GIFS="https://media.discordapp.net/attachments/821047460151427135/1181371808566493184/jjpQGeno.gif, https://tenor.com/view/chill-guy-my-new-character-gif-2777893510283028272,https://tenor.com/view/goodnight-goodnight-friends-weezer-weezer-goodnight-gif-7322052181075806988" +POSITIVE_GIFS="https://tenor.com/view/chill-guy-my-new-character-gif-2777893510283028272, https://tenor.com/view/goodnight-goodnight-friends-weezer-weezer-goodnight-gif-7322052181075806988" splashtext=" d8b ?88 diff --git a/locales/en.json b/locales/en.json index 79835d5..354f2c7 100644 --- a/locales/en.json +++ b/locales/en.json @@ -77,6 +77,6 @@ "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} \nCooldown: {cooldown_time} \nPing line: {PING_LINE} \nMemory Sharing Enabled: {showmemenabled} \nUser Training Enabled: {USERTRAIN_ENABLED} \nLast Random TT: {last_random_talk_time} \nSong: {song} \nSplashtext: ```{splashtext}```" + "command_stats_embed_field3value": "Name: {NAME} \nPrefix: {PREFIX} \nOwner ID: {ownerid} \nCooldown: {cooldown_time} \nPing line: {PING_LINE} \nMemory Sharing Enabled: {showmemenabled} \nUser Training Enabled: {USERTRAIN_ENABLED}\nSong: {song} \nSplashtext: ```{splashtext}```" } diff --git a/locales/es.json b/locales/es.json index c1156c1..eb7b743 100644 --- a/locales/es.json +++ b/locales/es.json @@ -73,5 +73,5 @@ "command_stats_embed_field2name": "Version", "command_stats_embed_field2value": "Version local: {local_version} \nUltima version: {latest_version}", "command_stats_embed_field3name": "informacion sobre las variables", - "command_stats_embed_field3value": "Nombre: {NAME} \nPrefijo: {PREFIX} \nID del propietario: {ownerid} \nTiempo de reutilizacion: {cooldown_time} \nLinea de ping: {PING_LINE} \nCompartir memoria habilitada: {showmemenabled} \nEntrenamiento de usuario habilitado: {USERTRAIN_ENABLED} \nUltima conversacion aleatoria: {last_random_talk_time} \nCancion: {song} \nTexto de bienvenida: ```{splashtext}```" + "command_stats_embed_field3value": "Nombre: {NAME} \nPrefijo: {PREFIX} \nID del propietario: {ownerid} \nTiempo de reutilizacion: {cooldown_time} \nLinea de ping: {PING_LINE} \nCompartir memoria habilitada: {showmemenabled} \nEntrenamiento de usuario habilitado: {USERTRAIN_ENABLED} \nCancion: {song} \nTexto de bienvenida: ```{splashtext}```" } \ No newline at end of file diff --git a/locales/fi.json b/locales/fi.json index 8fd3329..3f97506 100644 --- a/locales/fi.json +++ b/locales/fi.json @@ -73,6 +73,6 @@ "command_stats_embed_field2name": "Versio", "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} \nJäähtymisaika: {cooldown_time} \nPing-linja: {PING_LINE} \nMuistin jako päällä: {showmemenabled} \nOppiminen käyttäjistä: {USERTRAIN_ENABLED} \nViimeisin satunnainen TT: {last_random_talk_time} \nLaulu: {song} \nRoisketeksti: ```{splashtext}```" + "command_stats_embed_field3value": "Nimi: {NAME} \nEtuliite: {PREFIX} \nOmistajan ID: {ownerid} \nJäähtymisaika: {cooldown_time} \nPing-linja: {PING_LINE} \nMuistin jako päällä: {showmemenabled} \nOppiminen käyttäjistä: {USERTRAIN_ENABLED}\nLaulu: {song} \nRoisketeksti: ```{splashtext}```" } \ No newline at end of file diff --git a/locales/fr.json b/locales/fr.json index b7075ac..8209ba8 100644 --- a/locales/fr.json +++ b/locales/fr.json @@ -77,5 +77,5 @@ "command_stats_embed_field2name": "Version", "command_stats_embed_field2value": "Locale : {local_version} \nDernière : {latest_version}", "command_stats_embed_field3name": "Informations variables", - "command_stats_embed_field3value": "Nom : {NAME} \nPréfixe : {PREFIX} \nID du propriétaire : {ownerid} \nTemps de recharge : {cooldown_time} \nLigne de ping : {PING_LINE} \nPartage de mémoire activé : {showmemenabled} \nEntraînement utilisateur activé : {USERTRAIN_ENABLED} \nDernier TT aléatoire : {last_random_talk_time} \nChanson : {song} \nTexte de démarrage : ```{splashtext}```" + "command_stats_embed_field3value": "Nom : {NAME} \nPréfixe : {PREFIX} \nID du propriétaire : {ownerid} \nTemps de recharge : {cooldown_time} \nLigne de ping : {PING_LINE} \nPartage de mémoire activé : {showmemenabled} \nEntraînement utilisateur activé : {USERTRAIN_ENABLED} \nChanson : {song} \nTexte de démarrage : ```{splashtext}```" } \ No newline at end of file diff --git a/locales/it.json b/locales/it.json index b5a247a..8a88b29 100644 --- a/locales/it.json +++ b/locales/it.json @@ -76,6 +76,6 @@ "command_stats_embed_field2name": "Versione", "command_stats_embed_field2value": "Locale: {local_version} \nUltima: {latest_version}", "command_stats_embed_field3name": "Informazioni sulle variabili", - "command_stats_embed_field3value": "Nome: {NAME} \nPrefisso: {PREFIX} \nID Proprietario: {ownerid} \nCooldown: {cooldown_time} \nLinea ping: {PING_LINE} \nMemoria Condivisa Abilitata: {showmemenabled} \nAddestramento Utente Abilitato: {USERTRAIN_ENABLED} \nUltima TT Casuale: {last_random_talk_time} \nCanzone: {song} \nSplashtext: ```{splashtext}```" + "command_stats_embed_field3value": "Nome: {NAME} \nPrefisso: {PREFIX} \nID Proprietario: {ownerid} \nCooldown: {cooldown_time} \nLinea ping: {PING_LINE} \nMemoria Condivisa Abilitata: {showmemenabled} \nAddestramento Utente Abilitato: {USERTRAIN_ENABLED}\nCanzone: {song} \nSplashtext: ```{splashtext}```" } diff --git a/modules/globalvars.py b/modules/globalvars.py index bda96cc..c47716c 100644 --- a/modules/globalvars.py +++ b/modules/globalvars.py @@ -2,34 +2,32 @@ import os import platform from dotenv import load_dotenv import pathlib + env_path = pathlib.Path(__file__).parent.parent / '.env' load_dotenv(dotenv_path=env_path) - -RED = "\033[31m" -GREEN = "\033[32m" -YELLOW = "\033[33m" -DEBUG = "\033[1;30m" -RESET = "\033[0m" +ANSI = "\033[" +RED = f"{ANSI}31m" +GREEN = f"{ANSI}32m" +YELLOW = f"{ANSI}33m" +DEBUG = f"{ANSI}1;30m" +RESET = f"{ANSI}0m" VERSION_URL = "https://goober.expect.ovh" UPDATE_URL = VERSION_URL+"/latest_version.json" LOCAL_VERSION_FILE = "current_version.txt" -TOKEN = os.getenv("DISCORD_BOT_TOKEN") -PREFIX = os.getenv("BOT_PREFIX") -hourlyspeak = int(os.getenv("hourlyspeak")) +TOKEN = os.getenv("DISCORD_BOT_TOKEN", "0") +PREFIX = os.getenv("BOT_PREFIX", "g.") +hourlyspeak = int(os.getenv("hourlyspeak", "0")) PING_LINE = os.getenv("PING_LINE") -random_talk_channel_id1 = int(os.getenv("rnd_talk_channel1")) -LOCALE = os.getenv("locale") +LOCALE = os.getenv("locale", "en") gooberTOKEN = os.getenv("gooberTOKEN") -random_talk_channel_id2 = int(os.getenv("rnd_talk_channel2")) cooldown_time = os.getenv("cooldown") splashtext = os.getenv("splashtext") -ownerid = int(os.getenv("ownerid")) +ownerid = int(os.getenv("ownerid", "0")) showmemenabled = os.getenv("showmemenabled") BLACKLISTED_USERS = os.getenv("BLACKLISTED_USERS", "").split(",") USERTRAIN_ENABLED = os.getenv("USERTRAIN_ENABLED", "true").lower() == "true" NAME = os.getenv("NAME") -last_random_talk_time = 0 MEMORY_FILE = "memory.json" DEFAULT_DATASET_FILE = "defaultdataset.json" MEMORY_LOADED_FILE = "MEMORY_LOADED" diff --git a/modules/image.py b/modules/image.py index bbce31c..ed71ae0 100644 --- a/modules/image.py +++ b/modules/image.py @@ -45,6 +45,7 @@ async def gen_image(sentence_size=5, max_attempts=10): midpoint = len(words)//2 return " ".join(words[:midpoint]), " ".join(words[midpoint:]) + coherent_response = "no text generated" attempt = 0 while attempt < max_attempts: chosen_image_path = os.path.join(images_folder, random.choice(image_files)) @@ -97,8 +98,7 @@ async def gen_image(sentence_size=5, max_attempts=10): if top_height <= max_text_height and bottom_height <= max_text_height: # top text draw_text_with_outline(draw, top_text, (width - (top_bbox[2]-top_bbox[0])) / 2, 0, font) - # bottom text - y_bottom = height - bottom_height + y_bottom = height - bottom_height - int(height * 0.04) draw_text_with_outline(draw, bottom_text, (width - (bottom_bbox[2]-bottom_bbox[0])) / 2, y_bottom, font) img.save("output.png") return diff --git a/modules/prestartchecks.py b/modules/prestartchecks.py index 8bd73e0..1fb3073 100644 --- a/modules/prestartchecks.py +++ b/modules/prestartchecks.py @@ -3,13 +3,15 @@ import os import sys import subprocess import ast +import json +# import shutil psutilavaliable = True try: import requests import psutil except ImportError: psutilavaliable = False - print("Missing Requests! and Psutil!") + print("Missing requests and psutil! Please install them using pip: `pip install requests psutil`") import re import importlib.metadata @@ -169,33 +171,47 @@ def check_memory(): def check_cpu(): if psutilavaliable == False: return - print("Measuring CPU usage per core...") - cpu_per_core = psutil.cpu_percent(interval=1, percpu=True) - for idx, core_usage in enumerate(cpu_per_core): - bar_length = int(core_usage / 5) - bar = '█' * bar_length + '-' * (20 - bar_length) - if core_usage > 85: - color = RED - elif core_usage > 60: - color = YELLOW - else: - color = GREEN - print(f"Core {idx}: {color}[{bar}] {core_usage:.2f}%{RESET}") + print("Measuring CPU usage per core...") + cpu_per_core = psutil.cpu_percent(interval=1, percpu=True) + for idx, core_usage in enumerate(cpu_per_core): + bar_length = int(core_usage / 5) + bar = '█' * bar_length + '-' * (20 - bar_length) + if core_usage > 85: + color = RED + elif core_usage > 60: + color = YELLOW + else: + color = GREEN + print(f"Core {idx}: {color}[{bar}] {core_usage:.2f}%{RESET}") - total_cpu = sum(cpu_per_core) / len(cpu_per_core) - print(f"Total CPU Usage: {total_cpu:.2f}%") + total_cpu = sum(cpu_per_core) / len(cpu_per_core) + print(f"Total CPU Usage: {total_cpu:.2f}%") - if total_cpu > 85: - print(f"{YELLOW}High average CPU usage: {total_cpu:.2f}%{RESET}") - if total_cpu > 95: - print(f"{RED}Really high CPU load! System may throttle or hang.{RESET}") - sys.exit(1) + if total_cpu > 85: + print(f"{YELLOW}High average CPU usage: {total_cpu:.2f}%{RESET}") + if total_cpu > 95: + print(f"{RED}Really high CPU load! System may throttle or hang.{RESET}") + sys.exit(1) def check_memoryjson(): try: print(f"Memory file: {os.path.getsize(MEMORY_FILE) / (1024 ** 2):.2f} MB") if os.path.getsize(MEMORY_FILE) > 1_073_741_824: print(f"{YELLOW}Memory file is 1GB or higher, consider clearing it to free up space.{RESET}") + + # Check for corrupted memory.json file + try: + with open(MEMORY_FILE, 'r', encoding='utf-8') as f: + json.load(f) + except json.JSONDecodeError as e: + print(f"{RED}Memory file is corrupted! JSON decode error: {e}{RESET}") + print(f"{YELLOW}Consider backing up and recreating the memory file.{RESET}") + except UnicodeDecodeError as e: + print(f"{RED}Memory file has encoding issues: {e}{RESET}") + print(f"{YELLOW}Consider backing up and recreating the memory file.{RESET}") + except Exception as e: + print(f"{RED}Error reading memory file: {e}{RESET}") + except FileNotFoundError: print(f"{YELLOW}Memory file not found.{RESET}") @@ -232,13 +248,18 @@ def presskey2skip(timeout): termios.tcsetattr(fd, termios.TCSADRAIN, old_settings) def start_checks(): - print("Running pre-start checks...") - check_requirements() - check_latency() - check_memory() - check_memoryjson() - check_cpu() - print("Continuing in 5 seconds... Press any key to skip.") - presskey2skip(5) - os.system('cls' if os.name == 'nt' else 'clear') - print(splashtext) \ No newline at end of file + print("Running pre-start checks...") + check_requirements() + check_latency() + check_memory() + check_memoryjson() + check_cpu() + print("Continuing in 5 seconds... Press any key to skip.") + presskey2skip(timeout=5) + + os.system('cls' if os.name == 'nt' else 'clear') + + # i decided to experiment with this instead of the above line but it doesn't work too well so that's why i'm not using it + # print("\n" * (shutil.get_terminal_size(fallback=(80, 24))).lines, end="") + + print(splashtext) \ No newline at end of file diff --git a/modules/version.py b/modules/version.py index e93ea3f..2dd5cf7 100644 --- a/modules/version.py +++ b/modules/version.py @@ -1,7 +1,5 @@ -import hashlib from modules.translations import * from modules.globalvars import * -import traceback import requests import subprocess import sys