update
This commit is contained in:
+276
-7
@@ -25,6 +25,10 @@ class BotController:
|
||||
self.bots = {} # Stockage des instances de bots (pour l'utilisation interne)
|
||||
self.flux_list = [] # Liste des flux surveillés (pour l'API JSON)
|
||||
self.config = self.load_config()
|
||||
self.ia_generator = None
|
||||
self.control_twitch = None
|
||||
self.ia_generator_running = False
|
||||
self.control_twitch_running = False
|
||||
|
||||
def load_config(self):
|
||||
try:
|
||||
@@ -37,6 +41,21 @@ class BotController:
|
||||
with open('config/config.json', 'w') as file:
|
||||
json.dump(self.config, file, indent=4, ensure_ascii=False)
|
||||
|
||||
def get_system_status(self):
|
||||
"""Obtenir le statut de tous les composants"""
|
||||
return {
|
||||
'ia_generator': {
|
||||
'running': self.ia_generator_running,
|
||||
'status': 'En cours' if self.ia_generator_running else 'Arrêté'
|
||||
},
|
||||
'control_twitch': {
|
||||
'running': self.control_twitch_running,
|
||||
'status': 'En cours' if self.control_twitch_running else 'Arrêté'
|
||||
},
|
||||
'flux_count': len(self.flux_list),
|
||||
'active_flux': len([f for f in self.flux_list if f['active']])
|
||||
}
|
||||
|
||||
def add_flux(self, channel_name, record_audio=True):
|
||||
flux_id = len(self.flux_list) + 1
|
||||
|
||||
@@ -140,6 +159,112 @@ class BotController:
|
||||
# Retourner seulement les données JSON (pas les instances de bots)
|
||||
return self.flux_list
|
||||
|
||||
def start_ia_generator(self):
|
||||
"""Démarrer le générateur IA de manière contrôlée"""
|
||||
if self.ia_generator_running:
|
||||
return False, "IA Generator déjà en cours d'exécution"
|
||||
|
||||
try:
|
||||
self.ia_generator = IA_generator("config/config.json")
|
||||
self.ia_generator_running = True
|
||||
|
||||
# Activer l'envoi de messages quand l'IA Generator est démarré
|
||||
global chat_messages_enabled
|
||||
chat_messages_enabled = True
|
||||
|
||||
# Démarrer dans un thread séparé
|
||||
threading.Thread(target=self._ia_generator_loop, daemon=True).start()
|
||||
|
||||
print(f"[{datetime.now().strftime('%H:%M:%S')}] IA Generator démarré")
|
||||
return True, "IA Generator démarré avec succès"
|
||||
except Exception as e:
|
||||
self.ia_generator_running = False
|
||||
return False, f"Erreur lors du démarrage de l'IA Generator: {str(e)}"
|
||||
|
||||
def stop_ia_generator(self):
|
||||
"""Arrêter le générateur IA"""
|
||||
if not self.ia_generator_running:
|
||||
return False, "IA Generator n'est pas en cours d'exécution"
|
||||
|
||||
try:
|
||||
self.ia_generator_running = False
|
||||
if self.ia_generator:
|
||||
self.ia_generator.stop()
|
||||
|
||||
# Désactiver l'envoi de messages quand l'IA Generator est arrêté
|
||||
global chat_messages_enabled
|
||||
chat_messages_enabled = False
|
||||
|
||||
print(f"[{datetime.now().strftime('%H:%M:%S')}] IA Generator arrêté")
|
||||
return True, "IA Generator arrêté avec succès"
|
||||
except Exception as e:
|
||||
return False, f"Erreur lors de l'arrêt de l'IA Generator: {str(e)}"
|
||||
|
||||
def _ia_generator_loop(self):
|
||||
"""Boucle contrôlée pour l'IA Generator"""
|
||||
while self.ia_generator_running:
|
||||
try:
|
||||
if self.ia_generator:
|
||||
self.ia_generator.main_ask("") # Génération automatique
|
||||
time.sleep(20) # Attendre 20 secondes entre les générations
|
||||
except Exception as e:
|
||||
print(f"[{datetime.now().strftime('%H:%M:%S')}] Erreur dans IA Generator: {e}")
|
||||
time.sleep(10)
|
||||
|
||||
def start_control_twitch(self):
|
||||
"""Démarrer le contrôleur Twitch de manière contrôlée"""
|
||||
if self.control_twitch_running:
|
||||
return False, "Control Twitch déjà en cours d'exécution"
|
||||
|
||||
try:
|
||||
# Utiliser le premier utilisateur par défaut
|
||||
self.control_twitch = messageTwitch("config/user.json", "default")
|
||||
self.control_twitch_running = True
|
||||
|
||||
# Démarrer dans un thread séparé
|
||||
threading.Thread(target=self._control_twitch_loop, daemon=True).start()
|
||||
|
||||
print(f"[{datetime.now().strftime('%H:%M:%S')}] Control Twitch démarré")
|
||||
return True, "Control Twitch démarré avec succès"
|
||||
except Exception as e:
|
||||
self.control_twitch_running = False
|
||||
return False, f"Erreur lors du démarrage de Control Twitch: {str(e)}"
|
||||
|
||||
def stop_control_twitch(self):
|
||||
"""Arrêter le contrôleur Twitch"""
|
||||
if not self.control_twitch_running:
|
||||
return False, "Control Twitch n'est pas en cours d'exécution"
|
||||
|
||||
try:
|
||||
self.control_twitch_running = False
|
||||
if self.control_twitch:
|
||||
self.control_twitch.stop()
|
||||
print(f"[{datetime.now().strftime('%H:%M:%S')}] Control Twitch arrêté")
|
||||
return True, "Control Twitch arrêté avec succès"
|
||||
except Exception as e:
|
||||
return False, f"Erreur lors de l'arrêt de Control Twitch: {str(e)}"
|
||||
|
||||
def _control_twitch_loop(self):
|
||||
"""Boucle contrôlée pour Control Twitch"""
|
||||
while self.control_twitch_running:
|
||||
try:
|
||||
if self.control_twitch:
|
||||
# Vérifier s'il y a des générations à envoyer
|
||||
generation_data = storage.read("IA_generator")
|
||||
if generation_data:
|
||||
sorted_keys = sorted(generation_data.keys())
|
||||
if sorted_keys:
|
||||
last_generation = generation_data[sorted_keys[-1]]
|
||||
# Envoyer le message avec le premier utilisateur
|
||||
self.control_twitch.send_message_user(0, last_generation)
|
||||
# Supprimer la génération envoyée
|
||||
storage.delete("IA_generator", sorted_keys[-1])
|
||||
print(f"[{datetime.now().strftime('%H:%M:%S')}] Message envoyé: {last_generation[:50]}...")
|
||||
time.sleep(10) # Attendre 10 secondes entre les vérifications
|
||||
except Exception as e:
|
||||
print(f"[{datetime.now().strftime('%H:%M:%S')}] Erreur dans Control Twitch: {e}")
|
||||
time.sleep(10)
|
||||
|
||||
bot_controller = BotController()
|
||||
|
||||
@app.route('/')
|
||||
@@ -372,6 +497,33 @@ def get_subtitles():
|
||||
data = storage.read("subtitle_data")
|
||||
return jsonify(data)
|
||||
|
||||
@app.route('/api/subtitles/clear', methods=['POST'])
|
||||
def clear_subtitles():
|
||||
"""Nettoyer l'historique des sous-titres"""
|
||||
try:
|
||||
# Récupérer toutes les clés de sous-titres
|
||||
subtitle_data = storage.read("subtitle_data")
|
||||
|
||||
# Supprimer chaque clé une par une
|
||||
for key in list(subtitle_data.keys()):
|
||||
storage.delete("subtitle_data", key)
|
||||
|
||||
# Supprimer également le fichier JSON s'il existe
|
||||
storage_dir = "storage"
|
||||
subtitle_file = os.path.join(storage_dir, "subtitle_data.json")
|
||||
if os.path.exists(subtitle_file):
|
||||
os.remove(subtitle_file)
|
||||
|
||||
return jsonify({
|
||||
'success': True,
|
||||
'message': 'Historique des sous-titres nettoyé avec succès'
|
||||
})
|
||||
except Exception as e:
|
||||
return jsonify({
|
||||
'success': False,
|
||||
'error': f'Erreur lors du nettoyage: {str(e)}'
|
||||
}), 500
|
||||
|
||||
@app.route('/api/subtitles/process', methods=['POST'])
|
||||
def process_subtitles():
|
||||
"""Lancer manuellement le traitement des sous-titres"""
|
||||
@@ -643,21 +795,32 @@ auto_message_running = False
|
||||
current_message_bot = None
|
||||
|
||||
# Variable globale pour contrôler l'envoi de messages dans le chat
|
||||
chat_messages_enabled = True
|
||||
chat_messages_enabled = False
|
||||
|
||||
@app.route('/api/subtitles/auto/start', methods=['POST'])
|
||||
def start_auto_subtitle():
|
||||
"""Démarrer la génération automatique de sous-titres"""
|
||||
global auto_subtitle_running
|
||||
try:
|
||||
# Vérifier si déjà en cours
|
||||
if auto_subtitle_running:
|
||||
return jsonify({
|
||||
'success': False,
|
||||
'error': 'La génération automatique est déjà en cours'
|
||||
}), 400
|
||||
|
||||
auto_subtitle_running = True
|
||||
print(f"[{datetime.now().strftime('%H:%M:%S')}] Démarrage de la génération automatique de sous-titres")
|
||||
|
||||
# Démarrer le thread de génération automatique
|
||||
threading.Thread(target=auto_subtitle_loop, daemon=True).start()
|
||||
|
||||
return jsonify({
|
||||
'success': True,
|
||||
'message': 'Génération automatique démarrée'
|
||||
})
|
||||
except Exception as e:
|
||||
auto_subtitle_running = False
|
||||
return jsonify({
|
||||
'success': False,
|
||||
'error': f'Erreur lors du démarrage: {str(e)}'
|
||||
@@ -668,7 +831,15 @@ def stop_auto_subtitle():
|
||||
"""Arrêter la génération automatique de sous-titres"""
|
||||
global auto_subtitle_running
|
||||
try:
|
||||
if not auto_subtitle_running:
|
||||
return jsonify({
|
||||
'success': False,
|
||||
'error': 'La génération automatique n\'est pas en cours'
|
||||
}), 400
|
||||
|
||||
print(f"[{datetime.now().strftime('%H:%M:%S')}] Arrêt de la génération automatique de sous-titres")
|
||||
auto_subtitle_running = False
|
||||
|
||||
return jsonify({
|
||||
'success': True,
|
||||
'message': 'Génération automatique arrêtée'
|
||||
@@ -679,6 +850,25 @@ def stop_auto_subtitle():
|
||||
'error': f'Erreur lors de l\'arrêt: {str(e)}'
|
||||
}), 500
|
||||
|
||||
@app.route('/api/subtitles/auto/force-stop', methods=['POST'])
|
||||
def force_stop_auto_subtitle():
|
||||
"""Forcer l'arrêt de la génération automatique de sous-titres"""
|
||||
global auto_subtitle_running, current_processing_file
|
||||
try:
|
||||
print(f"[{datetime.now().strftime('%H:%M:%S')}] Arrêt forcé de la génération automatique de sous-titres")
|
||||
auto_subtitle_running = False
|
||||
current_processing_file = None
|
||||
|
||||
return jsonify({
|
||||
'success': True,
|
||||
'message': 'Arrêt forcé de la génération automatique de sous-titres'
|
||||
})
|
||||
except Exception as e:
|
||||
return jsonify({
|
||||
'success': False,
|
||||
'error': f'Erreur lors de l\'arrêt forcé: {str(e)}'
|
||||
}), 500
|
||||
|
||||
@app.route('/api/subtitles/auto/status', methods=['GET'])
|
||||
def get_auto_subtitle_status():
|
||||
"""Obtenir le statut de la génération automatique"""
|
||||
@@ -692,6 +882,8 @@ def auto_subtitle_loop():
|
||||
"""Boucle de génération automatique de sous-titres"""
|
||||
global auto_subtitle_running, current_processing_file
|
||||
|
||||
print(f"[{datetime.now().strftime('%H:%M:%S')}] Démarrage de la boucle de génération automatique de sous-titres")
|
||||
|
||||
while auto_subtitle_running:
|
||||
try:
|
||||
# Vérifier s'il y a des fichiers audio à traiter
|
||||
@@ -709,6 +901,8 @@ def auto_subtitle_loop():
|
||||
audio_file = audio_files[0]
|
||||
current_processing_file = audio_file
|
||||
|
||||
print(f"[{datetime.now().strftime('%H:%M:%S')}] Traitement de: {audio_file}")
|
||||
|
||||
# Émettre l'événement de début de traitement
|
||||
socketio.emit('subtitle_processing_start', {
|
||||
'file': audio_file,
|
||||
@@ -719,7 +913,7 @@ def auto_subtitle_loop():
|
||||
audio_path = os.path.join(record_dir, audio_file)
|
||||
|
||||
try:
|
||||
# Lancer Whisper
|
||||
# Lancer Whisper avec vérification périodique de l'arrêt
|
||||
command = [
|
||||
'whisper',
|
||||
'--language', 'fr',
|
||||
@@ -728,9 +922,30 @@ def auto_subtitle_loop():
|
||||
'--model', 'large-v3'
|
||||
]
|
||||
|
||||
result = subprocess.run(command, capture_output=True, text=True, timeout=60)
|
||||
# Utiliser Popen pour pouvoir interrompre le processus
|
||||
process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
|
||||
|
||||
if result.returncode == 0:
|
||||
# Attendre la fin du processus avec vérification périodique
|
||||
while process.poll() is None:
|
||||
if not auto_subtitle_running:
|
||||
print(f"[{datetime.now().strftime('%H:%M:%S')}] Arrêt demandé, interruption du processus Whisper")
|
||||
process.terminate()
|
||||
try:
|
||||
process.wait(timeout=5)
|
||||
except subprocess.TimeoutExpired:
|
||||
process.kill()
|
||||
break
|
||||
time.sleep(1)
|
||||
|
||||
# Si la boucle a été arrêtée, sortir
|
||||
if not auto_subtitle_running:
|
||||
print(f"[{datetime.now().strftime('%H:%M:%S')}] Arrêt de la boucle de génération automatique")
|
||||
break
|
||||
|
||||
result = process.returncode
|
||||
stdout, stderr = process.communicate()
|
||||
|
||||
if result == 0:
|
||||
# Lire le fichier .txt généré
|
||||
txt_file = audio_file.replace('.mp3', '.txt')
|
||||
if os.path.exists(txt_file):
|
||||
@@ -777,6 +992,8 @@ def auto_subtitle_loop():
|
||||
'timestamp': current_time
|
||||
})
|
||||
|
||||
print(f"[{datetime.now().strftime('%H:%M:%S')}] Sous-titre généré: {cleaned_content}")
|
||||
|
||||
# Nettoyer les fichiers temporaires
|
||||
os.remove(txt_file)
|
||||
os.remove(audio_path)
|
||||
@@ -787,38 +1004,49 @@ def auto_subtitle_loop():
|
||||
'file': audio_file,
|
||||
'error': 'Aucun fichier .txt généré'
|
||||
})
|
||||
print(f"[{datetime.now().strftime('%H:%M:%S')}] Erreur: Aucun fichier .txt généré")
|
||||
|
||||
else:
|
||||
# Émettre l'événement d'erreur
|
||||
socketio.emit('subtitle_processing_error', {
|
||||
'file': audio_file,
|
||||
'error': f'Erreur Whisper: {result.stderr}'
|
||||
'error': f'Erreur Whisper: {stderr}'
|
||||
})
|
||||
print(f"[{datetime.now().strftime('%H:%M:%S')}] Erreur Whisper: {stderr}")
|
||||
|
||||
except subprocess.TimeoutExpired:
|
||||
socketio.emit('subtitle_processing_error', {
|
||||
'file': audio_file,
|
||||
'error': 'Timeout - Whisper a pris trop de temps'
|
||||
})
|
||||
print(f"[{datetime.now().strftime('%H:%M:%S')}] Timeout - Whisper a pris trop de temps")
|
||||
except Exception as e:
|
||||
socketio.emit('subtitle_processing_error', {
|
||||
'file': audio_file,
|
||||
'error': f'Erreur: {str(e)}'
|
||||
})
|
||||
print(f"[{datetime.now().strftime('%H:%M:%S')}] Erreur lors du traitement: {str(e)}")
|
||||
|
||||
current_processing_file = None
|
||||
|
||||
# Vérifier à nouveau si la boucle doit continuer
|
||||
if not auto_subtitle_running:
|
||||
print(f"[{datetime.now().strftime('%H:%M:%S')}] Arrêt de la boucle de génération automatique")
|
||||
break
|
||||
|
||||
# Attendre avant de traiter le prochain fichier
|
||||
time.sleep(2)
|
||||
|
||||
except Exception as e:
|
||||
print(f"Erreur dans la boucle de génération automatique: {e}")
|
||||
print(f"[{datetime.now().strftime('%H:%M:%S')}] Erreur dans la boucle de génération automatique: {e}")
|
||||
time.sleep(5)
|
||||
|
||||
print(f"[{datetime.now().strftime('%H:%M:%S')}] Fin de la boucle de génération automatique de sous-titres")
|
||||
|
||||
@app.route('/api/messages/auto/start', methods=['POST'])
|
||||
def start_auto_message():
|
||||
"""Démarrer l'envoi automatique de messages"""
|
||||
global auto_message_running, current_message_bot
|
||||
global auto_message_running
|
||||
try:
|
||||
# Vérifier si déjà en cours
|
||||
if auto_message_running:
|
||||
@@ -1013,6 +1241,47 @@ def get_chat_messages_status():
|
||||
'enabled': chat_messages_enabled
|
||||
})
|
||||
|
||||
@app.route('/api/system-status', methods=['GET'])
|
||||
def get_system_status():
|
||||
"""Obtenir le statut de tous les composants"""
|
||||
return jsonify(bot_controller.get_system_status())
|
||||
|
||||
@app.route('/api/ia-generator/start', methods=['POST'])
|
||||
def start_ia_generator():
|
||||
"""Démarrer le générateur IA"""
|
||||
success, message = bot_controller.start_ia_generator()
|
||||
if success:
|
||||
# Synchroniser l'état de l'interface web
|
||||
socketio.emit('ia_generator_status_changed', {
|
||||
'running': True,
|
||||
'message': message
|
||||
})
|
||||
return jsonify({'success': success, 'message': message})
|
||||
|
||||
@app.route('/api/ia-generator/stop', methods=['POST'])
|
||||
def stop_ia_generator():
|
||||
"""Arrêter le générateur IA"""
|
||||
success, message = bot_controller.stop_ia_generator()
|
||||
if success:
|
||||
# Synchroniser l'état de l'interface web
|
||||
socketio.emit('ia_generator_status_changed', {
|
||||
'running': False,
|
||||
'message': message
|
||||
})
|
||||
return jsonify({'success': success, 'message': message})
|
||||
|
||||
@app.route('/api/control-twitch/start', methods=['POST'])
|
||||
def start_control_twitch():
|
||||
"""Démarrer le contrôleur Twitch"""
|
||||
success, message = bot_controller.start_control_twitch()
|
||||
return jsonify({'success': success, 'message': message})
|
||||
|
||||
@app.route('/api/control-twitch/stop', methods=['POST'])
|
||||
def stop_control_twitch():
|
||||
"""Arrêter le contrôleur Twitch"""
|
||||
success, message = bot_controller.stop_control_twitch()
|
||||
return jsonify({'success': success, 'message': message})
|
||||
|
||||
if __name__ == '__main__':
|
||||
# Démarrer les mises à jour en arrière-plan
|
||||
update_thread = threading.Thread(target=background_updates, daemon=True)
|
||||
|
||||
Reference in New Issue
Block a user