-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathmain.py
More file actions
199 lines (169 loc) · 6.75 KB
/
main.py
File metadata and controls
199 lines (169 loc) · 6.75 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
import asyncio
import datetime
import json
import logging
import os
import signal
from pathlib import Path
import utils.ressources as ressources
from api.api import start_api_async
from bots.admin_bot import run_admin_bot
from bots.bot import run_bot
from bots.logger_bot import run_logger_bot
from bots.sec_bots import run_addon_bots
from config import LOGGER_NAME
from logger import close_logging, setup_logging
from utils.database.db_manager import DatabaseManager
from utils.discord_utils.status import status_emulation
from utils.func_calling import initialize_function_caller
from utils.memory import initialize_memory_manager
from utils.ressources import start_monitoring, stop_monitoring
from utils.uptime_monitor import get_uptime_monitor
shutdown_event = asyncio.Event()
db_manager = DatabaseManager()
RUN_API = True
RUN_LOGGER_BOT = True
RUN_MAIN_BOT = True
RUN_ADMIN_BOT = True
RUN_SEC_BOTS = True
logging.basicConfig(level=logging.CRITICAL)
async def check_stop_file(restart_pending):
"""Vérifie périodiquement la présence du fichier stop.json"""
logger = logging.getLogger(LOGGER_NAME)
while not shutdown_event.is_set():
if Path("stop.json").exists():
try:
with open(Path("stop.json"), "r") as f:
data = json.load(f)
command = data.get("COMMAND")
if command == "STOP":
logger.info("Commande STOP détectée, arrêt en cours...")
shutdown_event.set()
elif command == "RESTART":
logger.info("Commande RESTART détectée, redémarrage en cours...")
shutdown_event.set()
restart_pending[0] = True
os.remove(Path("stop.json"))
break
except Exception as e:
logger.error(f"Erreur lors de la lecture du fichier stop.json: {e}")
await asyncio.sleep(1)
def handle_shutdown_signal(signum, frame):
"""Gestionnaire de signal pour arrêt propre"""
logger = logging.getLogger(LOGGER_NAME)
logger.debug(f"Signal {signum} reçu, arrêt en cours...")
shutdown_event.set()
async def run_with_shutdown(coro, name="task"):
"""Execute une coroutine et l'annule quand shutdown_event est set"""
logger = logging.getLogger(LOGGER_NAME)
logger.debug(f"Création de la tâche: {name}")
task = asyncio.create_task(coro)
done, pending = await asyncio.wait(
[task, asyncio.create_task(shutdown_event.wait())],
return_when=asyncio.FIRST_COMPLETED,
)
if task in done:
logger.info(f"Tâche {name} terminée")
if task.exception():
logger.error(f"Tâche {name} a levé une exception: {task.exception()}")
else:
logger.info(f"Tâche {name} terminée normalement")
if shutdown_event.is_set():
logger.debug(f"Arrêt de la tâche: {name}")
task.cancel()
try:
await asyncio.wait_for(task, timeout=2.0)
except asyncio.CancelledError:
logger.debug(f"Tâche {name} annulée proprement")
except asyncio.TimeoutError:
logger.warning(f"Tâche {name} n'a pas pu se terminer dans le délai")
except Exception as e:
logger.error(f"Erreur lors de l'arrêt de {name}: {e}")
return task.result() if task.done() and not task.cancelled() else None
async def main() -> None:
if Path("stop.json").exists():
try:
with open(Path("stop.json"), "r") as f:
data = json.load(f)
command = data.get("COMMAND")
if command == "STOP":
os.remove(Path("stop.json"))
return
elif command == "RESTART":
os.remove(Path("stop.json"))
except Exception as e:
logger = logging.getLogger(LOGGER_NAME)
logger.error(
f"Erreur lors de la lecture du fichier stop.json au démarrage: {e}"
)
restart_pending = [False]
while True:
shutdown_event.clear()
# Créer le dossier data s'il n'existe pas
data_dir = Path("data")
data_dir.mkdir(exist_ok=True)
setup_logging()
logger = logging.getLogger(LOGGER_NAME)
logger.info(f"Booting {LOGGER_NAME}")
signal.signal(signal.SIGTERM, handle_shutdown_signal)
signal.signal(signal.SIGINT, handle_shutdown_signal)
try:
ressources._monitor_instance = None
csv_file = "data/monitoring.csv"
logger.debug("Démarrage du monitoring des ressources...")
monitor = start_monitoring(interval=1.0, csv_file=csv_file)
logger.debug("Démarrage du monitoring d'uptime...")
uptime_monitor = get_uptime_monitor()
uptime_monitor.start()
monitor.fill_gaps(datetime.datetime.now())
await asyncio.gather(
initialize_memory_manager(), initialize_function_caller()
)
logger.debug("Initialisation de la base de données...")
await db_manager.initialize()
await db_manager.clone_tables()
tasks = [
(
run_with_shutdown(run_logger_bot(), "Logger Bot")
if RUN_LOGGER_BOT
else asyncio.sleep(0)
),
(
run_with_shutdown(run_bot(), "Main Bot")
if RUN_MAIN_BOT
else asyncio.sleep(0)
),
(
run_with_shutdown(run_admin_bot(), "Admin Bot")
if RUN_ADMIN_BOT
else asyncio.sleep(0)
),
(
run_with_shutdown(run_addon_bots(), "Sec Bots")
if RUN_SEC_BOTS
else asyncio.sleep(0)
),
(
run_with_shutdown(start_api_async(), "API Server")
if RUN_API
else asyncio.sleep(0)
),
run_with_shutdown(
check_stop_file(restart_pending), "Stop-File Checker"
),
run_with_shutdown(status_emulation(shutdown_event), "Status Emulation"),
]
await asyncio.gather(*tasks, return_exceptions=True)
except (SystemExit, KeyboardInterrupt):
logger.info("Arrêt complet du programme.")
finally:
try:
stop_monitoring()
uptime_monitor = get_uptime_monitor()
uptime_monitor.stop()
close_logging()
except Exception as e:
logger.warning(f"Erreur lors de l'arrêt du monitoring: {e}")
break
if __name__ == "__main__":
asyncio.run(main())