2025-07-01 16:21:34 +02:00
from modules . globalvars import *
2025-06-22 20:49:07 +02:00
import time
import os
import sys
import subprocess
2025-07-06 21:06:04 +02:00
import sysconfig
2025-06-22 20:49:07 +02:00
import ast
2025-06-28 16:56:05 -04:00
import json
2025-07-06 21:06:04 +02:00
import re
2025-07-07 17:17:44 +02:00
from spacy . util import is_package
2025-07-06 21:06:04 +02:00
import importlib . metadata
2025-07-08 17:02:10 +03:00
import logging
2025-07-22 19:32:19 +03:00
import modules . keys as k
from modules . settings import Settings as SettingsManager
settings_manager = SettingsManager ( )
settings = settings_manager . settings
2025-07-08 17:02:10 +03:00
logger = logging . getLogger ( " goober " )
2025-07-06 21:06:04 +02:00
2025-06-28 16:56:05 -04:00
# import shutil
2025-06-27 19:45:44 +02:00
psutilavaliable = True
try :
import requests
import psutil
except ImportError :
psutilavaliable = False
2025-07-22 19:32:19 +03:00
logger . error ( k . missing_requests_psutil ( ) )
2025-07-01 16:21:34 +02:00
2025-07-07 17:17:44 +02:00
def check_for_model ( ) :
if is_package ( " en_core_web_sm " ) :
2025-07-08 17:02:10 +03:00
logger . info ( " Model is installed. " )
2025-07-07 17:17:44 +02:00
else :
2025-07-08 17:02:10 +03:00
logger . info ( " Model is not installed. " )
2025-07-07 17:17:44 +02:00
2025-07-06 21:45:30 +02:00
def iscloned ( ) :
if os . path . exists ( " .git " ) :
return True
else :
2025-07-22 19:32:19 +03:00
logger . error ( f " { k . not_cloned ( ) } " )
2025-07-06 21:45:30 +02:00
sys . exit ( 1 )
2025-07-06 21:06:04 +02:00
def get_stdlib_modules ( ) :
stdlib_path = pathlib . Path ( sysconfig . get_paths ( ) [ ' stdlib ' ] )
modules = set ( )
if hasattr ( sys , ' builtin_module_names ' ) :
modules . update ( sys . builtin_module_names )
for file in stdlib_path . glob ( ' *.py ' ) :
if file . stem != ' __init__ ' :
modules . add ( file . stem )
for folder in stdlib_path . iterdir ( ) :
if folder . is_dir ( ) and ( folder / ' __init__.py ' ) . exists ( ) :
modules . add ( folder . name )
for file in stdlib_path . glob ( ' *.* ' ) :
if file . suffix in ( ' .so ' , ' .pyd ' ) :
modules . add ( file . stem )
return modules
2025-06-22 20:49:07 +02:00
def check_requirements ( ) :
2025-07-06 21:06:04 +02:00
STD_LIB_MODULES = get_stdlib_modules ( )
2025-06-22 20:49:07 +02:00
PACKAGE_ALIASES = {
" discord " : " discord.py " ,
2025-06-22 20:55:13 +02:00
" better_profanity " : " better-profanity " ,
2025-07-16 14:39:18 +02:00
" dotenv " : " python-dotenv " ,
" pil " : " pillow "
2025-06-22 20:49:07 +02:00
}
2025-06-22 20:55:13 +02:00
2025-06-22 20:49:07 +02:00
parent_dir = os . path . dirname ( os . path . abspath ( __file__ ) )
2025-07-06 21:06:04 +02:00
requirements_path = os . path . abspath ( os . path . join ( parent_dir , ' .. ' , ' requirements.txt ' ) )
2025-06-22 20:55:13 +02:00
2025-06-22 20:49:07 +02:00
if not os . path . exists ( requirements_path ) :
2025-07-22 19:32:19 +03:00
logger . error ( f " { k . requirements_not_found ( path = requirements_path ) } " )
2025-06-22 20:49:07 +02:00
return
2025-06-22 20:55:13 +02:00
2025-06-22 20:49:07 +02:00
with open ( requirements_path , ' r ' ) as f :
lines = f . readlines ( )
2025-07-16 14:39:18 +02:00
requirements = set ( )
for line in lines :
line = line . strip ( )
if line and not line . startswith ( ' # ' ) :
base_pkg = line . split ( ' == ' ) [ 0 ] . lower ( )
aliased_pkg = PACKAGE_ALIASES . get ( base_pkg , base_pkg )
requirements . add ( aliased_pkg )
2025-06-22 20:55:13 +02:00
installed_packages = { dist . metadata [ ' Name ' ] . lower ( ) for dist in importlib . metadata . distributions ( ) }
2025-06-22 20:49:07 +02:00
missing = [ ]
2025-06-22 20:55:13 +02:00
2025-06-22 20:49:07 +02:00
for req in sorted ( requirements ) :
if req in STD_LIB_MODULES or req == ' modules ' :
2025-07-22 19:32:19 +03:00
print ( k . std_lib_local_skipped ( package = req ) )
2025-06-22 20:49:07 +02:00
continue
2025-06-22 20:55:13 +02:00
2025-07-16 14:39:18 +02:00
check_name = req . lower ( )
2025-06-22 20:55:13 +02:00
if check_name in installed_packages :
2025-07-22 19:32:19 +03:00
logger . info ( f " { k . ok_installed ( ) } { check_name } " )
2025-06-22 20:55:13 +02:00
else :
2025-07-22 19:32:19 +03:00
logger . error ( f " { k . missing_package ( ) } { check_name } { k . missing_package2 ( ) } " )
2025-06-22 20:49:07 +02:00
missing . append ( check_name )
2025-06-22 20:55:13 +02:00
2025-06-22 20:49:07 +02:00
if missing :
2025-07-22 19:32:19 +03:00
logger . error ( k . missing_packages_detected ( ) )
2025-06-22 20:49:07 +02:00
for pkg in missing :
print ( f " - { pkg } " )
sys . exit ( 1 )
else :
2025-07-22 19:32:19 +03:00
logger . info ( k . all_requirements_satisfied ( ) )
2025-06-22 20:49:07 +02:00
def check_latency ( ) :
2025-06-23 13:56:23 +02:00
host = " 1.1.1.1 "
system = platform . system ( )
2025-07-16 14:39:18 +02:00
2025-06-23 13:56:23 +02:00
if system == " Windows " :
cmd = [ " ping " , " -n " , " 1 " , " -w " , " 1000 " , host ]
latency_pattern = r " Average = ( \ d+)ms "
2025-07-16 14:39:18 +02:00
elif system == " Darwin " :
cmd = [ " ping " , " -c " , " 1 " , host ]
latency_pattern = r " time=([ \ d \ .]+) ms "
2025-06-22 20:49:07 +02:00
else :
2025-06-23 13:56:23 +02:00
cmd = [ " ping " , " -c " , " 1 " , " -W " , " 1 " , host ]
2025-07-16 14:39:18 +02:00
latency_pattern = r " time=([ \ d \ .]+) ms "
2025-06-23 13:56:23 +02:00
try :
result = subprocess . run (
cmd ,
stdout = subprocess . PIPE ,
stderr = subprocess . PIPE ,
text = True
)
if result . returncode == 0 :
match = re . search ( latency_pattern , result . stdout )
if match :
latency_ms = float ( match . group ( 1 ) )
2025-07-22 19:32:19 +03:00
logger . info ( k . ping_to ( host = host , latency = latency_ms ) )
2025-06-23 13:56:23 +02:00
if latency_ms > 300 :
2025-07-22 19:32:19 +03:00
logger . warning ( f " { k . high_latency ( ) } " )
2025-06-23 13:56:23 +02:00
else :
2025-07-22 19:32:19 +03:00
logger . warning ( k . could_not_parse_latency ( ) )
2025-06-23 13:56:23 +02:00
else :
print ( result . stderr )
2025-07-22 19:32:19 +03:00
logger . error ( f " { k . ping_failed ( host = host ) } { RESET } " )
2025-06-23 13:56:23 +02:00
except Exception as e :
2025-07-22 19:32:19 +03:00
logger . error ( k . error_running_ping ( error = e ) )
2025-06-22 20:49:07 +02:00
def check_memory ( ) :
2025-06-27 19:45:44 +02:00
if psutilavaliable == False :
return
2025-06-22 20:49:07 +02:00
try :
2025-07-07 20:41:24 +02:00
memory_info = psutil . virtual_memory ( ) # type: ignore
2025-06-22 20:49:07 +02:00
total_memory = memory_info . total / ( 1024 * * 3 )
used_memory = memory_info . used / ( 1024 * * 3 )
free_memory = memory_info . available / ( 1024 * * 3 )
2025-07-22 19:32:19 +03:00
logger . info ( k . memory_usage ( used = used_memory , total = total_memory , percent = ( used_memory / total_memory ) * 100 ) )
2025-06-22 20:49:07 +02:00
if used_memory > total_memory * 0.9 :
2025-07-22 19:32:19 +03:00
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 ) )
2025-06-22 20:49:07 +02:00
if free_memory < 1 :
2025-07-22 19:32:19 +03:00
logger . warning ( f " { k . low_free_memory ( free = free_memory ) } " )
2025-06-22 20:49:07 +02:00
sys . exit ( 1 )
except ImportError :
2025-07-22 19:32:19 +03:00
logger . error ( k . psutil_not_installed ( ) ) # todo: translate this into italian and put it in the translations "psutil is not installed. Memory check skipped."
2025-06-22 20:49:07 +02:00
2025-06-22 23:08:33 +02:00
def check_cpu ( ) :
2025-06-27 19:45:44 +02:00
if psutilavaliable == False :
return
2025-07-22 19:32:19 +03:00
logger . info ( k . measuring_cpu ( ) )
2025-07-07 20:41:24 +02:00
cpu_per_core = psutil . cpu_percent ( interval = 1 , percpu = True ) # type: ignore
2025-06-28 16:56:05 -04:00
total_cpu = sum ( cpu_per_core ) / len ( cpu_per_core )
2025-07-22 19:32:19 +03:00
logger . info ( k . total_cpu_usage ( usage = total_cpu ) )
2025-06-28 16:56:05 -04:00
if total_cpu > 85 :
2025-07-22 19:32:19 +03:00
logger . warning ( f " { k . high_avg_cpu ( usage = total_cpu ) } " )
2025-06-28 16:56:05 -04:00
if total_cpu > 95 :
2025-07-22 19:32:19 +03:00
logger . error ( k . really_high_cpu ( ) )
2025-06-28 16:56:05 -04:00
sys . exit ( 1 )
2025-06-22 23:08:33 +02:00
2025-06-22 20:49:07 +02:00
def check_memoryjson ( ) :
try :
2025-07-22 19:32:19 +03:00
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 ( ) } " )
2025-06-28 16:56:05 -04:00
try :
2025-07-22 19:32:19 +03:00
with open ( settings [ " bot " ] [ " active_memory " ] , ' r ' , encoding = ' utf-8 ' ) as f :
2025-06-28 16:56:05 -04:00
json . load ( f )
except json . JSONDecodeError as e :
2025-07-22 19:32:19 +03:00
logger . error ( f " { k . memory_file_corrupted ( error = e ) } " )
logger . warning ( f " { k . consider_backup_memory ( ) } " )
2025-06-28 16:56:05 -04:00
except UnicodeDecodeError as e :
2025-07-22 19:32:19 +03:00
logger . error ( f " { k . memory_file_encoding ( error = e ) } " )
logger . warning ( f " { k . consider_backup_memory ( ) } " )
2025-06-28 16:56:05 -04:00
except Exception as e :
2025-07-22 19:32:19 +03:00
logger . error ( f " { k . error_reading_memory ( error = e ) } " )
2025-06-22 20:49:07 +02:00
except FileNotFoundError :
2025-07-22 19:32:19 +03:00
logger . info ( f " { k . memory_file_not_found ( ) } " )
2025-06-22 20:49:07 +02:00
def presskey2skip ( timeout ) :
if os . name == ' nt ' :
import msvcrt
start_time = time . time ( )
while True :
if msvcrt . kbhit ( ) :
msvcrt . getch ( )
break
if time . time ( ) - start_time > timeout :
break
time . sleep ( 0.1 )
else :
import select
import sys
import termios
import tty
fd = sys . stdin . fileno ( )
old_settings = termios . tcgetattr ( fd )
try :
tty . setcbreak ( fd )
start_time = time . time ( )
while True :
if select . select ( [ sys . stdin ] , [ ] , [ ] , 0 ) [ 0 ] :
sys . stdin . read ( 1 )
break
if time . time ( ) - start_time > timeout :
break
time . sleep ( 0.1 )
finally :
termios . tcsetattr ( fd , termios . TCSADRAIN , old_settings )
2025-07-05 20:15:54 +02:00
beta = beta
2025-06-22 20:49:07 +02:00
def start_checks ( ) :
2025-07-22 19:32:19 +03:00
if settings [ " disable_checks " ] :
logger . warning ( f " { k . checks_disabled ( ) } " )
2025-07-05 20:15:54 +02:00
return
2025-07-22 19:32:19 +03:00
logger . info ( k . running_prestart_checks ( ) )
2025-07-07 17:17:44 +02:00
check_for_model ( )
2025-07-06 21:45:30 +02:00
iscloned ( )
2025-06-28 16:56:05 -04:00
check_requirements ( )
check_latency ( )
check_memory ( )
check_memoryjson ( )
check_cpu ( )
2025-07-01 23:22:38 +02:00
if os . path . exists ( " .env " ) :
pass
else :
2025-07-22 19:32:19 +03:00
logger . warning ( f " { k . env_file_not_found ( ) } " )
2025-07-01 23:22:38 +02:00
sys . exit ( 1 )
2025-07-05 20:15:54 +02:00
if beta == True :
2025-07-08 17:02:10 +03:00
logger . warning ( f " this build isnt finished yet, some things might not work as expected " )
2025-07-05 20:15:54 +02:00
else :
pass
2025-07-22 19:32:19 +03:00
logger . info ( k . continuing_in_seconds ( seconds = 5 ) )
2025-06-28 16:56:05 -04:00
presskey2skip ( timeout = 5 )
os . system ( ' cls ' if os . name == ' nt ' else ' clear ' )
2025-07-22 19:32:19 +03:00
with open ( settings [ " splash_text_loc " ] , " r " ) as f :
print ( " " . join ( f . readlines ( ) ) )