diff --git a/clase1/david_casa.py b/clase1/david_casa.py
new file mode 100644
index 0000000..232d2b8
--- /dev/null
+++ b/clase1/david_casa.py
@@ -0,0 +1,78 @@
+import datetime
+import random
+
+def es_primo(n: int) -> bool:
+ """Determina si un número es primo."""
+ if n <= 1:
+ return False
+ if n == 2:
+ return True
+ if n % 2 == 0:
+ return False
+ for i in range(3, int(n**0.5) + 1, 2):
+ if n % i == 0:
+ return False
+ return True
+
+def solicitar_numero() -> int:
+ """Solicita al usuario un número entero y lo devuelve."""
+ while True:
+ entrada = input("Ingrese un número para verificar si es primo: ")
+ try:
+ return int(entrada)
+ except ValueError:
+ print("❌ Entrada inválida. Por favor, ingrese un número entero.")
+
+def verificar_primo():
+ """Verifica si el número ingresado es primo e informa al usuario."""
+ numero = solicitar_numero()
+ if es_primo(numero):
+ print(f"✅ {numero} es un número primo.")
+ else:
+ print(f"❌ {numero} no es un número primo.")
+
+def mostrar_menu():
+ """Muestra el menú principal."""
+ print("\n--- MENÚ PRINCIPAL ---")
+ print("1. Mostrar frase motivacional")
+ print("2. Mostrar fecha actual")
+ print("3. Salir")
+
+def obtener_frase_motivacional() -> str:
+ frases = [
+ "¡Tú puedes lograr todo lo que te propongas! 💪",
+ "Cada día es una nueva oportunidad para ser mejor. 🌟",
+ "La perseverancia es la clave del éxito. 🚀",
+ "No te rindas, el éxito está más cerca de lo que piensas. 🌈",
+ "Cree en ti mismo y todo será posible. ✨"
+ ]
+ return random.choice(frases)
+
+def mostrar_fecha_actual() -> str:
+ return datetime.datetime.now().strftime("%d/%m/%Y")
+
+def menu_interactivo():
+ """Muestra un menú interactivo con opciones para el usuario."""
+ while True:
+ mostrar_menu()
+ opcion = input("Selecciona una opción (1-3): ")
+
+ if opcion == "1":
+ print(f"\n📝 Frase motivacional: {obtener_frase_motivacional()}")
+ elif opcion == "2":
+ print(f"\n📅 Fecha actual: {mostrar_fecha_actual()}")
+ elif opcion == "3":
+ print("\n👋 ¡Hasta luego!")
+ break
+ else:
+ print("❌ Opción no válida. Por favor, elige 1, 2 o 3.")
+
+def main():
+ """Función principal del programa."""
+ print("🎉 Bienvenido al programa de ejercicios.")
+ verificar_primo()
+ menu_interactivo()
+ print("🙏 Gracias por participar. ¡Hasta la próxima!")
+
+if __name__ == "__main__":
+ main()
diff --git a/clase2/david_casa.py b/clase2/david_casa.py
new file mode 100644
index 0000000..6fe14bd
--- /dev/null
+++ b/clase2/david_casa.py
@@ -0,0 +1,120 @@
+from typing import List
+
+
+# ----------------------- Ejercicio 1: Clase Heroe -----------------------
+
+class Heroe:
+ def __init__(self, nombre: str, genero: str, identidad_secreta: str, poder: str):
+ self.nombre = nombre
+ self.genero = genero
+ self.identidad_secreta = identidad_secreta
+ self.poder = poder
+
+ def presentar(self) -> None:
+ print(f"🦸♂️ Soy {self.nombre}, tengo el poder de {self.poder}, "
+ f"y mi identidad secreta es {self.identidad_secreta}.")
+
+ def to_json(self) -> dict:
+ return {
+ "nombre": self.nombre,
+ "genero": self.genero,
+ "identidad_secreta": self.identidad_secreta,
+ "poder": self.poder
+ }
+
+
+# ----------------------- Ejercicio 2: Clase Pelicula -----------------------
+
+class Pelicula:
+ def __init__(self, titulo: str, director: str, anio: int):
+ self.titulo = titulo
+ self.director = director
+ self.anio = anio
+
+ def mostrar_info(self) -> None:
+ print(f"🎬 {self.titulo} ({self.anio}), dirigido por {self.director}.")
+
+
+# ----------------------- Ejercicio 3: Trivia con POO -----------------------
+
+class Pregunta:
+ def __init__(self, enunciado: str, opciones: List[str], respuesta_correcta: str):
+ self.enunciado = enunciado
+ self.opciones = opciones
+ self.respuesta_correcta = respuesta_correcta
+
+ def mostrar(self) -> None:
+ print(f"\n❓ {self.enunciado}")
+ for idx, opcion in enumerate(self.opciones, start=1):
+ print(f" {idx}. {opcion}")
+
+ def verificar_respuesta(self, respuesta_usuario: str) -> bool:
+ try:
+ indice = int(respuesta_usuario) - 1
+ return self.opciones[indice].strip().lower() == self.respuesta_correcta.strip().lower()
+ except (ValueError, IndexError):
+ return False
+
+
+class Trivia:
+ def __init__(self):
+ self.preguntas: List[Pregunta] = []
+
+ def agregar_pregunta(self, pregunta: Pregunta) -> None:
+ self.preguntas.append(pregunta)
+
+ def iniciar(self) -> None:
+ print("\n🧠 Bienvenido a la Trivia. ¡Buena suerte!\n")
+ for pregunta in self.preguntas:
+ pregunta.mostrar()
+ respuesta = input("👉 Ingresa el número de la opción correcta: ")
+ if pregunta.verificar_respuesta(respuesta):
+ print("✅ ¡Respuesta correcta!")
+ else:
+ print(f"❌ Respuesta incorrecta. La correcta era: {pregunta.respuesta_correcta}")
+
+
+# ----------------------- Bloque Principal -----------------------
+
+def main():
+ print("************ Ejercicio 1: Clase Heroe ************")
+ heroe = Heroe("Superman", "Masculino", "Clark Kent", "Super fuerza")
+ heroe.presentar()
+ heroe.poder = "Volar"
+ heroe.presentar()
+ print("📦 Héroe en formato JSON:", heroe.to_json())
+
+ print("\n************ Ejercicio 2: Lista de Películas ************")
+ peliculas = [
+ Pelicula("Toy Story", "John Lasseter", 1995),
+ Pelicula("Forrest Gump", "Robert Zemeckis", 1994),
+ Pelicula("Insidious", "James Wan", 2010),
+ Pelicula("El Padrino", "Francis Ford Coppola", 1972),
+ ]
+ for pelicula in peliculas:
+ pelicula.mostrar_info()
+
+ print("\n************ Ejercicio 3: Trivia ************")
+ trivia = Trivia()
+ trivia.agregar_pregunta(Pregunta(
+ "¿Cuál es la capital de Francia?",
+ ["Berlín", "Madrid", "París", "Roma"],
+ "París"
+ ))
+ trivia.agregar_pregunta(Pregunta(
+ "¿Cuál es el océano más grande del mundo?",
+ ["Atlántico", "Índico", "Ártico", "Pacífico"],
+ "Pacífico"
+ ))
+ trivia.agregar_pregunta(Pregunta(
+ "¿Quién escribió 'Cien años de soledad'?",
+ ["Gabriel García Márquez", "Mario Vargas Llosa", "Jorge Luis Borges", "Pablo Neruda"],
+ "Gabriel García Márquez"
+ ))
+ trivia.iniciar()
+
+ print("\n🎉 ¡Gracias por usar el programa!")
+
+
+if __name__ == "__main__":
+ main()
diff --git a/clase3/david_casa/app.py b/clase3/david_casa/app.py
new file mode 100644
index 0000000..2d643fb
--- /dev/null
+++ b/clase3/david_casa/app.py
@@ -0,0 +1,20 @@
+from flask import Flask, render_template
+import requests
+
+app = Flask(__name__)
+
+@app.route("/")
+def mostrar_personajes():
+ url = "https://rickandmortyapi.com/api/character"
+ response = requests.get(url)
+
+ if response.status_code == 200:
+ data = response.json()
+ personajes = data["results"] # Lista de personajes
+ else:
+ personajes = []
+
+ return render_template("personajes.html", personajes=personajes)
+
+if __name__ == "__main__":
+ app.run(debug=True)
diff --git a/clase3/david_casa/requirements.txt b/clase3/david_casa/requirements.txt
new file mode 100644
index 0000000..e635204
--- /dev/null
+++ b/clase3/david_casa/requirements.txt
@@ -0,0 +1,2 @@
+Flask
+requests
diff --git a/clase3/david_casa/templates/personajes.html b/clase3/david_casa/templates/personajes.html
new file mode 100644
index 0000000..d4a55a0
--- /dev/null
+++ b/clase3/david_casa/templates/personajes.html
@@ -0,0 +1,45 @@
+
+
+
+
+ Personajes de Rick and Morty
+
+
+
+ Personajes de Rick and Morty
+
+ {% for personaje in personajes %}
+
+

+
{{ personaje.name }}
+
Status: {{ personaje.status }}
+
Especie: {{ personaje.species }}
+
+ {% endfor %}
+
+
+
diff --git a/proyecto/david_casa/bot.py b/proyecto/david_casa/bot.py
new file mode 100644
index 0000000..dc21b0c
--- /dev/null
+++ b/proyecto/david_casa/bot.py
@@ -0,0 +1,260 @@
+import telebot
+from telebot.types import ReplyKeyboardMarkup, KeyboardButton, ReplyKeyboardRemove, ForceReply
+from flask import Flask, request, send_file
+import sqlite3
+import os
+from datetime import datetime
+import csv
+import smtplib
+from email.message import EmailMessage
+
+API_TOKEN = 'YOUR_KEY'
+ADMIN_ID = 123456789 # Cambia por tu ID de admin
+
+EMAIL_ADDRESS = "YOUREMAIL@gmail.com"
+EMAIL_PASSWORD = "YOUR_KEY"
+
+bot = telebot.TeleBot(API_TOKEN)
+app = Flask(__name__)
+
+# 🛠️ Base de datos
+def init_db():
+ with sqlite3.connect('database.db') as conn:
+ cursor = conn.cursor()
+ cursor.execute('''
+ CREATE TABLE IF NOT EXISTS auditorias (
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
+ user_id INTEGER,
+ username TEXT,
+ action TEXT,
+ timestamp TEXT
+ )
+ ''')
+ cursor.execute('''
+ CREATE TABLE IF NOT EXISTS productos (
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
+ nombre TEXT,
+ descripcion TEXT,
+ precio REAL
+ )
+ ''')
+ cursor.execute('''
+ CREATE TABLE IF NOT EXISTS usuarios (
+ user_id INTEGER PRIMARY KEY,
+ idioma TEXT
+ )
+ ''')
+ cursor.execute('''
+ CREATE TABLE IF NOT EXISTS ordenes (
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
+ user_id INTEGER,
+ productos TEXT,
+ direccion TEXT,
+ telefono TEXT,
+ correo TEXT,
+ total REAL
+ )
+ ''')
+
+ cursor.execute("SELECT COUNT(*) FROM productos")
+ if cursor.fetchone()[0] == 0:
+ productos = [
+ ("Té de manzanilla", "Relajante natural", 2.5),
+ ("Infusión de menta", "Alivia malestares digestivos", 2.0),
+ ("Té de jengibre y limón", "Refuerza sistema inmune", 3.0),
+ ("Infusión de frutos rojos", "Antioxidante", 3.5),
+ ("Té verde", "Energizante natural", 2.8),
+ ]
+ cursor.executemany("INSERT INTO productos (nombre, descripcion, precio) VALUES (?, ?, ?)", productos)
+ conn.commit()
+
+def es_admin(user_id):
+ return user_id == ADMIN_ID
+
+def registrar_auditoria(user_id, username, action):
+ with sqlite3.connect('database.db') as conn:
+ cursor = conn.cursor()
+ cursor.execute("INSERT INTO auditorias (user_id, username, action, timestamp) VALUES (?, ?, ?, ?)",
+ (user_id, username, action, datetime.now().isoformat()))
+ conn.commit()
+
+def get_language(user_id):
+ with sqlite3.connect('database.db') as conn:
+ cursor = conn.cursor()
+ cursor.execute("SELECT idioma FROM usuarios WHERE user_id = ?", (user_id,))
+ row = cursor.fetchone()
+ return row[0] if row else "es"
+
+def set_language(user_id, lang):
+ with sqlite3.connect('database.db') as conn:
+ cursor = conn.cursor()
+ cursor.execute("INSERT OR REPLACE INTO usuarios (user_id, idioma) VALUES (?, ?)", (user_id, lang))
+ conn.commit()
+
+@bot.message_handler(commands=['start'])
+def start(message):
+ markup = ReplyKeyboardMarkup(resize_keyboard=True)
+ markup.add(KeyboardButton("Español"), KeyboardButton("English"))
+ bot.send_message(message.chat.id, "Elige tu idioma / Choose your language", reply_markup=markup)
+
+@bot.message_handler(func=lambda m: m.text in ["Español", "English"])
+def seleccionar_idioma(message):
+ lang = "es" if message.text == "Español" else "en"
+ set_language(message.from_user.id, lang)
+ registrar_auditoria(message.from_user.id, message.from_user.username, f"Idioma: {lang}")
+ mostrar_productos(message)
+
+def mostrar_productos(message):
+ lang = get_language(message.from_user.id)
+ with sqlite3.connect('database.db') as conn:
+ cursor = conn.cursor()
+ cursor.execute("SELECT id, nombre FROM productos")
+ productos = cursor.fetchall()
+
+ markup = ReplyKeyboardMarkup(resize_keyboard=True, row_width=2)
+ for pid, nombre in productos:
+ markup.add(KeyboardButton(f"{nombre}"))
+ markup.add(KeyboardButton("✅ Finalizar selección"))
+
+ msg = "Selecciona los productos naturales que deseas:" if lang == "es" else "Select the natural products you want:"
+ bot.send_message(message.chat.id, msg, reply_markup=markup)
+ bot.register_next_step_handler(message, recolectar_productos, [])
+
+def recolectar_productos(message, seleccionados):
+ lang = get_language(message.from_user.id)
+
+ if message.text == "✅ Finalizar selección":
+ if not seleccionados:
+ bot.send_message(message.chat.id, "No seleccionaste ningún producto." if lang == "es" else "You didn't select any product.")
+ return mostrar_productos(message)
+ else:
+ productos_str = ", ".join(seleccionados)
+ bot.send_message(message.chat.id, "📍 Ingresa tu dirección de envío:" if lang == "es" else "📍 Enter your delivery address:", reply_markup=ForceReply())
+ bot.register_next_step_handler(message, pedir_direccion, productos_str)
+ return
+
+ seleccionados.append(message.text)
+ bot.send_message(message.chat.id, f"🟢 Agregado: {message.text}")
+ bot.register_next_step_handler(message, recolectar_productos, seleccionados)
+
+def pedir_direccion(message, productos_str):
+ direccion = message.text
+ user_id = message.from_user.id
+ lang = get_language(user_id)
+
+ total = calcular_total(productos_str)
+ total_con_iva = round(total * 1.15, 2)
+
+ mensaje = (
+ f"📟 Resumen de compra:\n{productos_str}\n📍 Dirección: {direccion}\n💵 Total con IVA (15%): ${total_con_iva}\n\nPor favor ingresa tu número de WhatsApp:"
+ if lang == "es" else
+ f"📟 Order summary:\n{productos_str}\n📍 Address: {direccion}\n💵 Total with VAT (15%): ${total_con_iva}\n\nPlease enter your WhatsApp number:"
+ )
+ bot.send_message(message.chat.id, mensaje, reply_markup=ForceReply())
+ registrar_auditoria(user_id, message.from_user.username, "Dirección ingresada")
+ bot.register_next_step_handler(message, pedir_numero_whatsapp, productos_str, direccion, total_con_iva)
+
+def pedir_numero_whatsapp(message, productos_str, direccion, total_con_iva):
+ numero = message.text.strip().replace("+", "").replace(" ", "")
+ user_id = message.from_user.id
+ lang = get_language(user_id)
+
+ registrar_auditoria(user_id, message.from_user.username, f"Número WhatsApp: {numero}")
+
+ pregunta = "📧 Ingresa tu correo electrónico para enviarte el resumen:" if lang == "es" else "📧 Enter your email to receive the summary:"
+ bot.send_message(message.chat.id, pregunta, reply_markup=ForceReply())
+ bot.register_next_step_handler(message, pedir_correo, productos_str, direccion, numero, total_con_iva)
+
+def pedir_correo(message, productos_str, direccion, numero, total_con_iva):
+ correo = message.text.strip()
+ user_id = message.from_user.id
+ lang = get_language(user_id)
+
+ with sqlite3.connect('database.db') as conn:
+ cursor = conn.cursor()
+ cursor.execute("INSERT INTO ordenes (user_id, productos, direccion, telefono, correo, total) VALUES (?, ?, ?, ?, ?, ?)",
+ (user_id, productos_str, direccion, numero, correo, total_con_iva))
+ conn.commit()
+
+ registrar_auditoria(user_id, message.from_user.username, f"Correo: {correo}")
+
+ enviar_correo(productos_str, direccion, numero, correo, total_con_iva)
+
+ texto_mensaje = (
+ f"Hola! Gracias por tu compra. Resumen:\nProductos: {productos_str}\nDirección: {direccion}\nTotal: ${total_con_iva}\nTe contactaremos pronto!"
+ )
+ texto_mensaje = texto_mensaje.replace(" ", "%20").replace("\n", "%0A")
+ enlace = f"https://wa.me/{numero}?text={texto_mensaje}"
+
+ mensaje_final = (
+ f"✅ Gracias por tu compra. Haz clic aquí para abrir WhatsApp:\n{enlace}"
+ if lang == "es" else
+ f"✅ Thanks for your purchase! Click here to open WhatsApp:\n{enlace}"
+ )
+ bot.send_message(message.chat.id, mensaje_final, reply_markup=ReplyKeyboardRemove())
+
+def enviar_correo(productos, direccion, telefono, correo, total):
+ msg = EmailMessage()
+ msg['Subject'] = 'Resumen de tu orden'
+ msg['From'] = EMAIL_ADDRESS
+ msg['To'] = correo
+
+ cuerpo = f"""
+ 📦 Resumen de tu orden:
+ Productos: {productos}
+ Dirección: {direccion}
+ Teléfono: {telefono}
+ Total: ${total}
+
+ Gracias por tu compra.
+ """
+ msg.set_content(cuerpo)
+
+ try:
+ with smtplib.SMTP_SSL('smtp.gmail.com', 465) as smtp:
+ smtp.login(EMAIL_ADDRESS, EMAIL_PASSWORD)
+ smtp.send_message(msg)
+ print("✅ Correo enviado correctamente.")
+ except Exception as e:
+ print(f"❌ Error al enviar correo: {e}")
+
+def calcular_total(productos_str):
+ nombres = [p.strip() for p in productos_str.split(",")]
+ total = 0
+ with sqlite3.connect('database.db') as conn:
+ cursor = conn.cursor()
+ for nombre in nombres:
+ cursor.execute("SELECT precio FROM productos WHERE nombre = ?", (nombre,))
+ row = cursor.fetchone()
+ if row:
+ total += row[0]
+ return total
+
+@app.route('/download_audits/', methods=['GET'])
+def download_audits(admin_id):
+ if str(ADMIN_ID) != admin_id:
+ return "No autorizado", 403
+ filename = 'auditorias.csv'
+ with sqlite3.connect('database.db') as conn:
+ cursor = conn.cursor()
+ cursor.execute("SELECT * FROM auditorias")
+ rows = cursor.fetchall()
+ with open(filename, 'w', newline='', encoding='utf-8') as f:
+ writer = csv.writer(f)
+ writer.writerow(['ID', 'User ID', 'Username', 'Action', 'Timestamp'])
+ writer.writerows(rows)
+ return send_file(filename, as_attachment=True)
+
+@app.route('/webhook', methods=['POST'])
+def webhook():
+ update = telebot.types.Update.de_json(request.get_data().decode("utf-8"))
+ bot.process_new_updates([update])
+ return '', 200
+
+@app.route('/')
+def home():
+ return 'Bot funcionando localmente'
+
+if __name__ == '__main__':
+ init_db()
+ bot.polling()
diff --git a/proyecto/david_casa/requirements.txt b/proyecto/david_casa/requirements.txt
new file mode 100644
index 0000000..19f39fa
--- /dev/null
+++ b/proyecto/david_casa/requirements.txt
@@ -0,0 +1,3 @@
+Flask
+sqlite3
+pyTelegramBotAPI
\ No newline at end of file