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
2025-07-23 15:42:13 +03:00
from modules . settings import instance as settings_manager
2025-07-27 12:24:51 +03:00
from modules . sync_conenctor import instance as sync_hub
2025-07-23 10:19:08 +03:00
2025-07-22 19:32:19 +03:00
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-23 10:19:08 +03: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-23 10:19:08 +03:00
2025-07-06 21:45:30 +02:00
def iscloned ( ) :
if os . path . exists ( " .git " ) :
return True
else :
2025-07-23 10:19:08 +03:00
logger . error ( f " { k . not_cloned ( ) } " )
2025-07-06 21:45:30 +02:00
sys . exit ( 1 )
2025-07-23 10:19:08 +03:00
2025-07-06 21:06:04 +02:00
def get_stdlib_modules ( ) :
2025-07-23 10:19:08 +03:00
stdlib_path = pathlib . Path ( sysconfig . get_paths ( ) [ " stdlib " ] )
2025-07-06 21:06:04 +02:00
modules = set ( )
2025-07-23 10:19:08 +03:00
if hasattr ( sys , " builtin_module_names " ) :
2025-07-06 21:06:04 +02:00
modules . update ( sys . builtin_module_names )
2025-07-23 10:19:08 +03:00
for file in stdlib_path . glob ( " *.py " ) :
if file . stem != " __init__ " :
2025-07-06 21:06:04 +02:00
modules . add ( file . stem )
for folder in stdlib_path . iterdir ( ) :
2025-07-23 10:19:08 +03:00
if folder . is_dir ( ) and ( folder / " __init__.py " ) . exists ( ) :
2025-07-06 21:06:04 +02:00
modules . add ( folder . name )
2025-07-23 10:19:08 +03:00
for file in stdlib_path . glob ( " *.* " ) :
if file . suffix in ( " .so " , " .pyd " ) :
2025-07-06 21:06:04 +02:00
modules . add ( file . stem )
return modules
2025-06-22 20:49:07 +02:00
2025-07-23 10:19:08 +03:00
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 " ,
2025-07-23 10:19:08 +03:00
" pil " : " pillow " ,
2025-07-27 12:24:51 +03:00
" websocket " : " websocket-client "
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-23 10:19:08 +03: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-07-23 10:19:08 +03:00
with open ( requirements_path , " r " ) as f :
2025-06-22 20:49:07 +02:00
lines = f . readlines ( )
2025-07-16 14:39:18 +02:00
requirements = set ( )
for line in lines :
line = line . strip ( )
2025-07-23 10:19:08 +03:00
if line and not line . startswith ( " # " ) :
base_pkg = line . split ( " == " ) [ 0 ] . lower ( )
2025-07-16 14:39:18 +02:00
aliased_pkg = PACKAGE_ALIASES . get ( base_pkg , base_pkg )
requirements . add ( aliased_pkg )
2025-06-22 20:55:13 +02:00
2025-07-23 10:19:08 +03: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 ) :
2025-07-23 10:19:08 +03:00
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
2025-07-23 10:19:08 +03:00
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 (
2025-07-23 10:19:08 +03:00
cmd , stdout = subprocess . PIPE , stderr = subprocess . PIPE , text = True
2025-06-23 13:56:23 +02:00
)
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
2025-07-23 10:19:08 +03:00
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-07-23 10:19:08 +03:00
total_memory = memory_info . total / ( 1024 * * 3 )
used_memory = memory_info . used / ( 1024 * * 3 )
free_memory = memory_info . available / ( 1024 * * 3 )
2025-06-22 20:49:07 +02:00
2025-07-23 10:19:08 +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-23 10:19:08 +03:00
print (
f " { YELLOW } { k . memory_above_90 ( percent = ( used_memory / total_memory ) * 100 ) } { RESET } "
)
2025-07-22 19:32:19 +03:00
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-07-26 13:23:08 +03:00
2025-06-22 20:49:07 +02:00
except ImportError :
2025-07-23 10:19:08 +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-07-23 14:51:57 +03:00
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-07-23 14:51:57 +03:00
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-07-23 10:19:08 +03:00
2025-06-22 20:49:07 +02:00
def check_memoryjson ( ) :
try :
2025-07-23 10:19:08 +03:00
logger . info (
k . memory_file (
size = os . path . getsize ( settings [ " bot " ] [ " active_memory " ] ) / ( 1024 * * 2 )
)
)
2025-07-22 19:32:19 +03:00
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-23 10:19:08 +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 )
2025-07-23 14:51:57 +03:00
2025-06-28 16:56:05 -04:00
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-07-23 14:51:57 +03:00
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-07-23 14:51:57 +03:00
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
2025-07-23 10:19:08 +03:00
2025-06-22 20:49:07 +02:00
def presskey2skip ( timeout ) :
2025-07-23 10:19:08 +03:00
if os . name == " nt " :
2025-06-22 20:49:07 +02:00
import msvcrt
2025-07-23 10:19:08 +03:00
2025-06-22 20:49:07 +02:00
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-23 10:19:08 +03:00
2025-07-27 12:24:51 +03:00
def check_synchub ( ) :
if not sync_hub . connected :
logger . warning ( " Sync hub not connected properly! The bot will not be able to react to messages, or create breaking news unless you disable synchub in settings " )
else :
logger . info ( " Sync hub is conencted " )
2025-07-23 10:19:08 +03:00
2025-07-05 20:15:54 +02:00
beta = beta
2025-07-23 10:19:08 +03:00
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-23 10:19:08 +03:00
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-27 12:24:51 +03:00
check_synchub ( )
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-23 10:19:08 +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 )
2025-07-23 10:19:08 +03:00
os . system ( " cls " if os . name == " nt " else " clear " )
2025-07-22 19:32:19 +03:00
2025-07-23 10:19:08 +03:00
with open ( settings [ " splash_text_loc " ] , " r " ) as f :
2025-07-22 19:32:19 +03:00
print ( " " . join ( f . readlines ( ) ) )