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 }} +

{{ 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