# database.py import logging import os from azure.cosmos import CosmosClient from azure.cosmos.exceptions import CosmosHttpResponseError from pymongo import MongoClient import certifi from datetime import datetime import io import base64 import bcrypt print(f"Bcrypt version: {bcrypt.__version__}") logging.basicConfig(level=logging.DEBUG) logger = logging.getLogger(__name__) # Variables globales para Cosmos DB SQL API cosmos_client = None user_database = None user_container = None # Variables globales para Cosmos DB MongoDB API mongo_client = None mongo_db = None analysis_collection = None #####################################################################################33 def initialize_cosmos_sql_connection(): global cosmos_client, user_database, user_container try: cosmos_endpoint = os.environ.get("COSMOS_ENDPOINT") cosmos_key = os.environ.get("COSMOS_KEY") print(f"Cosmos Endpoint: {cosmos_endpoint}") print(f"Cosmos Key: {'*' * len(cosmos_key) if cosmos_key else 'Not set'}") if not cosmos_endpoint or not cosmos_key: raise ValueError("Las variables de entorno COSMOS_ENDPOINT y COSMOS_KEY deben estar configuradas") cosmos_client = CosmosClient(cosmos_endpoint, cosmos_key) user_database = cosmos_client.get_database_client("user_database") user_container = user_database.get_container_client("users") print(f"user_container initialized: {user_container is not None}") logger.info("Conexión a Cosmos DB SQL API exitosa") return True except Exception as e: logger.error(f"Error al conectar con Cosmos DB SQL API: {str(e)}") return False ############################################################################################3 def initialize_mongodb_connection(): global mongo_client, mongo_db, analysis_collection try: cosmos_mongodb_connection_string = os.getenv("MONGODB_CONNECTION_STRING") if not cosmos_mongodb_connection_string: logger.error("La variable de entorno MONGODB_CONNECTION_STRING no está configurada") return False mongo_client = MongoClient(cosmos_mongodb_connection_string, tls=True, tlsCAFile=certifi.where(), retryWrites=False, serverSelectionTimeoutMS=5000, connectTimeoutMS=10000, socketTimeoutMS=10000) mongo_client.admin.command('ping') mongo_db = mongo_client['aideatext_db'] analysis_collection = mongo_db['text_analysis'] logger.info("Conexión a Cosmos DB MongoDB API exitosa") return True except Exception as e: logger.error(f"Error al conectar con Cosmos DB MongoDB API: {str(e)}", exc_info=True) return False ####################################################################################################### def create_user(username, password, role): global user_container try: print(f"Attempting to create user: {username} with role: {role}") if user_container is None: print("Error: user_container is None. Attempting to reinitialize connection.") if not initialize_cosmos_sql_connection(): raise Exception("Failed to initialize SQL connection") hashed_password = bcrypt.hashpw(password.encode('utf-8'), bcrypt.gensalt()).decode('utf-8') print(f"Password hashed successfully for user: {username}") user_data = { 'id': username, 'password': hashed_password, 'role': role, 'created_at': datetime.utcnow().isoformat() } user_container.create_item(body=user_data) print(f"Usuario {role} creado: {username}") # Log para depuración return True except Exception as e: print(f"Detailed error in create_user: {str(e)}") return False ####################################################################################################### def create_admin_user(username, password): return create_user(username, password, 'Administrador') ####################################################################################################### def create_student_user(username, password): return create_user(username, password, 'Estudiante') ####################################################################################################### # Funciones para Cosmos DB SQL API (manejo de usuarios) def get_user(username): try: query = f"SELECT * FROM c WHERE c.id = '{username}'" items = list(user_container.query_items(query=query, enable_cross_partition_query=True)) user = items[0] if items else None if user: print(f"Usuario encontrado: {username}, Rol: {user.get('role')}") # Log añadido else: print(f"Usuario no encontrado: {username}") # Log añadido return user except Exception as e: print(f"Error al obtener usuario {username}: {str(e)}") return None ################################################################################ # Funciones para Cosmos DB MongoDB API (análisis de texto) def get_student_data(username): if analysis_collection is None: logger.error("La conexión a MongoDB no está inicializada") return None try: logger.info(f"Buscando datos para el usuario: {username}") cursor = analysis_collection.find({"username": username}) formatted_data = { "username": username, "entries": [], "entries_count": 0, "word_count": {}, "semantic_analyses": [], "discourse_analyses": [], "chat_history": [] } for entry in cursor: formatted_entry = { "timestamp": entry["timestamp"], "text": entry["text"], "analysis_type": entry.get("analysis_type", "morphosyntax") } if formatted_entry["analysis_type"] == "morphosyntax": formatted_entry.update({ "word_count": entry.get("word_count", {}), "arc_diagrams": entry.get("arc_diagrams", []) }) for category, count in formatted_entry["word_count"].items(): formatted_data["word_count"][category] = formatted_data["word_count"].get(category, 0) + count elif formatted_entry["analysis_type"] == "semantic": formatted_entry["network_diagram"] = entry.get("network_diagram", "") formatted_data["semantic_analyses"].append(formatted_entry) elif formatted_entry["analysis_type"] == "discourse": formatted_entry.update({ "graph1": entry.get("graph1", ""), "graph2": entry.get("graph2", "") }) formatted_data["discourse_analyses"].append(formatted_entry) formatted_data["entries"].append(formatted_entry) formatted_data["entries_count"] = len(formatted_data["entries"]) formatted_data["entries"].sort(key=lambda x: x["timestamp"], reverse=True) for entry in formatted_data["entries"]: entry["timestamp"] = entry["timestamp"].isoformat() # Obtener el historial del chat chat_cursor = chat_collection.find({"username": username}) formatted_data["chat_history"] = list(chat_cursor) logger.info(f"Datos formateados para {username}: {formatted_data}") return formatted_data except Exception as e: logger.error(f"Error al obtener datos del estudiante {username}: {str(e)}") return None ####################################################################################################### def store_morphosyntax_result(username, text, repeated_words, arc_diagrams): if analysis_collection is None: logger.error("La conexión a MongoDB no está inicializada") return False try: word_count = {} for word, color in repeated_words.items(): category = color # Asumiendo que 'color' es la categoría gramatical word_count[category] = word_count.get(category, 0) + 1 analysis_document = { 'username': username, 'timestamp': datetime.utcnow(), 'text': text, 'word_count': word_count, 'arc_diagrams': arc_diagrams, } result = analysis_collection.insert_one(analysis_document) logger.info(f"Análisis guardado con ID: {result.inserted_id} para el usuario: {username}") return True except Exception as e: logger.error(f"Error al guardar el análisis para el usuario {username}: {str(e)}") return False ################################################################################################################ def store_semantic_result(username, text, network_diagram): try: # Convertir la figura a una imagen base64 buf = io.BytesIO() network_diagram.savefig(buf, format='png') buf.seek(0) img_str = base64.b64encode(buf.getvalue()).decode('utf-8') analysis_document = { 'username': username, 'timestamp': datetime.utcnow(), 'text': text, 'network_diagram': img_str, # Guardar la imagen como string base64 'analysis_type': 'semantic' } result = analysis_collection.insert_one(analysis_document) logger.info(f"Análisis semántico guardado con ID: {result.inserted_id} para el usuario: {username}") return True except Exception as e: logger.error(f"Error al guardar el análisis semántico para el usuario {username}: {str(e)}") return False ############################################################################################################### import io import base64 import matplotlib.pyplot as plt from matplotlib.figure import Figure def store_discourse_analysis_result(username, text1, text2, graph1, graph2): try: # Crear una nueva figura combinada fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(20, 10)) # Añadir la primera imagen con título ax1.imshow(graph1.get_figure().canvas.renderer.buffer_rgba()) ax1.set_title("Documento Patrón: Relaciones semánticas relevantes") ax1.axis('off') # Añadir la segunda imagen con título ax2.imshow(graph2.get_figure().canvas.renderer.buffer_rgba()) ax2.set_title("Documento Comparado con el documento patrón: Relaciones semánticas relevantes") ax2.axis('off') # Ajustar el diseño plt.tight_layout() # Convertir la figura combinada a una imagen base64 buf = io.BytesIO() fig.savefig(buf, format='png') buf.seek(0) img_str = base64.b64encode(buf.getvalue()).decode('utf-8') # Cerrar las figuras para liberar memoria plt.close(fig) plt.close(graph1.get_figure()) plt.close(graph2.get_figure()) analysis_document = { 'username': username, 'timestamp': datetime.utcnow(), 'text1': text1, 'text2': text2, 'combined_graph': img_str, 'analysis_type': 'discourse' } result = analysis_collection.insert_one(analysis_document) logger.info(f"Análisis discursivo guardado con ID: {result.inserted_id} para el usuario: {username}") return True except Exception as e: logger.error(f"Error al guardar el análisis discursivo para el usuario {username}: {str(e)}") return False ############################################################################################################### def store_chat_history(username, messages): try: chat_document = { 'username': username, 'timestamp': datetime.utcnow(), 'messages': messages } result = chat_collection.insert_one(chat_document) logger.info(f"Chat history saved with ID: {result.inserted_id} for user: {username}") return True except Exception as e: logger.error(f"Error saving chat history for user {username}: {str(e)}") return False