diff --git a/commands/admin.py b/commands/admin.py
new file mode 100644
index 0000000..e69de29
diff --git a/commands/help.py b/commands/help.py
new file mode 100644
index 0000000..31067f7
--- /dev/null
+++ b/commands/help.py
@@ -0,0 +1,41 @@
+from telegram import Update, InlineKeyboardButton, InlineKeyboardMarkup
+from telegram.ext import ContextTypes, Application, CommandHandler, CallbackQueryHandler
+from settings import VARIOS, INTERACCION, MATEMATICAS
+from util.messages import delete_user_message
+
+PAGES = [VARIOS, INTERACCION, MATEMATICAS]
+ITEMS_PER_PAGE = 1
+
+class Help:
+ def __init__(self, app: Application):
+ self.app = app
+ app.add_handler(CommandHandler("help", self.help))
+ app.add_handler(CallbackQueryHandler(self.callback, pattern="^help_"))
+
+ @delete_user_message
+ async def help(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
+ await self.send_help(update, page=0)
+
+ async def send_help(self, update: Update, page: int):
+ start_idx = page * ITEMS_PER_PAGE
+ end_idx = start_idx + ITEMS_PER_PAGE
+ text = "\n".join(PAGES[start_idx:end_idx])
+
+ keyboard = []
+ if page > 0:
+ keyboard.append(InlineKeyboardButton("⬅️ Anterior", callback_data=f"help_{page-1}"))
+ if end_idx < len(PAGES):
+ keyboard.append(InlineKeyboardButton("➡️ Siguiente", callback_data=f"help_{page+1}"))
+
+ reply_markup = InlineKeyboardMarkup([keyboard]) if keyboard else None
+
+ if update.message:
+ await update.message.reply_text(f"**Ayuda {page+1}/{(len(PAGES)-1)//ITEMS_PER_PAGE + 1}**\n\n{text}", parse_mode="Markdown", reply_markup=reply_markup)
+ elif update.callback_query:
+ await update.callback_query.edit_message_text(f"**Ayuda {page+1}/{(len(PAGES)-1)//ITEMS_PER_PAGE + 1}**\n\n{text}", parse_mode="Markdown", reply_markup=reply_markup)
+ await update.callback_query.answer()
+
+ async def callback(self, update: Update, context: ContextTypes.DEFAULT_TYPE):
+ query = update.callback_query
+ page = int(query.data.split("_")[1])
+ await self.send_help(update, page=page)
\ No newline at end of file
diff --git a/commands/interaction.py b/commands/interaction.py
new file mode 100644
index 0000000..80fa935
--- /dev/null
+++ b/commands/interaction.py
@@ -0,0 +1,553 @@
+from telegram import Update
+from telegram.ext import ContextTypes, Application, CommandHandler
+from time import time
+from settings import BOT_OWNER, BOT_NAME, BOT_VERSION, BOT_LANG, BOT_TYPE, BOT_OWNER_ID
+from random import randint, choice
+from util.messages import delete_user_message
+from util.anime import Anime
+
+class Interaction:
+ def __init__(self, app: Application):
+ self.app = app
+ self.anime = Anime()
+
+ app.add_handler(CommandHandler("waifu", self.waifu))
+ app.add_handler(CommandHandler("neko", self.neko))
+ app.add_handler(CommandHandler("shinobu", self.shinobu))
+ app.add_handler(CommandHandler("megumin", self.megumin))
+ app.add_handler(CommandHandler("bully", self.bully))
+ app.add_handler(CommandHandler("cuddle", self.cuddle))
+ app.add_handler(CommandHandler("cry", self.cry))
+ app.add_handler(CommandHandler("hug", self.hug))
+ app.add_handler(CommandHandler("awoo", self.awoo))
+ app.add_handler(CommandHandler("kiss", self.kiss))
+ app.add_handler(CommandHandler("lick", self.lick))
+ app.add_handler(CommandHandler("pat", self.pat))
+ app.add_handler(CommandHandler("smug", self.smug))
+ app.add_handler(CommandHandler("bonk", self.bonk))
+ app.add_handler(CommandHandler("yeet", self.yeet))
+ app.add_handler(CommandHandler("blush", self.blush))
+ app.add_handler(CommandHandler("smile", self.smile))
+ app.add_handler(CommandHandler("wave", self.wave))
+ app.add_handler(CommandHandler("highfive", self.highfive))
+ app.add_handler(CommandHandler("handhold", self.handhold))
+ app.add_handler(CommandHandler("nom", self.nom))
+ app.add_handler(CommandHandler("bite", self.bite))
+ app.add_handler(CommandHandler("glomp", self.glomp))
+ app.add_handler(CommandHandler("slap", self.slap))
+ app.add_handler(CommandHandler("kill", self.kill))
+ app.add_handler(CommandHandler("kick", self.kick))
+ app.add_handler(CommandHandler("happy", self.happy))
+ app.add_handler(CommandHandler("wink", self.wink))
+ app.add_handler(CommandHandler("poke", self.poke))
+ app.add_handler(CommandHandler("dance", self.dance))
+ app.add_handler(CommandHandler("cringe", self.cringe))
+ app.add_handler(CommandHandler("run", self.run))
+ app.add_handler(CommandHandler("fbi", self.fbi))
+ app.add_handler(CommandHandler("spank", self.spank))
+ app.add_handler(CommandHandler("ship", self.ship))
+ app.add_handler(CommandHandler("moan", self.moan))
+ app.add_handler(CommandHandler("femboize", self.femboize))
+
+ @delete_user_message
+ async def waifu(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
+ url = self.anime.sfw("waifu")
+ await update.effective_chat.send_animation(
+ animation=url,
+ caption=f"{update.effective_sender.first_name} ha pedido una waifu"
+ )
+
+ @delete_user_message
+ async def neko(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
+ url = self.anime.sfw("neko")
+ await update.effective_chat.send_animation(
+ animation=url,
+ caption=f"{update.effective_sender.first_name} ha pedido un neko"
+ )
+
+ @delete_user_message
+ async def shinobu(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
+ url = self.anime.sfw("shinobu")
+ await update.effective_chat.send_animation(
+ animation=url,
+ caption=f"{update.effective_sender.first_name} ha pedido una shinobu"
+ )
+
+ @delete_user_message
+ async def megumin(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
+ url = self.anime.sfw("megumin")
+ await update.effective_chat.send_animation(
+ animation=url,
+ caption=f"{update.effective_sender.first_name} ha pedido una megumin"
+ )
+
+ @delete_user_message
+ async def bully(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
+ if not context.args:
+ await update.effective_chat.send_message(
+ text=f"Debes especificar un usuario"
+ )
+ return
+
+
+ user = context.args[0]
+ url = self.anime.sfw("bully")
+ await update.effective_chat.send_animation(
+ animation=url,
+ caption=f"{update.effective_sender.first_name} le ha hecho bullying a {user}"
+ )
+
+ @delete_user_message
+ async def cuddle(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
+ if not context.args:
+ await update.effective_chat.send_message(
+ text=f"Debes especificar un usuario"
+ )
+ return
+
+
+ user = context.args[0]
+ url = self.anime.sfw("cuddle")
+ await update.effective_chat.send_animation(
+ animation=url,
+ caption=f"{update.effective_sender.first_name} se ha acurrucado con {user} uwu"
+ )
+
+ @delete_user_message
+ async def cry(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
+ url = self.anime.sfw("cry")
+ await update.effective_chat.send_animation(
+ animation=url,
+ caption=f"{update.effective_sender.first_name} se ha puesto a llorar :("
+ )
+
+ @delete_user_message
+ async def hug(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
+ if not context.args:
+ await update.effective_chat.send_message(
+ text=f"Debes especificar un usuario"
+ )
+ return
+
+
+ user = context.args[0]
+ url = self.anime.sfw("hug")
+ await update.effective_chat.send_animation(
+ animation=url,
+ caption=f"{update.effective_sender.first_name} ha abrazado a {user}"
+ )
+
+ @delete_user_message
+ async def awoo(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
+ url = self.anime.sfw("awoo")
+ await update.effective_chat.send_animation(
+ animation=url,
+ caption=f"{update.effective_sender.first_name} es un puto furro y ha pedido una foto de un furro"
+ )
+
+ @delete_user_message
+ async def kiss(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
+ if not context.args:
+ await update.effective_chat.send_message(
+ text=f"Debes especificar un usuario"
+ )
+ return
+
+
+ user = context.args[0]
+ url = self.anime.sfw("kiss")
+ await update.effective_chat.send_animation(
+ animation=url,
+ caption=f"{update.effective_sender.first_name} ha besado a {user} >///<"
+ )
+
+ @delete_user_message
+ async def lick(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
+ if not context.args:
+ await update.effective_chat.send_message(
+ text=f"Debes especificar un usuario"
+ )
+ return
+
+
+ user = context.args[0]
+ url = self.anime.sfw("lick")
+ await update.effective_chat.send_animation(
+ animation=url,
+ caption=f"{update.effective_sender.first_name} ha lamido a {user} OwO"
+ )
+
+ @delete_user_message
+ async def pat(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
+ if not context.args:
+ await update.effective_chat.send_message(
+ text=f"Debes especificar un usuario"
+ )
+ return
+
+
+ user = context.args[0]
+ url = self.anime.sfw("pat")
+ await update.effective_chat.send_animation(
+ animation=url,
+ caption=f"{update.effective_sender.first_name} ha acariciado a {user} >.<"
+ )
+
+ @delete_user_message
+ async def smug(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
+ if not context.args:
+ await update.effective_chat.send_message(
+ text=f"Debes especificar un usuario"
+ )
+ return
+
+
+ user = context.args[0]
+ url = self.anime.sfw("smug")
+ await update.effective_chat.send_animation(
+ animation=url,
+ caption=f"{update.effective_sender.first_name} se ha chuleado de {user}"
+ )
+
+ @delete_user_message
+ async def bonk(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
+ if not context.args:
+ await update.effective_chat.send_message(
+ text=f"Debes especificar un usuario"
+ )
+ return
+
+
+ user = context.args[0]
+ url = self.anime.sfw("bonk")
+ await update.effective_chat.send_animation(
+ animation=url,
+ caption=f"{update.effective_sender.first_name} le ha hecho bonk a {user}"
+ )
+
+ @delete_user_message
+ async def yeet(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
+ if not context.args:
+ await update.effective_chat.send_message(
+ text=f"Debes especificar un usuario"
+ )
+ return
+
+
+ user = context.args[0]
+ url = self.anime.sfw("yeet")
+ await update.effective_chat.send_animation(
+ animation=url,
+ caption=f"{update.effective_sender.first_name} ha lanzado a {user} a chuparla XD"
+ )
+
+ @delete_user_message
+ async def blush(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
+ url = self.anime.sfw("blush")
+ await update.effective_chat.send_animation(
+ animation=url,
+ caption=f"{update.effective_sender.first_name} se ha sonrojado >///<"
+ )
+
+ @delete_user_message
+ async def smile(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
+ url = self.anime.sfw("smile")
+ await update.effective_chat.send_animation(
+ animation=url,
+ caption=f"{update.effective_sender.first_name} ha sonreido"
+ )
+
+ @delete_user_message
+ async def wave(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
+ if not context.args:
+ await update.effective_chat.send_message(
+ text=f"Debes especificar un usuario"
+ )
+ return
+
+
+ user = context.args[0]
+ url = self.anime.sfw("wave")
+ await update.effective_chat.send_animation(
+ animation=url,
+ caption=f"{update.effective_sender.first_name} ha saludado a {user}"
+ )
+
+ @delete_user_message
+ async def highfive(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
+ if not context.args:
+ await update.effective_chat.send_message(
+ text=f"Debes especificar un usuario"
+ )
+ return
+
+
+ user = context.args[0]
+ url = self.anime.sfw("highfive")
+ await update.effective_chat.send_animation(
+ animation=url,
+ caption=f"{update.effective_sender.first_name} a chocado a {user} ;D"
+ )
+
+ @delete_user_message
+ async def handhold(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
+ if not context.args:
+ await update.effective_chat.send_message(
+ text=f"Debes especificar un usuario"
+ )
+ return
+
+
+ user = context.args[0]
+ url = self.anime.sfw("handhold")
+ await update.effective_chat.send_animation(
+ animation=url,
+ caption=f"{update.effective_sender.first_name} le ha cogido la manita a {user} u.u"
+ )
+
+ @delete_user_message
+ async def nom(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
+ url = self.anime.sfw("nom")
+ await update.effective_chat.send_animation(
+ animation=url,
+ caption=f"{update.effective_sender.first_name} se ha puesto a comer algo rico"
+ )
+
+ @delete_user_message
+ async def bite(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
+ if not context.args:
+ await update.effective_chat.send_message(
+ text=f"Debes especificar un usuario"
+ )
+ return
+
+
+ user = context.args[0]
+ url = self.anime.sfw("bite")
+ await update.effective_chat.send_animation(
+ animation=url,
+ caption=f"{update.effective_sender.first_name} ha mordido a {user} ùwú"
+ )
+
+ @delete_user_message
+ async def glomp(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
+ if not context.args:
+ await update.effective_chat.send_message(
+ text=f"Debes especificar un usuario"
+ )
+ return
+
+
+ user = context.args[0]
+ url = self.anime.sfw("glomp")
+ await update.effective_chat.send_animation(
+ animation=url,
+ caption=f"{update.effective_sender.first_name} se ha abalanzado sobre {user}"
+ )
+
+ @delete_user_message
+ async def slap(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
+ if not context.args:
+ await update.effective_chat.send_message(
+ text=f"Debes especificar un usuario"
+ )
+ return
+
+
+ user = context.args[0]
+ url = self.anime.sfw("slap")
+ await update.effective_chat.send_animation(
+ animation=url,
+ caption=f"{update.effective_sender.first_name} le ha dado una bofetada a {user}"
+ )
+
+ @delete_user_message
+ async def kill(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
+ if not context.args:
+ await update.effective_chat.send_message(
+ text=f"Debes especificar un usuario"
+ )
+ return
+
+
+ user = context.args[0]
+ url = self.anime.sfw("kill")
+ await update.effective_chat.send_animation(
+ animation=url,
+ caption=f"{update.effective_sender.first_name} ha matado a {user} 💀"
+ )
+
+ @delete_user_message
+ async def kick(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
+ if not context.args:
+ await update.effective_chat.send_message(
+ text=f"Debes especificar un usuario"
+ )
+ return
+
+
+ user = context.args[0]
+ url = self.anime.sfw("kick")
+ await update.effective_chat.send_animation(
+ animation=url,
+ caption=f"{update.effective_sender.first_name} le ha pegado una patada a {user}"
+ )
+
+ @delete_user_message
+ async def happy(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
+ url = self.anime.sfw("happy")
+ await update.effective_chat.send_animation(
+ animation=url,
+ caption=f"{update.effective_sender.first_name} está feliz :D"
+ )
+
+ @delete_user_message
+ async def wink(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
+ if not context.args:
+ await update.effective_chat.send_message(
+ text=f"Debes especificar un usuario"
+ )
+ return
+
+
+ user = context.args[0]
+ url = self.anime.sfw("wink")
+ await update.effective_chat.send_animation(
+ animation=url,
+ caption=f"{update.effective_sender.first_name} le ha guiñado el ojo a {user} ;)"
+ )
+
+ @delete_user_message
+ async def poke(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
+ if not context.args:
+ await update.effective_chat.send_message(
+ text=f"Debes especificar un usuario"
+ )
+ return
+
+
+ user = context.args[0]
+ url = self.anime.sfw("poke")
+ await update.effective_chat.send_animation(
+ animation=url,
+ caption=f"{update.effective_sender.first_name} está molestando a {user} ù.ú"
+ )
+
+ @delete_user_message
+ async def dance(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
+ url = self.anime.sfw("dance")
+ await update.effective_chat.send_animation(
+ animation=url,
+ caption=f"{update.effective_sender.first_name} se ha puesto a bailar"
+ )
+
+ @delete_user_message
+ async def cringe(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
+ if not context.args:
+ await update.effective_chat.send_message(
+ text=f"Debes especificar un usuario"
+ )
+ return
+
+
+ user = context.args[0]
+ caption=f"{update.effective_sender.first_name} le ha dado cringe lo que ha dicho {user}"
+ with open("data/images/interaction/cringe.gif", "rb") as gif:
+ await update.effective_chat.send_animation(
+ animation=gif,
+ caption=caption,
+ disable_notification=True
+ )
+
+
+ @delete_user_message
+ async def run(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
+ caption = f"{update.effective_sender.first_name} ha huido"
+ with open("data/images/interaction/run.gif", "rb") as gif:
+ await update.effective_chat.send_animation(
+ animation=gif,
+ caption=caption,
+ disable_notification=True
+ )
+
+ @delete_user_message
+ async def fbi(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
+ if not context.args:
+ await update.effective_chat.send_message(
+ text=f"Debes especificar un usuario"
+ )
+ return
+
+
+ user = context.args[0]
+ caption = f"{update.effective_sender.first_name} ha llamado al FBI! Corre {user}!!!!"
+ with open("data/images/interaction/fbi.gif", "rb") as gif:
+ await update.effective_chat.send_animation(
+ animation=gif,
+ caption=caption,
+ disable_notification=True
+ )
+
+ @delete_user_message
+ async def spank(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
+ if not context.args:
+ await update.effective_chat.send_message(
+ text=f"Debes especificar un usuario"
+ )
+ return
+
+
+ user = context.args[0]
+ caption = f"{update.effective_sender.first_name} le ha dado una nalgada a {user}"
+ with open("data/images/interaction/spank.gif", "rb") as gif:
+ await update.effective_chat.send_animation(
+ animation=gif,
+ caption=caption,
+ disable_notification=True
+ )
+
+ @delete_user_message
+ async def ship(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
+ if not context.args:
+ await update.effective_chat.send_message(
+ text=f"Debes especificar dos usuarios"
+ )
+ return
+
+ user1 = context.args[0]
+ user2 = context.args[1]
+ caption = f"{user1} x {user2} tienen una compatibilidad del {randint(0,100)}%"
+ with open("data/images/interaction/ship.gif", "rb") as gif:
+ await update.effective_chat.send_animation(
+ animation=gif,
+ caption=caption,
+ disable_notification=True
+ )
+
+ @delete_user_message
+ async def moan(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
+ caption = f"{update.effective_sender.first_name} ha gemido como una perra"
+ with open("data/images/interaction/moan.gif", "rb") as gif:
+ await update.effective_chat.send_animation(
+ animation=gif,
+ caption=caption,
+ disable_notification=True
+ )
+
+ @delete_user_message
+ async def femboize(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
+ if not context.args:
+ await update.effective_chat.send_message(
+ text=f"Debes especificar un usuario"
+ )
+ return
+
+
+ user = context.args[0]
+ caption = f"{update.effective_sender.first_name} ha convertido en femboy a {user}"
+ with open("data/images/interaction/femboy.png", "rb") as png:
+ await update.effective_chat.send_photo(
+ photo=png,
+ caption=caption,
+ disable_notification=True
+ )
\ No newline at end of file
diff --git a/commands/math.py b/commands/math.py
new file mode 100644
index 0000000..61b4808
--- /dev/null
+++ b/commands/math.py
@@ -0,0 +1,175 @@
+from telegram import Update
+from telegram.ext import ContextTypes, Application, CommandHandler
+from random import randint, choice
+from util.messages import delete_user_message
+import matplotlib.pyplot as plt
+import numpy as np
+from util.numbers import is_even, is_prime
+from settings import GRAPH_PATH
+from matplotlib.patches import Circle
+
+class Math:
+ def __init__(self, app: Application):
+ self.app = app
+ app.add_handler(CommandHandler("calcular", self.calculate))
+ app.add_handler(CommandHandler("par", self.even))
+ app.add_handler(CommandHandler("primo", self.prime))
+ app.add_handler(CommandHandler("seno", self.sine))
+ app.add_handler(CommandHandler("coseno", self.cosine))
+ app.add_handler(CommandHandler("recta", self.rect))
+ app.add_handler(CommandHandler("parabola", self.parable))
+ app.add_handler(CommandHandler("circunferencia", self.circle))
+ app.add_handler(CommandHandler("log", self.log))
+ app.add_handler(CommandHandler("exp", self.exp))
+
+ @delete_user_message
+ async def calculate(self, update:Update, context: ContextTypes.DEFAULT_TYPE) -> None:
+ if not context.args:
+ await update.effective_chat.send_message(
+ text="Debes especificar una expresión matemática",
+ disable_notification=True
+ )
+ return
+
+ expression = " ".join(context.args)
+ try:
+ result = eval(expression)
+ await update.effective_chat.send_message(
+ text=f"El resultado de {expression} es {result}",
+ disable_notification=True
+ )
+ except Exception as e:
+ await update.effective_chat.send_message(
+ text=f"Error al calcular la expresión: {e}",
+ disable_notification=True
+ )
+
+ @delete_user_message
+ async def even(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
+ if not context.args:
+ await update.effective_chat.send_message(
+ text="Debes especificar un número",
+ disable_notification=True
+ )
+ return
+
+ number = int(context.args[0])
+ await update.effective_chat.send_message(
+ text=f"{number} es un número par." if is_even(number) else f"{number} es un número impar.",
+ disable_notification=True
+ )
+
+ @delete_user_message
+ async def prime(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
+ if not context.args:
+ await update.effective_chat.send_message(
+ text="Debes especificar un número",
+ disable_notification=True
+ )
+ return
+
+ number = int(context.args[0])
+ await update.effective_chat.send_message(
+ text=f"{number} es un número primo." if is_prime(number) else f"{number} es un número compuesto.",
+ disable_notification=True
+ )
+
+ async def send_graph(self, update: Update):
+ await update.effective_chat.send_photo(open(GRAPH_PATH, "rb"))
+ plt.clf()
+
+ @delete_user_message
+ async def sine(self, update: Update, context: ContextTypes.DEFAULT_TYPE):
+ if len(context.args) < 2:
+ await update.effective_chat.send_message("Debes dar a y k: /grafseno a k")
+ return
+ a, k = map(int, context.args[:2])
+ x = np.linspace(0, 2*np.pi, 400)
+ y = a * np.sin(k*x)
+ plt.axhline(0, color="black")
+ plt.plot(x, y, color="#b2122f")
+ plt.savefig(GRAPH_PATH)
+ await self.send_graph(update)
+
+ @delete_user_message
+ async def cosine(self, update: Update, context: ContextTypes.DEFAULT_TYPE):
+ if len(context.args) < 2:
+ await update.effective_chat.send_message("Debes dar a y k: /grafcoseno a k")
+ return
+ a, k = map(int, context.args[:2])
+ x = np.linspace(0, 2*np.pi, 400)
+ y = a * np.cos(k*x)
+ plt.axhline(0, color="black")
+ plt.plot(x, y, color="#b2122f")
+ plt.savefig(GRAPH_PATH)
+ await self.send_graph(update)
+
+ @delete_user_message
+ async def rect(self, update: Update, context: ContextTypes.DEFAULT_TYPE):
+ if len(context.args) < 2:
+ await update.effective_chat.send_message("Debes dar m y n: /grafrecta m n")
+ return
+ m, n = map(int, context.args[:2])
+ x = np.linspace(-10, 10, 400)
+ y = m*x + n
+ plt.axhline(0, color="black")
+ plt.axvline(0, color="black")
+ plt.plot(x, y, color="#b2122f")
+ plt.savefig(GRAPH_PATH)
+ await self.send_graph(update)
+
+ @delete_user_message
+ async def parable(self, update: Update, context: ContextTypes.DEFAULT_TYPE):
+ if len(context.args) < 3:
+ await update.effective_chat.send_message("Debes dar a, b, c: /grafparabola a b c")
+ return
+ a, b, c = map(int, context.args[:3])
+ x = np.linspace(-10, 10, 400)
+ y = a*x**2 + b*x + c
+ plt.axhline(0, color="black")
+ plt.axvline(0, color="black")
+ plt.plot(x, y, color="#b2122f")
+ plt.savefig(GRAPH_PATH)
+ await self.send_graph(update)
+
+ @delete_user_message
+ async def circle(self, update: Update, context: ContextTypes.DEFAULT_TYPE):
+ if not context.args:
+ await update.effective_chat.send_message("Debes dar el radio: /grafcircunferencia r")
+ return
+ r = int(context.args[0])
+ fig, ax = plt.subplots()
+ ax.set_aspect('equal')
+ ax.add_artist(Circle((0, 0), r, color='r'))
+ plt.xlim(-10, 10)
+ plt.ylim(-10, 10)
+ plt.savefig(GRAPH_PATH)
+ await self.send_graph(update)
+
+ @delete_user_message
+ async def log(self, update: Update, context: ContextTypes.DEFAULT_TYPE):
+ if len(context.args) < 2:
+ await update.effective_chat.send_message("Debes dar a y b: /graflog a b")
+ return
+ a, b = map(int, context.args[:2])
+ x = np.linspace(0.01, 10, 400)
+ y = a*np.log(x) + b
+ plt.axhline(0, color="black")
+ plt.axvline(0, color="black")
+ plt.plot(x, y, color="#b2122f")
+ plt.savefig(GRAPH_PATH)
+ await self.send_graph(update)
+
+ @delete_user_message
+ async def exp(self, update: Update, context: ContextTypes.DEFAULT_TYPE):
+ if len(context.args) < 2:
+ await update.effective_chat.send_message("Debes dar a y b: /grafexp a b")
+ return
+ a, b = map(int, context.args[:2])
+ x = np.linspace(-10, 10, 400)
+ y = a*np.exp(b*x)
+ plt.axhline(0, color="black")
+ plt.axvline(0, color="black")
+ plt.plot(x, y, color="#b2122f")
+ plt.savefig(GRAPH_PATH)
+ await self.send_graph(update)
\ No newline at end of file
diff --git a/commands/misc.py b/commands/misc.py
new file mode 100644
index 0000000..8ec891c
--- /dev/null
+++ b/commands/misc.py
@@ -0,0 +1,162 @@
+from telegram import Update
+from telegram.ext import ContextTypes, Application, CommandHandler
+from time import time
+from settings import BOT_OWNER, BOT_NAME, BOT_VERSION, BOT_LANG, BOT_TYPE, BOT_OWNER_ID
+from random import randint, choice
+from util.messages import delete_user_message
+
+class Misc:
+ def __init__(self, app: Application):
+ self.app = app
+ app.add_handler(CommandHandler("ping", self.ping))
+ app.add_handler(CommandHandler("info", self.info))
+ app.add_handler(CommandHandler("say", self.say))
+ app.add_handler(CommandHandler("banana", self.banana))
+ app.add_handler(CommandHandler("dado", self.dice))
+ app.add_handler(CommandHandler("moneda", self.coin))
+ app.add_handler(CommandHandler("paredes", self.walls))
+ app.add_handler(CommandHandler("oooh", self.oooh))
+ app.add_handler(CommandHandler("beber", self.drink))
+ app.add_handler(CommandHandler("bombardeen", self.bomb))
+
+ @delete_user_message
+ async def ping(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
+ before = update.message.date.timestamp()
+ now = time()
+ await update.effective_chat.send_message(
+ text=f"🏓 Pong! Latency is {round((now - before) * 1000, 2)} ms",
+ parse_mode="HTML",
+ disable_notification=True
+ )
+
+ @delete_user_message
+ async def info(self, update:Update, context: ContextTypes.DEFAULT_TYPE) -> None:
+ group = update.effective_chat.title
+ chat_id = update.effective_chat.id
+ member_count = await context.bot.get_chat_member_count(chat_id)
+ command_count = sum(1 for c in context.application.handlers[0] if isinstance(c, CommandHandler))
+ info_text = f"""
+Grupo: {group}
+Miembros: {member_count}
+Creador: {BOT_OWNER}
+Nº Comandos: {command_count}
+
+Info técnica:
+Nombre: {BOT_NAME}
+Lenguaje: {BOT_LANG}
+Tipo: {BOT_TYPE}
+Versión: {BOT_VERSION}
+ """
+
+ await update.effective_chat.send_message(
+ text=info_text,
+ parse_mode="HTML",
+ disable_notification=True
+ )
+
+ @delete_user_message
+ async def say(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
+ if not context.args:
+ await update.effective_chat.send_message(
+ text="Pero dime lo que tengo que decir puta",
+ disable_notification=True
+ )
+ return
+ await update.effective_chat.send_message(
+ text=" ".join(arg for arg in context.args),
+ disable_notification=True
+ )
+
+ @delete_user_message
+ async def banana(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
+ if update.effective_sender.id == BOT_OWNER_ID:
+ await update.effective_chat.send_message(
+ text=f"La banana de {update.effective_user.first_name} mide 21 cm 😳",
+ disable_notification=True
+ )
+ else:
+ await update.effective_chat.send_message(
+ text=f"La banana de {update.effective_user.first_name} mide {randint(-5, 21)} cm 😳",
+ disable_notification=True
+ )
+
+ @delete_user_message
+ async def dice(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
+ await update.effective_chat.send_dice(
+ emoji='🎲',
+ disable_notification=True
+ )
+
+ @delete_user_message
+ async def coin(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
+ html =f"""
+🪙 Se ha lanzado la moneda
+Resultado: {choice(("Cara 😀", "Cruz ❌"))}
+ """
+ await update.effective_chat.send_message(
+ text=html,
+ parse_mode="HTML",
+ disable_notification=True
+ )
+
+ @delete_user_message
+ async def walls(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
+ if not context.args:
+ await update.effective_chat.send_message(
+ text="Debes especificar un usuario",
+ disable_notification=True
+ )
+ return
+
+ if not context.args[0].startswith("@"):
+ await update.effective_chat.send_message(
+ text="Debes mencionar a un usuario",
+ disable_notification=True
+ )
+ return
+
+ user = context.args[0]
+ caption = f"{user} está por las paredes"
+
+ with open("data/images/interaction/paredes.gif", "rb") as gif:
+ await update.effective_chat.send_animation(
+ animation=gif,
+ caption=caption,
+ disable_notification=True
+ )
+
+ @delete_user_message
+ async def oooh(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
+ with open("data/images/interaction/oooh.gif", "rb") as gif:
+ await update.effective_chat.send_animation(
+ animation=gif,
+ disable_notification=True
+ )
+
+ @delete_user_message
+ async def drink(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
+ drinks = ["cerveza", "vino", "whisky", "ron", "vodka", "tequila", "ginebra", "sidra", "champán", "cava", "sake", "absenta", "brandy", "licor", "vermut", "mezcal", "pacharán", "anís", "aguardiente", "coñac", "cóctel", "cubata", "cóctel", "cubalibre"]
+ with open("data/images/interaction/beber.gif", "rb") as gif:
+ await update.effective_chat.send_animation(
+ animation=gif,
+ caption=f"@{update.effective_sender.username} ha bebido {choice(drinks)}",
+ disable_notification=True
+ )
+
+ @delete_user_message
+ async def bomb(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
+ if not context.args:
+ await update.effective_chat.send_message(
+ text="Debes especificar algo que bombardear",
+ disable_notification=True
+ )
+ return
+
+ with open("data/images/interaction/bombardeen.gif") as gif:
+ await update.effective_chat.send_animation(
+ animation=gif,
+ caption=f"Bombardeen {context.args[0]}",
+ disable_notification=True
+ )
+
+
\ No newline at end of file
diff --git a/data/files/counter.csv b/data/files/counter.csv
new file mode 100644
index 0000000..56a6051
--- /dev/null
+++ b/data/files/counter.csv
@@ -0,0 +1 @@
+1
\ No newline at end of file
diff --git a/data/files/grupos.txt b/data/files/grupos.txt
new file mode 100644
index 0000000..a1afbbc
--- /dev/null
+++ b/data/files/grupos.txt
@@ -0,0 +1,60 @@
+Imagine Dragons
+Lil Nas X
+Ed Sheeran
+OneRepublic
+Harry Styles
+Mägo de Oz
+Black Eyed Peas
+Måneskin
+BoyWithUke
+Bad Bunny
+Bizarrap
+The Score
+bbno$
+The Weeknd
+Green Day
+Queen
+AC/DC
+Elton John
+Coldplay
+LiSA
+Glass Animals
+Post Malone
+KSI
+Cardi B
+JBalvin
+Marshmello
+Farruko
+Dua Lipa
+Ava Max
+Armin van Buuren
+Panic! At The Disco
+Billie Eilish
+Alan Walker
+Bebe Rexha
+Bruno Mars
+Miley Cyrus
+Maroon 5
+Tones And I
+Why don't we
+Ali Gatie
+Canserbero
+Residente
+Dire Straits
+Pink Floyd
+Prince
+The Police
+Guns N' Roses
+Linkin Park
+Scorpion
+Status Quo
+Justin Bieber
+Michael Jackson
+Ariana Grande
+Beyoncé
+Lady Gaga
+Katy Perry
+Adele
+Drake
+Taylor Swift
+Rihanna
\ No newline at end of file
diff --git a/data/files/hugs.json b/data/files/hugs.json
new file mode 100644
index 0000000..e69de29
diff --git a/data/files/juegos.txt b/data/files/juegos.txt
new file mode 100644
index 0000000..e01d4a4
--- /dev/null
+++ b/data/files/juegos.txt
@@ -0,0 +1,60 @@
+Dishonored 2
+The Witness
+Journey
+Uncharted 2: Among Thieves
+Overwatch
+Apex Legends
+Hollow Knig
+Ms. Pac-Man
+Counter-Strike 1.6
+Left 4 Dead 2
+EarthBound
+Diablo II
+StarCraft
+World of Warcraft
+Star Wars: Knights of the Old Republic
+Fallout: New Vegas
+Final Fantasy VI
+Pokémon Yellow
+Metroid Prime
+The Elder Scrolls V: Skyrim
+Resident Evil 4
+Shadow of the Colossus
+The Last of Us Part 2
+Red Dead Redemption
+Metal Gear Solid
+Sid Meier's Civilization IV
+The Legend of Zelda: Ocarina of Time
+Minecraft
+Halo: Combat Evolved
+Half-Life
+Final Fantasy XIV
+Doom
+Tetris
+Metal Gear Solid 3: Snake Eater
+Half-Life: Alyx
+God of War
+Chrono Trigger
+Portal
+Street Fighter II
+Super Mario Bros.
+Undertale
+Bloodborne
+BioShock
+The Last of Us
+The Witcher 3: Wild Hunt
+Halo 2
+Castlevania: Symphony of the Night
+Hades
+Grand Theft Auto V
+Super Mario Bros. 3
+Disco Elysium
+Half-Life 2
+Red Dead Redemption 2
+Super Mario 64
+Mass Effect 2
+Super Metroid
+The Legend of Zelda: A Link to the Past
+Portal 2
+Super Mario World
+The Legend of Zelda: Breath of the Wild
\ No newline at end of file
diff --git a/data/files/shows.txt b/data/files/shows.txt
new file mode 100644
index 0000000..77f0137
--- /dev/null
+++ b/data/files/shows.txt
@@ -0,0 +1,60 @@
+Squid Game
+La Casa de Papel
+Lupin
+Avatar
+Los Simpson
+Lightyear
+Tadeo Jones
+Los Minions
+Doraemon
+Shin-Chan
+JoJo's Bizarre Adventures
+Boku no Hero Academia
+Fullmetal Alchemist
+SPY X FAMILY
+Black Clover
+My Dress-up Darling
+New Amsterdam
+Death Note
+Cobra Kai
+Karate Kid
+Interstellar
+Cómo entrenar a tu dragón
+Free Guy
+Spider Man
+Dr Strange
+Matrix
+John Wick
+Iron Man
+The Good Doctor
+Komi-san can't communicate
+Big Mouth
+(Des)encanto
+Rick y Morty
+Historias Corrientes
+Hora de Aventuras
+Chowder
+Star Trek
+Star Wars
+Lost in Space
+Tokyo Revengers
+Gladiator
+The Crown
+Peaky Blinders
+Sex Education
+Enola Holmes
+Los Juegos del Hambre
+Juego de Tronos
+El Señor de los Anillos
+La princesa mononoke
+Hitman
+Los Croods
+Plan de Escape
+Código Lyoko
+El Padrino
+El viaje de Chihiro
+El castillo ambulante
+Coach Carter
+Mascotas
+Aida
+La que se avecina
\ No newline at end of file
diff --git a/data/files/warns.json b/data/files/warns.json
new file mode 100644
index 0000000..e69de29
diff --git a/data/images/djpype.png b/data/images/djpype.png
new file mode 100644
index 0000000..3cdcd8b
Binary files /dev/null and b/data/images/djpype.png differ
diff --git a/data/images/graph.png b/data/images/graph.png
new file mode 100644
index 0000000..6f151a9
Binary files /dev/null and b/data/images/graph.png differ
diff --git a/data/images/interaction/beber.gif b/data/images/interaction/beber.gif
new file mode 100644
index 0000000..54d9cef
Binary files /dev/null and b/data/images/interaction/beber.gif differ
diff --git a/data/images/interaction/bombardeen.gif b/data/images/interaction/bombardeen.gif
new file mode 100644
index 0000000..777d5ca
Binary files /dev/null and b/data/images/interaction/bombardeen.gif differ
diff --git a/data/images/interaction/carey.webm b/data/images/interaction/carey.webm
new file mode 100644
index 0000000..b37a5ed
Binary files /dev/null and b/data/images/interaction/carey.webm differ
diff --git a/data/images/interaction/cringe.gif b/data/images/interaction/cringe.gif
new file mode 100644
index 0000000..f1d7338
Binary files /dev/null and b/data/images/interaction/cringe.gif differ
diff --git a/data/images/interaction/fbi.gif b/data/images/interaction/fbi.gif
new file mode 100644
index 0000000..2d3e17b
Binary files /dev/null and b/data/images/interaction/fbi.gif differ
diff --git a/data/images/interaction/femboy.png b/data/images/interaction/femboy.png
new file mode 100644
index 0000000..970e9fa
Binary files /dev/null and b/data/images/interaction/femboy.png differ
diff --git a/data/images/interaction/moan.gif b/data/images/interaction/moan.gif
new file mode 100644
index 0000000..5301d40
Binary files /dev/null and b/data/images/interaction/moan.gif differ
diff --git a/data/images/interaction/oooh.gif b/data/images/interaction/oooh.gif
new file mode 100644
index 0000000..286533f
Binary files /dev/null and b/data/images/interaction/oooh.gif differ
diff --git a/data/images/interaction/paredes.gif b/data/images/interaction/paredes.gif
new file mode 100644
index 0000000..ecc6fbc
Binary files /dev/null and b/data/images/interaction/paredes.gif differ
diff --git a/data/images/interaction/run.gif b/data/images/interaction/run.gif
new file mode 100644
index 0000000..94a62dd
Binary files /dev/null and b/data/images/interaction/run.gif differ
diff --git a/data/images/interaction/ship.gif b/data/images/interaction/ship.gif
new file mode 100644
index 0000000..c5e56c2
Binary files /dev/null and b/data/images/interaction/ship.gif differ
diff --git a/data/images/interaction/spank.gif b/data/images/interaction/spank.gif
new file mode 100644
index 0000000..13f2480
Binary files /dev/null and b/data/images/interaction/spank.gif differ
diff --git a/data/images/logo.png b/data/images/logo.png
new file mode 100644
index 0000000..1740e79
Binary files /dev/null and b/data/images/logo.png differ
diff --git a/data/images/pype.png b/data/images/pype.png
new file mode 100644
index 0000000..882cd8c
Binary files /dev/null and b/data/images/pype.png differ
diff --git a/main.py b/main.py
new file mode 100644
index 0000000..470b453
--- /dev/null
+++ b/main.py
@@ -0,0 +1,33 @@
+import os
+from pathlib import Path
+from dotenv import load_dotenv
+from telegram import Update
+from telegram.ext import ApplicationBuilder, CommandHandler, ContextTypes
+
+# importing command classes
+from commands.misc import Misc
+from commands.math import Math
+from commands.interaction import Interaction
+from commands.help import Help
+
+class PypeBot:
+ def __init__(self):
+ load_dotenv()
+ self.app = ApplicationBuilder().token(os.getenv("TOKEN")).build()
+
+ # command registering
+ Misc(self.app)
+ Math(self.app)
+ Interaction(self.app)
+ Help(self.app)
+
+ async def start(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
+ await update.message.reply_text("Tamo' activo B)")
+
+def main() -> None:
+ bot = PypeBot()
+ bot.app.add_handler(CommandHandler("start", bot.start))
+ bot.app.run_polling()
+
+if __name__ == '__main__':
+ main()
\ No newline at end of file
diff --git a/requirements.txt b/requirements.txt
new file mode 100644
index 0000000..25b3a7b
--- /dev/null
+++ b/requirements.txt
@@ -0,0 +1,4 @@
+matplotlib
+telegram
+python-telegram-bot
+numpy
\ No newline at end of file
diff --git a/settings.py b/settings.py
new file mode 100644
index 0000000..939550c
--- /dev/null
+++ b/settings.py
@@ -0,0 +1,92 @@
+ ##### ####### # # ####### ### ##### # # ###### # ##### ### ####### # #
+ # # # # ## # # # # # # # # # # # # # # # # ## #
+ # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # ##### # # #### # # ###### # # # # # # # # #
+ # # # # # # # # # # # # # # ####### # # # # # # #
+ # # # # # ## # # # # # # # # # # # # # # # # ##
+ ##### ####### # # # ### ##### ##### # # # # ##### ### ####### # #
+
+# Configuración de parámetros del bot
+GUILD_NAME = "The Boys" # nombre del servidor
+BOT_OWNER = "Gallardo7761"
+BOT_OWNER_ID = 8068730345
+BOT_LOGO ="data/images/pype.png" # png/jpg
+BOT_NAME = "Pype" # nombre a elegir
+BOT_LANG = "Python" # lenguaje
+BOT_TYPE = "Multipropósito" # tipo
+BOT_VERSION = "1.0.0" # versión del bot
+LAVALINK_URI = '' # ip del servidor de Lavalink
+LAVALINK_PASSWORD = ''
+TIMEZONE = "Europe/Madrid" # zona horaria
+GRAPH_PATH = "data/images/graph.png" # ruta para guardar gráficos
+
+# Cofiguración de parámetros del comando /help
+VARIOS = """
+**MISCELÁNEA**
+**/ping** - Ping de Pype.
+**/info** - Info del discord.
+**/say ** - Pype dice algo.
+**/platano** - Banana!
+**/dado** - Tira un dado de 6 caras.
+**/moneda** - Tira una moneda al aire.
+**/paredes ** - Están por las paredes.
+**/oooh** - Ooooooooh! .- Exclamaron Mordecai y Rigby.
+**/beber** - Bebe algo.
+**/bombardeen ** - Bombardeen algo.
+"""
+
+INTERACCION = """
+**INTERACCIÓN**
+**/waifu** - Te da una waifu aleatoria en GIF.
+**/neko** - Te da un neko aleatorio en GIF.
+**/shinobu** - Te da un GIF de Shinobu.
+**/megumin** - Te da un GIF de Megumin.
+**/bully ** - Haz bullying a alguien (GIF).
+**/cuddle ** - Acurrúcate con alguien (GIF).
+**/cry** - Llora con un GIF.
+**/hug ** - Abraza a alguien (GIF).
+**/awoo** - Pide un GIF de furro.
+**/kiss ** - Besa a alguien (GIF).
+**/lick ** - Lame a alguien (GIF).
+**/pat ** - Acaricia a alguien (GIF).
+**/smug ** - Presume ante alguien (GIF).
+**/bonk ** - Da un bonk a alguien (GIF).
+**/yeet ** - Lanza a alguien (GIF).
+**/blush** - Sonrojarse (GIF).
+**/smile** - Sonríe (GIF).
+**/wave ** - Saluda a alguien (GIF).
+**/highfive ** - Choca la mano con alguien (GIF).
+**/handhold ** - Cógela mano a mano con alguien (GIF).
+**/nom** - Come algo rico (GIF).
+**/bite ** - Muérdele a alguien (GIF).
+**/glomp ** - Abalánzate sobre alguien (GIF).
+**/slap ** - Da una bofetada a alguien (GIF).
+**/kill ** - Mata a alguien (GIF).
+**/kick ** - Patea a alguien (GIF).
+**/happy** - Estás feliz (GIF).
+**/wink ** - Guiña el ojo a alguien (GIF).
+**/poke ** - Molesta a alguien (GIF).
+**/dance ** - Baila (GIF).
+**/cringe ** - Da cringe lo que hizo alguien (GIF).
+**/run** - Huyes (GIF local).
+**/fbi ** - Llama al FBI para alguien (GIF local).
+**/spank ** - Da una nalgada a alguien (GIF local).
+**/ship ** - Comprueba compatibilidad entre dos personas (GIF local).
+**/moan** - Gemido (GIF local).
+**/femboize ** - Convierte a alguien en femboy (PNG local).
+"""
+
+
+MATEMATICAS = """
+**MATEMÁTICAS**
+**/calcular ** - Calcula expresiones matemáticas varias.
+**/par ** - Comprueba si un número es par o no.
+**/primo ** - Comprueba si un número es primo o no.
+**/seno ** - Grafica una función seno.
+**/coseno ** - Grafica una función coseno.
+**/recta ** - Grafica una función lineal.
+**/parabola ** ** - Grafica una función cuadrática.
+**/circunferencia ** - Grafica una circunferencia.
+**/log **** - Grafica una función logarítmica.
+**/exp **** - Grafica una función exponencial.
+"""
\ No newline at end of file
diff --git a/util/anime.py b/util/anime.py
new file mode 100644
index 0000000..241ffbe
--- /dev/null
+++ b/util/anime.py
@@ -0,0 +1,24 @@
+import requests
+
+class Anime:
+ def __init__(self):
+ self.base_url = f"https://api.waifu.pics/"
+
+ def get(self, type: str, category: str) -> None:
+ if type != "nsfw" and type != "sfw":
+ raise Exception("Type not supported!")
+
+ if not isinstance(category, str):
+ raise Exception("Category must be a string!")
+
+ response = requests.get(f"{self.base_url}/{type}/{category}")
+ if response.status_code != 200:
+ raise Exception("Failed to retrieve data from API!")
+
+ return response.json()["url"]
+
+ def sfw(self, category: str) -> str:
+ return self.get("sfw", category)
+
+ def nsfw(self, category: str) -> str:
+ return self.get("nsfw", category)
\ No newline at end of file
diff --git a/util/files.py b/util/files.py
new file mode 100644
index 0000000..fd69242
--- /dev/null
+++ b/util/files.py
@@ -0,0 +1,17 @@
+import json
+
+def read(file: str) -> str:
+ with open(file, "r") as f:
+ return f.read()
+
+def read_json(file: str) -> dict:
+ with open(file, "r") as f:
+ return json.load(f)
+
+def write(file: str, content: str) -> None:
+ with open(file, "w") as f:
+ f.write(content)
+
+def write_json(file: str, content: dict) -> None:
+ with open(file, "w") as f:
+ json.dump(content, f, indent=4, sort_keys=True, separators=(',', ': '), ensure_ascii=False)
\ No newline at end of file
diff --git a/util/logger/colors.py b/util/logger/colors.py
new file mode 100644
index 0000000..6250538
--- /dev/null
+++ b/util/logger/colors.py
@@ -0,0 +1,13 @@
+class Colors:
+ RED = "\033[91m"
+ GREEN = "\033[92m"
+ YELLOW = "\033[93m"
+ BLUE = "\033[94m"
+ MAGENTA = "\033[95m"
+ CYAN = "\033[96m"
+ WHITE = "\033[97m"
+ RESET = "\033[0m"
+ BOLD = "\033[1m"
+ UNDERLINE = "\033[4m"
+ LIME = "\033[32m"
+ GRAY = "\033[90m"
\ No newline at end of file
diff --git a/util/logger/logger.py b/util/logger/logger.py
new file mode 100644
index 0000000..f2b34d1
--- /dev/null
+++ b/util/logger/logger.py
@@ -0,0 +1,43 @@
+from .colors import Colors
+from datetime import datetime
+import pytz
+import traceback
+
+class PypeLogger:
+ @staticmethod
+ def info(message):
+ now = datetime.now(tz=pytz.timezone("Europe/Madrid")).strftime("%H:%M:%S")
+ print(f"{Colors.GRAY}[{now}] {Colors.GREEN}[INFO] {message}{Colors.RESET}")
+
+ @staticmethod
+ def error(message, exception=None):
+ now = datetime.now(tz=pytz.timezone("Europe/Madrid")).strftime("%H:%M:%S")
+ main_error = f"{Colors.GRAY}[{now}] {Colors.RED}[ERROR] {message}{Colors.RESET}"
+ error_messages = [main_error]
+ if exception:
+ exception_message = f"\n{Colors.GRAY}[{now}] {Colors.RED}[ERROR] - Exception: {exception}"
+ traceback_message = f"\n{Colors.GRAY}[{now}] {Colors.RED}[ERROR] - Traceback: {traceback.format_exc()}"
+ error_messages.append(exception_message)
+ error_messages.append(traceback_message)
+ for error_message in error_messages:
+ print(error_message)
+
+ @staticmethod
+ def debug(message):
+ now = datetime.now(tz=pytz.timezone("Europe/Madrid")).strftime("%H:%M:%S")
+ print(f"{Colors.GRAY}[{now}] {Colors.BLUE}[DEBUG] {message}{Colors.RESET}")
+
+ @staticmethod
+ def warning(message):
+ now = datetime.now(tz=pytz.timezone("Europe/Madrid")).strftime("%H:%M:%S")
+ print(f"{Colors.GRAY}[{now}] {Colors.YELLOW}[WARNING] {message}{Colors.RESET}")
+
+ @staticmethod
+ def success(message):
+ now = datetime.now(tz=pytz.timezone("Europe/Madrid")).strftime("%H:%M:%S")
+ print(f"{Colors.GRAY}[{now}] {Colors.LIME}[SUCCESS] {message}{Colors.RESET}")
+
+ @staticmethod
+ def command(message):
+ now = datetime.now(tz=pytz.timezone("Europe/Madrid")).strftime("%H:%M:%S")
+ print(f"{Colors.GRAY}[{now}] {Colors.MAGENTA}[COMMAND] {message}{Colors.RESET}")
\ No newline at end of file
diff --git a/util/messages.py b/util/messages.py
new file mode 100644
index 0000000..eaad5ee
--- /dev/null
+++ b/util/messages.py
@@ -0,0 +1,18 @@
+from telegram import Update
+from telegram.ext import ContextTypes
+
+async def respond(context: ContextTypes.DEFAULT_TYPE, chat_id: int, message: str):
+ await context.bot.send_message(
+ chat_id=chat_id,
+ text="✅ Mensaje recibido",
+ disable_notification=True
+ )
+
+def delete_user_message(func):
+ async def wrapper(self, update: Update, context: ContextTypes.DEFAULT_TYPE):
+ await func(self, update, context)
+ try:
+ await context.bot.delete_message(update.effective_chat.id, update.message.message_id)
+ except:
+ pass
+ return wrapper
\ No newline at end of file
diff --git a/util/numbers.py b/util/numbers.py
new file mode 100644
index 0000000..2c7a1b0
--- /dev/null
+++ b/util/numbers.py
@@ -0,0 +1,10 @@
+def is_even(n: int) -> bool:
+ return n % 2 == 0
+
+def is_prime(n: int) -> bool:
+ if n <= 1:
+ return False
+ for i in range(2, int(n**0.5) + 1):
+ if n % i == 0:
+ return False
+ return True
\ No newline at end of file