interface web
This commit is contained in:
@@ -0,0 +1,312 @@
|
||||
from flask import Flask, render_template, request, jsonify, redirect, url_for
|
||||
from flask_socketio import SocketIO, emit
|
||||
import json
|
||||
import os
|
||||
import threading
|
||||
import time
|
||||
from datetime import datetime
|
||||
import sys
|
||||
|
||||
# Import des classes du bot
|
||||
sys.path.append('.')
|
||||
from fonction.first_class import RecordTwitch, Subtitle_translation, IA_generator, messageTwitch, TwitchChatBot, storage
|
||||
|
||||
app = Flask(__name__)
|
||||
app.config['SECRET_KEY'] = 'your-secret-key-here'
|
||||
socketio = SocketIO(app, cors_allowed_origins="*")
|
||||
|
||||
class BotController:
|
||||
def __init__(self):
|
||||
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()
|
||||
|
||||
def load_config(self):
|
||||
try:
|
||||
with open('config/config.json', 'r') as file:
|
||||
return json.load(file)
|
||||
except FileNotFoundError:
|
||||
return {}
|
||||
|
||||
def save_config(self):
|
||||
with open('config/config.json', 'w') as file:
|
||||
json.dump(self.config, file, indent=4, ensure_ascii=False)
|
||||
|
||||
def add_flux(self, channel_name, record_audio=True):
|
||||
flux_id = len(self.flux_list) + 1
|
||||
|
||||
# Créer l'objet flux pour l'API (sans les instances de bots)
|
||||
flux_data = {
|
||||
'id': flux_id,
|
||||
'name': channel_name,
|
||||
'twitchname': channel_name,
|
||||
'record_audio': record_audio,
|
||||
'active': True,
|
||||
'created_at': datetime.now().isoformat(),
|
||||
'status': 'starting'
|
||||
}
|
||||
|
||||
try:
|
||||
# Créer le bot de chat pour ce flux
|
||||
chat_bot = TwitchChatBot(channel_name)
|
||||
self.bots[flux_id] = {
|
||||
'chat_bot': chat_bot,
|
||||
'record_bot': None
|
||||
}
|
||||
chat_bot.start_background()
|
||||
|
||||
# Si enregistrement audio activé
|
||||
if record_audio:
|
||||
record_bot = RecordTwitch(channel_name, 60)
|
||||
self.bots[flux_id]['record_bot'] = record_bot
|
||||
threading.Thread(target=record_bot.main, daemon=True).start()
|
||||
|
||||
# Mettre à jour le statut
|
||||
flux_data['status'] = 'active'
|
||||
self.flux_list.append(flux_data)
|
||||
return flux_id
|
||||
|
||||
except Exception as e:
|
||||
print(f"Erreur lors de l'ajout du flux {channel_name}: {str(e)}")
|
||||
# Nettoyer en cas d'erreur
|
||||
if flux_id in self.bots:
|
||||
try:
|
||||
if self.bots[flux_id]['chat_bot']:
|
||||
self.bots[flux_id]['chat_bot'].stop()
|
||||
if self.bots[flux_id]['record_bot']:
|
||||
self.bots[flux_id]['record_bot'].stop()
|
||||
except:
|
||||
pass
|
||||
del self.bots[flux_id]
|
||||
flux_data['status'] = 'error'
|
||||
flux_data['error'] = str(e)
|
||||
self.flux_list.append(flux_data)
|
||||
raise e
|
||||
|
||||
def remove_flux(self, flux_id):
|
||||
for i, flux in enumerate(self.flux_list):
|
||||
if flux['id'] == flux_id:
|
||||
# Arrêter les bots si ils existent
|
||||
if flux_id in self.bots:
|
||||
try:
|
||||
if self.bots[flux_id]['chat_bot']:
|
||||
self.bots[flux_id]['chat_bot'].stop()
|
||||
if self.bots[flux_id]['record_bot']:
|
||||
self.bots[flux_id]['record_bot'].stop()
|
||||
except Exception as e:
|
||||
print(f"Erreur lors de l'arrêt des bots: {e}")
|
||||
del self.bots[flux_id]
|
||||
|
||||
del self.flux_list[i]
|
||||
return True
|
||||
return False
|
||||
|
||||
def get_flux_list(self):
|
||||
# Retourner seulement les données JSON (pas les instances de bots)
|
||||
return self.flux_list
|
||||
|
||||
bot_controller = BotController()
|
||||
|
||||
@app.route('/')
|
||||
def index():
|
||||
return render_template('index.html')
|
||||
|
||||
@app.route('/api/flux', methods=['GET'])
|
||||
def get_flux():
|
||||
return jsonify(bot_controller.get_flux_list())
|
||||
|
||||
@app.route('/api/flux', methods=['POST'])
|
||||
def add_flux():
|
||||
data = request.json
|
||||
channel_name = data.get('channel_name')
|
||||
record_audio = data.get('record_audio', True)
|
||||
|
||||
if not channel_name:
|
||||
return jsonify({'error': 'Nom du canal requis'}), 400
|
||||
|
||||
try:
|
||||
flux_id = bot_controller.add_flux(channel_name, record_audio)
|
||||
return jsonify({'success': True, 'flux_id': flux_id})
|
||||
except Exception as e:
|
||||
error_msg = f"Erreur lors de l'ajout du flux: {str(e)}"
|
||||
print(f"Erreur API add_flux: {error_msg}")
|
||||
return jsonify({'error': error_msg}), 500
|
||||
|
||||
@app.route('/api/flux/<int:flux_id>', methods=['DELETE'])
|
||||
def remove_flux(flux_id):
|
||||
if bot_controller.remove_flux(flux_id):
|
||||
return jsonify({'success': True})
|
||||
return jsonify({'error': 'Flux non trouvé'}), 404
|
||||
|
||||
@app.route('/api/flux/<int:flux_id>/status', methods=['GET'])
|
||||
def get_flux_status(flux_id):
|
||||
"""Obtenir le statut détaillé d'un flux spécifique"""
|
||||
for flux in bot_controller.flux_list:
|
||||
if flux['id'] == flux_id:
|
||||
status = {
|
||||
'id': flux_id,
|
||||
'name': flux['name'],
|
||||
'active': flux['active'],
|
||||
'status': flux.get('status', 'unknown'),
|
||||
'created_at': flux['created_at'],
|
||||
'bots': {}
|
||||
}
|
||||
|
||||
# Ajouter les informations des bots si disponibles
|
||||
if flux_id in bot_controller.bots:
|
||||
bots = bot_controller.bots[flux_id]
|
||||
if bots['chat_bot']:
|
||||
status['bots']['chat'] = {
|
||||
'running': bots['chat_bot'].is_running if hasattr(bots['chat_bot'], 'is_running') else True
|
||||
}
|
||||
if bots['record_bot']:
|
||||
status['bots']['record'] = {
|
||||
'running': bots['record_bot'].running if hasattr(bots['record_bot'], 'running') else True
|
||||
}
|
||||
|
||||
return jsonify(status)
|
||||
|
||||
return jsonify({'error': 'Flux non trouvé'}), 404
|
||||
|
||||
@app.route('/api/flux/<int:flux_id>/toggle', methods=['POST'])
|
||||
def toggle_flux(flux_id):
|
||||
"""Activer/désactiver un flux"""
|
||||
for flux in bot_controller.flux_list:
|
||||
if flux['id'] == flux_id:
|
||||
flux['active'] = not flux['active']
|
||||
|
||||
# Arrêter/démarrer les bots selon le nouveau statut
|
||||
if flux_id in bot_controller.bots:
|
||||
bots = bot_controller.bots[flux_id]
|
||||
if not flux['active']:
|
||||
# Arrêter les bots
|
||||
try:
|
||||
if bots['chat_bot']:
|
||||
bots['chat_bot'].stop()
|
||||
if bots['record_bot']:
|
||||
bots['record_bot'].stop()
|
||||
except Exception as e:
|
||||
print(f"Erreur lors de l'arrêt des bots: {e}")
|
||||
else:
|
||||
# Redémarrer les bots
|
||||
try:
|
||||
if bots['chat_bot']:
|
||||
bots['chat_bot'].start_background()
|
||||
if bots['record_bot']:
|
||||
threading.Thread(target=bots['record_bot'].main, daemon=True).start()
|
||||
except Exception as e:
|
||||
print(f"Erreur lors du redémarrage des bots: {e}")
|
||||
|
||||
return jsonify({'success': True, 'active': flux['active']})
|
||||
|
||||
return jsonify({'error': 'Flux non trouvé'}), 404
|
||||
|
||||
@app.route('/api/config/prompts', methods=['GET'])
|
||||
def get_prompts():
|
||||
return jsonify(bot_controller.config.get('list_prompt', []))
|
||||
|
||||
@app.route('/api/config/prompts', methods=['POST'])
|
||||
def update_prompts():
|
||||
data = request.json
|
||||
prompts = data.get('prompts', [])
|
||||
bot_controller.config['list_prompt'] = prompts
|
||||
bot_controller.save_config()
|
||||
return jsonify({'success': True})
|
||||
|
||||
@app.route('/api/subtitles', methods=['GET'])
|
||||
def get_subtitles():
|
||||
data = storage.read("subtitle_data")
|
||||
return jsonify(data)
|
||||
|
||||
@app.route('/api/generations', methods=['GET'])
|
||||
def get_generations():
|
||||
data = storage.read("IA_generator")
|
||||
return jsonify(data)
|
||||
|
||||
@app.route('/api/send-message', methods=['POST'])
|
||||
def send_message():
|
||||
data = request.json
|
||||
message = data.get('message')
|
||||
channel = data.get('channel', 'default')
|
||||
|
||||
if not message:
|
||||
return jsonify({'error': 'Message requis'}), 400
|
||||
|
||||
# Trouver le bot de message pour ce canal
|
||||
try:
|
||||
msg_bot = messageTwitch("config/user.json", channel)
|
||||
msg_bot.send_message(message)
|
||||
return jsonify({'success': True})
|
||||
except Exception as e:
|
||||
return jsonify({'error': str(e)}), 500
|
||||
|
||||
@app.route('/api/generate-response', methods=['POST'])
|
||||
def generate_response():
|
||||
data = request.json
|
||||
text = data.get('text', '')
|
||||
|
||||
try:
|
||||
ia_gen = IA_generator("config/config.json")
|
||||
ia_gen.main_ask(text)
|
||||
return jsonify({'success': True})
|
||||
except Exception as e:
|
||||
return jsonify({'error': str(e)}), 500
|
||||
|
||||
@app.route('/api/status', methods=['GET'])
|
||||
def get_status():
|
||||
status = {
|
||||
'flux_count': len(bot_controller.flux_list),
|
||||
'active_recordings': sum(1 for f in bot_controller.flux_list if f['record_audio'] and f['active']),
|
||||
'chat_connections': sum(1 for f in bot_controller.flux_list if f['active']),
|
||||
'last_subtitle': '',
|
||||
'next_message': '',
|
||||
'recent_messages': []
|
||||
}
|
||||
|
||||
# Récupérer le dernier sous-titre
|
||||
subtitle_data = storage.read("subtitle_data")
|
||||
if subtitle_data:
|
||||
sorted_keys = sorted(subtitle_data.keys())
|
||||
if sorted_keys:
|
||||
status['last_subtitle'] = subtitle_data[sorted_keys[-1]]
|
||||
|
||||
# Récupérer la dernière génération
|
||||
generation_data = storage.read("IA_generator")
|
||||
if generation_data:
|
||||
sorted_keys = sorted(generation_data.keys())
|
||||
if sorted_keys:
|
||||
status['next_message'] = generation_data[sorted_keys[-1]]
|
||||
|
||||
return jsonify(status)
|
||||
|
||||
@socketio.on('connect')
|
||||
def handle_connect():
|
||||
print('Client connecté')
|
||||
emit('status', {'message': 'Connecté au serveur'})
|
||||
|
||||
@socketio.on('disconnect')
|
||||
def handle_disconnect():
|
||||
print('Client déconnecté')
|
||||
|
||||
# Thread pour envoyer les mises à jour en temps réel
|
||||
def background_updates():
|
||||
while True:
|
||||
try:
|
||||
status = {
|
||||
'timestamp': datetime.now().isoformat(),
|
||||
'flux_count': len(bot_controller.flux_list),
|
||||
'active_recordings': sum(1 for f in bot_controller.flux_list if f['record_audio'] and f['active']),
|
||||
}
|
||||
socketio.emit('status_update', status)
|
||||
time.sleep(5) # Mise à jour toutes les 5 secondes
|
||||
except Exception as e:
|
||||
print(f"Erreur dans background_updates: {e}")
|
||||
time.sleep(10)
|
||||
|
||||
if __name__ == '__main__':
|
||||
# Démarrer les mises à jour en arrière-plan
|
||||
update_thread = threading.Thread(target=background_updates, daemon=True)
|
||||
update_thread.start()
|
||||
|
||||
# Démarrer l'application Flask
|
||||
socketio.run(app, host='0.0.0.0', port=5000, debug=True)
|
||||
Reference in New Issue
Block a user