From 38b35acef26e572af0911c04c167233d5f3b9406 Mon Sep 17 00:00:00 2001 From: EDcasa Date: Mon, 14 Jul 2025 21:45:13 -0500 Subject: [PATCH 1/7] [FEAT], deber clase 1 --- clase1/david_casa.py | 78 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 clase1/david_casa.py 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() From d415dedd73c81d5b5c3674677a85dacd9df445cf Mon Sep 17 00:00:00 2001 From: EDcasa Date: Mon, 14 Jul 2025 21:46:37 -0500 Subject: [PATCH 2/7] [FEAT], deber clase 2 --- clase2/david_casa.py | 120 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 120 insertions(+) create mode 100644 clase2/david_casa.py 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() From f6d8773778b6fff4f5f0e231d6c0ee53785df619 Mon Sep 17 00:00:00 2001 From: EDcasa Date: Mon, 14 Jul 2025 21:49:45 -0500 Subject: [PATCH 3/7] [FEAT], deber clase 3 --- clase3/david_casa/app.py | 20 +++++++++ clase3/david_casa/requirements.txt | 2 + clase3/david_casa/templates/personajes.html | 45 +++++++++++++++++++++ 3 files changed, 67 insertions(+) create mode 100644 clase3/david_casa/app.py create mode 100644 clase3/david_casa/requirements.txt create mode 100644 clase3/david_casa/templates/personajes.html 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 %} +
+ + From 7bbae84ac7f21103058b3c98924c3141655a071e Mon Sep 17 00:00:00 2001 From: EDcasa Date: Mon, 14 Jul 2025 22:05:47 -0500 Subject: [PATCH 4/7] [FEAT], proyect --- proyecto/david_casa/bot.py | 246 +++++++++++++++++++++++++++ proyecto/david_casa/requirements.txt | 3 + 2 files changed, 249 insertions(+) create mode 100644 proyecto/david_casa/bot.py create mode 100644 proyecto/david_casa/requirements.txt diff --git a/proyecto/david_casa/bot.py b/proyecto/david_casa/bot.py new file mode 100644 index 0000000..cc2c616 --- /dev/null +++ b/proyecto/david_casa/bot.py @@ -0,0 +1,246 @@ +import telebot +from telebot.types import ReplyKeyboardMarkup, KeyboardButton, ForceReply +from flask import Flask, request, send_file +import sqlite3 +import os +from datetime import datetime +import csv + +# 🧩 Configura tus variables +API_TOKEN = 'TU_BOT_TOKEN_AQUI' +WEBHOOK_URL = 'https://tudominio.com/webhook' +ADMIN_ID = 123456789 # 🔐 Reemplaza con tu ID real de Telegram + +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 + ) + ''') + cursor.execute(''' + CREATE TABLE IF NOT EXISTS usuarios ( + user_id INTEGER PRIMARY KEY, + idioma TEXT + ) + ''') + cursor.execute("SELECT COUNT(*) FROM productos") + if cursor.fetchone()[0] == 0: + cursor.execute("INSERT INTO productos (nombre, descripcion) VALUES (?, ?)", + ("Paracetamol", "Alivia el dolor y la fiebre")) + cursor.execute("INSERT INTO productos (nombre, descripcion) VALUES (?, ?)", + ("Ibuprofeno", "Antiinflamatorio y analgésico")) + conn.commit() + +# 👁‍🗨 Verificación admin +def es_admin(user_id): + return user_id == ADMIN_ID + +# 📝 Auditoría +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() + +# 🌐 Idioma +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() + +# 📋 Menú +def send_menu(message): + lang = get_language(message.from_user.id) + is_admin = es_admin(message.from_user.id) + markup = ReplyKeyboardMarkup(resize_keyboard=True) + if lang == "en": + buttons = ["💊 Show products"] + if is_admin: + buttons += ["Add product", "Delete product", "Statistics", "Download report"] + text = "Choose an option:" + else: + buttons = ["💊 Ver productos"] + if is_admin: + buttons += ["Agregar producto", "Eliminar producto", "Estadísticas", "Descargar reporte"] + text = "Elige una opción:" + for b in buttons: + markup.add(KeyboardButton(b)) + bot.send_message(message.chat.id, text, reply_markup=markup) + +# ▶️ /start +@bot.message_handler(commands=['start']) +def handle_start(message): + registrar_auditoria(message.from_user.id, message.from_user.username, "start") + 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) + +# 🧠 Manejo general +@bot.message_handler(func=lambda m: True) +def handle_message(message): + user_id = message.from_user.id + username = message.from_user.username + text = message.text.lower() + lang = get_language(user_id) + + # Cambio de idioma + if text in ["español", "spanish"]: + set_language(user_id, "es") + registrar_auditoria(user_id, username, "Idioma: Español") + bot.send_message(message.chat.id, "Idioma establecido a Español.") + send_menu(message) + elif text in ["english", "inglés"]: + set_language(user_id, "en") + registrar_auditoria(user_id, username, "Language: English") + bot.send_message(message.chat.id, "Language set to English.") + send_menu(message) + + # Ver productos + elif "ver productos" in text or "show products" in text: + registrar_auditoria(user_id, username, "Ver productos") + with sqlite3.connect('database.db') as conn: + cursor = conn.cursor() + cursor.execute("SELECT nombre, descripcion FROM productos") + productos = cursor.fetchall() + for nombre, descripcion in productos: + bot.send_message(message.chat.id, f"💊 *{nombre}*\n📝 {descripcion}", parse_mode='Markdown') + + # Agregar producto (admin) + elif text in ["agregar producto", "add product"] and es_admin(user_id): + prompt = "Nombre del producto:" if lang == "es" else "Product name:" + msg = bot.send_message(message.chat.id, prompt, reply_markup=ForceReply()) + bot.register_next_step_handler(msg, recibir_nombre_producto) + + # Eliminar producto (admin) + elif text in ["eliminar producto", "delete product"] and es_admin(user_id): + with sqlite3.connect('database.db') as conn: + cursor = conn.cursor() + cursor.execute("SELECT id, nombre FROM productos") + productos = cursor.fetchall() + if not productos: + msg = "No hay productos." if lang == "es" else "No products found." + bot.send_message(message.chat.id, msg) + else: + lista = "\n".join([f"{p[0]} - {p[1]}" for p in productos]) + prompt = "Escribe el ID del producto a eliminar:" if lang == "es" else "Enter the product ID to delete:" + bot.send_message(message.chat.id, lista) + msg = bot.send_message(message.chat.id, prompt, reply_markup=ForceReply()) + bot.register_next_step_handler(msg, eliminar_producto) + + # Estadísticas (admin) + elif text in ["estadísticas", "statistics"] and es_admin(user_id): + with sqlite3.connect('database.db') as conn: + cursor = conn.cursor() + cursor.execute("SELECT COUNT(*) FROM usuarios") + total_usuarios = cursor.fetchone()[0] + cursor.execute("SELECT COUNT(*) FROM auditorias") + total_auditorias = cursor.fetchone()[0] + cursor.execute("SELECT COUNT(*) FROM productos") + total_productos = cursor.fetchone()[0] + if lang == "es": + msg = f"📊 Estadísticas:\nUsuarios: {total_usuarios}\nAuditorías: {total_auditorias}\nProductos: {total_productos}" + else: + msg = f"📊 Statistics:\nUsers: {total_usuarios}\nAudits: {total_auditorias}\nProducts: {total_productos}" + registrar_auditoria(user_id, username, "Ver estadísticas") + bot.send_message(message.chat.id, msg) + + # Reporte CSV + elif text in ["descargar reporte", "download report"] and es_admin(user_id): + registrar_auditoria(user_id, username, "Descargar CSV") + url = f"{WEBHOOK_URL}/download_audits/{ADMIN_ID}" + msg = "📥 Haz clic para descargar el reporte CSV:\n" if lang == "es" else "📥 Click to download CSV report:\n" + bot.send_message(message.chat.id, msg + url) + + else: + mensaje = "Comando no reconocido." if lang == "es" else "Command not recognized." + bot.send_message(message.chat.id, mensaje) + +# ➕ Agregar producto paso a paso +def recibir_nombre_producto(message): + nombre = message.text + bot.send_message(message.chat.id, "Descripción del producto:") + bot.register_next_step_handler(message, lambda msg: guardar_producto(msg, nombre)) + +def guardar_producto(message, nombre): + descripcion = message.text + with sqlite3.connect('database.db') as conn: + cursor = conn.cursor() + cursor.execute("INSERT INTO productos (nombre, descripcion) VALUES (?, ?)", (nombre, descripcion)) + conn.commit() + registrar_auditoria(message.from_user.id, message.from_user.username, f"Agregó producto: {nombre}") + lang = get_language(message.from_user.id) + bot.send_message(message.chat.id, "Producto guardado." if lang == "es" else "Product saved.") + +# ❌ Eliminar producto +def eliminar_producto(message): + try: + id_producto = int(message.text.strip()) + with sqlite3.connect('database.db') as conn: + cursor = conn.cursor() + cursor.execute("DELETE FROM productos WHERE id = ?", (id_producto,)) + conn.commit() + registrar_auditoria(message.from_user.id, message.from_user.username, f"Eliminó producto {id_producto}") + lang = get_language(message.from_user.id) + bot.send_message(message.chat.id, "Producto eliminado." if lang == "es" else "Product deleted.") + except Exception: + bot.send_message(message.chat.id, "ID inválido.") + +# 🌐 Webhook Flask +@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('/set_webhook', methods=['GET']) +def set_webhook(): + bot.remove_webhook() + bot.set_webhook(url=WEBHOOK_URL) + return "Webhook configurado." + +# 📤 Descargar CSV +@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) + +# ▶️ Main +if __name__ == '__main__': + init_db() + app.run(host='0.0.0.0', port=int(os.environ.get('PORT', 5000))) 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 From e051a7149470fd0157d2edbc677b0a63726276fc Mon Sep 17 00:00:00 2001 From: EDcasa Date: Mon, 14 Jul 2025 22:24:36 -0500 Subject: [PATCH 5/7] [FEAT], proyect, agregar personalizaciones --- proyecto/david_casa/bot.py | 261 +++++++++++++++---------------------- 1 file changed, 107 insertions(+), 154 deletions(-) diff --git a/proyecto/david_casa/bot.py b/proyecto/david_casa/bot.py index cc2c616..c391266 100644 --- a/proyecto/david_casa/bot.py +++ b/proyecto/david_casa/bot.py @@ -1,15 +1,13 @@ import telebot -from telebot.types import ReplyKeyboardMarkup, KeyboardButton, ForceReply +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 -# 🧩 Configura tus variables -API_TOKEN = 'TU_BOT_TOKEN_AQUI' -WEBHOOK_URL = 'https://tudominio.com/webhook' -ADMIN_ID = 123456789 # 🔐 Reemplaza con tu ID real de Telegram +API_TOKEN = '7504345200:AAFl3uHBy3Qw0ZUW8INGrnoZamxcwjKe_lc' +ADMIN_ID = 123456789 # Cambia por tu ID de admin bot = telebot.TeleBot(API_TOKEN) app = Flask(__name__) @@ -31,7 +29,8 @@ def init_db(): CREATE TABLE IF NOT EXISTS productos ( id INTEGER PRIMARY KEY AUTOINCREMENT, nombre TEXT, - descripcion TEXT + descripcion TEXT, + precio REAL ) ''') cursor.execute(''' @@ -40,19 +39,33 @@ def init_db(): idioma TEXT ) ''') + cursor.execute(''' + CREATE TABLE IF NOT EXISTS ordenes ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + user_id INTEGER, + productos TEXT, + direccion TEXT, + total REAL + ) + ''') + + # Productos naturales por defecto cursor.execute("SELECT COUNT(*) FROM productos") if cursor.fetchone()[0] == 0: - cursor.execute("INSERT INTO productos (nombre, descripcion) VALUES (?, ?)", - ("Paracetamol", "Alivia el dolor y la fiebre")) - cursor.execute("INSERT INTO productos (nombre, descripcion) VALUES (?, ?)", - ("Ibuprofeno", "Antiinflamatorio y analgésico")) + 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() -# 👁‍🗨 Verificación admin +# 📒 Utilidades def es_admin(user_id): return user_id == ADMIN_ID -# 📝 Auditoría def registrar_auditoria(user_id, username, action): with sqlite3.connect('database.db') as conn: cursor = conn.cursor() @@ -60,7 +73,6 @@ def registrar_auditoria(user_id, username, action): (user_id, username, action, datetime.now().isoformat())) conn.commit() -# 🌐 Idioma def get_language(user_id): with sqlite3.connect('database.db') as conn: cursor = conn.cursor() @@ -74,157 +86,89 @@ def set_language(user_id, lang): cursor.execute("INSERT OR REPLACE INTO usuarios (user_id, idioma) VALUES (?, ?)", (user_id, lang)) conn.commit() -# 📋 Menú -def send_menu(message): - lang = get_language(message.from_user.id) - is_admin = es_admin(message.from_user.id) - markup = ReplyKeyboardMarkup(resize_keyboard=True) - if lang == "en": - buttons = ["💊 Show products"] - if is_admin: - buttons += ["Add product", "Delete product", "Statistics", "Download report"] - text = "Choose an option:" - else: - buttons = ["💊 Ver productos"] - if is_admin: - buttons += ["Agregar producto", "Eliminar producto", "Estadísticas", "Descargar reporte"] - text = "Elige una opción:" - for b in buttons: - markup.add(KeyboardButton(b)) - bot.send_message(message.chat.id, text, reply_markup=markup) - -# ▶️ /start +# 🚀 Iniciar @bot.message_handler(commands=['start']) -def handle_start(message): - registrar_auditoria(message.from_user.id, message.from_user.username, "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) -# 🧠 Manejo general -@bot.message_handler(func=lambda m: True) -def handle_message(message): +@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) + +# 🍵 Mostrar productos para elegir +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 - username = message.from_user.username - text = message.text.lower() lang = get_language(user_id) - # Cambio de idioma - if text in ["español", "spanish"]: - set_language(user_id, "es") - registrar_auditoria(user_id, username, "Idioma: Español") - bot.send_message(message.chat.id, "Idioma establecido a Español.") - send_menu(message) - elif text in ["english", "inglés"]: - set_language(user_id, "en") - registrar_auditoria(user_id, username, "Language: English") - bot.send_message(message.chat.id, "Language set to English.") - send_menu(message) - - # Ver productos - elif "ver productos" in text or "show products" in text: - registrar_auditoria(user_id, username, "Ver productos") - with sqlite3.connect('database.db') as conn: - cursor = conn.cursor() - cursor.execute("SELECT nombre, descripcion FROM productos") - productos = cursor.fetchall() - for nombre, descripcion in productos: - bot.send_message(message.chat.id, f"💊 *{nombre}*\n📝 {descripcion}", parse_mode='Markdown') - - # Agregar producto (admin) - elif text in ["agregar producto", "add product"] and es_admin(user_id): - prompt = "Nombre del producto:" if lang == "es" else "Product name:" - msg = bot.send_message(message.chat.id, prompt, reply_markup=ForceReply()) - bot.register_next_step_handler(msg, recibir_nombre_producto) - - # Eliminar producto (admin) - elif text in ["eliminar producto", "delete product"] and es_admin(user_id): - with sqlite3.connect('database.db') as conn: - cursor = conn.cursor() - cursor.execute("SELECT id, nombre FROM productos") - productos = cursor.fetchall() - if not productos: - msg = "No hay productos." if lang == "es" else "No products found." - bot.send_message(message.chat.id, msg) - else: - lista = "\n".join([f"{p[0]} - {p[1]}" for p in productos]) - prompt = "Escribe el ID del producto a eliminar:" if lang == "es" else "Enter the product ID to delete:" - bot.send_message(message.chat.id, lista) - msg = bot.send_message(message.chat.id, prompt, reply_markup=ForceReply()) - bot.register_next_step_handler(msg, eliminar_producto) - - # Estadísticas (admin) - elif text in ["estadísticas", "statistics"] and es_admin(user_id): - with sqlite3.connect('database.db') as conn: - cursor = conn.cursor() - cursor.execute("SELECT COUNT(*) FROM usuarios") - total_usuarios = cursor.fetchone()[0] - cursor.execute("SELECT COUNT(*) FROM auditorias") - total_auditorias = cursor.fetchone()[0] - cursor.execute("SELECT COUNT(*) FROM productos") - total_productos = cursor.fetchone()[0] - if lang == "es": - msg = f"📊 Estadísticas:\nUsuarios: {total_usuarios}\nAuditorías: {total_auditorias}\nProductos: {total_productos}" - else: - msg = f"📊 Statistics:\nUsers: {total_usuarios}\nAudits: {total_auditorias}\nProducts: {total_productos}" - registrar_auditoria(user_id, username, "Ver estadísticas") - bot.send_message(message.chat.id, msg) - - # Reporte CSV - elif text in ["descargar reporte", "download report"] and es_admin(user_id): - registrar_auditoria(user_id, username, "Descargar CSV") - url = f"{WEBHOOK_URL}/download_audits/{ADMIN_ID}" - msg = "📥 Haz clic para descargar el reporte CSV:\n" if lang == "es" else "📥 Click to download CSV report:\n" - bot.send_message(message.chat.id, msg + url) - - else: - mensaje = "Comando no reconocido." if lang == "es" else "Command not recognized." - bot.send_message(message.chat.id, mensaje) - -# ➕ Agregar producto paso a paso -def recibir_nombre_producto(message): - nombre = message.text - bot.send_message(message.chat.id, "Descripción del producto:") - bot.register_next_step_handler(message, lambda msg: guardar_producto(msg, nombre)) - -def guardar_producto(message, nombre): - descripcion = message.text + total = calcular_total(productos_str) + total_con_iva = round(total * 1.15, 2) + with sqlite3.connect('database.db') as conn: cursor = conn.cursor() - cursor.execute("INSERT INTO productos (nombre, descripcion) VALUES (?, ?)", (nombre, descripcion)) + cursor.execute("INSERT INTO ordenes (user_id, productos, direccion, total) VALUES (?, ?, ?, ?)", + (user_id, productos_str, direccion, total_con_iva)) conn.commit() - registrar_auditoria(message.from_user.id, message.from_user.username, f"Agregó producto: {nombre}") - lang = get_language(message.from_user.id) - bot.send_message(message.chat.id, "Producto guardado." if lang == "es" else "Product saved.") - -# ❌ Eliminar producto -def eliminar_producto(message): - try: - id_producto = int(message.text.strip()) - with sqlite3.connect('database.db') as conn: - cursor = conn.cursor() - cursor.execute("DELETE FROM productos WHERE id = ?", (id_producto,)) - conn.commit() - registrar_auditoria(message.from_user.id, message.from_user.username, f"Eliminó producto {id_producto}") - lang = get_language(message.from_user.id) - bot.send_message(message.chat.id, "Producto eliminado." if lang == "es" else "Product deleted.") - except Exception: - bot.send_message(message.chat.id, "ID inválido.") - -# 🌐 Webhook Flask -@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('/set_webhook', methods=['GET']) -def set_webhook(): - bot.remove_webhook() - bot.set_webhook(url=WEBHOOK_URL) - return "Webhook configurado." -# 📤 Descargar CSV + mensaje = ( + f"📟 Resumen de compra:\n{productos_str}\n📍 Dirección: {direccion}\n💵 Total con IVA (15%): ${total_con_iva}\n\n¡Gracias por tu compra! 🌿" + if lang == "es" else + f"📟 Order summary:\n{productos_str}\n📍 Address: {direccion}\n💵 Total with VAT (15%): ${total_con_iva}\n\nThanks for your purchase! 🌿" + ) + bot.send_message(message.chat.id, mensaje, reply_markup=ReplyKeyboardRemove()) + registrar_auditoria(user_id, message.from_user.username, "Compra realizada") + +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 + +# CSV y admin @app.route('/download_audits/', methods=['GET']) def download_audits(admin_id): if str(ADMIN_ID) != admin_id: @@ -240,7 +184,16 @@ def download_audits(admin_id): writer.writerows(rows) return send_file(filename, as_attachment=True) -# ▶️ Main +@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() - app.run(host='0.0.0.0', port=int(os.environ.get('PORT', 5000))) + bot.polling() From 740be4abff1894476077c5370891e5fbdf933ffa Mon Sep 17 00:00:00 2001 From: David Casa Date: Tue, 15 Jul 2025 10:15:14 -0500 Subject: [PATCH 6/7] [FEAT], open whatsapp, send email with gmail --- proyecto/david_casa/bot.py | 85 ++++++++++++++++++++++++++++++++------ 1 file changed, 73 insertions(+), 12 deletions(-) diff --git a/proyecto/david_casa/bot.py b/proyecto/david_casa/bot.py index c391266..31f3453 100644 --- a/proyecto/david_casa/bot.py +++ b/proyecto/david_casa/bot.py @@ -5,10 +5,15 @@ import os from datetime import datetime import csv +import smtplib +from email.message import EmailMessage API_TOKEN = '7504345200:AAFl3uHBy3Qw0ZUW8INGrnoZamxcwjKe_lc' ADMIN_ID = 123456789 # Cambia por tu ID de admin +EMAIL_ADDRESS = "homesoftcore@gmail.com" +EMAIL_PASSWORD = "xymrywxnprquxevz" + bot = telebot.TeleBot(API_TOKEN) app = Flask(__name__) @@ -45,11 +50,12 @@ def init_db(): user_id INTEGER, productos TEXT, direccion TEXT, + telefono TEXT, + correo TEXT, total REAL ) ''') - # Productos naturales por defecto cursor.execute("SELECT COUNT(*) FROM productos") if cursor.fetchone()[0] == 0: productos = [ @@ -62,7 +68,6 @@ def init_db(): cursor.executemany("INSERT INTO productos (nombre, descripcion, precio) VALUES (?, ?, ?)", productos) conn.commit() -# 📒 Utilidades def es_admin(user_id): return user_id == ADMIN_ID @@ -86,7 +91,6 @@ def set_language(user_id, lang): cursor.execute("INSERT OR REPLACE INTO usuarios (user_id, idioma) VALUES (?, ?)", (user_id, lang)) conn.commit() -# 🚀 Iniciar @bot.message_handler(commands=['start']) def start(message): markup = ReplyKeyboardMarkup(resize_keyboard=True) @@ -100,7 +104,6 @@ def seleccionar_idioma(message): registrar_auditoria(message.from_user.id, message.from_user.username, f"Idioma: {lang}") mostrar_productos(message) -# 🍵 Mostrar productos para elegir def mostrar_productos(message): lang = get_language(message.from_user.id) with sqlite3.connect('database.db') as conn: @@ -142,19 +145,78 @@ def pedir_direccion(message, productos_str): 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, total) VALUES (?, ?, ?, ?)", - (user_id, productos_str, direccion, total_con_iva)) + 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() - mensaje = ( - f"📟 Resumen de compra:\n{productos_str}\n📍 Dirección: {direccion}\n💵 Total con IVA (15%): ${total_con_iva}\n\n¡Gracias por tu compra! 🌿" + 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"📟 Order summary:\n{productos_str}\n📍 Address: {direccion}\n💵 Total with VAT (15%): ${total_con_iva}\n\nThanks for your purchase! 🌿" + f"✅ Thanks for your purchase! Click here to open WhatsApp:\n{enlace}" ) - bot.send_message(message.chat.id, mensaje, reply_markup=ReplyKeyboardRemove()) - registrar_auditoria(user_id, message.from_user.username, "Compra realizada") + 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(",")] @@ -168,7 +230,6 @@ def calcular_total(productos_str): total += row[0] return total -# CSV y admin @app.route('/download_audits/', methods=['GET']) def download_audits(admin_id): if str(ADMIN_ID) != admin_id: From bbc75fd8ab352fa9b2fcd5fc3fd25cab19b5cc2b Mon Sep 17 00:00:00 2001 From: David Casa Date: Tue, 15 Jul 2025 10:15:17 -0500 Subject: [PATCH 7/7] [FEAT], open whatsapp, send email with gmail --- proyecto/david_casa/bot.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/proyecto/david_casa/bot.py b/proyecto/david_casa/bot.py index 31f3453..dc21b0c 100644 --- a/proyecto/david_casa/bot.py +++ b/proyecto/david_casa/bot.py @@ -8,11 +8,11 @@ import smtplib from email.message import EmailMessage -API_TOKEN = '7504345200:AAFl3uHBy3Qw0ZUW8INGrnoZamxcwjKe_lc' +API_TOKEN = 'YOUR_KEY' ADMIN_ID = 123456789 # Cambia por tu ID de admin -EMAIL_ADDRESS = "homesoftcore@gmail.com" -EMAIL_PASSWORD = "xymrywxnprquxevz" +EMAIL_ADDRESS = "YOUREMAIL@gmail.com" +EMAIL_PASSWORD = "YOUR_KEY" bot = telebot.TeleBot(API_TOKEN) app = Flask(__name__)