from email.message import EmailMessage import smtplib import os import json import string import secrets from flask_bcrypt import Bcrypt import shortuuid from datetime import datetime, timezone from zoneinfo import ZoneInfo # Python 3.9+ bcrypt = Bcrypt() v = { 'home': 'a_home/home.html', 'about-us': 'b_about-us/about-us.html', 'solutions': 'c_solutions/solutions.html', 'methodology': 'd_methodology/methodology.html', "blog": { "all_posts": "e_blog/a_all_posts.html", "post": "e_blog/b_post.html", }, 'contact': 'f_contact/contact.html', 'login': 'g_login/login.html', 'recover_pswd': 'g_login/recover_pswd.html', 'tmp_user': { 'home': 'h_tmp_usr/a_home.html', 'txt_editor': 'h_tmp_usr/b_txt_editor.html', 'my_posts': 'h_tmp_usr/c_my_posts.html', 'read_post': 'h_tmp_usr/d_read_post.html', 'edit_post': 'h_tmp_usr/e_edit_post.html', 'change_pswd': 'h_tmp_usr/f_change_pswd.html', 'metrics': 'h_tmp_usr/g_metrics.html', 'manage_profiles': 'h_tmp_usr/h_manage_profiles.html', 'carousel': 'h_tmp_usr/i_carousel_form.html' } } l_flash_msj = lambda title, body, typeAlert: {'title': title, 'body': body, 'typeAlert': typeAlert} def min_read_pst(n_words: int) -> str: # https://uapas2.bunam.unam.mx/humanidades/velocidad_lectora/ # min 250 y más 500 = 750 / 2 = ~375 t = int(round(n_words / 375, 0)) resultado = f'{t} min' if t < 60 else f'{int(t/60)} hrs' return resultado def db_conf_obj(dbEnvVarName: str) -> object: ''' dbEnvVarName = nombre de la variable de entorno variable que contiene los datos de la base de datos ''' db = os.getenv(dbEnvVarName) db = json.loads(db) return db def generar_contrasena(): """ Genera una contraseña aleatoria de 25 caracteres. La contraseña se compone de una combinación de letras mayúsculas, letras minúsculas y dígitos. La función utiliza el módulo `secrets` para asegurar que la generación de la contraseña sea adecuada para propósitos de seguridad. Returns: ------- str Una cadena de caracteres aleatorios de 25 caracteres, formada por letras (mayúsculas y minúsculas) y dígitos. Example: -------- >>> generar_contrasena() 'A9gTz5bNp0Wk3L6Xq2vUv8YwRz1E' """ caracteres = string.ascii_letters + string.digits contrasena = ''.join(secrets.choice(caracteres) for _ in range(25)) return contrasena def hash_password(password): """ Genera un hash de la contraseña utilizando bcrypt. Esta función toma una contraseña en texto plano y la convierte en un hash seguro utilizando el algoritmo bcrypt. El hash generado es una cadena en formato UTF-8, adecuada para almacenamiento en bases de datos. Parámetros: ---------- password : str La contraseña en texto plano que se desea hashear. Returns: ------- str or None El hash de la contraseña en formato UTF-8 si la operación es exitosa. Devuelve `None` en caso de que ocurra una excepción durante el proceso de hashing. Example: -------- >>> hash_password('mi_contrasena_segura') '$2b$12$D4yU/jEaK4xdgK0R2J6c6Odnk8p3k/RtG2ByjF26.4gnBR4tdA/2i' """ try: hashed_password = bcrypt.generate_password_hash(password).decode('utf-8') return hashed_password except Exception as e: return None def getRandomId(): # POR DEFAULT SHORUUID SACA 22 CARACTERES # LOS PODEMOS ACORTAR DE LA SIGUIENTE MANERA: short_id_custom = shortuuid.uuid()[:10] # Configurar el generador con una semilla específica (opcional) # shortuuid.set_alphabet("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-!#$!%&/()=?¡¿") shortuuid.set_alphabet("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789") # Generar un UUID corto con la semilla personalizada short_id_custom = shortuuid.uuid() return short_id_custom def saludo_hr(): hora = datetime.now().hour if 5 <= hora < 12: return "🌅 Buenos días" elif 12 <= hora < 18: return "🌞 Buenas tardes" else: return "🌙 Buenas noches" def cur_date() -> datetime: fecha_actual = datetime.now(ZoneInfo("America/Mexico_City")) return fecha_actual def get_date_n_time(timestamp: datetime) -> dict: obj = { "date": timestamp.strftime("%d/%m/%Y"), "hour": timestamp.strftime("%H:%M:%S") } return obj def hex_to_rgb(hex_color): # Elimina el símbolo '#' si está presente hex_color = hex_color.lstrip('#') # Convierte los pares de caracteres hexadecimales a enteros if len(hex_color) == 6: r = int(hex_color[0:2], 16) g = int(hex_color[2:4], 16) b = int(hex_color[4:6], 16) return (r, g, b) else: raise ValueError("El color HEX debe tener 6 dígitos.") def rgba_to_string(rgba): r, g, b, a = rgba return f"rgba({r}, {g}, {b}, {a})"