Browse Source

Primer Crxs

CrxsMods 11 months ago
commit
8b246509a5
100 changed files with 14213 additions and 0 deletions
  1. 19 0
      Dockerfile
  2. 21 0
      LICENSE
  3. BIN
      Menu2.jpg
  4. 1 0
      Procfile
  5. 163 0
      README.md
  6. 18 0
      app.json
  7. 1 0
      audio/file
  8. 123 0
      config.js
  9. 705 0
      handler.js
  10. 77 0
      index.js
  11. 327 0
      install.sh
  12. 16 0
      koyeb.js
  13. 65 0
      lib/canvas.js
  14. 318 0
      lib/chatgpt.js
  15. 58 0
      lib/cloudDBAdapter.js
  16. 92 0
      lib/converter.js
  17. 70 0
      lib/database.js
  18. 773 0
      lib/ezgif-convert.js
  19. 74 0
      lib/gdrive.js
  20. 46 0
      lib/levelling.js
  21. 106 0
      lib/loadAllJadiBots.js
  22. 21 0
      lib/logs.js
  23. 193 0
      lib/mongoDB.js
  24. 84 0
      lib/plugins.js
  25. 107 0
      lib/print.js
  26. 94 0
      lib/queque.js
  27. 85 0
      lib/scraper.js
  28. 2143 0
      lib/simple.js
  29. 218 0
      lib/sticker.js
  30. 228 0
      lib/store.js
  31. 15 0
      lib/tictactoe.d.ts
  32. 95 0
      lib/tictactoe.js
  33. 58 0
      lib/tiktok.js
  34. 66 0
      lib/uploadFile.js
  35. 57 0
      lib/uploadImage.js
  36. 18 0
      lib/validators.js
  37. 1497 0
      lib/webp.js
  38. 171 0
      lib/webp2mp4.js
  39. 114 0
      lib/welcome.js
  40. 74 0
      lib/y2dl.js
  41. 314 0
      lib/youtubedl.js
  42. 0 0
      lib/yt-savetube.js
  43. 584 0
      main.js
  44. BIN
      media/Menu1.jpg
  45. BIN
      media/Menu2.jpg
  46. BIN
      media/Menu3.jpg
  47. BIN
      media/Menu4.jpg
  48. BIN
      media/a.mp3
  49. BIN
      menu.jpg
  50. 93 0
      package.json
  51. 118 0
      plugins/_allantilink.js
  52. 33 0
      plugins/_antiArabe.js
  53. 27 0
      plugins/_antifakes.js
  54. 59 0
      plugins/_antilink.js
  55. 62 0
      plugins/_antilink2.js
  56. 114 0
      plugins/_antiprivado.js
  57. 30 0
      plugins/_antitrabas.js
  58. 142 0
      plugins/_autodetec.js
  59. 89 0
      plugins/_autolevelup.js
  60. 84 0
      plugins/_autoresponder.js
  61. 35 0
      plugins/_autosticker.js
  62. 26 0
      plugins/_cmdWithMedia.js
  63. 90 0
      plugins/_fakeReply.js
  64. 33 0
      plugins/_simsimi.js
  65. 171 0
      plugins/_templateResponse.js
  66. 275 0
      plugins/adult-comandos+18.js
  67. 178 0
      plugins/adult-comandos-menu.js
  68. 226 0
      plugins/adult-pack_vid.js
  69. 95 0
      plugins/adult-xnxxdl.js
  70. 102 0
      plugins/adult-xnxxsearch.js
  71. 29 0
      plugins/afk-_afk.js
  72. 17 0
      plugins/afk-afk.js
  73. 46 0
      plugins/audio-efectos.js
  74. 52 0
      plugins/buscador-animeinfo.js
  75. 37 0
      plugins/buscador-wikipedia.js
  76. 370 0
      plugins/chatbot.js
  77. 605 0
      plugins/config-on y off.js
  78. 32 0
      plugins/convertidor-toanime.js
  79. 16 0
      plugins/convertidor-togifaud.js
  80. 17 0
      plugins/convertidor-toimg.js
  81. 17 0
      plugins/convertidor-tomp3.js
  82. 16 0
      plugins/convertidor-tourl.js
  83. 24 0
      plugins/convertidor-tovideo.js
  84. 43 0
      plugins/convertidor-tts.js
  85. 99 0
      plugins/descargas-consejos.js
  86. 99 0
      plugins/descargas-drive.js
  87. 25 0
      plugins/descargas-gitclone.js
  88. 86 0
      plugins/descargas-ig.js
  89. 47 0
      plugins/descargas-igstalk.js
  90. 19 0
      plugins/descargas-imagen.js
  91. 116 0
      plugins/descargas-mediafire.js
  92. 93 0
      plugins/descargas-modapk.js
  93. 22 0
      plugins/descargas-pinterest.js
  94. 242 0
      plugins/descargas-play.js
  95. 198 0
      plugins/descargas-play2.js
  96. 167 0
      plugins/descargas-playdoc.js
  97. 65 0
      plugins/descargas-playlist.js
  98. 128 0
      plugins/descargas-spotify.js
  99. 47 0
      plugins/descargas-tiktokimg.js
  100. 48 0
      plugins/descargas-tiktokstalk.js

+ 19 - 0
Dockerfile

@@ -0,0 +1,19 @@
+FROM node:lts-buster
+ 
+RUN apt-get update && \
+  apt-get install -y \
+  ffmpeg \
+  imagemagick \
+  webp && \
+  apt-get upgrade -y && \
+  rm -rf /var/lib/apt/lists/*
+
+COPY package.json .
+
+RUN npm install && npm install qrcode-terminal
+
+COPY . .
+
+EXPOSE 5000
+
+CMD ["node", "index.js"]

+ 21 - 0
LICENSE

@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2023 elrebelde21
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.

BIN
Menu2.jpg


+ 1 - 0
Procfile

@@ -0,0 +1 @@
+web: node . --server 

+ 163 - 0
README.md

@@ -0,0 +1,163 @@
+> <b>🚀 Versión actual: 1.9.5</b>
+ 
+<p align="center"> 
+<a href="https://github.com/elrebelde21"><img src="http://readme-typing-svg.herokuapp.com?font=mono&size=17&duration=4000&color=F7B11B&center=falso&vCenter=falso&lines=LoliBot-MD++%F0%9F%90%88;Gracias+por+visitar+este+repositorio.+%F0%9F%92%96" height="90px"></a> 
+</p>
+
+<p align="center">
+<img src="https://telegra.ph/file/c3396a8d9b8ba43aed33e.jpg" alt="LoliBot-MD" width="900"/>
+</p>
+
+<p align="center">
+<a href="#"><img title="LoliBot-MD" src="https://img.shields.io/badge/SI TE AGRADA EL REPOSITORIO APOYAME CON UNA 🌟 ¡GRACIAS! -red?colorA=%255ff0000&colorB=%23017e40&style=for-the-badge"></a> 
+<img src="https://i.pinimg.com/originals/d4/3c/90/d43c902873d4db8c85974dfd0798030b.gif" height="28px">
+</p>  
+
+<p align="center">
+<a href="#"><img title="The-LoliBot-MD" src="https://img.shields.io/badge/LEA TODO EL README-red?colorA=%F77F48FF&colorB=%F77F48FF&style=for-the-badge"></a> 
+<a href="#"><img title="LoliBot-MD" src="https://img.shields.io/badge/COMPATIBLE CON LA VERSIÓN MULTI DISPOSITIVOS DE WHATSAPP-red?colorA=%F77F48FF&colorB=%F77F48FF&style=for-the-badge">
+
+<p align="center">   
+<a href="https://github.com/elrebelde21/LoliBot-MD/network/members"><img title="Forks" src="https://img.shields.io/github/forks/elrebelde21/LoliBot-MD?label=Forks&color=blue&style=flat-square"></a>
+<a href="https://github.com/elrebelde21/LoliBot-MD/watchers"><img title="Watchers" src="https://img.shields.io/github/watchers/elrebelde21/LoliBot-MD?label=Watchers&color=green&style=flat-square"></a>
+<a href="https://github.com/elrebelde21/The-LoliBot-MD/stargazers"><img title="Stars" src="https://img.shields.io/github/stars/elrebelde21/LoliBot-MD?label=Stars&color=yellow&style=flat-square"></a>
+</p> 
+
+<div align="center">
+<a href="https://facebook.com/groups/872989990425789/">
+<img src="https://img.shields.io/badge/Facebook-1877F2?style=for-the-badge&logo=facebook&logoColor=white" alt="Facebook">
+</a>
+<a href="https://www.youtube.com/@elrebelde.21">
+<img src="https://img.shields.io/badge/YouTube-FF0000?style=for-the-badge&logo=youtube&logoColor=white" alt="YouTube">
+</a>
+<a href="https://www.tiktok.com/@lolibot_?_t=8ge2zeRZ04r&_r=1" target="_blank"> <img src="https://img.shields.io/badge/-TikTok-%23E4405F?style=for-the-badge&logo=tiktok&logoColor=black" target="_blank"></a> <img src="https://github.com/siegrin/siegrin/blob/main/Assets/Handshake.gif" height="30px">
+</a>
+
+ [![Enlaces](https://img.shields.io/badge/Encontra_todos_los_enlace_en_un_único_lugar-000000%7D?style=for-the-badge&logo=biolink&logoColor=white)](https://atom.bio/lolibot)
+</div>
+
+### 💫 𝗗𝘂𝗱𝗮 𝘀𝗼𝗯𝗿𝗲 𝗲𝗹 𝗯𝗼𝘁? 
+𝗖𝗼𝗻𝘁𝗮𝗰𝘁𝗮𝗺𝗲 ✨
+
+<a href="http://wa.me/573147616444" target="blank"><img src="https://img.shields.io/badge/Creador-25D366?style=for-the-badge&logo=whatsapp&logoColor=white" /> 
+
+<a href="http://wa.me/573046570706?text=.estado" target="blank"><img src="https://img.shields.io/badge/Bot oficial-25D366?style=for-the-badge&logo=whatsapp&logoColor=white" />
+</a>
+
+### ❇️ 𝙂𝙍𝙐𝙋𝙊𝙎 𝙊𝙁𝙄𝘾𝙄𝘼𝙇𝙀𝙎
+
+<a href="https://chat.whatsapp.com/HNDVUxHphPzG3cJHIwCaX5" target="blank"><img src="https://img.shields.io/badge/Grupo LoliBot ofc 1-25D366?style=for-the-badge&logo=whatsapp&logoColor=white" /> 
+<a href="https://chat.whatsapp.com/H4hxytyGvucIF1k0UAR7es" target="blank"><img src="https://img.shields.io/badge/Grupo LoliBot ofc 2-25D366?style=for-the-badge&logo=whatsapp&logoColor=white" />
+<a href="https://chat.whatsapp.com/IO5k0UOF7hOJHE1eH3Fcxh" target="blank"><img src="https://img.shields.io/badge/🐈 𝐆𝐚𝐭𝐚𝐁𝐨𝐭 & 𝐋𝐨𝐥𝐢𝐁𝐨𝐭 🥳-25D366?style=for-the-badge&logo=whatsapp&logoColor=white" />
+<a href="https://chat.whatsapp.com/IstOAq2RnBx687WhQpOYK8" target="blank"><img src="https://img.shields.io/badge/𝐄𝐧𝐥𝐚𝐜𝐞 𝐋𝐨𝐥𝐢𝐁𝐨𝐭 -25D366?style=for-the-badge&logo=whatsapp&logoColor=white" />
+<a href="https://chat.whatsapp.com/Jpshmvl9Ey4K30zKHoK20q" target="blank"><img src="https://img.shields.io/badge/💫 𝘾𝙤𝙢𝙪𝙣𝙞𝙙𝙖𝙙 𝙇𝙤𝙡𝙞𝘽𝙤𝙩 🥳-25D366?style=for-the-badge&logo=whatsapp&logoColor=white" />
+</a>
+
+<a href="https://chat.whatsapp.com/FRkr7jJHSJA5OjVtE64dDs" target="blank"><img src="https://img.shields.io/badge/Grupo ayuda sobre el bot-25D366?style=for-the-badge&logo=whatsapp&logoColor=white" />
+</a>
+
+[![Typing SVG](http://readme-typing-svg.herokuapp.com?font=Fira+Code&size=10&duration=3000&pause=1000&color=34F6F7&center=falso&vCenter=falso&width=435&lines=%C3%9Anete+y+Conoce+las+%C3%9Altimas+Novedades!!)](https://git.io/typing-svg)
+[![blog](https://img.shields.io/badge/Canal-actulizaciones-25D366?style=for-the-badge&logo=whatsapp&logoColor=white 
+)](https://whatsapp.com/channel/0029Va4QjH7DeON0ePwzjS1A)  <a href="https://whatsapp.com/channel/0029Va4QjH7DeON0ePwzjS1A"> <img src="https://upload.wikimedia.org/wikipedia/commons/thumb/1/19/WhatsApp_logo-color-vertical.svg/1200px-WhatsApp_logo-color-vertical.svg.png" height="29px">
+</a>
+-----
+### ☁️ Activar LoliBot-MD 24/7 activos en SkyPlus Host
+[![YouTube](https://img.shields.io/badge/SkyUltraPlus-Host-FF0000?style=for-the-badge&logo=youtube&logoColor=white)](https://youtu.be/fZbcCLpSH6Y?si=1sDen7Bzmb7jVpAI)
+
+<a href="https://dash.corinplus.com"><img src="https://qu.ax/zFzXF.png" height="125px"></a>
+
+### Información del Host
+- **Dashboard:** [`Aquí`](https://dash.skyultraplus.com)
+- **Panel:** [`Aquí`](https://panel.skyultraplus.com)
+- **Estado de servicios:** [`Aquí`](https://estado.skyultraplus.com)
+- **Canal de WhatsApp:** [`Aquí`](https://whatsapp.com/channel/0029VakUvreFHWpyWUr4Jr0g)
+- **Comunidad:** [`Aquí`](https://chat.whatsapp.com/JPwcXvPEUwlEOyjI3BpYys)
+- **Contacto(s):** [`Gata Dios`](https://wa.me/message/B3KTM5XN2JMRD1) / [`Russell`](https://api.whatsapp.com/send/?phone=15167096032&text&type=phone_number&app_absent=0) / [`elrebelde21`](https://facebook.com/elrebelde21)
+- **Discord:** [`aqui`](https://discord.gg/Ph4eWsZ8)
+
+- [x] **Configuración** <details><summary>**Ajustes del Servidor - LoliBot-MD**</summary><img src="https://telegra.ph/file/7ddd30dd7d77354fb01fe.jpg"></details>
+----
+
+### 𝐀𝐂𝐓𝐈𝐕𝐀 𝐄𝐋 𝐓𝐄𝐑𝐌𝐔𝐗 - 𝙂𝙄𝙏𝙃𝙐𝘽
+[![blog](https://img.shields.io/badge/Instalacion-Automatica-FF0000?style=for-the-badge&logo=youtube&logoColor=white)](https://youtu.be/O_j2q5xCg3A?si=rqKUJF-8w1OCeAxx?feature=share)
+> ⬇️ 𝐄𝐒𝐂𝐑𝐈𝐁𝐄 𝐋𝐎𝐒 𝐒𝐈𝐆𝐔𝐈𝐄𝐍𝐓𝐄𝐒 𝐂𝐎𝐌𝐀𝐍𝐃𝐎𝐒 𝐔𝐍𝐎 𝐏𝐎𝐑 𝐔𝐍𝐎 (Opción 1) 
+```bash
+termux-setup-storage
+```
+```bash
+apt update -y && yes | apt upgrade && pkg install -y bash wget mpv && wget -O - https://raw.githubusercontent.com/elrebelde21/LoliBot-MD/master/install.sh | bash
+```
+-----
+### 📁 (OPCIÓN 2) 𝐀𝐂𝐓𝐈𝐕𝐀 𝐄𝐋 𝐓𝐄𝐑𝐌𝐔𝐗 - 𝘼𝙍𝘾𝙃𝙄𝙑𝙊𝙎 
+> **Note** Descargué y Descomprime
+### [`LoliBot-MD ~ Archivos`](https://github.com/elrebelde21/LoliBot-MD/archive/refs/heads/master.zip)
+[![blog](https://img.shields.io/badge/Termux-LoliBotMD-FF0000?style=for-the-badge&logo=youtube&logoColor=white)
+](https://youtu.be/i1xjB4bmYCc?si=JBYC22-3mBkLpB8c)
+```bash
+termux-setup-storage
+```
+```bash
+apt update && apt upgrade && pkg install -y git nodejs ffmpeg imagemagick yarn
+```
+```bash
+cd storage/downloads/LoliBot-MD-master/LoliBot-MD-master 
+```
+```bash
+yarn install
+```
+```bash
+npm install
+```
+```bash
+npm start
+```
+-----
+### `𝐀𝐂𝐓𝐈𝐕𝐀𝐑 𝐄𝐍 𝐂𝐀𝐒𝐎 𝐃𝐄 𝐃𝐄𝐓𝐄𝐍𝐄𝐑𝐒𝐄`
+```bash
+𝐄𝐒𝐂𝐑𝐈𝐁𝐄 𝐋𝐎𝐒 𝐒𝐈𝐆𝐔𝐈𝐄𝐍𝐓𝐄𝐒 𝐂𝐎𝐌𝐀𝐍𝐃𝐎𝐒 𝐔𝐍𝐎 𝐏𝐎𝐑 𝐔𝐍𝐎:
+> cd 
+> cd LoliBot-MD
+> npm start
+```
+### `𝐎𝐁𝐓𝐄𝐍𝐄𝐑 𝐎𝐓𝐑𝐎 𝐂𝐎𝐃𝐈𝐆𝐎 𝐐𝐑 
+```bash
+𝐄𝐒𝐂𝐑𝐈𝐁𝐄 𝐋𝐎𝐒 𝐒𝐈𝐆𝐔𝐈𝐄𝐍𝐓𝐄𝐒 𝐂𝐎𝐌𝐀𝐍𝐃𝐎𝐒 𝐔𝐍𝐎 𝐏𝐎𝐑 𝐔𝐍𝐎:
+> cd 
+> cd LoliBot-MD
+> rm -rf BotSession
+> npm start
+```          
+-----
+### ⚡ ACTIVA EL REPLIT
+[![blog](https://img.shields.io/badge/Lolibot-YouTube-FF0000?style=for-the-badge&logo=youtube&logoColor=white)
+](https://youtu.be/SMjCcfuyWQE)
+<a target="_blank" href="https://replit.com/github/elrebelde21/LoliBot-MD"><img alt="Run on Replit" src="https://binbashbanana.github.io/deploy-buttons/buttons/remade/replit.svg"></a>
+<a href="https://replit.com/github/elrebelde21/LoliBot-MD"> <img src="https://media0.giphy.com/media/lMwu8EJAnv9kmn51KQ/giphy.gif" height="29px"></a>
+------------------
+- [x] Resultado <details><summary>Importar Repositorio - The-LoliBot-MD</summary><img src="https://i.imgur.com/GQyRnMf.jpg"></details>
+----  
+### `📝 NOTA 📝`
+```bash
+🔸ESTE REPOSITORIO SE PUBLICA LA VERSIÓN ACTUAL|OFICIAL DE LOLIBOT-MD
+🔸ES POSIBLE QUE EL BOT TENGA ALGUNAS FALLAS, SE IRAN SOLUCIONANDO CONFORME SE VAYAN DETECTANDO
+🔸SI VAS A EDITAR POR COMPLETO DEJA LOS CRÉDITOS DEL BOT
+🔸ATENTO A LAS NUEVAS ACTUALIZACIÓNES QUE SE HAGAN EN ESTE REPOSITORIO
+🔸EL ADD/KICK PUEDEN OCASIONAR QUE EL NÚMERO SE VAYA A SOPORTE POR ELLO SE ACTIVA CON #enable restrict
+🔸 LOLIBOT-MD, NO SE HACE RESPONSABLE DEL USO, NÚMERO, PRIVACIDAD Y CONTENIDO MANDADO, O USADO O GESTIONADO POR USTEDES O EL BOT (usarlo bajo tu responsabilidad). 
+```
+----
+
+### 🌟 EDITOR Y PROPIETARIO DEL BOT
+<a href="https://github.com/elrebelde21"><img src="https://github.com/elrebelde21.png" width="300" height="300" alt="elrebelde21"/></a>
+
+### 🌟 COLABORADORES
+[![GataNina-Li](https://github.com/GataNina-Li.png?size=100)](https://github.com/GataNina-Li) 
+[![Yesenia57](https://github.com/Yesenia57.png?size=100)](https://github.com/Yesenia57) 
+[![AzamiJs](https://github.com/AzamiJs.png?size=100)](https://github.com/AzamiJs)  
+[![KatashiFukushima](https://github.com/KatashiFukushima.png?size=100)](https://github.com/KatashiFukushima)
+[![DanixlJs](https://github.com/DanixlJs.png?size=100)](https://github.com/DanixlJs)
+[![edar123](https://github.com/edar123.png?size=100)](https://github.com/edar123)
+
+### 🌟 AGRADECIMIENTOS
+[![TheShadowBrokers1](https://github.com/BrunoSobrino.png?size=60)](https://github.com/BrunoSobrino) 
+

+ 18 - 0
app.json

@@ -0,0 +1,18 @@
+{
+  "name": "Kantu-Boy",  
+  "description": "Super Bot WhatsApp",
+  "repository": "https://github.com/elrebelde21/The-LoliBot-MD",
+  "logo": "https://i.imgur.com/8fK4h6F.jpg",
+  "keywords": ["java", "bot", "whatsapp-bot", "whatsapp-automation"],
+  "buildpacks": [
+    {
+      "url": "heroku/nodejs"
+    },
+    {
+      "url": "https://github.com/jonathanong/heroku-buildpack-ffmpeg-latest"
+    },
+    {
+      "url": "https://github.com/bogini/heroku-buildpack-graphicsmagick"
+    }    
+ ]
+}

+ 1 - 0
audio/file

@@ -0,0 +1 @@
+

+ 123 - 0
config.js

@@ -0,0 +1,123 @@
+import { watchFile, unwatchFile } from 'fs' 
+import chalk from 'chalk'
+import { fileURLToPath } from 'url'
+import fs from 'fs'
+import cheerio from 'cheerio'
+import fetch from 'node-fetch'
+import axios from 'axios'
+import moment from 'moment-timezone' 
+
+//---------[ Añada los numeros a ser Propietario/a ]---------
+
+global.owner = [['5217121649714', 'PROPIETARIO', true], ['51979334798'], ['595986172767'], ['5215656088756'], ['5217121649714']]
+global.mods = []
+global.prems = []
+//BETA: Si quiere evitar escribir el número que será bot en la consola, agregué desde aquí entonces:
+global.botNumberCode = "" //Ejemplo: +5217121649714
+global.confirmCode = "" 
+global.gataJadibts = true //cambia a false Desactivar en "auto-reconexion" de sub-bots
+
+//---------[ APIS GLOBAL ]---------
+
+global.baileys = '@whiskeysockets/baileys'
+global.apis = 'https://delirius-apiofc.vercel.app'
+
+global.APIs = { lolhuman: { url: 'https://api.lolhuman.xyz/api/', key: 'GataDiosV3' },
+skizo: { url: 'https://skizo.tech/api/', key: 'GataDios' },
+alyachan: { url: 'https://api.alyachan.dev/api/', key: null }, 
+neoxr: { url: 'https://api.neoxr.eu/api', key: 'GataDios' },
+fgmods: { url: 'https://api.fgmods.xyz/api', key: 'elrebelde21' },
+popcat: { url: 'https://api.popcat.xyz', key: null }}
+
+global.cheerio = cheerio
+global.fs = fs
+global.fetch = fetch
+global.axios = axios
+global.moment = moment	
+
+//------------------------[ Stickers ]-----------------------------
+
+global.packname = 'KantuBot'
+global.author = 'CrxsMods'
+
+//------------[ Versión | Nombre | cuentas ]------------
+
+global.wm = 'ᴋᴀɴᴛᴜ - ʙᴏᴛ' 
+global.botname = '𝐊𝐚𝐧𝐭𝐮 - 𝐁𝐨𝐭'
+global.vs = '1.9.5'
+global.yt = 'https://www.youtube.com/@crxsmods'
+global.tiktok = 'tiktok.com/@rawleys_ofc'
+global.md = 'https://github.com/crxsmods'
+global.fb = 'wa.me/5217121649714'
+global.face = 'https://t.me/CrxsMods'
+
+global.nna = 'https://chat.whatsapp.com/BO7qWoncCOgJfFNfUek89f' //Update
+global.nna2 = 'https://chat.whatsapp.com/FAwooQ3yBlx0PSsUtXpQup' //KantuBot update
+global.nnaa = 'https://whatsapp.com/channel/0029Vatpz6a0QeafN2T8K838' //KantuBot - Test
+global.nn = 'https://chat.whatsapp.com/BO7qWoncCOgJfFNfUek89f' //Grupo 1
+global.nnn = 'https://chat.whatsapp.com/CSRUKqOoTCNJkWnDt7QDHv' //Grupo 2
+global.nnnt = 'https://chat.whatsapp.com/CSRUKqOoTCNJkWnDt7QDHv' //Grupo del Colaboracion
+global.nnnt2 = 'https://chat.whatsapp.com/FAwooQ3yBlx0PSsUtXpQup' // Grupo COL 2
+global.nnntt = 'https://chat.whatsapp.com/FAwooQ3yBlx0PSsUtXpQup' //Grupo COL 3
+global.nnnttt = 'https://whatsapp.com/channel/0029VaaUgjW3mFY9DyxpWB0n' //enlace Kantubot
+global.nnntttt = 'https://whatsapp.com/channel/0029Vatpz6a0QeafN2T8K838' //Grupo ayuda sobre el bot
+global.bot = 'wa.me/5217121649714'
+global.asistencia = `${fb}`
+global.redes = [nna, nna2, yt, nn, nnn, nnnt, nnnttt, md, tiktok, fb, nnn, face]
+
+//------------------------[ Info | Datos ]---------------------------
+
+global.wait = 'Espera Un Momento\n\n> *❗Por favor no hacer spam👏❗*'
+global.waitt = '*⌛ _Cargando..._ ▬▬▭▭▭*'
+global.waittt = '*⌛ _Cargando..._ ▬▬▬▬▭▭*'
+global.waitttt = '*⌛ _Cargando..._ ▬▬▬▬▬▬▭*'
+global.waittttt = '*⌛ _Cargando..._ ▬▬▬▬▬▬▬*'
+global.rg = '『✅ 𝙍𝙀𝙎𝙐𝙇𝙏𝘼𝘿𝙊𝙎 ✅』\n\n'
+global.ag = '『⚠️ 𝘼𝘿𝙑𝙀𝙍𝙏𝙀𝙉𝘾𝙄𝘼 ⚠️』\n\n'
+global.iig = '『❕ 𝙄𝙉𝙁𝙊𝙍𝙈𝘼𝘾𝙄𝙊𝙉 』\n\n'
+global.fg = '『❌ 𝙀𝙍𝙍𝙊𝙍 ❌』\n\n'
+global.mg = '『❗️ 𝙇𝙊 𝙐𝙎𝙊 𝙈𝘼𝙇❗』\n\n'
+global.eeg = '『📩 𝙍𝙀𝙋𝙊𝙍𝙏𝙀 📩』\n\n'
+global.eg = '『💚 𝙀𝙓𝙄𝙏𝙊 💚』\n\n'
+
+//-------------------------[ IMAGEN ]------------------------------
+//global.img = "https://qu.ax/Zgqq.jpg"
+global.img1 = 'https://qu.ax/hNJk.jpg'
+global.img2 = 'https://qu.ax/jzhN.jpg'
+
+global.imagen = fs.readFileSync('./Menu2.jpg')
+global.imagen1 = fs.readFileSync('./media/Menu1.jpg')
+global.imagen2 = fs.readFileSync('./media/Menu2.jpg')
+global.imagen3 = fs.readFileSync('./media/Menu3.jpg')
+global.imagen4 = fs.readFileSync('./media/Menu4.jpg')
+global.imagen5 = 'https://qu.ax/rULv.jpg'
+global.imagen6 = 'https://qu.ax/CySs.jpg'
+global.menu18 = 'https://qu.ax/MOgO.jpg'
+global.vid1 = 'https://qu.ax/dcAc.mp4'
+global.img = [imagen, imagen1, imagen2, imagen3, imagen4]
+global.imageUrl = ["https://qu.ax/HJnWj.jpg", "https://qu.ax/ehPzQ.jpg", "https://qu.ax/ilfbC.jpg"]
+
+//----------------------------[ NIVELES | RPG ]---------------------------------
+
+global.multiplier = 850 // Cuanto más alto, más difícil subir de nivel
+global.maxwarn = '4' // máxima advertencias
+
+//---------------[ IDs de canales ]----------------
+
+global.ch = {
+ch1: '120363371008200788@newsletter', 
+ch2: '120363178718483875@newsletter',
+ch3: '120363178718483875@newsletter',
+ch4: '120363371008200788@newsletter',
+ch5: '120363178718483875@newsletter', 
+ch6: '120363371008200788@newsletter',
+}
+
+//----------------------------------------------------
+
+let file = fileURLToPath(import.meta.url)
+watchFile(file, () => {
+  unwatchFile(file)
+  console.log(chalk.redBright("Update 'config.js'"))
+  import(`${file}?update=${Date.now()}`)
+})

+ 705 - 0
handler.js

@@ -0,0 +1,705 @@
+import { smsg } from './lib/simple.js'
+import { format } from 'util' 
+import { fileURLToPath } from 'url'
+import path, { join } from 'path'
+import { unwatchFile, watchFile } from 'fs'
+import chalk from 'chalk'
+import fetch from 'node-fetch'
+import ws from 'ws';
+import { tr, translateText } from './lib/_checkLang.js';
+
+/**
+ * @type {import('@whiskeysockets/baileys')}
+ */
+const { proto } = (await import('@whiskeysockets/baileys')).default
+const isNumber = x => typeof x === 'number' && !isNaN(x)
+const delay = ms => isNumber(ms) && new Promise(resolve => setTimeout(function () {
+clearTimeout(this)
+resolve()
+}, ms))
+ 
+/**
+ * Handle messages upsert
+ * @param {import('@whiskeysockets/baileys').BaileysEventMap<unknown>['messages.upsert']} groupsUpdate 
+ */
+export async function handler(chatUpdate) {
+this.msgqueque = this.msgqueque || [];
+this.uptime = this.uptime || Date.now();
+if (!chatUpdate) return
+this.pushMessage(chatUpdate.messages).catch(console.error)
+let m = chatUpdate.messages[chatUpdate.messages.length - 1]
+if (!m) return
+if (global.db.data == null)
+await global.loadDatabase()
+try {
+m = smsg(this, m) || m
+global.currentMessageContext = m;
+if (!m) return
+m.exp = 0
+m.limit = false
+m.money = false        
+try {
+let user = global.db.data.users[m.sender]
+if (typeof user !== 'object')
+global.db.data.users[m.sender] = {}
+if (user) {
+if (!isNumber(user.exp)) user.exp = 0;
+if (user.exp < 0) user.exp = 0; 
+if (!isNumber(user.money)) user.money = 10;
+if (user.money < 0) user.money = 0; 
+if (!isNumber(user.limit)) user.limit = 8;
+if (user.limit < 0) user.limit = 0; 
+if (!('premium' in user)) user.premium = false;
+if (!('registered' in user)) user.registered = false;
+if (!user.registered) {
+if (!('name' in user)) user.name = m.name;
+if (!isNumber(user.age)) user.age = -1;
+if (!isNumber(user.premiumDate)) user.premiumDate = -1;
+if (!isNumber(user.regTime)) user.regTime = -1;
+}
+if (!isNumber(user.afk)) user.afk = -1;
+if (!('autolevelup' in user)) user.autolevelup = true;
+if (!('role' in user)) user.role = 'Novato';        
+if (!isNumber(user.level)) user.level = 0;
+if (!('language' in user)) user.language = 'es'
+if (!user.gender) user.gender = null
+if (!user.birthday) user.birthday = null
+if (!isNumber(user.antispam)) user.antispam = 0;
+if (!isNumber(user.banco)) user.banco = 0        
+if (!user.premium) user.premium = false;
+if (!user.warnPv) user.warnPv = false
+if (!user.premium) user.premiumTime = 0;
+if (!user.marry) user.marry = 0;
+if (!user.wait) user.wait = 0;
+if (!user.lastmiming) user.lastmiming = 0;
+if (!user.lastwork) user.lastwork = 0;
+if (!user.lastcofre) user.lastcofre = 0;
+if (!user.lastclaim) user.lastclaim = 0;
+if (!user.messageSpam) user.messageSpam = 0;
+if (!user.crime) user.crime = 0;
+if (!user.lastrob) user.lastrob = 0;
+if (!user.packname) user.packname = null
+if (!user.author) user.author = null
+if (!user.timeRy) user.timeRy = 0;
+if (!user.timevot) user.timevot = 0;
+if (!user.mensaje) user.mensaje = 0;
+if (!user.rtrofi) user.rtrofi = 'Bronce';
+} else
+global.db.data.users[m.sender] = {
+exp: 0,
+money: 10,
+limit: 8,
+registered: false,     
+premium: false,
+regTime: -1,        
+premiumTime: 0,     
+role: 'Novato',     
+autolevelup: true,       
+banned: false,
+language: 'es',
+gender: null,
+birthday: null,
+afk: -1,
+afkReason: '',
+lastwork: 0,
+messageSpam: 0,
+lastclaim: 0,
+level: 0,
+wait: 0,
+age: -1,             
+marry: 0,
+bank: 0,
+BannedReason: '',
+Banneduser: false,          
+warnPv: false,
+packname: null,
+author: null,
+banco: 0,
+timeRy: 0,               
+lastmiming: 0,
+lastcofre: 0,
+crime: 0,
+lastrob: 0,
+timevot: 0,
+rtrofi: 'bronce',          
+mensaje: 0,
+}
+let chat = global.db.data.chats[m.chat]
+if (typeof chat !== 'object')
+global.db.data.chats[m.chat] = {}
+if (chat) {
+if (!('sAutorespond' in chat)) chat.sAutorespond = '' 
+if (!('isBanned' in chat)) chat.isBanned = false       
+if (!('welcome' in chat)) chat.welcome = true        
+if (!('detect' in chat)) chat.detect = true             
+if (!('sWelcome' in chat)) chat.sWelcome = ''        
+if (!('sBye' in chat)) chat.sBye = ''                    
+if (!('sPromote' in chat)) chat.sPromote = ''         
+if (!('sDemote' in chat)) chat.sDemote = '' 
+if (!('delete' in chat)) chat.delete = false            
+if (!('modohorny' in chat)) chat.modohorny = true   
+if (!('stickers' in chat)) chat.stickers = false         
+if (!('autosticker' in chat)) chat.autosticker = false   
+if (!('audios' in chat)) chat.audios = false           
+if (!('antiLink' in chat)) chat.antiLink = false     
+if (!('antiLink2' in chat)) chat.antiLink2 = false
+if (!('antiTiktok' in chat)) chat.antiTiktok = false
+if (!('antiYoutube' in chat)) chat.antiYoutube = false
+if (!('antiTelegram' in chat)) chat.antiTelegram = false
+if (!('antiFacebook' in chat)) chat.antiFacebook = false
+if (!('antiInstagram' in chat)) chat.antiInstagram = false
+if (!('antiTwitter' in chat)) chat.antiTwitter = false
+if (!('antiDiscord' in chat)) chat.antiDiscord = false
+if (!('antiThreads' in chat)) chat.antiThreads = false
+if (!('antiTwitch' in chat)) chat.antiTwitch = false
+if (!('antifake' in chat)) chat.antifake = false
+if (!('reaction' in chat)) chat.reaction = true       
+if (!('modoadmin' in chat)) chat.modoadmin = false 
+if (!('game' in chat)) chat.game = true
+if (!('game2' in chat)) chat.game2 = false
+if (!('simi' in chat)) chat.simi = false
+if (!('antiTraba' in chat)) chat.antiTraba = true 
+if (!('primaryBot' in chat)) chat.primaryBot = null
+if (!('autorespond' in chat)) chat.autorespond = true 
+if (!('autolevelup' in chat))  chat.autolevelup = true
+if (!isNumber(chat.expired)) chat.expired = 0
+if (!('horarioNsfw' in chat)) { 
+chat.horarioNsfw = {
+inicio: "00:00", 
+fin: "23:59"
+};
+}
+} else
+global.db.data.chats[m.chat] = {
+isBanned: false,
+welcome: true,
+detect: true,
+sWelcome: '',
+sBye: '',
+sPromote: '',
+sDemote: '', 
+sAutorespond: '', 
+delete: false,
+modohorny: true,
+stickers: false,
+autosticker: false,
+audios: false,
+antiLink: false,
+antiLink2: false,
+antiTiktok: false,
+antiYoutube: false,
+antiTelegram: false,
+antiFacebook: false,
+antiInstagram: false,
+antiTwitter: false,
+antiDiscord: false,
+antiThreads: false,
+antiTwitch: false,
+antifake: false,
+reaction: true,
+modoadmin: false,
+antitoxic: false,
+game: true, 
+game2: false, 
+simi: false,
+primaryBot: null,
+antiTraba: true,
+autorespond: true, 
+autolevelup: true,
+expired: 0,
+horarioNsfw: {
+inicio: "00:00", 
+fin: "23:59"
+}
+}
+var settings = global.db.data.settings[this.user.jid]
+if (typeof settings !== 'object') global.db.data.settings[this.user.jid] = {}
+if (settings) {
+if (!('self' in settings)) settings.self = false
+if (!('autoread' in settings)) settings.autoread = false
+if (!('autoread2' in settings)) settings.autoread2 = false
+if (!('restrict' in settings)) settings.restrict = true
+if (!('temporal' in settings)) settings.temporal = false
+if (!('antiPrivate' in settings)) settings.antiPrivate = false
+if (!('antiCall' in settings)) settings.antiCall = true
+if (!('antiSpam' in settings)) settings.antiSpam = true 
+if (!('modoia' in settings)) settings.modoia = false
+if (!('anticommand' in settings)) settings.anticommand = false	
+if (!('jadibotmd' in settings)) settings.jadibotmd = true
+if (!('prefix' in settings)) settings.prefix = opts['prefix'] || '*/i!#$%+£¢€¥^°=¶∆×÷π√✓©®&.\\-.@';
+if (!('status' in settings)) settings.status = 0
+} else global.db.data.settings[this.user.jid] = {
+self: false,
+autoread: false,
+autoread2: false,
+restrict: true,
+temporal: false,
+antiPrivate: false,
+antiCall: true,
+antiSpam: true,
+modoia: false, 
+anticommand: false, 	
+jadibotmd: true,
+prefix: opts['prefix'] || '*/i!#$%+£¢€¥^°=¶∆×÷π√✓©®&.\\-.@',
+status: 0
+}} catch (e) {
+console.error(e)
+}
+
+var settings = global.db.data.settings[this.user.jid];
+let prefix;
+const defaultPrefix = '*/i!#$%+£¢€¥^°=¶∆×÷π√✓©®&.\\-.@'; 
+if (settings.prefix) {
+if (settings.prefix.includes(',')) {
+const prefixes = settings.prefix.split(',').map(p => p.trim());
+prefix = new RegExp('^(' + prefixes.map(p => p.replace(/[|\\{}()[\]^$+*.\-\^]/g, '\\$&')).join('|') + ')');
+} else if (settings.prefix === defaultPrefix) {
+prefix = new RegExp('^[' + settings.prefix.replace(/[|\\{}()[\]^$+*.\-\^]/g, '\\$&') + ']');
+} else {
+prefix = new RegExp('^' + settings.prefix.replace(/[|\\{}()[\]^$+*.\-\^]/g, '\\$&'));
+}} else {
+prefix = new RegExp(''); 
+}
+const isROwner = [conn.decodeJid(global.conn.user.id), ...global.owner.map(([number]) => number)].map(v => v.replace(/[^0-9]/g, '') + '@s.whatsapp.net').includes(m.sender)
+const isOwner = isROwner || m.fromMe
+const isMods = isOwner || global.mods.map(v => v.replace(/[^0-9]/g, '') + '@s.whatsapp.net').includes(m.sender)
+//const isPrems = isROwner || global.prems.map(v => v.replace(/[^0-9]/g, '') + '@s.whatsapp.net').includes(m.sender)
+const isPrems = isROwner || global.db.data.users[m.sender].premiumTime > 0
+
+if (opts['queque'] && m.text && !(isMods || isPrems)) {
+let queque = this.msgqueque, time = 1000 * 5
+const previousID = queque[queque.length - 1]
+queque.push(m.id || m.key.id)
+setInterval(async function () {
+if (queque.indexOf(previousID) === -1) clearInterval(this)
+await delay(time)
+}, time)
+}
+
+//if(m.id.startsWith('NJX-') || m.id.startsWith('BAE5') && m.id.length === 16 || m.id.startsWith('3EB0') && m.id.length === 12 || m.id.startsWith('3EB0') && (m.id.length === 20 || m.id.length === 22) || m.id.startsWith('B24E') && m.id.length === 20 || m.id.startsWith('FizzxyTheGreat-')) return
+if(m.id.startsWith('NJX-') || m.id.startsWith('Lyru-') || m.id.startsWith('EvoGlobalBot-') || m.id.startsWith('BAE5') && m.id.length === 16 || m.id.startsWith('3EB0') && m.id.length === 12 || m.id.startsWith('3EB0') && (m.id.length === 20 || m.id.length === 22) || m.id.startsWith('B24E') || m.id.startsWith('8SCO') && m.id.length === 20 || m.id.startsWith('FizzxyTheGreat-')) return
+if (opts['nyimak']) return
+if (!isROwner && opts['self']) return 
+if (opts['pconly'] && m.chat.endsWith('g.us')) return
+if (opts['gconly'] && !m.chat.endsWith('g.us')) return
+if (opts['swonly'] && m.chat !== 'status@broadcast') return
+if (typeof m.text !== 'string')
+m.text = ''
+
+//if (m.isBaileys) return 	    
+let _user = global.db.data && global.db.data.users && global.db.data.users[m.sender]	    
+//m.exp += Math.ceil(Math.random() * 10)
+let usedPrefix      
+const groupMetadata = (m.isGroup ? ((conn.chats[m.chat] || {}).metadata || await this.groupMetadata(m.chat).catch(_ => null)) : {}) || {}
+const participants = (m.isGroup ? groupMetadata.participants : []) || []
+const user = (m.isGroup ? participants.find(u => conn.decodeJid(u.id) === m.sender) : {}) || {} // User Data
+const bot = (m.isGroup ? participants.find(u => conn.decodeJid(u.id) == this.user.jid) : {}) || {} // Your Data
+const isRAdmin = user?.admin == 'superadmin' || false
+const isAdmin = isRAdmin || user?.admin == 'admin' || false // Is User Admin?
+const isBotAdmin = bot?.admin || false // Are you Admin?
+m.isWABusiness = global.conn.authState?.creds?.platform === 'smba' || global.conn.authState?.creds?.platform === 'smbi'
+//m.isChannel = m.chat.includes('@newsletter') || m.sender.includes('@newsletter')
+
+const ___dirname = path.join(path.dirname(fileURLToPath(import.meta.url)), './plugins')
+for (let name in global.plugins) {
+let plugin = global.plugins[name]
+if (!plugin) continue
+if (plugin.disabled) continue
+const __filename = join(___dirname, name)
+if (typeof plugin.all === 'function') {
+try {
+await plugin.all.call(this, m, { chatUpdate, __dirname: ___dirname, __filename })
+} catch (e) {
+// if (typeof e === 'string') continue
+console.error(e)
+/*for (let [jid] of global.owner.filter(([number, _, isDeveloper]) => isDeveloper && number)) {
+let data = (await conn.onWhatsApp(jid))[0] || {}
+if (data.exists)
+m.reply(`*Plugin:* ${name}\n*Sender:* ${m.sender}\n*Chat:* ${m.chat}\n*Command:* ${m.text}\n\n${format(e)}.trim(), data.jid)
+}*/
+}}
+if (!opts['restrict'])
+if (plugin.tags && plugin.tags.includes('admin')) {
+//global.dfail('restrict', m, this)
+continue
+}
+const str2Regex = str => str.replace(/[|\\{}()[\]^$+*?.]/g, '\\$&');
+            let _prefix = plugin.customPrefix ? plugin.customPrefix : this.prefix ? this.prefix : prefix; // Usamos prefix local
+            let match = (_prefix instanceof RegExp ?
+                [[_prefix.exec(m.text), _prefix]] :
+                Array.isArray(_prefix) ?
+                _prefix.map(p => {
+                    let re = p instanceof RegExp ? p : new RegExp(str2Regex(p));
+                    return [re.exec(m.text), re];
+                }) :
+                typeof _prefix === 'string' ?
+                [[new RegExp(str2Regex(_prefix)).exec(m.text), new RegExp(str2Regex(_prefix))]] :
+                [[[], new RegExp]]
+            ).find(p => p[1]);
+            if (typeof plugin.before === 'function') {
+                if (await plugin.before.call(this, m, {
+                    match,
+                    conn: this,
+                    participants,
+                    groupMetadata,
+                    user,
+                    bot,
+                    isROwner,
+                    isOwner,
+                    isRAdmin,
+                    isAdmin,
+                    isBotAdmin,
+                    isPrems,
+                    chatUpdate,
+                    __dirname: ___dirname,
+                    __filename
+                })) continue;
+            }
+            if (typeof plugin !== 'function') continue;
+            if ((usedPrefix = (match[0] || '')[0])) {
+                let noPrefix = m.text.replace(usedPrefix, '');
+                let [command, ...args] = noPrefix.trim().split` `.filter(v => v);
+                args = args || [];
+                let _args = noPrefix.trim().split` `.slice(1);
+                let text = _args.join` `;
+                command = (command || '').toLowerCase();
+                let fail = plugin.fail || global.dfail;
+                let isAccept = plugin.command instanceof RegExp ?
+                    plugin.command.test(command) :
+                    Array.isArray(plugin.command) ?
+                    plugin.command.some(cmd => cmd instanceof RegExp ? cmd.test(command) : cmd === command) :
+                    typeof plugin.command === 'string' ?
+                    plugin.command === command :
+                    false;
+
+                if (!isAccept) continue;
+                m.plugin = name;
+if (m.chat in global.db.data.chats || m.sender in global.db.data.users) {
+let chat = global.db.data.chats[m.chat]
+let user = global.db.data.users[m.sender]
+if (!['owner-unbanchat.js'].includes(name) && chat && chat.isBanned && !isROwner) return // Except this
+if (name != 'owner-unbanchat.js' && name != 'owner-exec.js' && name != 'owner-exec2.js' && name != 'tool-delete.js' && chat?.isBanned && !isROwner) return 
+if (m.text && user.banned && !isROwner) {
+if (user.antispam > 2) return
+m.reply(`⚠️ ${await tr("ESTAS BANEADO")} ⚠️\n*• ${await tr("Motivo")}:* ${user.messageSpam === 0 ? 'Spam' : user.messageSpam}\n*👉🏻 ${await tr("Puedes contactar al propietario del Bot si crees que se trata de un error o para charlar sobre tu desbaneo")}*\n\n👉 ${fb}`)
+user.antispam++	
+return
+}
+
+/*if (settings.antiPrivate && !m.isGroup && !m.fromMe) {
+let user = global.db.data.users[m.sender] || {};
+if (user.warnPv && !m.text.includes('code')) {
+console.log(`[AntiPrivate]`);
+return;
+}
+
+if (!user.warnPv) {
+m.reply(`Hola esta prohibido usar los comando al privado del bot...\n\n> _*Para usar mi funciones unirte al  grupo oficial 👇*_\n${[nnn, nnnttt, nnnt].getRandom()}`); 
+user.warnPv = true;
+global.db.data.users[m.sender] = user;
+return;
+}}
+*/
+
+//Antispam2		
+if (user.antispam2 && isROwner) return
+let time = global.db.data.users[m.sender].spam + 3000
+if (new Date - global.db.data.users[m.sender].spam < 3000) return console.log(`[ SPAM ]`) 
+global.db.data.users[m.sender].spam = new Date * 1
+}
+                
+const hl = _prefix;
+const adminMode = global.db.data.chats[m.chat].modoadmin;
+const lolibott = `${plugin.botAdmin || plugin.admin || plugin.group || plugin || noPrefix || hl || m.text.slice(0, 1) == hl || plugin.command}`;
+if (adminMode && !isOwner && !isROwner && m.isGroup && !isAdmin && lolibott) return; 
+if (plugin.rowner && plugin.owner && !(isROwner || isOwner)) { // Both Owner
+fail('owner', m, this)
+continue
+}
+if (plugin.rowner && !isROwner) { // Real Owner
+fail('rowner', m, this)
+continue
+}
+if (plugin.owner && !isOwner) { // Number Owner
+fail('owner', m, this)
+continue
+}
+if (plugin.mods && !isMods) { // Moderator
+fail('mods', m, this)
+continue
+}
+if (plugin.premium && !isPrems) { // Usuarios Premium
+fail('premium', m, this)
+continue
+}
+if (plugin.group && !m.isGroup) { // Group Only
+fail('group', m, this)
+continue
+} else if (plugin.botAdmin && !isBotAdmin) { // You Admin
+fail('botAdmin', m, this)
+continue
+} else if (plugin.admin && !isAdmin) { // User Admin
+fail('admin', m, this)
+continue
+}
+if (plugin.private && m.isGroup) { // Private Chat Only
+fail('private', m, this)
+continue
+}
+if (plugin.register == true && _user.registered == false) { // Butuh daftar?
+fail('unreg', m, this)
+continue
+}
+m.isCommand = true
+/*let xp = 'exp' in plugin ? parseInt(plugin.exp) : 1 // Ganancia de XP por comando 
+if (xp > 9000) m.reply('chirrido -_-') //
+else
+m.exp += xp*/
+if (!isPrems && plugin.limit && global.db.data.users[m.sender].limit < plugin.limit * 1) {
+m.reply(`*⚠ ${await tr("Sus diamante")} 💎 ${await tr("Se han agotado puede comprar mas usando el comando:")}:* #buy`)
+//conn.sendMessage(m.chat, {text: `*⚠ 𝐒𝐮𝐬 𝐝𝐢𝐚𝐦𝐚𝐧𝐭𝐞 💎 𝐬𝐞 𝐡𝐚𝐧 𝐚𝐠𝐨𝐭𝐚𝐝𝐨 𝐩𝐮𝐞𝐝𝐞 𝐜𝐨𝐦𝐩𝐫𝐚𝐫 𝐦𝐚𝐬 𝐮𝐬𝐚𝐧𝐝𝐨 𝐞𝐥 𝐜𝐨𝐦𝐚𝐧𝐝𝐨:* #buy`, contextInfo: {externalAdReply : {mediaUrl: null, mediaType: 1, description: null, "title": wm, body: '', previewType: 0, "thumbnail": img.getRandom(), sourceUrl: [nna, nna2, md, yt, nnn, nnnt, nnnttt, tiktok].getRandom()}}}, { quoted: m })         
+continue
+}
+if (plugin.level > _user.level) {
+m.reply(`*⚠️ ${await tr("Necesita el nivel")} ${plugin.level} ${await tr("para poder usar este comando, Tu nivel actual es:")}* ${_user.level}`)
+//conn.sendMessage(m.chat, {text: `*⚠️𝐍𝐞𝐜𝐞𝐬𝐢𝐭𝐚 𝐞𝐥 𝐧𝐢𝐯𝐞𝐥 ${plugin.level} 𝐩𝐚𝐫𝐚 𝐩𝐨𝐝𝐞𝐫 𝐮𝐬𝐚𝐫 𝐞𝐬𝐭𝐞 𝐜𝐨𝐦𝐚𝐧𝐝𝐨, 𝐓𝐮 𝐧𝐢𝐯𝐞𝐥 𝐚𝐜𝐭𝐮𝐚𝐥 𝐞𝐬:* ${_user.level}`, contextInfo: {externalAdReply : {mediaUrl: null, mediaType: 1, description: null, "title": wm, body: '', previewType: 0, "thumbnail": img.getRandom(), sourceUrl: [nna, nna2, md, yt, nnn, nnnt, nnnttt, tiktok].getRandom()}}}, { quoted: m })         
+continue // Si no se ha alcanzado el nivel
+}
+let extra = {match, usedPrefix, noPrefix, _args, args, command, text, conn: this, participants, groupMetadata, user, bot, isROwner, isOwner, isRAdmin, isAdmin,  isBotAdmin, isPrems, chatUpdate, __dirname: ___dirname, __filename }
+try {
+await plugin.call(this, m, extra)
+if (!isPrems)
+m.limit = m.limit || plugin.limit || false
+} catch (e) {
+// Error occured
+m.error = e
+console.error(e)
+if (e) {
+let text = format(e) || 'Error desconocido';
+for (let api in global.APIs) {
+let key = global.APIs[api].key;
+if (key) text = text.replace(new RegExp(key, 'g'), '#HIDDEN#');
+}
+m.reply(text);
+}
+/*if (e) {
+let text = format(e)
+for (let key of Object.values(global.APIs))
+text = text.replace(new RegExp(key, 'g'), '#HIDDEN#')
+m.reply(text)
+}*/
+} finally {
+// m.reply(util.format(_user))
+if (typeof plugin.after === 'function') {
+try {
+await plugin.after.call(this, m, extra)
+} catch (e) {
+console.error(e)
+}}
+if (m.limit) m.reply(`*${+m.limit}* ${await tr("diamante")} 💎 ${await tr("usados")}`)
+if (m.money) m.reply(+m.money + ` KantuCoins ${await tr("usados")} 🪙`) 
+}
+break
+}}} catch (e) {
+console.error(e)
+} finally {
+if (opts['queque'] && m.text) {
+const quequeIndex = this.msgqueque.indexOf(m.id || m.key.id)
+if (quequeIndex !== -1)
+this.msgqueque.splice(quequeIndex, 1)
+}
+//console.log(global.db.data.users[m.sender])
+let user, stats = global.db.data.stats
+if (m) {
+if (m.sender && (user = global.db.data.users[m.sender])) {
+user.exp += m.exp
+user.limit -= m.limit * 1
+}
+
+let stat
+if (m.plugin) {
+let now = +new Date
+if (m.plugin in stats) {
+stat = stats[m.plugin]
+if (!isNumber(stat.total))
+stat.total = 1
+if (!isNumber(stat.success))
+stat.success = m.error != null ? 0 : 1
+if (!isNumber(stat.last))
+stat.last = now
+if (!isNumber(stat.lastSuccess))
+stat.lastSuccess = m.error != null ? 0 : now
+} else
+stat = stats[m.plugin] = {
+total: 1,
+success: m.error != null ? 0 : 1,
+last: now,
+lastSuccess: m.error != null ? 0 : now
+}
+stat.total += 1
+stat.last = now
+if (m.error == null) {
+stat.success += 1
+stat.lastSuccess = now
+}}}
+
+try {
+if (!opts['noprint']) await (await import(`./lib/print.js`)).default(m, this)
+} catch (e) {
+console.log(m, m.quoted, e)}
+let settingsREAD = global.db.data.settings[this.user.jid] || {}  
+if (opts['autoread']) await this.readMessages([m.key])
+if (settingsREAD.autoread2) await this.readMessages([m.key])  
+//if (settingsREAD.autoread2 == 'true') await this.readMessages([m.key])    
+	    
+if (!m.fromMem && m.text.match(/(@5217121649714|KantuBot|Botsito|Bot|:v)/gi)) {
+let emot = pickRandom(["🐣", "💥", "😹", "🧐", "✨", "🤠", "🙀", "👻", "👽", "🤩", "👾", "😳", "🥵", "🤯", "😱", "😨", "👇", "🥴", "🤧", "🤑", "🤠", "🤖", "🤝", "💪", "👑", "🔎", "🐱", "🚨", "⚓", "🎁", "⚡️", "💯", "☃️", "⛄️", "🌝", "🌛", "🌜", "🍓", "🍎", "🎈", "🪄", "❤️", "🧡", "💛", "💚", "💙", "💜", "🖤", "🤍", "💘", "💝", "💟", "🌝", "😎", "🔥", "🖕", "🐦"])
+this.sendMessage(m.chat, { react: { text: emot, key: m.key }})}
+function pickRandom(list) { return list[Math.floor(Math.random() * list.length)]}}}
+
+/**
+ * Handle groups participants update
+ * @param {import('@adiwajshing/baileys').BaileysEventMap<unknown>['group-participants.update']} groupsUpdate 
+ */
+export async function participantsUpdate({ id, participants, action }) {
+if (opts['self']) return;
+if (this.isInit) return;
+if (global.db.data == null) await loadDatabase();
+let chat = global.db.data.chats[id] || {};
+let text = '';
+switch (action) {
+case 'add':
+if (chat.welcome) {
+let groupMetadata = await this.groupMetadata(id) || (conn.chats[id] || {}).metadata;
+for (let user of participants) {
+let userJoinTime = Date.now(); 
+if (userJoinTime < global.botStartTime) {
+console.log(`Bienvenida ignorada para ${user}: unión anterior al inicio del bot (${new Date(userJoinTime)} < ${new Date(global.botStartTime)})`);
+continue;
+}
+
+let pp = './src/sinfoto.jpg';
+try {
+pp = await this.profilePictureUrl(user, 'image');
+} catch (e) {
+} finally {
+let apii = await this.getFile(pp);
+const botTt2 = groupMetadata.participants.find(u => this.decodeJid(u.id) == this.user.jid) || {};
+const isBotAdminNn = botTt2?.admin === "admin" || false;
+text = (action === 'add' ? (chat.sWelcome || this.welcome || conn.welcome || 'Welcome, @user!').replace('@subject', await this.getName(id)).replace('@desc', groupMetadata.desc?.toString() || '*ᴜɴ ɢʀᴜᴘᴏ ɢᴇɴɪᴀ😸*\n *sɪɴ ʀᴇɢʟᴀ 😉*') :
+(chat.sBye || this.bye || conn.bye || 'Bye, @user!')).replace('@user', '@' + user.split('@')[0]);
+
+if (chat.antifake && isBotAdminNn && action === 'add') {
+const numerosPermitidos = ["212", "265", "92", "91", "90", "210", "60", "61", "62", "40", "48", "49", "93", "94", "98", "258"];
+if (numerosPermitidos.some(num => user.startsWith(num))) {
+this.sendMessage(id, { text: `@${user.split("@")[0]} ${await tr("Nos numero fake no esta permitido el este grupo hasta la próxima...")}`, mentions: [user] }, { quoted: null });
+let responseb = await this.groupParticipantsUpdate(id, [user], 'remove');
+if (responseb[0].status === "404") return;
+return;
+}}
+let username = this.getName(id);
+let fkontak2 = { "key": { "participants": "0@s.whatsapp.net", "remoteJid": "status@broadcast", "fromMe": false, "id": "Halo" }, "message": { "contactMessage": { "vcard": `BEGIN:VCARD\nVERSION:3.0\nN:Sy;Bot;;;\nFN:y\nitem1.TEL;waid=${user.split('@')[0]}:${user.split('@')[0]}\nitem1.X-ABLabel:Ponsel\nEND:VCARD` } }, "participant": "0@s.whatsapp.net" };
+let vn = 'https://qu.ax/cUYg.mp3';
+let or = ['texto', 'audio'];
+let media = or[Math.floor(Math.random() * 2)];
+if (media === 'texto') {
+this.sendMessage(id, { text: text, contextInfo: { forwardedNewsletterMessageInfo: { newsletterJid: '120363371008200788@newsletter', serverMessageId: '', newsletterName: 'Kantu Bot 🐣' }, forwardingScore: 9999999, isForwarded: true, mentionedJid: [user], externalAdReply: { showAdAttribution: true, renderLargerThumbnail: true, thumbnail: apii.data, title: [wm, ' ' + wm + '😊', '🌟'].getRandom(), containsAutoReply: true, mediaType: 1, sourceUrl: [nna, nna2, nnntt, yt].getRandom() } } }, { quoted: fkontak2 });
+}
+if (media === 'audio') {
+this.sendMessage(id, { audio: { url: vn }, contextInfo: { forwardedNewsletterMessageInfo: { newsletterJid: '120363371008200788@newsletter', serverMessageId: '', newsletterName: 'Kantu Bot 🐣' }, forwardingScore: 9999999, isForwarded: true, mentionedJid: [user], externalAdReply: { mediaType: 1, previewType: "PHOTO", thumbnail: apii.data, title: `乂 WELCOME 乂`, body: [wm, ' ' + wm + '😊', '🌟'].getRandom(), showAdAttribution: true, renderLargerThumbnail: true, sourceUrl: [nna, nna2, nnntt, yt].getRandom() } }, ptt: true, mimetype: 'audio/mpeg', fileName: `error.mp3` }, { quoted: fkontak2 });
+}}}}
+			    
+break
+case 'promote':
+case 'daradmin':
+case 'darpoder':
+text = (chat.sPromote || this.spromote || conn.spromote || '@user ```is now Admin```')
+case 'demote':
+case 'quitarpoder':
+case 'quitaradmin':
+if (!text)
+text = (chat.sDemote || this.sdemote || conn.sdemote || '@user ```is no longer Admin```')
+text = text.replace('@user', '@' + participants[0].split('@')[0])
+if (chat.detect)
+//this.sendMessage(id, { text, mentions: this.parseMention(text) })
+break
+}}
+
+/** 
+ * Actualización de grupos de control
+ * Handle groups update
+ * @param {import('@adiwajshing/baileys').BaileysEventMap<unknown>['groups.update']} groupsUpdate 
+ */
+export async function groupsUpdate(groupsUpdate) {
+if (opts['self'])
+return
+for (const groupUpdate of groupsUpdate) {
+const id = groupUpdate.id
+if (!id) continue
+let chats = global.db.data.chats[id], text = ''
+if (!chats?.detect) continue
+// if (groupUpdate.desc) text = (chats.sDesc || this.sDesc || conn.sDesc || '```Description has been changed to```\n@desc').replace('@desc', groupUpdate.desc)
+//if (groupUpdate.subject) text = (chats.sSubject || this.sSubject || conn.sSubject || '```Subject has been changed to```\n@subject').replace('@subject', groupUpdate.subject)
+//if (groupUpdate.icon) text = (chats.sIcon || this.sIcon || conn.sIcon || '```Icon has been changed to```').replace('@icon', groupUpdate.icon)
+//if (groupUpdate.revoke) text = (chats.sRevoke || this.sRevoke || conn.sRevoke || '```Group link has been changed to```\n@revoke').replace('@revoke', groupUpdate.revoke)
+if (!text) continue
+await this.sendMessage(id, { text, mentions: this.parseMention(text) })
+}}
+
+export async function callUpdate(callUpdate) {
+let isAnticall = global.db.data.settings[this.user.jid].antiCall
+if (!isAnticall) return
+for (let nk of callUpdate) {
+if (nk.isGroup == false) {
+if (nk.status == "offer") {
+let callmsg = await this.reply(nk.from, `ʜᴏʟᴀ *@${nk.from.split('@')[0]}*, ʟᴀs ${nk.isVideo ? 'videollamadas' : 'llamadas'} ɴᴏ ᴇsᴛᴀɴ ᴘᴇʀᴍɪᴛɪᴅᴀs, sᴇʀᴀs ʙʟᴏǫᴜᴇᴀᴅᴏ.\n\nsɪ ᴀᴄᴄɪᴅᴇɴᴛᴀʟᴍᴇɴᴛᴇ ʟʟᴀᴍᴀsᴛᴇ ᴘᴏɴɢᴀsᴇ ᴇɴ ᴄᴏɴᴛᴀᴄᴛᴏ ᴄᴏɴ ᴍɪ ᴄʀᴇᴀᴅᴏʀ ᴘᴀʀᴀ ǫᴜᴇ ᴛᴇ ᴅᴇsʙʟᴏǫᴜᴇᴇ!\n\nɢʀᴜᴘᴏ ᴀsɪsᴛᴇɴᴄɪᴀ ғᴀᴄᴇʙᴏᴏᴋ: ${fb}`, false, { mentions: [nk.from] })
+let vcard = `BEGIN:VCARD\nVERSION:3.0\nN:;𝐊𝐚𝐧𝐭𝐮 - 𝐁𝐨𝐭 👑;;;\nFN:𝐊𝐚𝐧𝐭𝐮 - 𝐁𝐨𝐭\nORG:𝐊𝐚𝐧𝐭𝐮 - 𝐁𝐨𝐭 👑\nTITLE:\nitem1.TEL;waid=5217121649714:+52 712 164 9714\nitem1.X-ABLabel:𝐊𝐚𝐧𝐭𝐮 - 𝐁𝐨𝐭 👑\nX-WA-BIZ-DESCRIPTION:[❗] ᴇsᴄʀɪʙɪ sᴏʟᴏ ᴘᴏʀ ᴄᴏsᴀs ᴅᴇʟ ʙᴏᴛ.\nX-WA-BIZ-NAME:𝐊𝐚𝐧𝐭𝐮 - 𝐁𝐨𝐭 👑\nEND:VCARD`
+await this.sendMessage(nk.from, { contacts: { displayName: '𝐊𝐚𝐧𝐭𝐮 - 𝐁𝐨𝐭 👑', contacts: [{ vcard }] }}, {quoted: callmsg})
+await this.updateBlockStatus(nk.from, 'block')
+}}}}
+
+export async function deleteUpdate(message) {
+try {
+const { fromMe, id, participant } = message
+if (fromMe) return 
+let msg = this.serializeM(this.loadMessage(id))
+let chat = global.db.data.chats[msg?.chat] || {}
+if (!chat?.delete) return 
+if (!msg) return 
+if (!msg?.isGroup) return 
+const antideleteMessage = `*[ ${await tr("ANTI ELIMINAR")} ]*\n\n@${participant.split`@`[0]} ${await tr("Elimino un mensaje\nEnviando el mensaje...\n\n*Para desactivar esta función escriba:*")}\n#disable delete`.trim();
+await this.sendMessage(msg.chat, {text: antideleteMessage, mentions: [participant]}, {quoted: msg})
+this.copyNForward(msg.chat, msg).catch(e => console.log(e, msg))
+} catch (e) {
+console.error(e)
+}}
+
+global.dfail = async (type, m, conn, usedPrefix) => { 
+let msg = {
+rowner: await tr('「 ꛕ 」 Este comando es solo para mi propietario. ¡Lo siento, este es exclusivo! 🔒'),
+owner: await tr('「 ꛕ 」 Este comando es solo para mi propietario. ¡Lo siento, este es exclusivo! 🔒.'),
+mods: await tr('「 ꛕ 」 Este comando solo lo puedo usar yo.'),
+premium: await tr('「 ꛕ 」 Este comando es solo para usuarios Premium (VIP). ¡Ser VIP tiene sus beneficios! 🌟'),
+group: await tr('「 ꛕ 」 Este comando es solo para grupos'),
+private: await tr('「 ꛕ 」 Este comando solo funciona en el privado del bot. ¡Escribeme en privado! ⚡'),
+admin: await tr('「 ꛕ 」No eres admin. Solo los admins pueden usar este comando. 😇'),
+botAdmin: await tr('「 ꛕ 」 Necesito ser admin para poder usar este comando.'),
+unreg: await tr('「🚨」 *¡Hey! no estas registrado, registrese para usar esta función*\n\n*/reg nombre.edad*\n*_❕ Ejemplo_* : */reg Crxs.18*'),
+restrict: await tr('[ 🔐 ] Este comando esta desactivado por Crxs')
+}[type];
+if (msg) return conn.sendMessage(m.chat, {text: msg, contextInfo: { mentionedJid: null, forwardingScore: 1, isForwarded: true, forwardedNewsletterMessageInfo: { newsletterJid: '120363371008200788@newsletter', serverMessageId: '', newsletterName: 'Kantu Bot 🐣' }, externalAdReply : {mediaUrl: null, mediaType: 1, description: null, "title": `ℹ️𝐈𝐍𝐅𝐎 ℹ️`, body: wm, previewType: 0, "thumbnail": img.getRandom(), sourceUrl: [nna, nna2, md, yt, nn, tiktok].getRandom()}}}, { quoted: m })
+}
+
+const file = global.__filename(import.meta.url, true);
+watchFile(file, async () => {
+unwatchFile(file)
+console.log(chalk.redBright('Update \'handler.js\''));
+//if (global.reloadHandler) console.log(await global.reloadHandler());
+  
+/*if (global.conns && global.conns.length > 0 ) {
+const users = [...new Set([...global.conns.filter((conn) => conn.user && conn.ws.socket && conn.ws.socket.readyState !== ws.CLOSED).map((conn) => conn)])];
+for (const userr of users) {
+userr.subreloadHandler(false)
+}}
+*/  
+}); 

+ 77 - 0
index.js

@@ -0,0 +1,77 @@
+console.log('Iniciando 🚀🚀🚀') 
+import { join, dirname } from 'path'
+import { createRequire } from 'module'
+import { fileURLToPath } from 'url'
+import { setupMaster, fork } from 'cluster'
+import { watchFile, unwatchFile } from 'fs'
+import cfonts from 'cfonts'
+import { createInterface } from 'readline'
+import yargs from 'yargs'
+const __dirname = dirname(fileURLToPath(import.meta.url))
+const require = createRequire(__dirname)
+const { name, author } = require(join(__dirname, './package.json'))
+const { say } = cfonts
+const rl = createInterface(process.stdin, process.stdout)
+ 
+say('KantuBot', {
+font: 'chrome',
+align: 'center',
+gradient: ['red', 'magenta']})
+say(`by: CrxsMods`, {
+font: 'console',
+align: 'center',
+gradient: ['red', 'magenta']});
+
+let isRunning = false
+/**
+* Start a js file
+* @param {String} file `path/to/file`
+*/
+function start(file) {
+if (isRunning) return
+isRunning = true
+const args = [join(__dirname, file), ...process.argv.slice(2)]
+
+setupMaster({
+exec: args[0],
+args: args.slice(1)})
+const p = fork()
+p.on('message', (data) => {
+//console.log('╭--------- - - - ✓\n┆ ✅ TIEMPO DE ACTIVIDAD ACTUALIZADA\n╰-------------------- - - -', data)
+switch (data) {
+case 'reset':
+p.process.kill()
+isRunning = false
+start.apply(this, arguments)
+break
+case 'uptime':
+p.send(process.uptime())
+break
+}
+})
+p.on('exit', (_, code) => {
+isRunning = false;
+console.error('⚠️ Error Inesperado ⚠️', code)
+p.process.kill()
+isRunning = false
+start.apply(this, arguments)
+if (process.env.pm_id) {
+process.exit(1)
+} else {
+process.exit()
+}})
+const opts = new Object(yargs(process.argv.slice(2)).exitProcess(false).parse())
+if (!opts['test']) {
+if (!rl.listenerCount()) {
+rl.on('line', (line) => {
+p.emit('message', line.trim())
+})
+}}}
+
+setInterval(() => {
+console.log('♻️ Reiniciando bot automáticamente...');
+process.exit(0); 
+}, 14400000) //4hs
+
+start('main.js');
+

+ 327 - 0
install.sh

@@ -0,0 +1,327 @@
+# Código creado por @gata_dios      
+
+#!/data/data/com.termux/files/usr/bin/bash 
+# Interpretación determinada para la ejecución      
+
+echo -e "\e[35m
+─█▀▀█ ───░█ ░█─░█ ░█▀▀▀█ ▀▀█▀▀ ░█▀▀▀   ░█─── ─█▀▀█   ░█▀▀█ ─█▀▀█ ░█▄─░█ ▀▀█▀▀ ─█▀▀█ ░█─── ░█─── ─█▀▀█ 
+░█▄▄█ ─▄─░█ ░█─░█ ─▀▀▀▄▄ ─░█── ░█▀▀▀   ░█─── ░█▄▄█   ░█▄▄█ ░█▄▄█ ░█░█░█ ─░█── ░█▄▄█ ░█─── ░█─── ░█▄▄█ 
+░█─░█ ░█▄▄█ ─▀▄▄▀ ░█▄▄▄█ ─░█── ░█▄▄▄   ░█▄▄█ ░█─░█   ░█─── ░█─░█ ░█──▀█ ─░█── ░█─░█ ░█▄▄█ ░█▄▄█ ░█─░█\n\e[0m" 
+
+: <<'COMMENT'
+...
+COMMENT
+
+echo -e "\033[01;93mPreparando instalación...\n\033[0m"
+mp3_array=("https://qu.ax/vkZR.mp3" "https://qu.ax/FYQy.mp3" "https://qu.ax/rSUn.mp3" "https://qu.ax/CCzM.mp3" "https://qu.ax/nuFz.mp3" "https://qu.ax/YKe.mp3")
+random_mp3=${mp3_array[$RANDOM % ${#mp3_array[@]}]}
+echo -e ""
+while true; do
+mpv --no-terminal "$random_mp3" &
+sleep 2
+wait
+done &
+echo -e ""
+ 
+echo -e "\033[01;32m\033[01mInstalando dependencias!!\n\033[0m" 
+echo -e "\e[36m
+██╗███╗░░██╗░██████╗████████╗░█████╗░██╗░░░░░██╗░░░░░
+██║████╗░██║██╔════╝╚══██╔══╝██╔══██╗██║░░░░░██║░░░░░
+██║██╔██╗██║╚█████╗░░░░██║░░░███████║██║░░░░░██║░░░░░
+██║██║╚████║░╚═══██╗░░░██║░░░██╔══██║██║░░░░░██║░░░░░
+██║██║░╚███║██████╔╝░░░██║░░░██║░░██║███████╗███████╗
+╚═╝╚═╝░░╚══╝╚═════╝░░░░╚═╝░░░╚═╝░░╚═╝╚══════╝╚══════╝
+
+░██████╗░██╗████████╗
+██╔════╝░██║╚══██╔══╝
+██║░░██╗░██║░░░██║░░░
+██║░░╚██╗██║░░░██║░░░
+╚██████╔╝██║░░░██║░░░
+░╚═════╝░╚═╝░░░╚═╝░░░\n\e[0m"
+
+if command -v git >/dev/null 2>&1; then
+echo -e "\033[01;33mGit ya estaba instalado anteriormente.\033[0m"
+else
+if pkg install git -y 2>&1 >/dev/null | grep -E -i -q '(command not found|unable to locate package|E: Could not get lock|debconf: delaying package configuration|Package not found|Failed to fetch|404 Not Found|Hash sum mismatch|503 Service Unavailable|504 Gateway Timeout|408 Request Timeout|Connection timed out|Temporary failure resolving)'; then
+error=$(pkg install git -y 2>&1 >/dev/null)
+echo -e "\033[0;31mError: $error\033[0m" 
+echo -e "\033[0;34mNo se pudo instalar Git. Verifique su conexión a Internet e inténtelo de nuevo. Si el error continúa, instale de forma manual!!\033[0m" 
+echo -e "\033[01;33mpkg install git -y\npkg install nodejs -y\npkg install ffmpeg -y\npkg install imagemagick -y\npkg install -y yarn\ngit clone https://github.com/elrebelde21/LoliBot-MD\ncd LoliBot-MD\nyarn install\nnpm install\nnpm start\033[0m"
+exit 1
+else
+echo -e "\033[01;32m\033[01mGit se ha instalado correctamente.\n\033[0m" 
+fi
+fi
+ 
+echo -e "\e[35m
+██╗███╗░░██╗░██████╗████████╗░█████╗░██╗░░░░░██╗░░░░░
+██║████╗░██║██╔════╝╚══██╔══╝██╔══██╗██║░░░░░██║░░░░░
+██║██╔██╗██║╚█████╗░░░░██║░░░███████║██║░░░░░██║░░░░░
+██║██║╚████║░╚═══██╗░░░██║░░░██╔══██║██║░░░░░██║░░░░░
+██║██║░╚███║██████╔╝░░░██║░░░██║░░██║███████╗███████╗
+╚═╝╚═╝░░╚══╝╚═════╝░░░░╚═╝░░░╚═╝░░╚═╝╚══════╝╚══════╝
+
+███╗░░██╗░█████╗░██████╗░███████╗░░░░░░░░██╗░██████╗
+████╗░██║██╔══██╗██╔══██╗██╔════╝░░░░░░░░██║██╔════╝
+██╔██╗██║██║░░██║██║░░██║█████╗░░░░░░░░░░██║╚█████╗░
+██║╚████║██║░░██║██║░░██║██╔══╝░░░░░██╗░░██║░╚═══██╗
+██║░╚███║╚█████╔╝██████╔╝███████╗██╗╚█████╔╝██████╔╝
+╚═╝░░╚══╝░╚════╝░╚═════╝░╚══════╝╚═╝░╚════╝░╚═════╝░\n\e[0m"
+
+if command -v node >/dev/null 2>&1; then
+echo -e "\033[01;33mNodejs ya estaba instalado anteriormente.\033[0m"
+else
+if pkg install nodejs -y 2>&1 >/dev/null | grep -E -i -q '(command not found|unable to locate package|E: Could not get lock|debconf: delaying package configuration|Package not found|Failed to fetch|404 Not Found|Hash sum mismatch|503 Service Unavailable|504 Gateway Timeout|408 Request Timeout|Connection timed out|Temporary failure resolving)'; then
+error=$(pkg install nodejs -y 2>&1 >/dev/null)
+echo -e "\033[0;31mError: $error\033[0m" 
+echo -e "\033[0;34mNo se pudo instalar Node.js. Verifique su conexión a Internet e inténtelo de nuevo. Si el error continúa, instale de forma manual!!\033[0m" 
+echo -e "\033[01;33mpkg install git -y\npkg install nodejs -y\npkg install ffmpeg -y\npkg install imagemagick -y\npkg install -y yarn\ngit clone https://github.com/elrebelde21/LoliBot-MD\ncd LoliBot-MD\nyarn install\nnpm install\nnpm start\033[0m"
+exit 1
+else
+echo -e "\033[01;32m\033[01mNode.js se ha instalado correctamente.\n\033[0m" 
+fi
+fi
+
+echo -e "\e[36m
+██╗███╗░░██╗░██████╗████████╗░█████╗░██╗░░░░░██╗░░░░░
+██║████╗░██║██╔════╝╚══██╔══╝██╔══██╗██║░░░░░██║░░░░░
+██║██╔██╗██║╚█████╗░░░░██║░░░███████║██║░░░░░██║░░░░░
+██║██║╚████║░╚═══██╗░░░██║░░░██╔══██║██║░░░░░██║░░░░░
+██║██║░╚███║██████╔╝░░░██║░░░██║░░██║███████╗███████╗
+╚═╝╚═╝░░╚══╝╚═════╝░░░░╚═╝░░░╚═╝░░╚═╝╚══════╝╚══════╝
+
+███████╗███████╗███╗░░░███╗██████╗░███████╗░██████╗░
+██╔════╝██╔════╝████╗░████║██╔══██╗██╔════╝██╔════╝░
+█████╗░░█████╗░░██╔████╔██║██████╔╝█████╗░░██║░░██╗░
+██╔══╝░░██╔══╝░░██║╚██╔╝██║██╔═══╝░██╔══╝░░██║░░╚██╗
+██║░░░░░██║░░░░░██║░╚═╝░██║██║░░░░░███████╗╚██████╔╝
+╚═╝░░░░░╚═╝░░░░░╚═╝░░░░░╚═╝╚═╝░░░░░╚══════╝░╚═════╝░\n\e[0m"
+
+if command -v ffmpeg >/dev/null 2>&1; then
+echo -e "\033[01;33mFfmpeg ya estaba instalado anteriormente..\033[0m"
+else
+if pkg install ffmpeg -y 2>&1 >/dev/null | grep -E -i -q '(command not found|unable to locate package|E: Could not get lock|debconf: delaying package configuration|Package not found|Failed to fetch|404 Not Found|Hash sum mismatch|503 Service Unavailable|504 Gateway Timeout|408 Request Timeout|Connection timed out|Temporary failure resolving)'; then
+error=$(pkg install ffmpeg -y 2>&1 >/dev/null)
+echo -e "\033[0;31mError: $error\033[0m" 
+echo -e "\033[0;34mNo se pudo instalar FFmpeg. Verifique su conexión a Internet e inténtelo de nuevo. Si el error continúa, instale de forma manual!!\033[0m" 
+echo -e "\033[01;33mpkg install git -y\npkg install nodejs -y\npkg install ffmpeg -y\npkg install imagemagick -y\npkg install -y yarn\ngit clone https://github.com/elrebelde21/LoliBot-MD\ncd LoliBot-MD\nyarn install\nnpm install\nnpm start\033[0m"
+exit 1
+else
+echo -e "\033[01;32m\033[01mFFmpeg se ha instalado correctamente.\n\033[0m" 
+fi
+fi
+
+echo -e "\e[35m
+██╗███╗░░██╗░██████╗████████╗░█████╗░██╗░░░░░██╗░░░░░
+██║████╗░██║██╔════╝╚══██╔══╝██╔══██╗██║░░░░░██║░░░░░
+██║██╔██╗██║╚█████╗░░░░██║░░░███████║██║░░░░░██║░░░░░
+██║██║╚████║░╚═══██╗░░░██║░░░██╔══██║██║░░░░░██║░░░░░
+██║██║░╚███║██████╔╝░░░██║░░░██║░░██║███████╗███████╗
+╚═╝╚═╝░░╚══╝╚═════╝░░░░╚═╝░░░╚═╝░░╚═╝╚══════╝╚══════╝
+
+██╗███╗░░░███╗░█████╗░░██████╗░███████╗███╗░░░███╗░█████╗░░██████╗░██╗░█████╗░██╗░░██╗
+██║████╗░████║██╔══██╗██╔════╝░██╔════╝████╗░████║██╔══██╗██╔════╝░██║██╔══██╗██║░██╔╝
+██║██╔████╔██║███████║██║░░██╗░█████╗░░██╔████╔██║███████║██║░░██╗░██║██║░░╚═╝█████═╝░
+██║██║╚██╔╝██║██╔══██║██║░░╚██╗██╔══╝░░██║╚██╔╝██║██╔══██║██║░░╚██╗██║██║░░██╗██╔═██╗░
+██║██║░╚═╝░██║██║░░██║╚██████╔╝███████╗██║░╚═╝░██║██║░░██║╚██████╔╝██║╚█████╔╝██║░╚██╗
+╚═╝╚═╝░░░░░╚═╝╚═╝░░╚═╝░╚═════╝░╚══════╝╚═╝░░░░░╚═╝╚═╝░░╚═╝░╚═════╝░╚═╝░╚════╝░╚═╝░░╚═╝\n\e[0m"
+
+if command -v convert >/dev/null 2>&1; then
+echo -e "\033[01;33mImagemagick ya estaba instalado anteriormente.\033[0m"
+else
+if pkg install imagemagick -y 2>&1 >/dev/null | grep -E -i -q '(command not found|unable to locate package|E: Could not get lock|debconf: delaying package configuration|Package not found|Failed to fetch|404 Not Found|Hash sum mismatch|503 Service Unavailable|504 Gateway Timeout|408 Request Timeout|Connection timed out|Temporary failure resolving)'; then
+error=$(pkg install imagemagick -y 2>&1 >/dev/null)
+echo -e "\033[0;31mError: $error\033[0m" 
+echo -e "\033[0;34mNo se pudo instalar ImageMagick. Verifique su conexión a Internet e inténtelo de nuevo. Si el error continúa, instale de forma manual!!\033[0m" 
+echo -e "\033[01;33mpkg install git -y\npkg install nodejs -y\npkg install ffmpeg -y\npkg install imagemagick -y\npkg install -y yarn\ngit clone https://github.com/elrebelde21/LoliBot-MD\ncd LoliBot-MD\nyarn install\nnpm install\nnpm start\033[0m"
+exit 1
+else
+echo -e "\033[01;32m\033[01mImageMagick se ha instalado correctamente\n\033[0m" 
+fi
+fi
+
+echo -e "\e[36m
+██╗███╗░░██╗░██████╗████████╗░█████╗░██╗░░░░░██╗░░░░░
+██║████╗░██║██╔════╝╚══██╔══╝██╔══██╗██║░░░░░██║░░░░░
+██║██╔██╗██║╚█████╗░░░░██║░░░███████║██║░░░░░██║░░░░░
+██║██║╚████║░╚═══██╗░░░██║░░░██╔══██║██║░░░░░██║░░░░░
+██║██║░╚███║██████╔╝░░░██║░░░██║░░██║███████╗███████╗
+╚═╝╚═╝░░╚══╝╚═════╝░░░░╚═╝░░░╚═╝░░╚═╝╚══════╝╚══════╝
+
+██╗░░░██╗░█████╗░██████╗░███╗░░██╗
+╚██╗░██╔╝██╔══██╗██╔══██╗████╗░██║
+░╚████╔╝░███████║██████╔╝██╔██╗██║
+░░╚██╔╝░░██╔══██║██╔══██╗██║╚████║
+░░░██║░░░██║░░██║██║░░██║██║░╚███║
+░░░╚═╝░░░╚═╝░░╚═╝╚═╝░░╚═╝╚═╝░░╚══╝\n\e[0m"
+
+if command -v yarn >/dev/null 2>&1; then
+echo -e ""
+else
+if npm install -g yarn 2>&1 >/dev/null | grep -E -i -q '(command not found|unable to locate package|E: Could not get lock|debconf: delaying package configuration|Package not found|Failed to fetch|404 Not Found|Hash sum mismatch|503 Service Unavailable|504 Gateway Timeout|408 Request Timeout|Connection timed out|Temporary failure resolving)'; then
+error=$(npm install -g yarn 2>&1 >/dev/null)
+echo -e "\033[0;31mError: $error\033[0m" 
+echo -e "\033[0;34mNo se pudo instalar Yarn. Verifique su conexión a Internet e inténtelo de nuevo. Si el error continúa, instale de forma manual!!\033[0m" 
+echo -e "\033[01;33mpkg install git -y\npkg install nodejs -y\npkg install ffmpeg -y\npkg install imagemagick -y\npkg install -y yarn\ngit clone https://github.com/elrebelde21/LoliBot-MD\ncd LoliBot-MD\nyarn install\nnpm install\nnpm start\033[0m"
+exit 1
+else
+echo -e "" 
+fi
+fi
+
+echo -e "\e[36m
+▀▀█▀▀ ▒█▀▀▀█ ▒█▀▀▄ ▒█▀▀▀█   ▒█▀▀█ ▒█▀▀▀█ ▒█▀▀█ ▒█▀▀█ ▒█▀▀▀ ▒█▀▀█ ▀▀█▀▀ ▒█▀▀▀█ 
+░▒█░░ ▒█░░▒█ ▒█░▒█ ▒█░░▒█   ▒█░░░ ▒█░░▒█ ▒█▄▄▀ ▒█▄▄▀ ▒█▀▀▀ ▒█░░░ ░▒█░░ ▒█░░▒█ 
+░▒█░░ ▒█▄▄▄█ ▒█▄▄▀ ▒█▄▄▄█   ▒█▄▄█ ▒█▄▄▄█ ▒█░▒█ ▒█░▒█ ▒█▄▄▄ ▒█▄▄█ ░▒█░░ ▒█▄▄▄█\n\e[0m"
+echo -e "\033[01;32m\033[01m\nTodas las dependencias se han instalado correctamente.\n\033[0m" 
+
+echo -e "\e[35m
+██╗░░██╗░░██╗░░  ██╗███╗░░██╗░██████╗████████╗░█████╗░██╗░░░░░██╗░░░░░
+╚██╗░╚██╗░╚██╗░  ██║████╗░██║██╔════╝╚══██╔══╝██╔══██╗██║░░░░░██║░░░░░
+░╚██╗░╚██╗░╚██╗  ██║██╔██╗██║╚█████╗░░░░██║░░░███████║██║░░░░░██║░░░░░
+░██╔╝░██╔╝░██╔╝  ██║██║╚████║░╚═══██╗░░░██║░░░██╔══██║██║░░░░░██║░░░░░
+██╔╝░██╔╝░██╔╝░  ██║██║░╚███║██████╔╝░░░██║░░░██║░░██║███████╗███████╗
+╚═╝░░╚═╝░░╚═╝░░  ╚═╝╚═╝░░╚══╝╚═════╝░░░░╚═╝░░░╚═╝░░╚═╝╚══════╝╚══════╝
+
+╔══╗╔╗╔╗╔═╗────╔╗─╔═╗╔╗─╔══╗╔══╗╔═╗╔══╗────╔═╦═╗╔══╗  
+╚╗╔╝║╚╝║║╦╝╔══╗║║─║║║║║─╚║║╝║╔╗║║║║╚╗╔╝╔══╗║║║║║╚╗╗║  
+─║║─║╔╗║║╩╗╚══╝║╚╗║║║║╚╗╔║║╗║╔╗║║║║─║║─╚══╝║║║║║╔╩╝║  
+─╚╝─╚╝╚╝╚═╝────╚═╝╚═╝╚═╝╚══╝╚══╝╚═╝─╚╝─────╚╩═╩╝╚══╝  
+────────────────────────────────────────────────────\n\e[0m"
+
+echo -e "\033[1;35m"
+git clone https://github.com/elrebelde21/LoliBot-MD && cd LoliBot-MD
+echo -e "\033[01;32m\033[01mLa clonación se ha descargado e instalado correctamente.\n\033[0m"
+
+echo -e "\033[01;32m\033[01mCambiando al directorio del repositorio!!\n\033[0m" 
+cd LoliBot-MD
+
+echo -e "\e[36m
+██╗███╗░░██╗░██████╗████████╗░█████╗░██╗░░░░░██╗░░░░░  ███╗░░██╗██████╗░███╗░░░███╗
+██║████╗░██║██╔════╝╚══██╔══╝██╔══██╗██║░░░░░██║░░░░░  ████╗░██║██╔══██╗████╗░████║
+██║██╔██╗██║╚█████╗░░░░██║░░░███████║██║░░░░░██║░░░░░  ██╔██╗██║██████╔╝██╔████╔██║
+██║██║╚████║░╚═══██╗░░░██║░░░██╔══██║██║░░░░░██║░░░░░  ██║╚████║██╔═══╝░██║╚██╔╝██║
+██║██║░╚███║██████╔╝░░░██║░░░██║░░██║███████╗███████╗  ██║░╚███║██║░░░░░██║░╚═╝░██║
+╚═╝╚═╝░░╚══╝╚═════╝░░░░╚═╝░░░╚═╝░░╚═╝╚══════╝╚══════╝  ╚═╝░░╚══╝╚═╝░░░░░╚═╝░░░░░╚═╝\n\e[0m"
+
+if command npm install >/dev/null 2>&1; then
+echo -e "\033[01;33m Se actualizará NPM automáticamente. Espere un momento por favor.\033[0m"
+else
+echo -e "\033[0;34mNPM no se encontró en su sistema. Se instalará NPM automáticamente.\n\033[0m"
+if npm install 2>&1 >/dev/null | grep -E -i -q '(command not found|unable to locate package|E: Could not get lock|debconf: delaying package configuration|Package not found|Failed to fetch|404 Not Found|Hash sum mismatch|503 Service Unavailable|504 Gateway Timeout|408 Request Timeout|Connection timed out|Temporary failure resolving)'; then
+error=$(npm install 2>&1 >/dev/null)
+echo -e "\033[0;31mError: $error\033[0m" 
+echo -e "\033[0;34mNo se pudo instalar NPM. Verifique su conexión a Internet e inténtelo de nuevo. Si el error continúa, instale de forma manual!!\nIf the error continues, install manually!!\033[0m" 
+echo -e "\033[01;33mpkg install git -y\npkg install nodejs -y\npkg install ffmpeg -y\npkg install imagemagick -y\npkg install yarn -y\npkg install npm -y\ngit clone https://github.com/elrebelde21/LoliBot-MD\ncd LoliBot-MD\nnpm install\nyarn install\nnpm start\033[0m"
+exit 1
+else
+echo -e "\033[01;32m\033[01mNPM se ha instalado correctamente..\n\033[0m" 
+fi
+fi
+
+echo -e "\e[35m
+██╗███╗░░██╗░██████╗████████╗░█████╗░██╗░░░░░██╗░░░░░  ██╗░░░██╗░█████╗░██████╗░███╗░░██╗
+██║████╗░██║██╔════╝╚══██╔══╝██╔══██╗██║░░░░░██║░░░░░  ╚██╗░██╔╝██╔══██╗██╔══██╗████╗░██║
+██║██╔██╗██║╚█████╗░░░░██║░░░███████║██║░░░░░██║░░░░░  ░╚████╔╝░███████║██████╔╝██╔██╗██║
+██║██║╚████║░╚═══██╗░░░██║░░░██╔══██║██║░░░░░██║░░░░░  ░░╚██╔╝░░██╔══██║██╔══██╗██║╚████║
+██║██║░╚███║██████╔╝░░░██║░░░██║░░██║███████╗███████╗  ░░░██║░░░██║░░██║██║░░██║██║░╚███║
+╚═╝╚═╝░░╚══╝╚═════╝░░░░╚═╝░░░╚═╝░░╚═╝╚══════╝╚══════╝  ░░░╚═╝░░░╚═╝░░╚═╝╚═╝░░╚═╝╚═╝░░╚══╝\n\e[0m"
+
+if command yarn install >/dev/null 2>&1; then
+echo -e "\033[01;33mSe actualizará yarn automáticamente. Espere un momento por favor...\033[0m"
+else
+if yarn install 2>&1 >/dev/null | grep -E -i -q '(command not found|unable to locate package|E: Could not get lock|debconf: delaying package configuration|Package not found|Failed to fetch|404 Not Found|Hash sum mismatch|503 Service Unavailable|504 Gateway Timeout|408 Request Timeout|Connection timed out|Temporary failure resolving)'; then
+error=$(yarn install 2>&1 >/dev/null)
+echo -e "\033[0;31mError: $error\033[0m" 
+echo -e "\033[0;34mNo se pudo instalar Yarn. Verifique su conexión a Internet e inténtelo de nuevo. Si el error continúa, instale de forma manual!!\nIf the error continues, install manually!!\033[0m" 
+echo -e "\033[01;33mpkg install git -y\npkg install nodejs -y\npkg install ffmpeg -y\npkg install imagemagick -y\npkg install yarn\ngit clone https://github.com/elrebelde21/LoliBot-MD\ncd LoliBot-MD\nnpm install\nyarn install\nnpm start\033[0m"
+exit 1
+else
+echo -e "\033[01;32m\033[01mYarn se ha instalado correctamente.....\n\033[0m" 
+fi
+fi
+
+: <<'COMMENT'
+v="${b}\033[1;32m"
+v1="${b}\033[32m"
+b="\033[0m"
+
+menu() {
+	#LoliBot-MD
+	echo -e "${v1} MENÚ DE CONFIGURACIÓN"
+	printf "\n"
+	printf "${v1}[${b}01${v1}]${v} Visistar Grupo de Actualizaciones\n"
+	printf "\n"
+	printf "${v1}[${b}02${v1}]${v} Elegir idioma español\n"
+	printf "\n"
+	printf "${v1}[${b}03${v1}]${v} Elegir idioma inglés\n"
+	printf "\n"
+	printf "${v1}[${b}04${v1}]${v} Continuar\n"
+	printf "\n"
+}
+
+menu_ayuda() {
+    #printf "${v1}[${b}++${v1}]${v} GataBot-MD${b}: "
+	read opcion
+	case $opcion in
+            01|1)
+                am start -a android.intent.action.VIEW https://chat.whatsapp.com/DVhu9S9Zr7cBFFl26N61U3 &>> /dev/null
+                echo -e "${b}[${v1}++${b}]${v} Accediendo al Grupo Oficial\n"
+                
+                ;;
+            02|2)
+                echo -e "${b}[${v1}++${b}]${v} Seleccionado idioma español\n"
+                
+                ;;
+            03|3)
+                echo -e "${b}[${v1}++${b}]${v} Seleccionado idioma inglés\n"
+                
+                ;;
+	    04|4)
+	        iniciar
+                echo -e "${b}[${v1}++${b}]${v} Continuando...\n"
+                
+                ;;
+            *)
+                echo -e "${v1}Comando: '"${r1}${opcion}${v1}"' invalido."
+		echo ""
+		inicio
+                ;;
+        esac
+}
+
+menu
+menu_ayuda
+COMMENT
+
+clear
+echo -e "\e[36m
+░█▀▀█ ░█▀▀█ ─█▀▀█ ░█▀▀█ ▀█▀ ─█▀▀█ ░█▀▀▀█   ░█▀▀█ ░█▀▀▀█ ░█▀▀█   ░█▀▀▀█ ░█─░█ 
+░█─▄▄ ░█▄▄▀ ░█▄▄█ ░█─── ░█─ ░█▄▄█ ─▀▀▀▄▄   ░█▄▄█ ░█──░█ ░█▄▄▀   ─▀▀▀▄▄ ░█─░█ 
+░█▄▄█ ░█─░█ ░█─░█ ░█▄▄█ ▄█▄ ░█─░█ ░█▄▄▄█   ░█─── ░█▄▄▄█ ░█─░█   ░█▄▄▄█ ─▀▄▄▀ 
+
+░█▀▀█ ░█▀▀█ ░█▀▀▀ ░█▀▀▀ ░█▀▀▀ ░█▀▀█ ░█▀▀▀ ░█▄─░█ ░█▀▀█ ▀█▀ ─█▀▀█ 
+░█▄▄█ ░█▄▄▀ ░█▀▀▀ ░█▀▀▀ ░█▀▀▀ ░█▄▄▀ ░█▀▀▀ ░█░█░█ ░█─── ░█─ ░█▄▄█ 
+░█─── ░█─░█ ░█▄▄▄ ░█─── ░█▄▄▄ ░█─░█ ░█▄▄▄ ░█──▀█ ░█▄▄█ ▄█▄ ░█─░█\n\e[0m"
+
+echo -e "\e[31m
+_░▒███████
+░██▓▒░░▒▓██
+██▓▒░__░▒▓██___██████
+██▓▒░____░▓███▓__░▒▓██
+██▓▒░___░▓██▓_____░▒▓██
+██▓▒░_______________░▒▓██
+_██▓▒░______________░▒▓██
+__██▓▒░____________░▒▓██
+___██▓▒░__________░▒▓██
+____██▓▒░________░▒▓██
+_____██▓▒░_____░▒▓██
+______██▓▒░__░▒▓██
+_______█▓▒░░▒▓██
+_________░▒▓██
+_______░▒▓██
+_____░▒▓██\n\e[0m"
+    
+sleep 15 && pkill mpv > /dev/null 2>&1 && sleep 2 && rm -f /data/data/com.termux/files/home/"$random_mp3" &
+echo -e "\033[01;32m\033[01mIniciando Kantu!\n\033[0m"
+npm start

+ 16 - 0
koyeb.js

@@ -0,0 +1,16 @@
+FROM fedora:37
+ 
+RUN sudo dnf -y update &&\
+    sudo dnf install -y https://mirrors.rpmfusion.org/free/fedora/rpmfusion-free-release-$(rpm -E %fedora).noarch.rpm https://mirrors.rpmfusion.org/nonfree/fedora/rpmfusion-nonfree-release-$(rpm -E %fedora).noarch.rpm &&\
+    sudo dnf install -y git ffmpeg ImageMagick nodejs yarnpkg libwebp &&\
+    sudo dnf clean all -y
+
+RUN git clone https://github.com/elrebelde21/The-LoliBot-MD
+
+WORKDIR /root/The-LoliBot-MD
+
+COPY ./root/The-LoliBot-MD
+
+RUN yarn install
+
+CMD ["node", "index.js"]

+ 65 - 0
lib/canvas.js

@@ -0,0 +1,65 @@
+import {spawn} from 'child_process';
+import {join} from 'path';
+
+const __dirname = global.__dirname(import.meta.url);
+/**
+ * Levelup image
+ * @param {String} teks
+ * @param {Number} level
+ * @return {Promise<Buffer>}
+ */
+export function levelup(teks, level) {
+  return new Promise(async (resolve, reject) => {
+    if (!(global.support.convert || global.support.magick || global.support.gm)) return reject('Not Support!');
+    const font = join(__dirname, '../src/font');
+    const fontLevel = join(font, './level_c.otf');
+    const fontTexts = join(font, './texts.otf');
+    const xtsx = join(__dirname, '../src/lvlup_template.jpg');
+    let anotations = '+1385+260'; // gapake else if kadang error
+    if (level > 2) anotations = '+1370+260';
+    if (level > 10) anotations = '+1330+260';
+    if (level > 50) anotations = '+1310+260';
+    if (level > 100) anotations = '+1260+260';
+
+    const [_spawnprocess, ..._spawnargs] = [...(global.support.gm ? ['gm'] : global.support.magick ? ['magick'] : []),
+      'convert',
+      xtsx,
+      '-font',
+      fontTexts,
+      '-fill',
+      '#0F3E6A',
+      '-size',
+      '1024x784',
+      '-pointsize',
+      '68',
+      '-interline-spacing',
+      '-7.5',
+      '-annotate',
+      '+153+200',
+      teks,
+      // original together
+      '-font',
+      fontLevel,
+      '-fill',
+      '#0A2A48',
+      '-size',
+      '1024x784',
+      '-pointsize',
+      '140',
+      '-interline-spacing',
+      '-1.2',
+      '-annotate',
+      anotations,
+      level,
+      '-append',
+      'jpg:-',
+    ];
+    const bufs = [];
+    spawn(_spawnprocess, _spawnargs)
+        .on('error', reject)
+        .on('close', () => {
+          return resolve(Buffer.concat(bufs));
+        })
+        .stdout.on('data', (chunk) => bufs.push(chunk));
+  });
+}

+ 318 - 0
lib/chatgpt.js

@@ -0,0 +1,318 @@
+import axios from 'axios';
+
+const perplexity = {
+  api: {
+    base: 'https://api.perplexity.ai/chat/completions',
+    
+    models: {
+      'sonar-medium-online': {
+        description: 'Online-enabled medium model',
+        context: 12000
+      },
+      'sonar-small-online': {
+        description: 'Online-enabled small model',
+        context: 12000
+      },
+      'sonar-medium-chat': {
+        description: 'Optimized medium chat model',
+        context: 12000
+      },
+      'sonar-small-chat': {
+        description: 'Optimized small chat model', 
+        context: 12000
+      },
+      'sonar-reasoning-pro': {
+        description: 'Advanced reasoning model with enhanced capabilities',
+        context: 16384
+      },
+      'sonar-reasoning': {
+        description: 'Balanced reasoning model',
+        context: 8192
+      },
+      'sonar-pro': {
+        description: 'Enhanced general purpose model',
+        context: 8192
+      },
+      'sonar': {
+        description: 'Fast and efficient model',
+        context: 4096
+      },
+      'mixtral-8x7b-instruct': {
+        description: 'Mixtral instruction model',
+        context: 8192
+      },
+      'codellama-70b-instruct': {
+        description: 'Code specialized model',
+        context: 8192
+      },
+      'llama-2-70b-chat': {
+        description: 'LLaMA 2 chat model',
+        context: 4096
+      }
+    },
+
+    headers: {
+      'Content-Type': 'application/json',
+      'Accept': 'application/json',
+      'User-Agent': 'Postify/1.0.0'
+    },
+
+    keys: [
+      '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',
+      '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',
+      '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',
+      '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'
+    ],
+
+    retry: {
+      maxAttempts: 3,
+      delayMs: 2000,
+      timeoutMs: 60000
+    }
+  },
+
+  isParams: (messages, model, temperature) => {
+    const errors = [];
+
+    if (!messages || !Array.isArray(messages) || messages.length === 0) {
+      errors.push({
+        param: 'messages',
+        error: 'Udah capek yak gua ngasih tau lu, input tuh minimal diisi napa 🗿',
+        example: [{
+          role: 'user',
+          content: 'inputnya disini yakk'
+        }]
+      });
+    } else {
+      messages.forEach((msg, index) => {
+        if (!msg.role || !msg.content) {
+          errors.push({
+            param: `messages[${index}]`,
+            error: 'Format message lu ngaco anjirr 🗿',
+            example: {
+              role: 'user/assistant',
+              content: 'inputnya disini yakk'
+            }
+          });
+        }
+      });
+    }
+
+    if (!model) {
+      errors.push({
+        param: 'model',
+        error: 'Literally modelnya kagak diisi bree?? Minimal input lah 1 mah 🗿',
+        available: Object.keys(perplexity.api.models)
+      });
+    } else if (!perplexity.api.models[model]) {
+      errors.push({
+        param: 'model',
+        error: 'Model yang lu pilih kagak ada bree! Pilih aja salah satu dari list ini yak ..',
+        available: Object.keys(perplexity.api.models)
+      });
+    }
+
+    if (temperature === undefined || temperature === null) {
+      errors.push({
+        param: 'temperature',
+        error: 'Temperaturenya mana bree?! Kagak kosong begini dong 🗿',
+        range: '0.0 - 1.0',
+        recommended: 0.7
+      });
+    } else if (temperature < 0 || temperature > 1) {
+      errors.push({
+        param: 'temperature',
+        error: 'Temperaturenya kebanyakan atau kurang ngab! Rangenya 0-1 doang yak 🙃',
+        range: '0.0 - 1.0',
+        recommended: 0.7
+      });
+    }
+
+    return errors;
+  },
+
+  key: () => perplexity.api.keys[Math.floor(Math.random() * perplexity.api.keys.length)],
+
+  delay: (ms) => new Promise(resolve => setTimeout(resolve, ms)),
+
+  retry: async (operation, attempt = 1) => {
+    try {
+      return await operation();
+    } catch (error) {
+      if (attempt >= perplexity.api.retry.maxAttempts) {
+        throw error;
+      }
+
+      console.log(`🔄 Ngetry attempt yang ke-${attempt}, nunggu ${perplexity.api.retry.delayMs}ms yak bree 😂...`);
+      console.error(error.message);
+
+      await perplexity.delay(perplexity.api.retry.delayMs * attempt);
+      return await perplexity.retry(operation, attempt + 1);
+    }
+  },
+
+  createAxiosInstance: () => axios.create({
+    baseURL: perplexity.api.base,
+    timeout: perplexity.api.retry.timeoutMs,
+    maxContentLength: Infinity,
+    maxBodyLength: Infinity
+  }),
+
+  getHeaders: (apiKey) => {
+    return {
+      'Authorization': `Bearer ${apiKey}`,
+      ...perplexity.api.headers
+    };
+  },
+
+  chat: async (messages, model = 'sonar', temperature = 0.7) => {
+    const ve = perplexity.isParams(messages, model, temperature);
+    if (ve.length > 0) {
+      return {
+        status: false,
+        code: 400,
+        result: {
+          error: 'Parameter lu pada ngaco semua anjiir 🌝',
+          details: ve
+        }
+      };
+    }
+
+    return await perplexity.retry(async () => {
+      const axiosInstance = perplexity.createAxiosInstance();
+      const perplexityKey = perplexity.key();
+
+      try {
+        const response = await axiosInstance.post('', {
+          model: model,
+          messages: messages,
+          temperature: temperature,
+          max_tokens: 4096,
+          stream: false
+        }, {
+          headers: perplexity.getHeaders(perplexityKey)
+        });
+
+        return {
+          status: true,
+          code: 200,
+          result: {
+            response: response.data.choices[0].message.content,
+            model: {
+              name: model,
+              ...perplexity.api.models[model]
+            }
+          }
+        };
+
+      } catch (error) {
+        const e = {
+          status: false,
+          code: error.response?.status || 500,
+          result: {
+            error: 'Error bree 🗿',
+            details: `${error.message}`,
+            solution: 'Coba lagi nanti aja bree, sapa tau berhasil nanti 😂'
+          }
+        };
+        throw e;
+      }
+    });
+  },
+
+  stream: async (messages, model = 'sonar', temperature = 0.7, onChunk) => {
+    const ve = perplexity.isParams(messages, model, temperature);
+    if (ve.length > 0) {
+      return {
+        status: false,
+        code: 400,
+        result: {
+          error: 'Parameter lu pada ngaco semua bree 😫',
+          details: ve
+        }
+      };
+    }
+
+    if (typeof onChunk !== 'function') {
+      return {
+        status: false,
+        code: 400,
+        result: {
+          error: 'Function callbacknya mana bree?! 😤',
+          details: [{
+            param: 'onChunk',
+            error: 'Kudu pake callback function buat streaminnya bree!',
+            example: '(chunk) => console.log(chunk)'
+          }]
+        }
+      };
+    }
+
+    return await perplexity.retry(async () => {
+      const axiosInstance = perplexity.createAxiosInstance();
+      const perplexityKey = perplexity.key();
+
+      try {
+        const response = await axiosInstance.post('', {
+          model: model,
+          messages: messages,
+          temperature: temperature,
+          max_tokens: 4096,
+          stream: true
+        }, {
+          headers: perplexity.getHeaders(perplexityKey),
+          responseType: 'stream'
+        });
+
+        let pull = '';
+        
+        for await (const chunk of response.data) {
+          const lines = chunk.toString().split('\n');
+          
+          for (const line of lines) {
+            if (line.startsWith('data: ')) {
+              try {
+                const result = JSON.parse(line.slice(5));
+                if (result.choices?.[0]?.delta?.content) {
+                  const content = result.choices[0].delta.content;
+                  pull += content;
+                  onChunk(content);
+                }
+              } catch (e) {
+                if (!line.includes('[DONE]')) {
+                  console.warn('❌ Gagal parse chunknya bree: ', e);
+                }
+              }
+            }
+          }
+        }
+
+        return {
+          status: true,
+          code: 200,
+          result: {
+            response: pull,
+            model: {
+              name: model,
+              ...perplexity.api.models[model]
+            }
+          }
+        };
+
+      } catch (error) {
+        const e = {
+          status: false,
+          code: error.response?.status || 500,
+          result: {
+            error: 'Streamingnya error bree 😑',
+            details: error.message,
+            solution: 'Reset ulang aja dah streamingnya bree 🔄'
+          }
+        };
+        throw e;
+      }
+    });
+  }
+};
+
+export { perplexity };

+ 58 - 0
lib/cloudDBAdapter.js

@@ -0,0 +1,58 @@
+import got from 'got';
+
+const stringify = (obj) => JSON.stringify(obj, null, 2);
+const parse = (str) => JSON.parse(str, (_, v) => {
+  if (
+    v !== null &&
+        typeof v === 'object' &&
+        'type' in v &&
+        v.type === 'Buffer' &&
+        'data' in v &&
+        Array.isArray(v.data)) {
+    return Buffer.from(v.data);
+  }
+  return v;
+});
+class CloudDBAdapter {
+  constructor(url, {
+    serialize = stringify,
+    deserialize = parse,
+    fetchOptions = {},
+  } = {}) {
+    this.url = url;
+    this.serialize = serialize;
+    this.deserialize = deserialize;
+    this.fetchOptions = fetchOptions;
+  }
+
+  async read() {
+    try {
+      const res = await got(this.url, {
+        method: 'GET',
+        headers: {
+          'Accept': 'application/json;q=0.9,text/plain',
+        },
+        ...this.fetchOptions,
+      });
+      if (res.statusCode !== 200) throw res.statusMessage;
+      return this.deserialize(res.body);
+    } catch (e) {
+      return null;
+    }
+  }
+
+  async write(obj) {
+    const res = await got(this.url, {
+      method: 'POST',
+      headers: {
+        'Content-Type': 'application/json',
+      },
+      ...this.fetchOptions,
+      body: this.serialize(obj),
+    });
+    if (res.statusCode !== 200) throw res.statusMessage;
+    return res.body;
+  }
+}
+
+export default CloudDBAdapter;

+ 92 - 0
lib/converter.js

@@ -0,0 +1,92 @@
+import {promises} from 'fs';
+import {join} from 'path';
+import {spawn} from 'child_process';
+
+function ffmpeg(buffer, args = [], ext = '', ext2 = '') {
+  return new Promise(async (resolve, reject) => {
+    try {
+      const tmp = join(global.__dirname(import.meta.url), '../tmp', + new Date + '.' + ext);
+      const out = tmp + '.' + ext2;
+      await promises.writeFile(tmp, buffer);
+      spawn('ffmpeg', [
+        '-y',
+        '-i', tmp,
+        ...args,
+        out,
+      ])
+          .on('error', reject)
+          .on('close', async (code) => {
+            try {
+              await promises.unlink(tmp);
+              if (code !== 0) return reject(code);
+              resolve({
+                data: await promises.readFile(out),
+                filename: out,
+                delete() {
+                  return promises.unlink(out);
+                },
+              });
+            } catch (e) {
+              reject(e);
+            }
+          });
+    } catch (e) {
+      reject(e);
+    }
+  });
+}
+
+/**
+ * Convert Audio to Playable WhatsApp Audio
+ * @param {Buffer} buffer Audio Buffer
+ * @param {String} ext File Extension
+ * @return {Promise<{data: Buffer, filename: String, delete: Function}>}
+ */
+function toPTT(buffer, ext) {
+  return ffmpeg(buffer, [
+    '-vn',
+    '-c:a', 'libopus',
+    '-b:a', '128k',
+    '-vbr', 'on',
+  ], ext, 'ogg');
+}
+
+/**
+ * Convert Audio to Playable WhatsApp PTT
+ * @param {Buffer} buffer Audio Buffer
+ * @param {String} ext File Extension
+ * @return {Promise<{data: Buffer, filename: String, delete: Function}>}
+ */
+function toAudio(buffer, ext) {
+  return ffmpeg(buffer, [
+    '-vn',
+    '-c:a', 'libopus',
+    '-b:a', '128k',
+    '-vbr', 'on',
+    '-compression_level', '10',
+  ], ext, 'opus');
+}
+
+/**
+ * Convert Audio to Playable WhatsApp Video
+ * @param {Buffer} buffer Video Buffer
+ * @param {String} ext File Extension
+ * @return {Promise<{data: Buffer, filename: String, delete: Function}>}
+ */
+function toVideo(buffer, ext) {
+  return ffmpeg(buffer, [
+    '-c:v', 'libx264',
+    '-c:a', 'aac',
+    '-ab', '128k',
+    '-ar', '44100',
+    '-crf', '32',
+    '-preset', 'slow',
+  ], ext, 'mp4');
+}
+
+export {
+  toAudio,
+  toPTT,
+  toVideo,
+  ffmpeg,
+};

+ 70 - 0
lib/database.js

@@ -0,0 +1,70 @@
+import {resolve, dirname as _dirname} from 'path';
+import _fs, {existsSync, readFileSync} from 'fs';
+const {promises: fs} = _fs;
+
+class Database {
+  /**
+     * Create new Database
+     * @param {String} filepath Path to specified json database
+     * @param  {...any} args JSON.stringify arguments
+     */
+  constructor(filepath, ...args) {
+    this.file = resolve(filepath);
+    this.logger = console;
+
+    this._load();
+
+    this._jsonargs = args;
+    this._state = false;
+    this._queue = [];
+    this._interval = setInterval(async () => {
+      if (!this._state && this._queue && this._queue[0]) {
+        this._state = true;
+        await this[this._queue.shift()]().catch(this.logger.error);
+        this._state = false;
+      }
+    }, 1000);
+  }
+
+  get data() {
+    return this._data;
+  }
+
+  set data(value) {
+    this._data = value;
+    this.save();
+  }
+
+  /**
+     * Queue Load
+     */
+  load() {
+    this._queue.push('_load');
+  }
+
+  /**
+     * Queue Save
+     */
+  save() {
+    this._queue.push('_save');
+  }
+
+  _load() {
+    try {
+      return this._data = existsSync(this.file) ? JSON.parse(readFileSync(this.file)) : {};
+    } catch (e) {
+      this.logger.error(e);
+      return this._data = {};
+    }
+  }
+
+  async _save() {
+    const dirname = _dirname(this.file);
+    if (!existsSync(dirname)) await fs.mkdir(dirname, {recursive: true});
+    await fs.writeFile(this.file, JSON.stringify(this._data, ...this._jsonargs));
+    return this.file;
+  }
+}
+
+export default Database;
+

+ 773 - 0
lib/ezgif-convert.js

@@ -0,0 +1,773 @@
+import {
+    FormData 
+} from 'formdata-node';
+import axios from 'axios';
+
+const linksConvert = {
+    "video-gif": {
+        "url": "https://ezgif.com/video-to-gif",
+        "params": {
+            "start": 0,
+            "end": 10,
+            "size": "original",
+            "fps": 10,
+            "method": "ffmpeg"
+        },
+        "req_params": [],
+        "split": {
+            "start": "<img src=\"",
+            "end": "\" style=\"width:"
+        },
+        "either_params": []
+    },
+    "gif-mp4": {
+        "url": "https://ezgif.com/gif-to-mp4",
+        "params": {
+            "convert": "Convert GIF to MP4!"
+        },
+        "req_params": [],
+        "split": {
+            "start": "\" controls><source src=\"",
+            "end": "\" type=\"video/mp4\">Your browser"
+        },
+        "either_params": []
+    },
+    "video-jpg": {
+        "url": "https://ezgif.com/video-to-jpg",
+        "params": {
+            "start": 0,
+            "end": 10,
+            "size": "original",
+            "fps": 10
+        },
+        "req_params": [],
+        "split": {
+            "start": "\"small button danger\" href=\"",
+            "end": "\">Download frames as ZIP"
+        },
+        "either_params": []
+    },
+    "video-png": {
+        "url": "https://ezgif.com/video-to-png",
+        "params": {
+            "start": 0,
+            "end": 10,
+            "size": "original",
+            "fps": 10
+        },
+        "req_params": [],
+        "split": {
+            "start": "\"small button danger\" href=\"",
+            "end": "\">Download frames as ZIP"
+        },
+        "either_params": []
+    },
+    "gif-png": {
+        "url": "https://ezgif.com/split",
+        "params": {
+            "method": "im"
+        },
+        "req_params": [],
+        "split": {
+            "start": "\"small button danger\" href=\"",
+            "end": "\">Download frames as ZIP"
+        },
+        "either_params": []
+    },
+    "gif-sprite": {
+        "url": "https://ezgif.com/gif-to-sprite",
+        "params": {},
+        "req_params": [
+            "format"
+        ],
+        "split": {
+            "start": "<img src=\"",
+            "end": "\" style=\"width:"
+        },
+        "either_params": ["horizontally", "vertically", "custom"]
+    },
+    "sprite-imgage": {
+        "url": "https://ezgif.com/sprite-cutter",
+        "params": {},
+        "req_params": ["format"],
+        "split": {
+            "start": "\"small button danger\" href=\"",
+            "end": "\">Download frames as ZIP"
+        },
+        "either_params": ["by-grid", "by-size"]
+    },
+    "sprite-img": {
+        "url": "https://ezgif.com/sprite-cutter",
+        "params": {},
+        "req_params": ["format"],
+        "split": {
+            "start": "\"small button danger\" href=\"",
+            "end": "\">Download frames as ZIP"
+        },
+        "either_params": ["by-grid", "by-size"]
+    },
+    "bmp-jpg": {
+        "url": "https://ezgif.com/bmp-to-jpg",
+        "params": {
+            "format": "jpg"
+        },
+        "req_params": [],
+        "split": {
+            "start": "<img src=\"",
+            "end": "\" style=\"width:"
+        },
+        "either_params": []
+    },
+    "bmp-png": {
+        "url": "https://ezgif.com/bmp-to-jpg",
+        "params": {
+            "format": "png"
+        },
+        "req_params": [],
+        "split": {
+            "start": "<img src=\"",
+            "end": "\" style=\"width:"
+        },
+        "either_params": []
+    },
+    "bmp-gif": {
+        "url": "https://ezgif.com/bmp-to-jpg",
+        "params": {
+            "format": "gif"
+        },
+        "req_params": [],
+        "split": {
+            "start": "<img src=\"",
+            "end": "\" style=\"width:"
+        },
+        "either_params": []
+    },
+    "png-jpg": {
+        "url": "https://ezgif.com/png-to-jpg",
+        "params": {
+            "format": "jpg",
+            "percentage": 85,
+            "background": "#ffffff"
+        },
+        "req_params": [],
+        "split": {
+            "start": "<img src=\"",
+            "end": "\" style=\"width:"
+        },
+        "either_params": []
+    },
+    "png-gif": {
+        "url": "https://ezgif.com/png-to-jpg",
+        "params": {
+            "format": "gif",
+            "percentage": 85,
+            "background": "#ffffff"
+        },
+        "req_params": [],
+        "split": {
+            "start": "<img src=\"",
+            "end": "\" style=\"width:"
+        },
+        "either_params": []
+    },
+    "png-bmp": {
+        "url": "https://ezgif.com/png-to-jpg",
+        "params": {
+            "format": "bmp",
+            "percentage": 85,
+            "background": "#ffffff"
+        },
+        "req_params": [],
+        "split": {
+            "start": "<img src=\"",
+            "end": "\" style=\"width:"
+        },
+        "either_params": []
+    },
+    "gif-jpg": {
+        "url": "https://ezgif.com/gif-to-jpg",
+        "params": {
+            "background": "#ffffff"
+        },
+        "req_params": [],
+        "split": {
+            "start": "\"small button danger\" href=\"",
+            "end": "\">Download all files as ZIP archive"
+        },
+        "either_params": []
+    },
+    "svg-png": {
+        "url": "https://ezgif.com/svg-to-png",
+        "params": {
+            "currentcolor": "#000000"
+        },
+        "req_params": [],
+        "split": {
+            "start": "<img src=\"",
+            "end": "\" style=\"width:"
+        },
+        "either_params": []
+    },
+    "svg-jpg": {
+        "url": "https://ezgif.com/svg-to-jpg",
+        "params": {
+            "percentage": 85,
+            "background": "#ffffff",
+            "currentcolor": "#000000"
+        },
+        "req_params": [],
+        "split": {
+            "start": "<img src=\"",
+            "end": "\" style=\"width:"
+        },
+        "either_params": []
+    },
+    "apng-gif": {
+        "url": "https://ezgif.com/apng-to-gif",
+        "params": {},
+        "req_params": [],
+        "split": {
+            "start": "<img src=\"",
+            "end": "\" style=\"width:"
+        },
+        "either_params": []
+    },
+    "apng-webp": {
+        "url": "https://ezgif.com/apng-to-webp",
+        "params": {},
+        "req_params": [],
+        "split": {
+            "start": "<img src=\"",
+            "end": "\" style=\"width:"
+        },
+        "either_params": []
+    },
+    "apng-mp4": {
+        "url": "https://ezgif.com/apng-to-mp4",
+        "params": {},
+        "req_params": [],
+        "split": {
+            "start": "<source src=\"",
+            "end": "\" type=\"video/mp4\">"
+        },
+        "either_params": []
+    },
+    "mng-apng": {
+        "url": "https://ezgif.com/mng-to-apng",
+        "params": {},
+        "req_params": [],
+        "split": {
+            "start": "<img src=\"",
+            "end": "\" style=\"width:"
+        },
+        "either_params": []
+    },
+    "video-apng": {
+        "url": "https://ezgif.com/video-to-apng",
+        "params": {
+            "start": 0,
+            "end": 10,
+            "size": "original",
+            "fps": 10,
+            "method": "ffmpeg"
+        },
+        "req_params": [],
+        "split": {
+            "start": "<img src=\"",
+            "end": "\" style=\"width:"
+        },
+        "either_params": []
+    },
+    "gif-apng": {
+        "url": "https://ezgif.com/gif-to-apng",
+        "params": {},
+        "req_params": [],
+        "split": {
+            "start": "<img src=\"",
+            "end": "\" style=\"width:"
+        },
+        "either_params": []
+    },
+    "video-webp": {
+        "url": "https://ezgif.com/video-to-webp",
+        "params": {
+            "start": 0,
+            "end": 10,
+            "size": "original",
+            "fps": 10,
+            "loop": "on"
+        },
+        "req_params": [],
+        "split": {
+            "start": "<img src=\"",
+            "end": "\" style=\"width:"
+        },
+        "either_params": []
+    },
+    "gif-webp": {
+        "url": "https://ezgif.com/gif-to-webp",
+        "params": {},
+        "req_params": [],
+        "split": {
+            "start": "<img src=\"",
+            "end": "\" style=\"width:"
+        },
+        "either_params": []
+    },
+    "jpg-webp": {
+        "url": "https://ezgif.com/jpg-to-webp",
+        "params": {},
+        "req_params": [],
+        "split": {
+            "start": "<img src=\"",
+            "end": "\" style=\"width:"
+        },
+        "either_params": []
+    },
+    "png-webp": {
+        "url": "https://ezgif.com/png-to-webp",
+        "params": {},
+        "req_params": [],
+        "split": {
+            "start": "<img src=\"",
+            "end": "\" style=\"width:"
+        },
+        "either_params": []
+    },
+    "webp-gif": {
+        "url": "https://ezgif.com/webp-to-gif",
+        "params": {},
+        "req_params": [],
+        "split": {
+            "start": "<img src=\"",
+            "end": "\" style=\"width:"
+        },
+        "either_params": []
+    },
+    "webp-jpg": {
+        "url": "https://ezgif.com/webp-to-jpg",
+        "params": {},
+        "req_params": [],
+        "split": {
+            "start": "\"small button danger\" href=\"",
+            "end": "\">Download all files as ZIP archive"
+        },
+        "either_params": []
+    },
+    "webp-png": {
+        "url": "https://ezgif.com/webp-to-png",
+        "params": {},
+        "req_params": [],
+        "split": {
+            "start": "<img src=\"",
+            "end": "\" style=\"width:"
+        },
+        "either_params": []
+    },
+    "webp-mp4": {
+        "url": "https://ezgif.com/webp-to-mp4",
+        "params": {},
+        "req_params": [],
+        "split": {
+            "start": "\" controls><source src=\"",
+            "end": "\" type=\"video/mp4\">Your browser"
+        },
+        "either_params": []
+    },
+    "video-avif": {
+        "url": "https://ezgif.com/video-to-avif",
+        "params": {
+            "start": 0,
+            "end": 10,
+            "size": "original",
+            "fps": 10
+        },
+        "req_params": [],
+        "split": {
+            "start": "<img src=\"",
+            "end": "\" style=\"width:"
+        },
+        "either_params": []
+    },
+    "gif-avif": {
+        "url": "https://ezgif.com/gif-to-avif",
+        "params": {},
+        "req_params": [],
+        "split": {
+            "start": "<img src=\"",
+            "end": "\" style=\"width:"
+        },
+        "either_params": []
+    },
+    "apng-avif": {
+        "url": "https://ezgif.com/apng-to-avif",
+        "params": {},
+        "req_params": [],
+        "split": {
+            "start": "<img src=\"",
+            "end": "\" style=\"width:"
+        },
+        "either_params": []
+    },
+    "webp-avif": {
+        "url": "https://ezgif.com/webp-to-avif",
+        "params": {},
+        "req_params": [],
+        "split": {
+            "start": "<img src=\"",
+            "end": "\" style=\"width:"
+        },
+        "either_params": []
+    },
+    "jpg-avif": {
+        "url": "https://ezgif.com/jpg-to-avif",
+        "params": {},
+        "req_params": [],
+        "split": {
+            "start": "<img src=\"",
+            "end": "\" style=\"width:"
+        },
+        "either_params": []
+    },
+    "avif-gif": {
+        "url": "https://ezgif.com/avif-to-gif",
+        "params": {},
+        "req_params": [],
+        "split": {
+            "start": "<img src=\"",
+            "end": "\" style=\"width:"
+        },
+        "either_params": []
+    },
+    "avif-jpg": {
+        "url": "https://ezgif.com/avif-to-jpg",
+        "params": {
+            "percentage": 85,
+            "background": "#ffffff"
+        },
+        "req_params": [],
+        "split": {
+            "start": "<img src=\"",
+            "end": "\" style=\"width:"
+        },
+        "either_params": []
+    },
+    "avif-png": {
+        "url": "https://ezgif.com/avif-to-png",
+        "params": {},
+        "req_params": [],
+        "split": {
+            "start": "<img src=\"",
+            "end": "\" style=\"width:"
+        },
+        "either_params": []
+    }
+};
+
+async function convert(fields) {
+    if (typeof fields === 'string' && fields?.toLowerCase() === 'list') return Object.keys(linksConvert);
+
+    let type = linksConvert?.[fields?.type];
+    if (!type) throw new Error(`Invalid conversion type "${fields?.type}"`);
+    let form = new FormData();
+
+    if (fields?.file) {
+        if (!fields.filename) throw new Error(`filename must be provided to upload files.(with extension)`);
+        form.append('new-image', fields.file, {
+            filename: fields.filename,
+        });
+    } else if (fields?.url) {
+        form.append('new-image-url', fields.url);
+    } else throw new Error('Either file or url field is required.');
+
+    delete fields.type;
+    delete fields.file;
+    delete fields.filename;
+    delete fields.url;
+
+    let org_keys = Object.keys(fields);
+    if (type.req_params) {
+        type.req_params.forEach(e => {
+            if (!org_keys.includes(e)) throw new Error(`"${e}" is a required param.`);
+        });
+    }
+    if (type.either_params.length) {
+        let check = false;
+        type.either_params.forEach(e => {
+            if (org_keys.includes(e)) check = true;
+        });
+        if (!check) throw new Error(`Either one of these params has to be provided: ${type.either_params.join(', ')}`);
+    }
+
+    let link = await axios({
+        method: 'post',
+        url: type.url,
+        headers: {
+            'Content-Type': 'multipart/form-data',
+        },
+        data: form,
+    }).catch(function(error) {
+        if (error.response) {
+            throw new Error(
+                JSON.stringify({
+                        statusCode: error.response.status,
+                        data: error.response.data.length ? error.response.data : "Try again. If it continues, report to the creator.",
+                    },
+                    null,
+                    4
+                )
+            );
+        } else {
+            throw new Error("Oops, something unknown happened! :(");
+        }
+    });
+
+    let redir = String(link?.request?.res?.responseUrl);
+    if (!redir) throw new Error(`Oops! Something unknown happened!`);
+    let id = redir.split('/')[redir.split('/').length - 1];
+    type.params.file = id;
+
+    let image = await axios({
+        method: 'post',
+        url: `${redir}?ajax=true`,
+        headers: {
+            'Content-Type': 'application/x-www-form-urlencoded',
+        },
+        data: new URLSearchParams({
+            ...type.params,
+            ...fields,
+        }),
+    }).catch(function(error) {
+        if (error.response) {
+            throw new Error(
+                JSON.stringify({
+                        statusCode: error.response.status,
+                        data: error.response.data.length ? error.response.data : "Try again. If it continues, report to the creator.",
+                    },
+                    null,
+                    4
+                )
+            );
+        } else {
+            throw new Error("Oops, something unknown happened! :(");
+        }
+    });
+
+    let img_url = `https:${(image?.data?.toString()?.split(type.split.start)?.[1]?.split(type.split.end)?.[0])?.replace('https:', '')}`;
+    if (img_url.includes('undefined')) throw new Error(`Something unknown happened here... please report to the creator`);
+    return img_url;
+}
+
+async function overlay(fields) {
+    let form = new FormData();
+    let form_over = new FormData();
+    form.append('new-image', fields.file, {
+        filename: fields.filename,
+    });
+
+    let link = await axios({
+        method: 'post',
+        url: 'https://ezgif.com/overlay',
+        headers: {
+            'Content-Type': 'multipart/form-data',
+        },
+        data: form
+    }).catch(function(error) {
+        if (error.response) {
+            throw new Error(JSON.stringify({
+                statusCode: error.response.status,
+                data: error.response.data.length ? error.response.data : "Try again. If it continues, report to the creator."
+            }, null, 4))
+        } else {
+            throw new Error("Oops, something unknown happened! :(")
+        }
+    });
+
+    let redir = String(link?.request?.res?.responseUrl);
+    if (!redir) throw new Error(`Oops! Something unknown happened!`);
+    let id = redir.split('/')[redir.split('/').length - 1];
+
+    form_over.append('new-overlay', Buffer.from(fields.overlay.file), {
+        filename: `${fields.overlay.filename}`,
+    });
+    form_over.append('overlay', 'Upload image!');
+
+    let link_over = await axios({
+        method: 'post',
+        url: redir,
+        headers: {
+            'Content-Type': 'multipart/form-data',
+        },
+        data: form_over
+    }).catch(function(error) {
+        if (error.response) {
+            throw new Error(JSON.stringify({
+                statusCode: error.response.status,
+                data: error.response.data.length ? error.response.data : "Try again. If it continues, report to the creator."
+            }, null, 4))
+        } else {
+            throw new Error("Oops, something unknown happened! :(")
+        }
+    });
+
+    let redir_over = String(link_over?.request?.res?.responseUrl);
+    if (!redir_over) throw new Error(`Oops! Something unknown happened!`);
+    let id_over = redir_over.split('/')[redir_over.split('/').length - 1];
+
+    let image = await axios({
+        method: 'post',
+        url: `${redir_over}?ajax=true`,
+        headers: {
+            'Content-Type': 'application/x-www-form-urlencoded'
+        },
+        data: new URLSearchParams({
+            file: id,
+            'overlay-file': id_over,
+            posX: fields.x || 0,
+            posY: fields.y || 0
+        })
+    }).catch(function(error) {
+        if (error.response) {
+            throw new Error(JSON.stringify({
+                statusCode: error.response.status,
+                data: error.response.data.length ? error.response.data : "Try again. If it continues, report to the creator."
+            }, null, 4))
+        } else {
+            throw new Error("Oops, something unknown happened! :(")
+        }
+    });
+
+    let img_url = `https:${(image?.data?.toString()?.split('<img src="')?.[1]?.split('" style="width:')?.[0])?.replace('https:', '')}`;
+    if (img_url.includes('undefined')) throw new Error(`Something unknown happened here... please report to the creator`);
+
+    return img_url;
+}
+
+const linksRender = {
+    "gif": "https://ezgif.com/maker",
+    "webp": "https://ezgif.com/webp-maker",
+    "apng": "https://ezgif.com/apng-maker",
+    "avif": "https://ezgif.com/avif-maker"
+};
+
+async function render(fields) {
+    let type = linksRender?.[fields?.type];
+    let form = new FormData();
+    if (!type) throw new Error(`Invalid rendering type "${fields?.type}"`);
+    let default_ = {
+        delay: 20,
+        dfrom: 1,
+        dto: 5,
+        'fader-delay': 6,
+        'fader-frames': 10,
+        loop: 0,
+        'delays[]': [],
+        'files[]': []
+    };
+    fields = {
+        ...default_,
+        ...fields
+    };
+
+    for (let i = 0; i < fields.files.length; i++) {
+        if (!fields.files[i].data) throw new Error(`File buffer not provided for files[${i}]`);
+        if (!fields.files[i].name) throw new Error(`File name not provided for files[${i}]`);
+        form.append('files[]', fields.files[i].data, {
+            filename: fields.files[i].name
+        });
+        fields['delays[]'].push(fields.files[i].delay ?? fields.delay);
+    }
+
+    delete fields.type;
+    delete fields.files;
+
+    form.append('msort', '1');
+    form.append('upload', 'Upload and make a GIF!');
+
+    let link = await axios({
+        method: 'post',
+        url: type,
+        headers: {
+            'Content-Type': 'multipart/form-data',
+        },
+        data: form
+    }).catch(function(error) {
+        if (error.response) {
+            throw new Error(JSON.stringify({
+                statusCode: error.response.status,
+                data: error.response.data.length ? error.response.data : "Try again. If it continues, report to the creator."
+            }, null, 4))
+        } else {
+            throw new Error("Oops, something unknown happened! :(")
+        }
+    });
+
+    let redir = String(link?.request?.res?.responseUrl);
+    let html = await axios.get(redir);
+    fields.file = redir.split('/')[redir.split('/').length - 1];
+    html.data.toString().split('(drag and drop frames to change order)')[1].split('<p class="options"><strong>Toggle a range of frames:</strong>')[0].split('<span class="frame-tools">').slice(0, -1).map(i => i.split('value="')[1].split('" name="files[]"')[0]).forEach(e => {
+        fields['files[]'].push(e)
+    });
+    let image = await axios({
+        method: 'post',
+        url: `${redir}?ajax=true`,
+        headers: {
+            'Content-Type': 'application/x-www-form-urlencoded'
+        },
+        data: new URLSearchParams(fields)
+    }).catch(function(error) {
+        if (error.response) {
+            throw new Error(JSON.stringify({
+                statusCode: error.response.status,
+                data: error.response.data.length ? error.response.data : "Try again. If it continues, report to the creator."
+            }, null, 4))
+        } else {
+            throw new Error("Oops, something unknown happened! :(")
+        }
+    });
+
+    let img_url = `https:${(image?.data?.toString()?.split('<img src="')?.[1]?.split('" style="width')?.[0])?.replace('https:', '')}`;
+    if (img_url.includes('undefined')) throw new Error(`Something unknown happened here... please report to the creator`);
+    return img_url;
+}
+
+export {
+    convert,
+    overlay,
+    render
+};
+
+async function webp2mp4(url) {
+    return await convert({
+        type: 'webp-mp4',
+        url
+    })
+}
+
+async function webp2img(url) {
+    return await convert({
+        type: 'webp-png',
+        url
+    })
+}
+
+async function img2webp(url) {
+    return await convert({
+        type: 'png-webp',
+        url
+    })
+}
+
+async function vid2webp(url) {
+    return await convert({
+        type: 'video-webp',
+        url
+    })
+}
+
+export {
+    webp2mp4,
+    webp2img,
+    img2webp,
+    vid2webp
+}

+ 74 - 0
lib/gdrive.js

@@ -0,0 +1,74 @@
+import {join} from 'path';
+import {promises as fs} from 'fs';
+import {promisify} from 'util';
+import {google} from 'googleapis';
+
+
+// If modifying these scopes, delete token.json.
+const SCOPES = ['https://www.googleapis.com/auth/drive.metadata.readonly'];
+// The file token.json stores the user's access and refresh tokens, and is
+// created automatically when the authorization flow completes for the first
+// time.
+const TOKEN_PATH = join(__dirname, '..', 'token.json');
+
+class GoogleAuth extends EventEmitter {
+  constructor() {
+    super();
+  }
+
+  async authorize(credentials) {
+    let token;
+    const {client_secret, client_id} = credentials;
+    const oAuth2Client = new google.auth.OAuth2(client_id, client_secret, `http://localhost:${port}`);
+    try {
+      token = JSON.parse(await fs.readFile(TOKEN_PATH));
+    } catch (e) {
+      const authUrl = oAuth2Client.generateAuthUrl({
+        access_type: 'offline',
+        scope: SCOPES,
+      });
+      this.emit('auth', authUrl);
+      const code = await promisify(this.once).bind(this)('token');
+      token = await oAuth2Client.getToken(code);
+      await fs.writeFile(TOKEN_PATH, JSON.stringify(token));
+    } finally {
+      await oAuth2Client.setCredentials(token);
+    }
+  }
+
+  token(code) {
+    this.emit('token', code);
+  }
+}
+
+class GoogleDrive extends GoogleAuth {
+  constructor() {
+    super();
+    this.path = '/drive/api';
+  }
+
+  async getFolderID(path) {
+
+  }
+
+  async infoFile(path) {
+
+  }
+
+  async folderList(path) {
+
+  }
+
+  async downloadFile(path) {
+
+  }
+
+  async uploadFile(path) {
+
+  }
+}
+
+export {
+  GoogleAuth,
+  GoogleDrive,
+};

+ 46 - 0
lib/levelling.js

@@ -0,0 +1,46 @@
+export const growth = Math.pow(Math.PI / Math.E, 1.618) * Math.E * .75;
+export function xpRange(level, multiplier = global.multiplier || 1) {
+  if (level < 0) {
+    throw new TypeError('level cannot be negative value');
+  }
+  level = Math.floor(level);
+  const min = level === 0 ? 0 : Math.round(Math.pow(level, growth) * multiplier) + 1;
+  const max = Math.round(Math.pow(++level, growth) * multiplier);
+  return {
+    min,
+    max,
+    xp: max - min,
+  };
+}
+export function findLevel(xp, multiplier = global.multiplier || 1) {
+  if (xp === Infinity) {
+    return Infinity;
+  }
+  if (isNaN(xp)) {
+    return NaN;
+  }
+  if (xp <= 0) {
+    return -1;
+  }
+  let level = 0;
+  do {
+    level++;
+  }
+  while (xpRange(level, multiplier).min <= xp);
+  return --level;
+}
+export function canLevelUp(level, xp, multiplier = global.multiplier || 1) {
+  if (level < 0) {
+    return false;
+  }
+  if (xp === Infinity) {
+    return true;
+  }
+  if (isNaN(xp)) {
+    return false;
+  }
+  if (xp <= 0) {
+    return false;
+  }
+  return level < findLevel(xp, multiplier);
+}

+ 106 - 0
lib/loadAllJadiBots.js

@@ -0,0 +1,106 @@
+/*
+
+    CÓDIGO SIMPLE PARA LA RECARGA DE JADIBOTS AL INICIAR, SE PUEDE EXTENDER Y MEJORAR DE ACUERDO A TÚS NECESIDADES.
+
+    SI QUIERES QUE MANEJE MÁS EVENTOS LOS TIENES QUE AGREGAR AQUI.
+
+    CÓDIGO HECHO POR: DanixlJs - si asi es, el nuvsito ese.
+    [https://github.com/DanixlJs]
+
+    DEJA LOS CRÉDITOS HDP
+
+*/
+import path from "path";
+import { fileURLToPath } from "url";
+import { promises as fs } from "fs";
+import pino from 'pino'
+import { makeWASocket } from "./simple.js";
+import { makeCacheableSignalKeyStore, useMultiFileAuthState, fetchLatestBaileysVersion } from "@whiskeysockets/baileys";
+import { Boom } from "@hapi/boom";
+import { handler } from "../handler.js";
+const __dirname = path.join(fileURLToPath(import.meta.url));
+export default async function loadAllJadiBots() {
+	const authJadi = path.join(__dirname, "../../jadibts");
+	const sesions = await fs.readdir(authJadi);
+	if (sesions.length !== 0) {
+        console.log("Cargando " + sesions.length + " Sesiones de la carpeta 'jadibts'"); // que asco tiene 'bts' :v
+		for (const sesion of sesions) {
+			const auth = path.join(authJadi, sesion);
+			try {
+				await fs.access(path.join(auth, "creds.json"));
+			} catch {
+				continue;
+			}
+			await connect(auth);
+		}
+	} else {
+        console.log("Sin JadiBots que cargar.");
+    }
+}
+async function connect(sesionFile, retries = 0) {
+	const { state, saveCreds } = await useMultiFileAuthState(sesionFile);
+	const { version } = await fetchLatestBaileysVersion();
+	const conn = makeWASocket({
+		markOnlineOnConnect: true,
+		defaultQueryTimeoutMs: undefined,
+		auth: {
+			creds: state.creds,
+			keys: makeCacheableSignalKeyStore(state.keys, pino({
+				level: "silent"
+			}).child({
+				level: "silent"
+			}))
+		},
+		logger: pino({
+			level: "silent"
+		}),
+		browser: ["Ubuntu", "Edge", "20.0.4"],
+		syncFullHistory: true,
+		printQRInTerminal: false,
+		patchMessageBeforeSending: async message => {
+			try {
+				await sock.uploadPreKeysToServerIfRequired();
+			} catch (err) {
+				console.error(err);
+			}
+			return message;
+		},
+		generateHighQualityLinkPreview: true,
+		version
+	});
+	conn.ev.on("creds.update", saveCreds);
+	conn.ev.on("connection.update", async update => {
+		const { connection, lastDisconnect } = update;
+		if (connection === "close") {
+			const code = new Boom(lastDisconnect?.error)?.output?.statusCode;
+			// ojo al ingles de la más alta calidad 🗿
+			switch (code) {
+				case 401: //logout
+				case 500: //bad sesion?
+				case 403: //forbiden
+				case 405: //conn end
+					try {
+						console.log("error inesperado") 
+						//await fs.rm(sesionFile, { recursive: true, force: true });
+					} catch (err) {
+						console.error(err);
+					}
+					break;
+				default:
+					if (retries < 6) {
+						await connect(sesionFile, retries + 1);
+					} else {
+						try {
+							//await fs.rm(sesionFile, { recursive: true, force: true });
+						} catch (err) {
+							console.error(err);
+						}
+					}
+					break;
+			}
+		} else if (connection === "open") {
+			global.conns.push(conn);
+		}
+	});
+	conn.ev.on("messages.upsert", handler);
+}

+ 21 - 0
lib/logs.js

@@ -0,0 +1,21 @@
+const stdouts = [];
+export default (maxLength = 200) => {
+  const oldWrite = process.stdout.write.bind(process.stdout);
+  module.exports.disable = () => {
+    module.exports.isModified = false;
+    return process.stdout.write = oldWrite;
+  };
+  process.stdout.write = (chunk, encoding, callback) => {
+    stdouts.push(Buffer.from(chunk, encoding));
+    oldWrite(chunk, encoding, callback);
+    if (stdouts.length > maxLength) stdouts.shift();
+  };
+  module.exports.isModified = true;
+  return module.exports;
+};
+
+export const isModified = false;
+export function logs() {
+  return Buffer.concat(stdouts);
+}
+

+ 193 - 0
lib/mongoDB.js

@@ -0,0 +1,193 @@
+import mongoose from 'mongoose';
+
+const {Schema, connect, model: _model} = mongoose;
+const defaultOptions = {useNewUrlParser: true, useUnifiedTopology: true};
+
+export class mongoDB {
+  constructor(url, options = defaultOptions) {
+    /**
+     * @type {string}
+     */
+    this.url = url;
+    /**
+     * @type {mongoose.ConnectOptions}
+     */
+    this.options = options;
+    this.data = this._data = {};
+    /**
+     * @type {mongoose.Schema}
+     */
+    this._schema = {};
+    /**
+     * @type {mongoose.Model}
+     */
+    this._model = {};
+    /**
+     * @type {Promise<typeof mongoose>}
+     */
+    this.db = connect(this.url, {...this.options}).catch(console.error);
+  }
+  async read() {
+    this.conn = await this.db;
+    const schema = this._schema = new Schema({
+      data: {
+        type: Object,
+        required: true, // depends on whether the field is mandatory or not
+        default: {},
+      },
+    });
+    try {
+      this._model = _model('data', schema);
+    } catch {
+      this._model = _model('data');
+    }
+    this._data = await this._model.findOne({});
+    if (!this._data) {
+      this.data = {};
+      const [_, _data] = await Promise.all([
+        this.write(this.data),
+        this._model.findOne({}),
+      ]);
+      this._data = _data;
+    } else this.data = this._data.data;
+    return this.data;
+  }
+
+  write(data) {
+    return new Promise(async (resolve, reject) => {
+      if (!data) return reject(data);
+      if (!this._data) return resolve((new this._model({data})).save());
+      this._model.findById(this._data._id, (err, docs) => {
+        if (err) return reject(err);
+        if (!docs.data) docs.data = {};
+        docs.data = data;
+        this.data = {};
+        return docs.save(resolve);
+      });
+    });
+  }
+}
+
+export const mongoDBV2 = class MongoDBV2 {
+  constructor(url, options = defaultOptions) {
+    /**
+     * @type {string}
+     */
+    this.url = url;
+    /**
+     * @type {mongoose.ConnectOptions}
+     */
+    this.options = options;
+    /**
+     * @type {{ name: string, model: mongoose.Model}[]}
+     */
+    this.models = [];
+    /**
+     * @type {{ [Key: string]: any }}
+     */
+    this.data = {};
+    this.lists;
+    /**
+     * @type {mongoose.Model}
+     */
+    this.list;
+    /**
+     * @type {Promise<typeof mongoose>}
+     */
+    this.db = connect(this.url, {...this.options}).catch(console.error);
+  }
+  async read() {
+    this.conn = await this.db;
+    const schema = new Schema({
+      data: [{
+        name: String,
+      }],
+    });
+    try {
+      this.list = _model('lists', schema);
+    } catch (e) {
+      this.list = _model('lists');
+    }
+    this.lists = await this.list.findOne({});
+    if (!lists?.data) {
+      await this.list.create({data: []});
+      // await (new this.list({ data: [] })).save()
+      this.lists = await this.list.findOne({});
+    }
+    const garbage = [];
+    for (const {name} of this.lists.data) { // get data from list
+      /**
+       * @type {mongoose.Model}
+       */
+      let collection;
+      try {
+        collection = _model(name, new Schema({data: Array}));
+      } catch (e) {
+        console.error(e);
+        try {
+          collection = _model(name);
+        } catch (e) {
+          garbage.push(name);
+          console.error(e);
+        }
+      }
+      if (collection) {
+        this.models.push({name, model: collection});
+        const collectionsData = await collection.find({});
+        this.data[name] = Object.fromEntries(collectionsData.map((v) => v.data));
+      }
+    }
+    try {
+      // Delete list if not exist
+      const del = await this.list.findById(this.lists._id);
+      del.data = del.data.filter((v) => !garbage.includes(v.name));
+      await del.save();
+    } catch (e) {
+      console.error(e);
+    }
+
+    return this.data;
+  }
+  write(data) {
+    return new Promise(async (resolve, reject) => {
+      if (!this.lists || !data) return reject(data || this.lists);
+      const collections = Object.keys(data); const listDoc = []; let index = 0;
+      for (const key of collections) {
+        // Update if exist
+        if ((index = this.models.findIndex((v) => v.name === key)) !== -1) {
+          const doc = this.models[index].model;
+          await doc.deleteMany().catch(console.error); // alwasy insert, no matter delete error
+          await doc.insertMany(Object.entries(data[key]).map((v) => ({data: v})));
+          if (doc && key) listDoc.push({name: key});
+        } else { // if not exist, create new model
+          const schema = new Schema({
+            data: Array,
+          });
+          /**
+           * @type {mongoose.Model}
+           */
+          let doc;
+          try {
+            doc = _model(key, schema);
+          } catch (e) {
+            console.error(e);
+            doc = _model(key);
+          }
+          index = this.models.findIndex((v) => v.name === key);
+          this.models[index === -1 ? this.models.length : index] = {name: key, model: doc};
+          await doc.insertMany(Object.entries(data[key]).map((v) => ({data: v})));
+          if (doc && key) listDoc.push({name: key});
+        }
+      }
+
+      // save list
+      this.list.findById(this.lists._id, function(err, doc) {
+        if (err) return reject(err);
+        doc.data = listDoc;
+        this.data = {};
+        return doc.save(resolve);
+      });
+      return resolve(true);
+    });
+  }
+};

+ 84 - 0
lib/plugins.js

@@ -0,0 +1,84 @@
+import { readdirSync, existsSync, readFileSync, watch } from 'fs'
+import { join, resolve } from 'path'
+import { format } from 'util'
+import syntaxerror from 'syntax-error'
+import importFile from './import.js'
+import Helper from './helper.js'
+
+const __dirname = Helper.__dirname(import.meta)
+const pluginFolder = Helper.__dirname(join(__dirname, '../plugins/index'))
+const pluginFilter = filename => /\.(mc)?js$/.test(filename)
+
+// inspired from https://github.com/Nurutomo/mahbod/blob/main/src/util/PluginManager.ts
+
+let watcher, plugins, pluginFolders = []
+watcher = plugins = {}
+
+async function filesInit(pluginFolder = pluginFolder, pluginFilter = pluginFilter, conn) {
+    const folder = resolve(pluginFolder)
+    if (folder in watcher) return
+    pluginFolders.push(folder)
+
+    await Promise.all(readdirSync(folder).filter(pluginFilter).map(async filename => {
+        try {
+            let file = global.__filename(join(folder, filename))
+            const module = await import(file)
+            if (module) plugins[filename] = 'default' in module ? module.default : module
+        } catch (e) {
+            conn?.logger.error(e)
+            delete plugins[filename]
+        }
+    }))
+
+
+    const watching = watch(folder, reload.bind(null, conn, folder, pluginFilter))
+    watching.on('close', () => deletePluginFolder(folder, true))
+    watcher[folder] = watching
+
+    return plugins
+}
+
+function deletePluginFolder(folder, isAlreadyClosed = false) {
+    const resolved = resolve(folder)
+    if (!(resolved in watcher)) return
+    if (!isAlreadyClosed) watcher[resolved].close()
+    delete watcher[resolved]
+    pluginFolders.splice(pluginFolders.indexOf(resolved), 1)
+}
+
+async function reload(conn, pluginFolder = pluginFolder, pluginFilter = pluginFilter, _ev, filename) {
+    if (pluginFilter(filename)) {
+        let dir = global.__filename(join(pluginFolder, filename), true)
+        if (filename in plugins) {
+            if (existsSync(dir)) conn.logger.info(` updated plugin - '${filename}'`)
+            else {
+                conn?.logger.warn(`deleted plugin - '${filename}'`)
+                return delete plugins[filename]
+            }
+        } else conn?.logger.info(`new plugin - '${filename}'`)
+        let err = syntaxerror(readFileSync(dir), filename, {
+            sourceType: 'module',
+            allowAwaitOutsideFunction: true
+        })
+        if (err) conn.logger.error(`syntax error while loading '${filename}'\n${format(err)}`)
+        else try {
+            const module = await importFile(global.__filename(dir)).catch(console.error)
+            if (module) plugins[filename] = module
+        } catch (e) {
+            conn?.logger.error(`error require plugin '${filename}\n${format(e)}'`)
+        } finally {
+            plugins = Object.fromEntries(Object.entries(plugins).sort(([a], [b]) => a.localeCompare(b)))
+        }
+    }
+}
+
+export {
+    pluginFolder,
+    pluginFilter,
+    plugins,
+    watcher,
+    pluginFolders,
+    filesInit,
+    deletePluginFolder,
+    reload
+}

+ 107 - 0
lib/print.js

@@ -0,0 +1,107 @@
+ import {WAMessageStubType} from '@whiskeysockets/baileys';
+import PhoneNumber from 'awesome-phonenumber'
+import chalk from 'chalk'
+import { watchFile } from 'fs'
+
+const terminalImage = global.opts['img'] ? require('terminal-image') : ''
+const urlRegex = (await import('url-regex-safe')).default({ strict: false })
+
+export default async function (m, conn = { user: {} }) {
+let _name = await conn.getName(m.sender)
+let sender = PhoneNumber('+' + m.sender.replace('@s.whatsapp.net', '')).getNumber('international') + (_name ? ' ~' + _name : '')
+let chat = await conn.getName(m.chat)
+let img
+try {
+if (global.opts['img'])
+img = /sticker|image/gi.test(m.mtype) ? await terminalImage.buffer(await m.download()) : false
+} catch (e) {
+console.error(e)
+}
+let filesize = (m.msg ?
+m.msg.vcard ?
+m.msg.vcard.length :
+m.msg.fileLength ?
+m.msg.fileLength.low || m.msg.fileLength :
+m.msg.axolotlSenderKeyDistributionMessage ?
+m.msg.axolotlSenderKeyDistributionMessage.length :
+m.text ?
+m.text.length :
+0
+: m.text ? m.text.length : 0) || 0
+let user = global.db.data.users[m.sender]
+let me = PhoneNumber('+' + (conn.user?.jid).replace('@s.whatsapp.net', '')).getNumber('international')
+
+console.log(`${chalk.redBright('%s')} ${chalk.black(chalk.bgYellow('%s'))} ${chalk.black(chalk.bgGreen('%s'))} ${chalk.magenta('%s [%s %sB]')}
+ ${chalk.green('%s')} ${chalk.yellow('%s%s')} ${chalk.blueBright('-')} ${chalk.green('%s')} ${chalk.cyanBright(chalk.blueBright('%s'))}`.trim(),
+            
+me + ' ~' + conn.user.name + `${conn.user.jid == global.conn.user.jid ? '' : ' (𝗦𝗨𝗕 𝗕𝗢𝗧)'}`,
+(m.messageTimestamp ? new Date(1000 * (m.messageTimestamp.low || m.messageTimestamp)) : new Date).toTimeString(),
+m.messageStubType ? WAMessageStubType[m.messageStubType] : '',
+filesize,
+filesize === 0 ? 0 : (filesize / 1009 ** Math.floor(Math.log(filesize) / Math.log(1000))).toFixed(1),
+['', ...'KMGTP'][Math.floor(Math.log(filesize) / Math.log(1000))] || '',
+sender,
+m ? m.exp : '?',
+user ? '|' + user.exp + '|' + user.money : '' + ('|' + user.level + user.limit ),
+//user ? '|' + user.exp + '|' + user.money + '|' + user.limit : '' + ('|' + user.level),
+m.chat + (chat ? ' ~' + chat : ''),
+m.mtype ? m.mtype.replace(/message$/i, '').replace('audio', m.msg.ptt ? 'PTT' : 'audio').replace(/^./, v => v.toUpperCase()) : ''
+)
+if (img) console.log(img.trimEnd())
+if (typeof m.text === 'string' && m.text) {
+let log = m.text.replace(/\u200e+/g, '')
+
+// Nuevos formatos/estilos para el texto en consola
+// Créditos para: https://github.com/GataNina-Li
+let mdRegex = /(?<=(?:^|[\s\n])\S?)(?:([*_~`])(?!`)(.+?)\1|```((?:.|[\n\r])+?)```|`([^`]+?)`)(?=\S?(?:[\s\n]|$))/g
+let mdFormat = (depth = 4) => (_, type, text, monospace) => {
+let types = {
+'_': 'italic',
+'*': 'bold',
+'~': 'strikethrough',
+'`': 'bgGray'
+}
+text = text || monospace
+let formatted = !types[type] || depth < 1 ? text : chalk[types[type]](text.replace(/`/g, '').replace(mdRegex, mdFormat(depth - 1)))
+return formatted
+}               
+log = log.replace(mdRegex, mdFormat(4))
+log = log.split('\n').map(line => {
+if (line.trim().startsWith('>')) {
+return chalk.bgGray.dim(line.replace(/^>/, '┃'))
+} else if (/^([1-9]|[1-9][0-9])\./.test(line.trim())) {
+return line.replace(/^(\d+)\./, (match, number) => {
+const padding = number.length === 1 ? '  ' : ' '
+return padding + number + '.'
+})
+} else if (/^[-*]\s/.test(line.trim())) {
+return line.replace(/^[*-]/, '  •')
+}
+return line
+}).join('\n')
+if (log.length < 1024)
+log = log.replace(urlRegex, (url, i, text) => {
+let end = url.length + i
+return i === 0 || end === text.length || (/^\s$/.test(text[end]) && /^\s$/.test(text[i - 1])) ? chalk.blueBright(url) : url
+})
+log = log.replace(mdRegex, mdFormat(4))
+if (m.mentionedJid) for (let user of m.mentionedJid) log = log.replace('@' + user.split`@`[0], chalk.blueBright('@' +await conn.getName(user)))
+console.log(m.error != null ? chalk.red(log) : m.isCommand ? chalk.yellow(log) : log)
+}
+if (m.messageStubParameters) console.log(m.messageStubParameters.map(jid => {
+jid = conn.decodeJid(jid)
+let name = conn.getName(jid)
+return chalk.gray(PhoneNumber('+' + jid.replace('@s.whatsapp.net', '')).getNumber('international') + (name ? ' ~' + name : ''))
+}).join(', '))
+if (/document/i.test(m.mtype)) console.log(`🗂️ ${m.msg.fileName || m.msg.displayName || 'Document'}`)
+else if (/ContactsArray/i.test(m.mtype)) console.log(`👨‍👩‍👧‍👦 ${' ' || ''}`)
+else if (/contact/i.test(m.mtype)) console.log(`👨 ${m.msg.displayName || ''}`)
+else if (/audio/i.test(m.mtype)) {
+const duration = m.msg.seconds
+console.log(`${m.msg.ptt ? '🎤ㅤ(PTT ' : '🎵ㅤ('}AUDIO) ${Math.floor(duration / 60).toString().padStart(2, 0)}:${(duration % 60).toString().padStart(2, 0)}`)
+}
+console.log()
+}
+let file = global.__filename(import.meta.url)
+watchFile(file, () => {
+console.log(chalk.redBright("Update 'lib/print.js'"))})

+ 94 - 0
lib/queque.js

@@ -0,0 +1,94 @@
+import EventEmitter from "events"
+
+const isNumber = x => typeof x === 'number' && !isNaN(x)
+const delay = ms => isNumber(ms) && new Promise(resolve => setTimeout(resolve, ms))
+
+const QUEQUE_DELAY = 5 * 1000
+
+export default class Queque extends EventEmitter {
+    _queque = new Set()
+
+    constructor() {
+        super()
+    }
+
+    add(item) {
+        this._queque.add(item)
+        // console.debug('add item to queque', item, 'in index', this._queque.size)
+    }
+    has(item) {
+        return this._queque.has(item)
+    }
+    delete(item) {
+        this._queque.delete(item)
+        // console.debug('delete item from queque', item, 'now have', this._queque.size, 'in queque')
+    }
+
+    first() {
+        return [...this._queque].shift()
+    }
+    isFirst(item) {
+        return this.first() === item
+    }
+    last() {
+        return [...this._queque].pop()
+    }
+    isLast(item) {
+        return this.last() === item
+    }
+
+    getIndex(item) {
+        return [...this._queque].indexOf(item)
+    }
+
+    getSize() {
+        return this._queque.size
+    }
+
+    isEmpty() {
+        return this.getSize() === 0
+    }
+
+    unqueue(item) {
+        let queque;
+        if (item) {
+            if (this.has(item)) {
+                queque = item
+                const isFirst = this.isFirst(item)
+                if (!isFirst) {
+                    throw new Error('Item is not first in queque')
+                }
+            } else {
+                // console.error('try to unqueue item', item, 'but not found')
+            }
+        } else {
+            queque = this.first()
+        }
+
+        if (queque) {
+            this.delete(queque)
+            this.emit(queque)
+        }
+    }
+    waitQueue(item) {
+        return new Promise((resolve, reject) => {
+            // console.debug('wait queque', item)
+            if (this.has(item)) {
+                const solve = async (removeQueque = false) => {
+                    await delay(QUEQUE_DELAY)
+                    // console.debug('wait queque', item, 'done!')
+                    if (removeQueque) this.unqueue(item)
+                    if (!this.isEmpty()) this.unqueue()
+                    resolve()
+                }
+
+                if (this.isFirst(item)) {
+                    // console.debug('wait queque', item, 'is first in queque')
+                    solve(true)
+                } else this.once(item, solve)
+            } else {
+                reject(new Error('item not found'))
+            }
+        })
+    }
+}

+ 85 - 0
lib/scraper.js

@@ -0,0 +1,85 @@
+import cheerio from 'cheerio'
+import fetch from 'node-fetch'
+import axios from 'axios'
+
+async function sekaikomikDl(url) {
+	let res = await fetch(url)
+	let $ = cheerio.load(await res.text())
+	let data = $('script').map((idx, el) => $(el).html()).toArray()
+	data = data.filter(v => /wp-content/i.test(v))
+	data = eval(data[0].split('"images":')[1].split('}],')[0])
+	return data.map(v => encodeURI(v))
+}
+
+async function facebookDl(url) {
+	let res = await fetch('https://fdownloader.net/')
+	let $ = cheerio.load(await res.text())
+	let token = $('input[name="__RequestVerificationToken"]').attr('value')
+	let json = await (await fetch('https://fdownloader.net/api/ajaxSearch', {
+		method: 'post',
+		headers: {
+			cookie: res.headers.get('set-cookie'),
+			'content-type': 'application/x-www-form-urlencoded; charset=UTF-8',
+			referer: 'https://fdownloader.net/'
+		},
+		body: new URLSearchParams(Object.entries({ __RequestVerificationToken: token, q: url }))
+	})).json()
+	let $$ = cheerio.load(json.data)
+	let result = {}
+	$$('.button.is-success.is-small.download-link-fb').each(function () {
+		let quality = $$(this).attr('title').split(' ')[1]
+		let link = $$(this).attr('href')
+		if (link) result[quality] = link
+	})
+	return result
+}
+//--
+ 
+  async function tiktokStalk(user) {
+  let res = await axios.get(`https://urlebird.com/user/${user}/`)
+  let $ = cheerio.load(res.data), obj = {}
+  obj.pp_user = $('div[class="col-md-auto justify-content-center text-center"] > img').attr('src')
+  obj.name = $('h1.user').text().trim()
+  obj.username = $('div.content > h5').text().trim()
+  obj.followers = $('div[class="col-7 col-md-auto text-truncate"]').text().trim().split(' ')[1]
+  obj.following = $('div[class="col-auto d-none d-sm-block text-truncate"]').text().trim().split(' ')[1]
+  obj.description = $('div.content > p').text().trim()
+  return obj
+} 
+//--
+async function igStalk(username) {
+    username = username.replace(/^@/, '')
+    const html = await (await fetch(`https://dumpor.com/v/${username}`)).text()
+    const $$ = cheerio.load(html)
+    const name = $$('div.user__title > a > h1').text().trim()
+    const Uname = $$('div.user__title > h4').text().trim()
+    const description = $$('div.user__info-desc').text().trim()
+    const profilePic = $$('div.user__img').attr('style')?.replace("background-image: url('", '').replace("');", '')
+    const row = $$('#user-page > div.container > div > div > div:nth-child(1) > div > a')
+    const postsH = row.eq(0).text().replace(/Posts/i, '').trim()
+    const followersH = row.eq(2).text().replace(/Followers/i, '').trim()
+    const followingH = row.eq(3).text().replace(/Following/i, '').trim()
+    const list = $$('ul.list > li.list__item')
+    const posts = parseInt(list.eq(0).text().replace(/Posts/i, '').trim().replace(/\s/g, ''))
+    const followers = parseInt(list.eq(1).text().replace(/Followers/i, '').trim().replace(/\s/g, ''))
+    const following = parseInt(list.eq(2).text().replace(/Following/i, '').trim().replace(/\s/g, ''))
+    return {
+        name,
+        username: Uname,
+        description,
+        postsH,
+        posts,
+        followersH,
+        followers,
+        followingH,
+        following,
+        profilePic
+    }
+}
+
+export {
+	sekaikomikDl,
+	igStalk, 
+	facebookDl, 
+	tiktokStalk
+}

+ 2143 - 0
lib/simple.js

@@ -0,0 +1,2143 @@
+import path from 'path';
+import {toAudio} from './converter.js';
+import chalk from 'chalk';
+import fetch from 'node-fetch';
+import PhoneNumber from 'awesome-phonenumber';
+import fs from 'fs';
+import util from 'util';
+import {fileTypeFromBuffer} from 'file-type';
+import {format} from 'util';
+import {fileURLToPath} from 'url';
+import store from './store.js';
+
+const __dirname = path.dirname(fileURLToPath(import.meta.url));
+
+/**
+ * @type {import('@whiskeysockets/baileys')}
+ */
+const {
+  default: _makeWaSocket,
+  makeWALegacySocket,
+  proto,
+  downloadContentFromMessage,
+  jidDecode,
+  areJidsSameUser,
+  generateWAMessage,
+  generateForwardMessageContent,
+  generateWAMessageFromContent,
+  WAMessageStubType,
+  extractMessageContent,
+  WA_DEFAULT_EPHEMERAL,
+  prepareWAMessageMedia, 
+} = (await import('@whiskeysockets/baileys')).default;
+
+export function makeWASocket(connectionOptions, options = {}) {
+  /**
+     * @type {import('@whiskeysockets/baileys').WASocket | import('@whiskeysockets/baileys').WALegacySocket}
+     */
+  const conn = (global.opts['legacy'] ? makeWALegacySocket : _makeWaSocket)(connectionOptions);
+
+  const sock = Object.defineProperties(conn, {
+    chats: {
+      value: {...(options.chats || {})},
+      writable: true,
+    },
+    decodeJid: {
+      value(jid) {
+        if (!jid || typeof jid !== 'string') return (!nullish(jid) && jid) || null;
+        return jid.decodeJid();
+      },
+    },
+    logger: {
+      get() {
+        return {
+          info(...args) {
+            console.log(
+                chalk.bold.bgRgb(51, 204, 51)('INFO '),
+                `[${chalk.rgb(255, 255, 255)(new Date().toUTCString())}]:`,
+                chalk.cyan(format(...args)),
+            );
+          },
+          error(...args) {
+            console.log(
+                chalk.bold.bgRgb(247, 38, 33)('ERROR '),
+                `[${chalk.rgb(255, 255, 255)(new Date().toUTCString())}]:`,
+                chalk.rgb(255, 38, 0)(format(...args)),
+            );
+          },
+          warn(...args) {
+            console.log(
+                chalk.bold.bgRgb(255, 153, 0)('WARNING '),
+                `[${chalk.rgb(255, 255, 255)(new Date().toUTCString())}]:`,
+                chalk.redBright(format(...args)),
+            );
+          },
+          trace(...args) {
+            console.log(
+                chalk.grey('TRACE '),
+                `[${chalk.rgb(255, 255, 255)(new Date().toUTCString())}]:`,
+                chalk.white(format(...args)),
+            );
+          },
+          debug(...args) {
+            console.log(
+                chalk.bold.bgRgb(66, 167, 245)('DEBUG '),
+                `[${chalk.rgb(255, 255, 255)(new Date().toUTCString())}]:`,
+                chalk.white(format(...args)),
+            );
+          },
+        };
+      },
+      enumerable: true,
+    },
+    sendNyanCat: {
+      async value(jid, text = '', buffer, title, body, url, quoted, options) {
+        if (buffer) {
+          try {
+            (type = await conn.getFile(buffer), buffer = type.data);
+          } catch {
+            buffer = buffer;
+          }
+        }
+	     const prep = generateWAMessageFromContent(jid, {extendedTextMessage: {text: text, contextInfo: {externalAdReply: {title: title, body: body, thumbnail: buffer, sourceUrl: url}, mentionedJid: await conn.parseMention(text)}}}, {quoted: quoted});
+        return conn.relayMessage(jid, prep.message, {messageId: prep.key.id});
+      },
+    },
+    sendPayment: {
+      async value(jid, amount, text, quoted, options) {
+        conn.relayMessage(jid, {
+          requestPaymentMessage: {
+            currencyCodeIso4217: 'PEN',
+            amount1000: amount,
+            requestFrom: null,
+            noteMessage: {
+              extendedTextMessage: {
+                text: text,
+                contextInfo: {
+                  externalAdReply: {
+                    showAdAttribution: true,
+                  }, mentionedJid: conn.parseMention(text)}}}}}, {});
+      },
+    },
+    getFile: {
+      /**
+             * getBuffer hehe
+             * @param {fs.PathLike} PATH
+             * @param {Boolean} saveToFile
+             */
+      async value(PATH, saveToFile = false) {
+        let res; let filename;
+        const data = Buffer.isBuffer(PATH) ? PATH : PATH instanceof ArrayBuffer ? PATH.toBuffer() : /^data:.*?\/.*?;base64,/i.test(PATH) ? Buffer.from(PATH.split`,`[1], 'base64') : /^https?:\/\//.test(PATH) ? await (res = await fetch(PATH)).buffer() : fs.existsSync(PATH) ? (filename = PATH, fs.readFileSync(PATH)) : typeof PATH === 'string' ? PATH : Buffer.alloc(0);
+        if (!Buffer.isBuffer(data)) throw new TypeError('Result is not a buffer');
+        const type = await fileTypeFromBuffer(data) || {
+          mime: 'application/octet-stream',
+          ext: '.bin',
+        };
+        if (data && saveToFile && !filename) (filename = path.join(__dirname, '../tmp/' + new Date * 1 + '.' + type.ext), await fs.promises.writeFile(filename, data));
+        return {
+          res,
+          filename,
+          ...type,
+          data,
+          deleteFile() {
+            return filename && fs.promises.unlink(filename);
+          },
+        };
+      },
+      enumerable: true,
+    },
+    waitEvent: {
+      /**
+             * waitEvent
+             * @param {String} eventName
+             * @param {Boolean} is
+             * @param {Number} maxTries
+             */
+      value(eventName, is = () => true, maxTries = 25) { // Idk why this exist?
+        return new Promise((resolve, reject) => {
+          let tries = 0;
+          const on = (...args) => {
+            if (++tries > maxTries) reject('Max tries reached');
+            else if (is()) {
+              conn.ev.off(eventName, on);
+              resolve(...args);
+            }
+          };
+          conn.ev.on(eventName, on);
+        });
+      },
+    },
+    relayWAMessage: {
+      async value(pesanfull) {
+        if (pesanfull.message.audioMessage) {
+          await conn.sendPresenceUpdate('recording', pesanfull.key.remoteJid);
+        } else {
+          await conn.sendPresenceUpdate('composing', pesanfull.key.remoteJid);
+        }
+        const mekirim = await conn.relayMessage(pesanfull.key.remoteJid, pesanfull.message, {messageId: pesanfull.key.id});
+        conn.ev.emit('messages.upsert', {messages: [pesanfull], type: 'append'});
+        return mekirim;
+      },
+    },
+    sendFile: {
+      /**
+             * Send Media/File with Automatic Type Specifier
+             * @param {String} jid
+             * @param {String|Buffer} path
+             * @param {String} filename
+             * @param {String} caption
+             * @param {import('@whiskeysockets/baileys').proto.WebMessageInfo} quoted
+             * @param {Boolean} ptt
+             * @param {Object} options
+             */
+      async value(jid, path, filename = '', caption = '', quoted, ptt = false, options = {}) {
+        const type = await conn.getFile(path, true);
+        let {res, data: file, filename: pathFile} = type;
+        if (res && res.status !== 200 || file.length <= 65536) {
+          try {
+            throw {json: JSON.parse(file.toString())};
+          } catch (e) {
+            if (e.json) throw e.json;
+          }
+        }
+        // const fileSize = fs.statSync(pathFile).size / 1024 / 1024
+        // if (fileSize >= 100) throw new Error('File size is too big!')
+        const opt = {};
+        if (quoted) opt.quoted = quoted;
+        if (!type) options.asDocument = true;
+        let mtype = ''; let mimetype = options.mimetype || type.mime; let convert;
+        if (/webp/.test(type.mime) || (/image/.test(type.mime) && options.asSticker)) mtype = 'sticker';
+        else if (/image/.test(type.mime) || (/webp/.test(type.mime) && options.asImage)) mtype = 'image';
+        else if (/video/.test(type.mime)) mtype = 'video';
+        else if (/audio/.test(type.mime)) {
+          (
+            convert = await toAudio(file, type.ext),
+            file = convert.data,
+            pathFile = convert.filename,
+            mtype = 'audio',
+            mimetype = options.mimetype || 'audio/mpeg; codecs=opus'
+          );
+        } else mtype = 'document';
+        if (options.asDocument) mtype = 'document';
+
+        delete options.asSticker;
+        delete options.asLocation;
+        delete options.asVideo;
+        delete options.asDocument;
+        delete options.asImage;
+
+        const message = {
+          ...options,
+          caption,
+          ptt,
+          [mtype]: {url: pathFile},
+          mimetype,
+          fileName: filename || pathFile.split('/').pop(),
+        };
+        /**
+                 * @type {import('@whiskeysockets/baileys').proto.WebMessageInfo}
+                 */
+        let m;
+        try {
+          m = await conn.sendMessage(jid, message, {...opt, ...options});
+        } catch (e) {
+          console.error(e);
+          m = null;
+        } finally {
+          if (!m) m = await conn.sendMessage(jid, {...message, [mtype]: file}, {...opt, ...options});
+          file = null; // releasing the memory
+          return m;
+        }
+      },
+      enumerable: true,
+    },
+    sendContact: {
+      /**
+             * Send Contact
+             * @param {String} jid
+             * @param {String[][]|String[]} data
+             * @param {import('@whiskeysockets/baileys').proto.WebMessageInfo} quoted
+             * @param {Object} options
+             */
+      async value(jid, data, quoted, options) {
+        if (!Array.isArray(data[0]) && typeof data[0] === 'string') data = [data];
+        const contacts = [];
+        for (let [number, name] of data) {
+          number = number.replace(/[^0-9]/g, '');
+          const njid = number + '@s.whatsapp.net';
+          const biz = await conn.getBusinessProfile(njid).catch((_) => null) || {};
+          const vcard = `
+BEGIN:VCARD
+VERSION:3.0
+N:;${name.replace(/\n/g, '\\n')};;;
+FN:${name.replace(/\n/g, '\\n')}
+TEL;type=CELL;type=VOICE;waid=${number}:${PhoneNumber('+' + number).getNumber('international')}${biz.description ? `
+X-WA-BIZ-NAME:${(conn.chats[njid]?.vname || conn.getName(njid) || name).replace(/\n/, '\\n')}
+X-WA-BIZ-DESCRIPTION:${biz.description.replace(/\n/g, '\\n')}
+`.trim() : ''}
+END:VCARD
+        `.trim();
+          contacts.push({vcard, displayName: name});
+        }
+        return await conn.sendMessage(jid, {
+          ...options,
+          contacts: {
+            ...options,
+            displayName: (contacts.length >= 2 ? `${contacts.length} kontak` : contacts[0].displayName) || null,
+            contacts,
+          },
+        }, {quoted, ...options});
+      },
+      enumerable: true,
+    },
+reply: {
+/**
+* Reply to a message
+* @param {String} jid
+* @param {String|Buffer} text
+* @param {import('@adiwajshing/baileys').proto.WebMessageInfo} quoted
+* @param {Object} options
+*/
+
+async value(jid, text = '', quoted, options) {
+if (Buffer.isBuffer(text)) {
+return conn.sendFile(jid, text, 'file', '', quoted, false, options)
+} else {
+let canalId = ["120363371008200788@newsletter", "120363371008200788@newsletter", "120363371008200788@newsletter", "120363178718483875@newsletter"]
+let canalNombre = ["Hack Store X 💫", "Kantu Bot Ofc ⚡", "The Kantu Bot 🔥", "KantuBot Test ✨"]
+
+async function getRandomChannel() {
+let randomIndex = Math.floor(Math.random() * canalId.length)
+let id = canalId[randomIndex]
+let nombre = canalNombre[randomIndex]
+return { id, nombre }
+} 
+	
+let randomChannel = await getRandomChannel()
+const contextInfo = {
+mentionedJid: await conn.parseMention(text),
+isForwarded: true,
+forwardingScore: 1, 
+forwardedNewsletterMessageInfo: {
+newsletterJid: randomChannel.id, 
+newsletterName: randomChannel.nombre
+}}
+        
+const messageOptions = { ...options, text, contextInfo }
+return conn.sendMessage(jid, messageOptions, { quoted, ...options })
+}}
+},
+                 //   sendButton: {
+            /**
+             * send Button
+             * @param {String} jid
+             * @param {String} text
+             * @param {String} footer
+             * @param {Buffer} buffer
+             * @param {String[] | String[][]} buttons
+             * @param {import('@whiskeysockets/baileys').proto.WebMessageInfo} quoted
+             * @param {Object} options
+             */
+ /*           async value(jid, text = '', footer = '', buffer, buttons, quoted, options) {
+                let type
+                if (Array.isArray(buffer)) (options = quoted, quoted = buttons, buttons = buffer, buffer = null)
+                else if (buffer) try { (type = await conn.getFile(buffer), buffer = type.data) } catch { buffer = null }
+                if (!Array.isArray(buttons[0]) && typeof buttons[0] === 'string') buttons = [buttons]
+                if (!options) options = {}
+                let message = {
+                    ...options,
+                    [buffer ? 'caption' : 'text']: text || '',
+                    footer,
+                    buttons: buttons.map(btn => ({
+                        buttonId: !nullish(btn[1]) && btn[1] || !nullish(btn[0]) && btn[0] || '',
+                        buttonText: {
+                            displayText: !nullish(btn[0]) && btn[0] || !nullish(btn[1]) && btn[1] || ''
+                        }
+                    })),
+                    ...(buffer ?
+                        options.asLocation && /image/.test(type.mime) ? {
+                            location: {
+                                ...options,
+                                jpegThumbnail: buffer
+                            }
+                        } : {
+                            [/video/.test(type.mime) ? 'video' : /image/.test(type.mime) ? 'image' : 'document']: buffer
+                        } : {})
+                }
+
+                return await conn.sendMessage(jid, message, {
+                    quoted,
+                    upload: conn.waUploadToServer,
+                    ...options
+                })
+            },
+            enumerable: true
+        },
+        */        
+                
+        //-- new
+sendButton: {
+    async value(jid, text = '', footer = '', buffer, buttons, copy, urls, list, quoted, options) {
+        let img, video
+
+    
+        if (/^https?:\/\//i.test(buffer)) {
+            try {
+                // Obtener el tipo MIME de la URL
+                const response = await fetch(buffer)
+                const contentType = response.headers.get('content-type')
+                if (/^image\//i.test(contentType)) {
+                    img = await prepareWAMessageMedia({ image: { url: buffer } }, { upload: conn.waUploadToServer })
+                } else if (/^video\//i.test(contentType)) {
+                    video = await prepareWAMessageMedia({ video: { url: buffer } }, { upload: conn.waUploadToServer })
+                } else {
+                    console.error("Tipo MIME no compatible:", contentType)
+                }
+            } catch (error) {
+                console.error("Error al obtener el tipo MIME:", error)
+            }
+        } else {
+            
+            try {
+                const type = await conn.getFile(buffer)
+               if (/^image\//i.test(type.mime)) {
+                    img = await prepareWAMessageMedia({ image: { url: buffer } }, { upload: conn.waUploadToServer })
+                } else if (/^video\//i.test(type.mime)) {
+                    video = await prepareWAMessageMedia({ video: { url: buffer } }, { upload: conn.waUploadToServer })
+                }
+            } catch (error) {
+                console.error("Error al obtener el tipo de archivo:", error);
+            }
+        }
+
+const dynamicButtons = []
+
+// Botones de tipo quick_reply
+if (buttons && Array.isArray(buttons)) {
+    dynamicButtons.push(...buttons.map(btn => ({
+        name: 'quick_reply',
+        buttonParamsJson: JSON.stringify({
+            display_text: btn[0],
+            id: btn[1]
+        })
+    })));
+}
+
+// Botones de copiar
+if (copy && Array.isArray(copy)) {
+    dynamicButtons.push(...copy.map(copyBtn => ({
+        name: 'cta_copy',
+        buttonParamsJson: JSON.stringify({
+            display_text: copyBtn[0] || 'Copy', 
+            copy_code: copyBtn[1] 
+        })
+    })));
+}
+
+// Botones de URL
+if (urls && Array.isArray(urls)) {
+    urls.forEach(url => {
+        dynamicButtons.push({
+            name: 'cta_url',
+            buttonParamsJson: JSON.stringify({
+                display_text: url[0],
+                url: url[1],
+                merchant_url: url[1]
+            })
+        });
+    });
+}
+
+// Botones de lista
+if (list && Array.isArray(list)) {
+            list.forEach(lister => {
+                dynamicButtons.push({
+                    name: 'single_select',
+                    buttonParamsJson: JSON.stringify({
+                        title: lister[0], 
+                        sections: lister[1]
+                    })
+                })
+            })
+        }
+        const interactiveMessage = {
+            body: { text: text },
+            footer: { text: footer },
+            header: {
+                hasMediaAttachment: false,
+                imageMessage: img ? img.imageMessage : null,
+                videoMessage: video ? video.videoMessage : null
+            },
+            nativeFlowMessage: {
+                buttons: dynamicButtons,
+                messageParamsJson: ''
+            }
+        }
+
+              
+        let msgL = generateWAMessageFromContent(jid, {
+            viewOnceMessage: {
+                message: {
+                    interactiveMessage } } }, { userJid: conn.user.jid, quoted })
+        
+       conn.relayMessage(jid, msgL.message, { messageId: msgL.key.id, ...options })
+            
+    }
+},
+
+sendAlbumMessage: {
+    async value(jid, medias, caption = "", quoted = null) {
+        let img, video;
+        
+        const album = generateWAMessageFromContent(jid, {
+            albumMessage: {
+                expectedImageCount: medias.filter(media => media.type === "image").length,
+                expectedVideoCount: medias.filter(media => media.type === "video").length,
+                ...(quoted ? {
+                    contextInfo: {
+                        remoteJid: quoted.key.remoteJid,
+                        fromMe: quoted.key.fromMe,
+                        stanzaId: quoted.key.id,
+                        participant: quoted.key.participant || quoted.key.remoteJid,
+                        quotedMessage: quoted.message
+                    }
+                } : {})
+            }
+        }, { quoted: quoted });
+        
+        await conn.relayMessage(album.key.remoteJid, album.message, {
+            messageId: album.key.id
+        });
+
+        for (const media of medias) {
+            const { type, data } = media;
+            
+            if (/^https?:\/\//i.test(data.url)) {
+                try {
+                    const response = await fetch(data.url);
+                    const contentType = response.headers.get('content-type');
+                    
+                    if (/^image\//i.test(contentType)) {
+                        img = await prepareWAMessageMedia({ image: { url: data.url } }, { upload: conn.waUploadToServer });
+                    } else if (/^video\//i.test(contentType)) {
+                        video = await prepareWAMessageMedia({ video: { url: data.url } }, { upload: conn.waUploadToServer });
+                    }
+                } catch (error) {
+                    console.error("Error al obtener el tipo MIME:", error);
+                }
+            }
+            
+            const mediaMessage = await generateWAMessage(album.key.remoteJid, {
+                [type]: data,
+                ...(media === medias[0] ? { caption } : {})
+            }, {
+                upload: conn.waUploadToServer
+            });
+
+            mediaMessage.message.messageContextInfo = {
+                messageAssociation: {
+                    associationType: 1,
+                    parentMessageKey: album.key
+                }
+            };
+
+            await conn.relayMessage(mediaMessage.key.remoteJid, mediaMessage.message, {
+                messageId: mediaMessage.key.id
+            });
+        }
+
+        return album;
+    }
+},
+
+/**
+     * Send nativeFlowMessage
+     */
+    sendNCarousel: {
+      async value(jid, text = '', footer = '', buffer, buttons, copy, urls, list, quoted, options) {
+        let img, video;
+        if (buffer) {
+          if (/^https?:\/\//i.test(buffer)) {
+            try {
+              const response = await fetch(buffer);
+              const contentType = response.headers.get('content-type');
+              if (/^image\//i.test(contentType)) {
+                img = await prepareWAMessageMedia({
+                  image: {
+                    url: buffer
+                  }
+                }, {
+                  upload: conn.waUploadToServer,
+                  ...options
+                });
+              } else if (/^video\//i.test(contentType)) {
+                video = await prepareWAMessageMedia({
+                  video: {
+                    url: buffer
+                  }
+                }, {
+                  upload: conn.waUploadToServer,
+                  ...options
+                });
+              } else {
+                console.error("Incompatible MIME type:", contentType);
+              }
+            } catch (error) {
+              console.error("Failed to get MIME type:", error);
+            }
+          } else {
+            try {
+              const type = await conn.getFile(buffer);
+              if (/^image\//i.test(type.mime)) {
+                img = await prepareWAMessageMedia({
+                  image: (/^https?:\/\//i.test(buffer)) ? {
+                    url: buffer
+                  } : (type && type?.data)
+                }, {
+                  upload: conn.waUploadToServer,
+                  ...options
+                });
+              } else if (/^video\//i.test(type.mime)) {
+                video = await prepareWAMessageMedia({
+                  video: (/^https?:\/\//i.test(buffer)) ? {
+                    url: buffer
+                  } : (type && type?.data)
+                }, {
+                  upload: conn.waUploadToServer,
+                  ...options
+                });
+              }
+            } catch (error) {
+              console.error("Failed to get file type:", error);
+            }
+          }
+        }
+        const dynamicButtons = buttons.map(btn => ({
+          name: 'quick_reply',
+          buttonParamsJson: JSON.stringify({
+            display_text: btn[0],
+            id: btn[1]
+          }),
+        }));
+        dynamicButtons.push(
+          (copy && (typeof copy === 'string' || typeof copy === 'number')) ? {
+            name: 'cta_copy',
+            buttonParamsJson: JSON.stringify({
+              display_text: 'Copy',
+              copy_code: copy
+            })
+          } : null)
+	      
+        urls?.forEach(url => {
+          dynamicButtons.push({
+            name: 'cta_url',
+            buttonParamsJson: JSON.stringify({
+              display_text: url[0],
+              url: url[1],
+              merchant_url: url[1]
+            })
+          });
+        });
+        list?.forEach(lister => {
+          dynamicButtons.push({
+            name: 'single_select',
+            buttonParamsJson: JSON.stringify({
+              title: lister[0],
+              sections: lister[1]
+            })
+          });
+        })
+        const interactiveMessage = {
+          body: {
+            text: text || ''
+          },
+          footer: {
+            text: footer || wm
+          },
+          header: {
+            hasMediaAttachment: img?.imageMessage || video?.videoMessage ? true : false,
+            imageMessage: img?.imageMessage || null,
+            videoMessage: video?.videoMessage || null
+          },
+          nativeFlowMessage: {
+            buttons: dynamicButtons.filter(Boolean),
+            messageParamsJson: ''
+          },
+          ...Object.assign({
+            mentions: typeof text === 'string' ? conn.parseMention(text || '@0') : [],
+            contextInfo: {
+              mentionedJid: typeof text === 'string' ? conn.parseMention(text || '@0') : [],
+            }
+          }, {
+            ...(options || {}),
+            ...(conn.temareply?.contextInfo && {
+              contextInfo: {
+                ...(options?.contextInfo || {}),
+                ...conn.temareply?.contextInfo,
+                externalAdReply: {
+                  ...(options?.contextInfo?.externalAdReply || {}),
+                  ...conn.temareply?.contextInfo?.externalAdReply,
+                },
+              },
+            })
+          })
+        };
+        const messageContent = proto.Message.fromObject({
+          viewOnceMessage: {
+            message: {
+              messageContextInfo: {
+                deviceListMetadata: {},
+                deviceListMetadataVersion: 2
+              },
+              interactiveMessage
+            }
+          }
+        });
+        const msgs = await generateWAMessageFromContent(jid, messageContent, {
+          userJid: conn.user.jid,
+          quoted: quoted,
+          upload: conn.waUploadToServer,
+          ephemeralExpiration: WA_DEFAULT_EPHEMERAL
+        });
+        await conn.relayMessage(jid, msgs.message, {
+          messageId: msgs.key.id
+        });
+      }
+    }, 
+
+/**
+     * Send carouselMessage
+     */
+    sendCarousel: {
+  async value(jid, text = '', footer = '', messages, quoted, options = {}) {
+    try {
+      if (messages.length > 1) {
+        const cards = await Promise.all(messages.map(async ([text = '', footer = '', buffer, buttons, copy, urls, list]) => {
+          let img, video;
+
+          if (/^https?:\/\//i.test(buffer)) {
+            try {
+              const response = await fetch(buffer);
+              const contentType = response.headers.get('content-type');
+              if (/^image\//i.test(contentType)) {
+                img = await prepareWAMessageMedia({ image: { url: buffer } }, { upload: conn.waUploadToServer, ...options });
+              } else if (/^video\//i.test(contentType)) {
+                video = await prepareWAMessageMedia({ video: { url: buffer } }, { upload: conn.waUploadToServer, ...options });
+              } else {
+                console.error("Tipo MIME no compatible:", contentType);
+              }
+            } catch (error) {
+              console.error("Error al obtener el tipo MIME:", error);
+            }
+          } else {
+            try {
+              const type = await conn.getFile(buffer);
+              if (/^image\//i.test(type.mime)) {
+                img = await prepareWAMessageMedia({ image: { url: buffer } }, { upload: conn.waUploadToServer, ...options });
+              } else if (/^video\//i.test(type.mime)) {
+                video = await prepareWAMessageMedia({ video: { url: buffer } }, { upload: conn.waUploadToServer, ...options });
+              }
+            } catch (error) {
+              console.error("Error al obtener el tipo de archivo:", error);
+            }
+          }
+
+          const dynamicButtons = [];
+          if (buttons && Array.isArray(buttons)) {
+            buttons.forEach(btn => {
+              dynamicButtons.push({
+                name: 'quick_reply',
+                buttonParamsJson: JSON.stringify({
+                  display_text: btn[0],
+                  id: btn[1]
+                })
+              });
+            });
+          }
+
+          if (copy && Array.isArray(copy)) {
+            copy.forEach(copyBtn => {
+              dynamicButtons.push({
+                name: 'cta_copy',
+                buttonParamsJson: JSON.stringify({
+                  display_text: copyBtn[0] || 'Copy',
+                  copy_code: copyBtn[1]
+                })
+              });
+            });
+          }
+
+          if (urls && Array.isArray(urls)) {
+            urls.forEach(url => {
+              dynamicButtons.push({
+                name: 'cta_url',
+                buttonParamsJson: JSON.stringify({
+                  display_text: url[0],
+                  url: url[1],
+                  merchant_url: url[1]
+                })
+              });
+            });
+          }
+
+          if (list && Array.isArray(list)) {
+            list.forEach(lister => {
+              dynamicButtons.push({
+                name: 'single_select',
+                buttonParamsJson: JSON.stringify({
+                  title: lister[0],
+                  sections: lister[1]
+                })
+              });
+            });
+          }
+
+          return {
+            body: proto.Message.InteractiveMessage.Body.fromObject({
+              text: text || ''
+            }),
+            footer: proto.Message.InteractiveMessage.Footer.fromObject({
+              text: footer || null
+            }),
+            header: proto.Message.InteractiveMessage.Header.fromObject({
+              title: text || null,
+              subtitle: text || null,
+              hasMediaAttachment: img?.imageMessage || video?.videoMessage ? true : false,
+              imageMessage: img?.imageMessage || null,
+              videoMessage: video?.videoMessage || null
+            }),
+            nativeFlowMessage: proto.Message.InteractiveMessage.NativeFlowMessage.fromObject({
+              buttons: dynamicButtons.filter(Boolean),
+              messageParamsJson: ''
+            })
+          };
+        }));
+
+        const interactiveMessage = proto.Message.InteractiveMessage.create({
+          body: proto.Message.InteractiveMessage.Body.fromObject({
+            text: text || ''
+          }),
+          footer: proto.Message.InteractiveMessage.Footer.fromObject({
+            text: footer || ''
+          }),
+          header: proto.Message.InteractiveMessage.Header.fromObject({
+            title: text || '',
+            subtitle: text || '',
+            hasMediaAttachment: false
+          }),
+          carouselMessage: proto.Message.InteractiveMessage.CarouselMessage.fromObject({
+            cards: cards
+          })
+        });
+
+        const messageContent = proto.Message.fromObject({
+          viewOnceMessage: {
+            message: {
+              messageContextInfo: {
+                deviceListMetadata: {},
+                deviceListMetadataVersion: 2
+              },
+              interactiveMessage
+            }
+          }
+        });
+
+        const msgs = await generateWAMessageFromContent(jid, messageContent, {
+          userJid: conn.user.jid,
+          quoted: quoted,
+          upload: conn.waUploadToServer,
+          ephemeralExpiration: WA_DEFAULT_EPHEMERAL
+        });
+
+        await conn.relayMessage(jid, msgs.message, { messageId: msgs.key.id });
+      } else {
+        await conn.sendNCarousel(jid, ...messages[0], quoted, options);
+      }
+    } catch (error) {
+      console.error("Error en sendCarousel:", error);
+      throw error;
+    }
+  }
+},
+        
+sendButton2: {
+    async value(jid, text = '', footer = '', buffer, buttons, copy, urls, quoted, options) {
+        let img, video
+
+    
+        if (/^https?:\/\//i.test(buffer)) {
+            try {
+                // Obtener el tipo MIME de la URL
+                const response = await fetch(buffer)
+                const contentType = response.headers.get('content-type')
+                if (/^image\//i.test(contentType)) {
+                    img = await prepareWAMessageMedia({ image: { url: buffer } }, { upload: conn.waUploadToServer })
+                } else if (/^video\//i.test(contentType)) {
+                    video = await prepareWAMessageMedia({ video: { url: buffer } }, { upload: conn.waUploadToServer })
+                } else {
+                    console.error("Tipo MIME no compatible:", contentType)
+                }
+            } catch (error) {
+                console.error("Error al obtener el tipo MIME:", error)
+            }
+        } else {
+            
+            try {
+                const type = await conn.getFile(buffer)
+               if (/^image\//i.test(type.mime)) {
+                    img = await prepareWAMessageMedia({ image: { url: buffer } }, { upload: conn.waUploadToServer })
+                } else if (/^video\//i.test(type.mime)) {
+                    video = await prepareWAMessageMedia({ video: { url: buffer } }, { upload: conn.waUploadToServer })
+                }
+            } catch (error) {
+                console.error("Error al obtener el tipo de archivo:", error);
+            }
+        }
+
+        const dynamicButtons = buttons.map(btn => ({
+            name: 'quick_reply',
+            buttonParamsJson: JSON.stringify({
+                display_text: btn[0],
+                id: btn[1]
+            }),
+        }));
+
+       
+        if (copy && (typeof copy === 'string' || typeof copy === 'number')) {
+            // Añadir botón de copiar
+            dynamicButtons.push({
+                name: 'cta_copy',
+                buttonParamsJson: JSON.stringify({
+                    display_text: 'Copy',
+                    copy_code: copy
+                })
+            });
+        }
+
+        // Añadir botones de URL
+        if (urls && Array.isArray(urls)) {
+            urls.forEach(url => {
+                dynamicButtons.push({
+                    name: 'cta_url',
+                    buttonParamsJson: JSON.stringify({
+                        display_text: url[0],
+                        url: url[1],
+                        merchant_url: url[1]
+                    })
+                })
+            })
+        }
+
+
+        const interactiveMessage = {
+            body: { text: text },
+            footer: { text: footer },
+            header: {
+                hasMediaAttachment: false,
+                imageMessage: img ? img.imageMessage : null,
+                videoMessage: video ? video.videoMessage : null
+            },
+            nativeFlowMessage: {
+                buttons: dynamicButtons,
+                messageParamsJson: ''
+            }
+        }
+
+              
+        let msgL = generateWAMessageFromContent(jid, {
+            viewOnceMessage: {
+                message: {
+                    interactiveMessage } } }, { userJid: conn.user.jid, quoted })
+        
+       conn.relayMessage(jid, msgL.message, { messageId: msgL.key.id, ...options })
+            
+    }
+}, 
+
+        //---
+        
+sendList: {
+    async value(jid, title, text, buttonText, buffer, listSections, quoted, options = {}) {
+      let img, video
+    
+        if (/^https?:\/\//i.test(buffer)) {
+            try {
+                // Obtener el tipo MIME de la URL
+                const response = await fetch(buffer)
+                const contentType = response.headers.get('content-type')
+                if (/^image\//i.test(contentType)) {
+                    img = await prepareWAMessageMedia({ image: { url: buffer } }, { upload: conn.waUploadToServer })
+                } else if (/^video\//i.test(contentType)) {
+                    video = await prepareWAMessageMedia({ video: { url: buffer } }, { upload: conn.waUploadToServer })
+                } else {
+                    console.error("Tipo MIME no compatible:", contentType)
+                }
+            } catch (error) {
+                console.error("Error al obtener el tipo MIME:", error)
+            }
+        } else {
+            
+            try {
+                const type = await conn.getFile(buffer)
+               if (/^image\//i.test(type.mime)) {
+                    img = await prepareWAMessageMedia({ image: { url: buffer } }, { upload: conn.waUploadToServer })
+                } else if (/^video\//i.test(type.mime)) {
+                    video = await prepareWAMessageMedia({ video: { url: buffer } }, { upload: conn.waUploadToServer })
+                }
+            } catch (error) {
+                console.error("Error al obtener el tipo de archivo:", error);
+            }
+        }
+
+  const sections = [...listSections]
+        
+        const message = {
+            interactiveMessage: {
+                header: {title: title, 
+                hasMediaAttachment: false,
+                imageMessage: img ? img.imageMessage : null,
+                videoMessage: video ? video.videoMessage : null 
+                   } ,
+                body: {text: text}, 
+                nativeFlowMessage: {
+                    buttons: [
+                        {
+                            name: 'single_select',
+                            buttonParamsJson: JSON.stringify({
+                                title: buttonText,
+                                sections
+                            })
+                        }
+                    ],
+                    messageParamsJson: ''
+                }
+            }
+        };
+        
+        let msgL = generateWAMessageFromContent(jid, {
+            viewOnceMessage: {
+                message} }, { userJid: conn.user.jid, quoted })
+        
+        //await conn.relayMessage(jid, { viewOnceMessage: { message } }, {});
+        conn.relayMessage(jid, msgL.message, { messageId: msgL.key.id, ...options })
+
+    }
+},
+
+    sendPoll: {
+      async value(jid, name = '', optiPoll, options) {
+        if (!Array.isArray(optiPoll[0]) && typeof optiPoll[0] === 'string') optiPoll = [optiPoll];
+        if (!options) options = {};
+        const pollMessage = {
+          name: name,
+          options: optiPoll.map((btn) => ({
+            optionName: !nullish(btn[0]) && btn[0] || '',
+          })),
+          selectableOptionsCount: 1,
+        };
+        return conn.relayMessage(jid, {pollCreationMessage: pollMessage}, {...options});
+      },
+    },
+    sendHydrated: {
+      /**
+             *
+             * @param {String} jid
+             * @param {String} text
+             * @param {String} footer
+             * @param {fs.PathLike} buffer
+             * @param {String|string[]} url
+             * @param {String|string[]} urlText
+             * @param {String|string[]} call
+             * @param {String|string[]} callText
+             * @param {String[][]} buttons
+             * @param {import('@whiskeysockets/baileys').proto.WebMessageInfo} quoted
+             * @param {Object} options
+             */
+      async value(jid, text = '', footer = '', buffer, url, urlText, call, callText, buttons, quoted, options) {
+        let type;
+        if (buffer) {
+          try {
+            (type = await conn.getFile(buffer), buffer = type.data);
+          } catch {
+            buffer = buffer;
+          }
+        }
+        if (buffer && !Buffer.isBuffer(buffer) && (typeof buffer === 'string' || Array.isArray(buffer))) (options = quoted, quoted = buttons, buttons = callText, callText = call, call = urlText, urlText = url, url = buffer, buffer = null);
+        if (!options) options = {};
+        const templateButtons = [];
+        if (url || urlText) {
+          if (!Array.isArray(url)) url = [url];
+          if (!Array.isArray(urlText)) urlText = [urlText];
+          templateButtons.push(...(
+            url.map((v, i) => [v, urlText[i]])
+                .map(([url, urlText], i) => ({
+                  index: templateButtons.length + i + 1,
+                  urlButton: {
+                    displayText: !nullish(urlText) && urlText || !nullish(url) && url || '',
+                    url: !nullish(url) && url || !nullish(urlText) && urlText || '',
+                  },
+                })) || []
+          ));
+        }
+        if (call || callText) {
+          if (!Array.isArray(call)) call = [call];
+          if (!Array.isArray(callText)) callText = [callText];
+          templateButtons.push(...(
+            call.map((v, i) => [v, callText[i]])
+                .map(([call, callText], i) => ({
+                  index: templateButtons.length + i + 1,
+                  callButton: {
+                    displayText: !nullish(callText) && callText || !nullish(call) && call || '',
+                    phoneNumber: !nullish(call) && call || !nullish(callText) && callText || '',
+                  },
+                })) || []
+          ));
+        }
+        if (buttons.length) {
+          if (!Array.isArray(buttons[0])) buttons = [buttons];
+          templateButtons.push(...(
+            buttons.map(([text, id], index) => ({
+              index: templateButtons.length + index + 1,
+              quickReplyButton: {
+                displayText: !nullish(text) && text || !nullish(id) && id || '',
+                id: !nullish(id) && id || !nullish(text) && text || '',
+              },
+            })) || []
+          ));
+        }
+        const message = {
+          ...options,
+          [buffer ? 'caption' : 'text']: text || '',
+          footer,
+          templateButtons,
+          ...(buffer ?
+                        options.asLocation && /image/.test(type.mime) ? {
+                          location: {
+                            ...options,
+                            jpegThumbnail: buffer,
+                          },
+                        } : {
+                          [/video/.test(type.mime) ? 'video' : /image/.test(type.mime) ? 'image' : 'document']: buffer,
+                        } : {}),
+        };
+        return await conn.sendMessage(jid, message, {
+          quoted,
+          upload: conn.waUploadToServer,
+          ...options,
+        });
+      },
+      enumerable: true,
+    },
+    sendHydrated2: {
+      /**
+             *
+             * @param {String} jid
+             * @param {String} text
+             * @param {String} footer
+             * @param {fs.PathLike} buffer
+             * @param {String|string[]} url
+             * @param {String|string[]} urlText
+             * @param {String|string[]} call
+             * @param {String|string[]} callText
+             * @param {String[][]} buttons
+             * @param {import('@whiskeysockets/baileys').proto.WebMessageInfo} quoted
+             * @param {Object} options
+             */
+      async value(jid, text = '', footer = '', buffer, url, urlText, url2, urlText2, buttons, quoted, options) {
+        let type;
+        if (buffer) {
+          try {
+            (type = await conn.getFile(buffer), buffer = type.data);
+          } catch {
+            buffer = buffer;
+          }
+        }
+        if (buffer && !Buffer.isBuffer(buffer) && (typeof buffer === 'string' || Array.isArray(buffer))) (options = quoted, quoted = buttons, buttons = callText, callText = call, call = urlText, urlText = url, url = buffer, buffer = null);
+        if (!options) options = {};
+        const templateButtons = [];
+        if (url || urlText) {
+          if (!Array.isArray(url)) url = [url];
+          if (!Array.isArray(urlText)) urlText = [urlText];
+          templateButtons.push(...(
+            url.map((v, i) => [v, urlText[i]])
+                .map(([url, urlText], i) => ({
+                  index: templateButtons.length + i + 1,
+                  urlButton: {
+                    displayText: !nullish(urlText) && urlText || !nullish(url) && url || '',
+                    url: !nullish(url) && url || !nullish(urlText) && urlText || '',
+                  },
+                })) || []
+          ));
+        }
+        if (url2 || urlText2) {
+          if (!Array.isArray(url2)) url2 = [url2];
+          if (!Array.isArray(urlText2)) urlText2 = [urlText2];
+          templateButtons.push(...(
+            url2.map((v, i) => [v, urlText2[i]])
+                .map(([url2, urlText2], i) => ({
+                  index: templateButtons.length + i + 1,
+                  urlButton: {
+                    displayText: !nullish(urlText2) && urlText2 || !nullish(url2) && url2 || '',
+                    url: !nullish(url2) && url2 || !nullish(urlText2) && urlText2 || '',
+                  },
+                })) || []
+          ));
+        }
+        if (buttons.length) {
+          if (!Array.isArray(buttons[0])) buttons = [buttons];
+          templateButtons.push(...(
+            buttons.map(([text, id], index) => ({
+              index: templateButtons.length + index + 1,
+              quickReplyButton: {
+                displayText: !nullish(text) && text || !nullish(id) && id || '',
+                id: !nullish(id) && id || !nullish(text) && text || '',
+              },
+            })) || []
+          ));
+        }
+        const message = {
+          ...options,
+          [buffer ? 'caption' : 'text']: text || '',
+          footer,
+          templateButtons,
+          ...(buffer ?
+                        options.asLocation && /image/.test(type.mime) ? {
+                          location: {
+                            ...options,
+                            jpegThumbnail: buffer,
+                          },
+                        } : {
+                          [/video/.test(type.mime) ? 'video' : /image/.test(type.mime) ? 'image' : 'document']: buffer,
+                        } : {}),
+        };
+        return await conn.sendMessage(jid, message, {
+          quoted,
+          upload: conn.waUploadToServer,
+          ...options,
+        });
+      },
+      enumerable: true,
+    },
+    cMod: {
+      /**
+             * cMod
+             * @param {String} jid
+             * @param {import('@whiskeysockets/baileys').proto.WebMessageInfo} message
+             * @param {String} text
+             * @param {String} sender
+             * @param {*} options
+             * @returns
+             */
+      value(jid, message, text = '', sender = conn.user.jid, options = {}) {
+        if (options.mentions && !Array.isArray(options.mentions)) options.mentions = [options.mentions];
+        const copy = message.toJSON();
+        delete copy.message.messageContextInfo;
+        delete copy.message.senderKeyDistributionMessage;
+        const mtype = Object.keys(copy.message)[0];
+        const msg = copy.message;
+        const content = msg[mtype];
+        if (typeof content === 'string') msg[mtype] = text || content;
+        else if (content.caption) content.caption = text || content.caption;
+        else if (content.text) content.text = text || content.text;
+        if (typeof content !== 'string') {
+          msg[mtype] = {...content, ...options};
+          msg[mtype].contextInfo = {
+            ...(content.contextInfo || {}),
+            mentionedJid: options.mentions || content.contextInfo?.mentionedJid || [],
+          };
+        }
+        if (copy.participant) sender = copy.participant = sender || copy.participant;
+        else if (copy.key.participant) sender = copy.key.participant = sender || copy.key.participant;
+        if (copy.key.remoteJid.includes('@s.whatsapp.net')) sender = sender || copy.key.remoteJid;
+        else if (copy.key.remoteJid.includes('@broadcast')) sender = sender || copy.key.remoteJid;
+        copy.key.remoteJid = jid;
+        copy.key.fromMe = areJidsSameUser(sender, conn.user.id) || false;
+        return proto.WebMessageInfo.fromObject(copy);
+      },
+      enumerable: true,
+    },
+    copyNForward: {
+      /**
+             * Exact Copy Forward
+             * @param {String} jid
+             * @param {import('@whiskeysockets/baileys').proto.WebMessageInfo} message
+             * @param {Boolean|Number} forwardingScore
+             * @param {Object} options
+             */
+      async value(jid, message, forwardingScore = true, options = {}) {
+        let vtype;
+        if (options.readViewOnce && message.message.viewOnceMessage?.message) {
+          vtype = Object.keys(message.message.viewOnceMessage.message)[0];
+          delete message.message.viewOnceMessage.message[vtype].viewOnce;
+          message.message = proto.Message.fromObject(
+              JSON.parse(JSON.stringify(message.message.viewOnceMessage.message)),
+          );
+          message.message[vtype].contextInfo = message.message.viewOnceMessage.contextInfo;
+        }
+        const mtype = Object.keys(message.message)[0];
+        let m = generateForwardMessageContent(message, !!forwardingScore);
+        const ctype = Object.keys(m)[0];
+        if (forwardingScore && typeof forwardingScore === 'number' && forwardingScore > 1) m[ctype].contextInfo.forwardingScore += forwardingScore;
+        m[ctype].contextInfo = {
+          ...(message.message[mtype].contextInfo || {}),
+          ...(m[ctype].contextInfo || {}),
+        };
+        m = generateWAMessageFromContent(jid, m, {
+          ...options,
+          userJid: conn.user.jid,
+        });
+        await conn.relayMessage(jid, m.message, {messageId: m.key.id, additionalAttributes: {...options}});
+        return m;
+      },
+      enumerable: true,
+    },
+    fakeReply: {
+      /**
+             * Fake Replies
+             * @param {String} jid
+             * @param {String|Object} text
+             * @param {String} fakeJid
+             * @param {String} fakeText
+             * @param {String} fakeGroupJid
+             * @param {String} options
+             */
+      value(jid, text = '', fakeJid = this.user.jid, fakeText = '', fakeGroupJid, options) {
+        return conn.reply(jid, text, {key: {fromMe: areJidsSameUser(fakeJid, conn.user.id), participant: fakeJid, ...(fakeGroupJid ? {remoteJid: fakeGroupJid} : {})}, message: {conversation: fakeText}, ...options});
+      },
+    },
+    downloadM: {
+      /**
+             * Download media message
+             * @param {Object} m
+             * @param {String} type
+             * @param {fs.PathLike | fs.promises.FileHandle} saveToFile
+             * @return {Promise<fs.PathLike | fs.promises.FileHandle | Buffer>}
+             */
+      async value(m, type, saveToFile) {
+        let filename;
+        if (!m || !(m.url || m.directPath)) return Buffer.alloc(0);
+        const stream = await downloadContentFromMessage(m, type);
+        let buffer = Buffer.from([]);
+        for await (const chunk of stream) {
+          buffer = Buffer.concat([buffer, chunk]);
+        }
+        if (saveToFile) ({filename} = await conn.getFile(buffer, true));
+        return saveToFile && fs.existsSync(filename) ? filename : buffer;
+      },
+      enumerable: true,
+    },
+    parseMention: {
+      /**
+             * Parses string into mentionedJid(s)
+             * @param {String} text
+             * @return {Array<String>}
+             */
+      value(text = '') {
+        return [...text.matchAll(/@([0-9]{5,16}|0)/g)].map((v) => v[1] + '@s.whatsapp.net');
+      },
+      enumerable: true,
+    },
+    getName: {
+      /**
+             * Get name from jid
+             * @param {String} jid
+             * @param {Boolean} withoutContact
+             */
+      value(jid = '', withoutContact = false) {
+        jid = conn.decodeJid(jid);
+        withoutContact = conn.withoutContact || withoutContact;
+        let v;
+        if (jid.endsWith('@g.us')) {
+          return new Promise(async (resolve) => {
+            v = conn.chats[jid] || {};
+            if (!(v.name || v.subject)) v = await conn.groupMetadata(jid) || {};
+            resolve(v.name || v.subject || PhoneNumber('+' + jid.replace('@s.whatsapp.net', '')).getNumber('international'));
+          });
+        } else {
+          v = jid === '0@s.whatsapp.net' ? {
+            jid,
+            vname: 'WhatsApp',
+          } : areJidsSameUser(jid, conn.user.id) ?
+                    conn.user :
+                    (conn.chats[jid] || {});
+        }
+        return (withoutContact ? '' : v.name) || v.subject || v.vname || v.notify || v.verifiedName || PhoneNumber('+' + jid.replace('@s.whatsapp.net', '')).getNumber('international');
+      },
+      enumerable: true,
+    },
+    loadMessage: {
+      /**
+             *
+             * @param {String} messageID
+             * @returns {import('@whiskeysockets/baileys').proto.WebMessageInfo}
+             */
+      value(messageID) {
+        return Object.entries(conn.chats)
+            .filter(([_, {messages}]) => typeof messages === 'object')
+            .find(([_, {messages}]) => Object.entries(messages)
+                .find(([k, v]) => (k === messageID || v.key?.id === messageID)))
+            ?.[1].messages?.[messageID];
+      },
+      enumerable: true,
+    },
+    sendGroupV4Invite: {
+      /**
+             * sendGroupV4Invite
+             * @param {String} jid
+             * @param {*} participant
+             * @param {String} inviteCode
+             * @param {Number} inviteExpiration
+             * @param {String} groupName
+             * @param {String} caption
+             * @param {Buffer} jpegThumbnail
+             * @param {*} options
+             */
+      async value(jid, participant, inviteCode, inviteExpiration, groupName = 'unknown subject', caption = 'Invitation to join my WhatsApp group', jpegThumbnail, options = {}) {
+        const msg = proto.Message.fromObject({
+          groupInviteMessage: proto.GroupInviteMessage.fromObject({
+            inviteCode,
+            inviteExpiration: parseInt(inviteExpiration) || + new Date(new Date + (3 * 86400000)),
+            groupJid: jid,
+            groupName: (groupName ? groupName : await conn.getName(jid)) || null,
+            jpegThumbnail: Buffer.isBuffer(jpegThumbnail) ? jpegThumbnail : null,
+            caption,
+          }),
+        });
+        const message = generateWAMessageFromContent(participant, msg, options);
+        await conn.relayMessage(participant, message.message, {messageId: message.key.id, additionalAttributes: {...options}});
+        return message;
+      },
+      enumerable: true,
+    },
+    processMessageStubType: {
+      /**
+             * to process MessageStubType
+             * @param {import('@whiskeysockets/baileys').proto.WebMessageInfo} m
+             */
+      async value(m) {
+    if (!m.messageStubType) return;
+    const chat = conn.decodeJid(m.key.remoteJid || m.message?.senderKeyDistributionMessage?.groupId || '');
+    if (!chat || chat === 'status@broadcast') return;
+    
+    const emitGroupUpdate = (update) => {
+        conn.ev.emit('groups.update', [{ id: chat, ...update }]);
+    };
+
+    switch (m.messageStubType) {
+        case WAMessageStubType.REVOKE:
+        case WAMessageStubType.GROUP_CHANGE_INVITE_LINK:
+            if (Array.isArray(m.messageStubParameters) && m.messageStubParameters.length > 0) {
+                emitGroupUpdate({ revoke: m.messageStubParameters[0] });
+            }
+            break;
+        case WAMessageStubType.GROUP_CHANGE_ICON:
+            if (Array.isArray(m.messageStubParameters) && m.messageStubParameters.length > 0) {
+                emitGroupUpdate({ icon: m.messageStubParameters[0] });
+            }
+            break;
+        default: {
+            console.log({
+                messageStubType: m.messageStubType,
+                messageStubParameters: m.messageStubParameters || [],
+                type: WAMessageStubType[m.messageStubType]
+            });
+            break;
+        }
+    }
+
+    const isGroup = chat.endsWith('@g.us');
+    if (!isGroup) return;
+
+    let chats = conn.chats[chat];
+    if (!chats) chats = conn.chats[chat] = { id: chat };
+    chats.isChats = true;
+
+    const metadata = await conn.groupMetadata(chat).catch(() => null);
+    if (!metadata) return;
+
+    chats.subject = metadata.subject;
+    chats.metadata = metadata;
+}
+},
+    insertAllGroup: {
+      async value() {
+        const groups = await conn.groupFetchAllParticipating().catch((_) => null) || {};
+        for (const group in groups) conn.chats[group] = {...(conn.chats[group] || {}), id: group, subject: groups[group].subject, isChats: true, metadata: groups[group]};
+        return conn.chats;
+      },
+    },
+    pushMessage: {
+      /**
+             * pushMessage
+             * @param {import('@whiskeysockets/baileys').proto.WebMessageInfo[]} m
+             */
+      async value(m) {
+        if (!m) return;
+        if (!Array.isArray(m)) m = [m];
+        for (const message of m) {
+          try {
+            // if (!(message instanceof proto.WebMessageInfo)) continue // https://github.com/adiwajshing/Baileys/pull/696/commits/6a2cb5a4139d8eb0a75c4c4ea7ed52adc0aec20f
+            if (!message) continue;
+            if (message.messageStubType && message.messageStubType != WAMessageStubType.CIPHERTEXT) conn.processMessageStubType(message).catch(console.error);
+            const _mtype = Object.keys(message.message || {});
+            const mtype = (!['senderKeyDistributionMessage', 'messageContextInfo'].includes(_mtype[0]) && _mtype[0]) ||
+                            (_mtype.length >= 3 && _mtype[1] !== 'messageContextInfo' && _mtype[1]) ||
+                            _mtype[_mtype.length - 1];
+            const chat = conn.decodeJid(message.key.remoteJid || message.message?.senderKeyDistributionMessage?.groupId || '');
+            if (message.message?.[mtype]?.contextInfo?.quotedMessage) {
+              /**
+                             * @type {import('@whiskeysockets/baileys').proto.IContextInfo}
+                             */
+              const context = message.message[mtype].contextInfo;
+              let participant = conn.decodeJid(context.participant);
+              const remoteJid = conn.decodeJid(context.remoteJid || participant);
+              /**
+                             * @type {import('@whiskeysockets/baileys').proto.IMessage}
+                             *
+                             */
+              const quoted = message.message[mtype].contextInfo.quotedMessage;
+              if ((remoteJid && remoteJid !== 'status@broadcast') && quoted) {
+                let qMtype = Object.keys(quoted)[0];
+                if (qMtype == 'conversation') {
+                  quoted.extendedTextMessage = {text: quoted[qMtype]};
+                  delete quoted.conversation;
+                  qMtype = 'extendedTextMessage';
+                }
+                if (!quoted[qMtype].contextInfo) quoted[qMtype].contextInfo = {};
+                quoted[qMtype].contextInfo.mentionedJid = context.mentionedJid || quoted[qMtype].contextInfo.mentionedJid || [];
+                const isGroup = remoteJid.endsWith('g.us');
+                if (isGroup && !participant) participant = remoteJid;
+                const qM = {
+                  key: {
+                    remoteJid,
+                    fromMe: areJidsSameUser(conn.user.jid, remoteJid),
+                    id: context.stanzaId,
+                    participant,
+                  },
+                  message: JSON.parse(JSON.stringify(quoted)),
+                  ...(isGroup ? {participant} : {}),
+                };
+                let qChats = conn.chats[participant];
+                if (!qChats) qChats = conn.chats[participant] = {id: participant, isChats: !isGroup};
+                if (!qChats.messages) qChats.messages = {};
+                if (!qChats.messages[context.stanzaId] && !qM.key.fromMe) qChats.messages[context.stanzaId] = qM;
+                let qChatsMessages;
+                if ((qChatsMessages = Object.entries(qChats.messages)).length > 40) qChats.messages = Object.fromEntries(qChatsMessages.slice(30, qChatsMessages.length)); // maybe avoid memory leak
+              }
+            }
+            if (!chat || chat === 'status@broadcast') continue;
+            const isGroup = chat.endsWith('@g.us');
+            let chats = conn.chats[chat];
+            if (!chats) {
+              if (isGroup) await conn.insertAllGroup().catch(console.error);
+              chats = conn.chats[chat] = {id: chat, isChats: true, ...(conn.chats[chat] || {})};
+            }
+            let metadata; let sender;
+            if (isGroup) {
+              if (!chats.subject || !chats.metadata) {
+                metadata = await conn.groupMetadata(chat).catch((_) => ({})) || {};
+                if (!chats.subject) chats.subject = metadata.subject || '';
+                if (!chats.metadata) chats.metadata = metadata;
+              }
+              sender = conn.decodeJid(message.key?.fromMe && conn.user.id || message.participant || message.key?.participant || chat || '');
+              if (sender !== chat) {
+                let chats = conn.chats[sender];
+                if (!chats) chats = conn.chats[sender] = {id: sender};
+                if (!chats.name) chats.name = message.pushName || chats.name || '';
+              }
+            } else if (!chats.name) chats.name = message.pushName || chats.name || '';
+            if (['senderKeyDistributionMessage', 'messageContextInfo'].includes(mtype)) continue;
+            chats.isChats = true;
+            if (!chats.messages) chats.messages = {};
+            const fromMe = message.key.fromMe || areJidsSameUser(sender || chat, conn.user.id);
+            if (!['protocolMessage'].includes(mtype) && !fromMe && message.messageStubType != WAMessageStubType.CIPHERTEXT && message.message) {
+              delete message.message.messageContextInfo;
+              delete message.message.senderKeyDistributionMessage;
+              chats.messages[message.key.id] = JSON.parse(JSON.stringify(message, null, 2));
+              let chatsMessages;
+              if ((chatsMessages = Object.entries(chats.messages)).length > 40) chats.messages = Object.fromEntries(chatsMessages.slice(30, chatsMessages.length));
+            }
+          } catch (e) {
+            console.error(e);
+          }
+        }
+      },
+    },
+    serializeM: {
+      /**
+             * Serialize Message, so it easier to manipulate
+             * @param {import('@whiskeysockets/baileys').proto.WebMessageInfo} m
+             */
+      value(m) {
+        return smsg(conn, m);
+      },
+    },
+    ...(typeof conn.chatRead !== 'function' ? {
+      chatRead: {
+        /**
+                 * Read message
+                 * @param {String} jid
+                 * @param {String|undefined|null} participant
+                 * @param {String} messageID
+                 */
+        value(jid, participant = conn.user.jid, messageID) {
+          return conn.sendReadReceipt(jid, participant, [messageID]);
+        },
+        enumerable: true,
+      },
+    } : {}),
+    ...(typeof conn.setStatus !== 'function' ? {
+      setStatus: {
+        /**
+                 * setStatus bot
+                 * @param {String} status
+                 */
+        value(status) {
+          return conn.query({
+            tag: 'iq',
+            attrs: {
+              to: S_WHATSAPP_NET,
+              type: 'set',
+              xmlns: 'status',
+            },
+            content: [
+              {
+                tag: 'status',
+                attrs: {},
+                content: Buffer.from(status, 'utf-8'),
+              },
+            ],
+          });
+        },
+        enumerable: true,
+      },
+    } : {}),
+  });
+  if (sock.user?.id) sock.user.jid = sock.decodeJid(sock.user.id);
+  store.bind(sock);
+  return sock;
+}
+/**
+ * Serialize Message
+ * @param {ReturnType<typeof makeWASocket>} conn
+ * @param {import('@whiskeysockets/baileys').proto.WebMessageInfo} m
+ * @param {Boolean} hasParent
+ */
+export function smsg(conn, m, hasParent) {
+  if (!m) return m;
+  /**
+     * @type {import('@whiskeysockets/baileys').proto.WebMessageInfo}
+     */
+  const M = proto.WebMessageInfo;
+  m = M.fromObject(m);
+  m.conn = conn;
+  let protocolMessageKey;
+  if (m.message) {
+    if (m.mtype == 'protocolMessage' && m.msg.key) {
+      protocolMessageKey = m.msg.key;
+      if (protocolMessageKey == 'status@broadcast') protocolMessageKey.remoteJid = m.chat;
+      if (!protocolMessageKey.participant || protocolMessageKey.participant == 'status_me') protocolMessageKey.participant = m.sender;
+      protocolMessageKey.fromMe = conn.decodeJid(protocolMessageKey.participant) === conn.decodeJid(conn.user.id);
+      if (!protocolMessageKey.fromMe && protocolMessageKey.remoteJid === conn.decodeJid(conn.user.id)) protocolMessageKey.remoteJid = m.sender;
+    }
+    if (m.quoted) if (!m.quoted.mediaMessage) delete m.quoted.download;
+  }
+  if (!m.mediaMessage) delete m.download;
+
+  try {
+    if (protocolMessageKey && m.mtype == 'protocolMessage') conn.ev.emit('message.delete', protocolMessageKey);
+  } catch (e) {
+    console.error(e);
+  }
+  return m;
+}
+
+// https://github.com/Nurutomo/wabot-aq/issues/490
+export function serialize() {
+  const MediaType = ['imageMessage', 'videoMessage', 'audioMessage', 'stickerMessage', 'documentMessage'];
+  return Object.defineProperties(proto.WebMessageInfo.prototype, {
+    conn: {
+      value: undefined,
+      enumerable: false,
+      writable: true,
+    },
+    id: {
+      get() {
+        return this.key?.id;
+      },
+    },
+    isBaileys: {
+      get() {
+      return (this?.fromMe || areJidsSameUser(this.conn?.user.id, this.sender)) && this.id.startsWith('3EB0') && (this.id.length === 20 || this.id.length === 22 || this.id.length === 12) || false
+	},
+    }, 
+    chat: {
+      get() {
+        const senderKeyDistributionMessage = this.message?.senderKeyDistributionMessage?.groupId;
+        return (
+          this.key?.remoteJid ||
+                    (senderKeyDistributionMessage &&
+                        senderKeyDistributionMessage !== 'status@broadcast'
+                    ) || ''
+        ).decodeJid();
+      },
+    },
+    isGroup: {
+      get() {
+        return this.chat.endsWith('@g.us');
+      },
+      enumerable: true,
+    },
+           sender: {
+            get() {
+                return this.conn?.decodeJid(this.key?.fromMe && this.conn?.user.id || this.participant || this.key.participant || this.chat || '')
+            },
+            enumerable: true
+        },
+        fromMe: {
+            get() {
+                return this.key?.fromMe || areJidsSameUser(this.conn?.user.id, this.sender) || false
+            }
+    },
+    mtype: {
+      get() {
+        if (!this.message) return '';
+        const type = Object.keys(this.message);
+        return (!['senderKeyDistributionMessage', 'messageContextInfo'].includes(type[0]) && type[0]) || // Sometimes message in the front
+                    (type.length >= 3 && type[1] !== 'messageContextInfo' && type[1]) || // Sometimes message in midle if mtype length is greater than or equal to 3
+                    type[type.length - 1]; // common case
+      },
+      enumerable: true,
+    },
+    msg: {
+      get() {
+        if (!this.message) return null;
+        return this.message[this.mtype];
+      },
+    },
+    mediaMessage: {
+      get() {
+        if (!this.message) return null;
+        const Message = ((this.msg?.url || this.msg?.directPath) ? {...this.message} : extractMessageContent(this.message)) || null;
+        if (!Message) return null;
+        const mtype = Object.keys(Message)[0];
+        return MediaType.includes(mtype) ? Message : null;
+      },
+      enumerable: true,
+    },
+    mediaType: {
+      get() {
+        let message;
+        if (!(message = this.mediaMessage)) return null;
+        return Object.keys(message)[0];
+      },
+      enumerable: true,
+    },
+    quoted: {
+      get() {
+        /**
+                 * @type {ReturnType<typeof makeWASocket>}
+                 */
+        const self = this;
+        const msg = self.msg;
+        const contextInfo = msg?.contextInfo;
+        const quoted = contextInfo?.quotedMessage;
+        if (!msg || !contextInfo || !quoted) return null;
+        const type = Object.keys(quoted)[0];
+        const q = quoted[type];
+        const text = typeof q === 'string' ? q : q.text;
+        return Object.defineProperties(JSON.parse(JSON.stringify(typeof q === 'string' ? {text: q} : q)), {
+          mtype: {
+            get() {
+              return type;
+            },
+            enumerable: true,
+          },
+          mediaMessage: {
+            get() {
+              const Message = ((q.url || q.directPath) ? {...quoted} : extractMessageContent(quoted)) || null;
+              if (!Message) return null;
+              const mtype = Object.keys(Message)[0];
+              return MediaType.includes(mtype) ? Message : null;
+            },
+            enumerable: true,
+          },
+          mediaType: {
+            get() {
+              let message;
+              if (!(message = this.mediaMessage)) return null;
+              return Object.keys(message)[0];
+            },
+            enumerable: true,
+          },
+          id: {
+            get() {
+              return contextInfo.stanzaId;
+            },
+            enumerable: true,
+          },
+          chat: {
+            get() {
+              return contextInfo.remoteJid || self.chat;
+            },
+            enumerable: true,
+          },
+          isBaileys: {
+            get() {
+            return (this?.fromMe || areJidsSameUser(this.conn?.user.id, this.sender)) && this.id.startsWith('3EB0') && (this.id.length === 20 || this.id.length === 22 || this.id.length === 12) || false
+                       },
+            enumerable: true,
+          },
+          sender: {
+            get() {
+              return (contextInfo.participant || this.chat || '').decodeJid();
+            },
+            enumerable: true,
+          },
+          fromMe: {
+            get() {
+              return areJidsSameUser(this.sender, self.conn?.user.jid);
+            },
+            enumerable: true,
+          },
+          text: {
+            get() {
+              return text || this.caption || this.contentText || this.selectedDisplayText || '';
+            },
+            enumerable: true,
+          },
+          mentionedJid: {
+            get() {
+              return q.contextInfo?.mentionedJid || self.getQuotedObj()?.mentionedJid || [];
+            },
+            enumerable: true,
+          },
+          name: {
+            get() {
+              const sender = this.sender;
+              return sender ? self.conn?.getName(sender) : null;
+            },
+            enumerable: true,
+
+          },
+          vM: {
+            get() {
+              return proto.WebMessageInfo.fromObject({
+                key: {
+                  fromMe: this.fromMe,
+                  remoteJid: this.chat,
+                  id: this.id,
+                },
+                message: quoted,
+                ...(self.isGroup ? {participant: this.sender} : {}),
+              });
+            },
+          },
+          fakeObj: {
+            get() {
+              return this.vM;
+            },
+          },
+          download: {
+            value(saveToFile = false) {
+              const mtype = this.mediaType;
+              return self.conn?.downloadM(this.mediaMessage[mtype], mtype.replace(/message/i, ''), saveToFile);
+            },
+            enumerable: true,
+            configurable: true,
+          },
+          reply: {
+            /**
+                         * Reply to quoted message
+                         * @param {String|Object} text
+                         * @param {String|false} chatId
+                         * @param {Object} options
+                         */
+            value(text, chatId, options) {
+              return self.conn?.reply(chatId ? chatId : this.chat, text, this.vM, options);
+            },
+            enumerable: true,
+          },
+          copy: {
+            /**
+                         * Copy quoted message
+                         */
+            value() {
+              const M = proto.WebMessageInfo;
+              return smsg(conn, M.fromObject(M.toObject(this.vM)));
+            },
+            enumerable: true,
+          },
+          forward: {
+            /**
+                         * Forward quoted message
+                         * @param {String} jid
+                         *  @param {Boolean} forceForward
+                         */
+            value(jid, force = false, options) {
+              return self.conn?.sendMessage(jid, {
+                forward: this.vM, force, ...options,
+              }, {...options});
+            },
+            enumerable: true,
+          },
+          copyNForward: {
+            /**
+                         * Exact Forward quoted message
+                         * @param {String} jid
+                         * @param {Boolean|Number} forceForward
+                         * @param {Object} options
+                         */
+            value(jid, forceForward = false, options) {
+              return self.conn?.copyNForward(jid, this.vM, forceForward, options);
+            },
+            enumerable: true,
+
+          },
+          cMod: {
+                        /**
+                         * Modify quoted Message
+                         * @param {String} jid
+                         * @param {String} text
+                         * @param {String} sender
+                         * @param {Object} options
+                         */
+                        value(jid, text = '', sender = this.sender, options = {}) {
+                            return self.conn?.cMod(jid, this.vM, text, sender, options)
+                        },
+                        enumerable: true,
+                        
+                    },
+                    delete: {
+                        /**
+                         * Delete quoted message
+                         */
+                        value() {
+                            return self.conn?.sendMessage(this.chat, { delete: this.vM.key })
+                        },
+                        enumerable: true,
+                        
+                    }, 
+                    //react
+                      react: {
+                        value(text) {
+                            return self.conn?.sendMessage(this.chat, {
+                                react: {
+                                    text,
+                                    key: this.vM.key
+                                }
+                            })
+                        },
+                        enumerable: true,
+                    }
+                    //
+                })
+            },
+            enumerable: true
+        },
+        _text: {
+            value: null,
+            writable: true,
+        },
+        text: {
+            get() {
+                const msg = this.msg
+                const text = (typeof msg === 'string' ? msg : msg?.text) || msg?.caption || msg?.contentText || ''
+                return typeof this._text === 'string' ? this._text : '' || (typeof text === 'string' ? text : (
+                    text?.selectedDisplayText ||
+                    text?.hydratedTemplate?.hydratedContentText ||
+                    text
+                )) || ''
+            },
+            set(str) {
+                return this._text = str
+            },
+            enumerable: true
+        },
+        mentionedJid: {
+            get() {
+                return this.msg?.contextInfo?.mentionedJid?.length && this.msg.contextInfo.mentionedJid || []
+            },
+            enumerable: true
+        },
+        name: {
+            get() {
+                return !nullish(this.pushName) && this.pushName || this.conn?.getName(this.sender)
+            },
+            enumerable: true
+        },
+        download: {
+            value(saveToFile = false) {
+                const mtype = this.mediaType
+                return this.conn?.downloadM(this.mediaMessage[mtype], mtype.replace(/message/i, ''), saveToFile)
+            },
+            enumerable: true,
+            configurable: true
+        },
+        reply: {
+            value(text, chatId, options) {
+                return this.conn?.reply(chatId ? chatId : this.chat, text, this, options)
+            }
+        },
+        copy: {
+            value() {
+                const M = proto.WebMessageInfo
+                return smsg(this.conn, M.fromObject(M.toObject(this)))
+            },
+            enumerable: true
+        },
+        forward: {
+            value(jid, force = false, options = {}) {
+                return this.conn?.sendMessage(jid, {
+                    forward: this, force, ...options
+                }, { ...options })
+            },
+            enumerable: true
+        },
+        copyNForward: {
+            value(jid, forceForward = false, options = {}) {
+                return this.conn?.copyNForward(jid, this, forceForward, options)
+            },
+            enumerable: true
+        },
+        cMod: {
+            value(jid, text = '', sender = this.sender, options = {}) {
+                return this.conn?.cMod(jid, this, text, sender, options)
+            },
+            enumerable: true
+        },
+        getQuotedObj: {
+            value() {
+                if (!this.quoted.id) return null
+                const q = proto.WebMessageInfo.fromObject(this.conn?.loadMessage(this.quoted.id) || this.quoted.vM)
+                return smsg(this.conn, q)
+            },
+            enumerable: true
+        },
+        getQuotedMessage: {
+            get() {
+                return this.getQuotedObj
+            }
+        },
+        delete: {
+            value() {
+                return this.conn?.sendMessage(this.chat, { delete: this.key })
+            },
+            enumerable: true
+        }, 
+        //react 
+          react: {
+            value(text) {
+                return this.conn?.sendMessage(this.chat, {
+                    react: {
+                        text,
+                        key: this.key
+                    }
+                })
+            },
+            enumerable: true
+        }
+        //
+    })
+}
+
+export function logic(check, inp, out) {
+  if (inp.length !== out.length) throw new Error('Input and Output must have same length');
+  for (const i in inp) if (util.isDeepStrictEqual(check, inp[i])) return out[i];
+  return null;
+}
+
+export function protoType() {
+  Buffer.prototype.toArrayBuffer = function toArrayBufferV2() {
+    const ab = new ArrayBuffer(this.length);
+    const view = new Uint8Array(ab);
+    for (let i = 0; i < this.length; ++i) {
+      view[i] = this[i];
+    }
+    return ab;
+  };
+  /**
+     * @return {ArrayBuffer}
+     */
+  Buffer.prototype.toArrayBufferV2 = function toArrayBuffer() {
+    return this.buffer.slice(this.byteOffset, this.byteOffset + this.byteLength);
+  };
+  /**
+     * @return {Buffer}
+     */
+  ArrayBuffer.prototype.toBuffer = function toBuffer() {
+    return Buffer.from(new Uint8Array(this));
+  };
+  // /**
+  //  * @returns {String}
+  //  */
+  // Buffer.prototype.toUtilFormat = ArrayBuffer.prototype.toUtilFormat = Object.prototype.toUtilFormat = Array.prototype.toUtilFormat = function toUtilFormat() {
+  //     return util.format(this)
+  // }
+  Uint8Array.prototype.getFileType = ArrayBuffer.prototype.getFileType = Buffer.prototype.getFileType = async function getFileType() {
+    return await fileTypeFromBuffer(this);
+  };
+  /**
+     * @returns {Boolean}
+     */
+  String.prototype.isNumber = Number.prototype.isNumber = isNumber;
+  /**
+     *
+     * @return {String}
+     */
+  String.prototype.capitalize = function capitalize() {
+    return this.charAt(0).toUpperCase() + this.slice(1, this.length);
+  };
+  /**
+     * @return {String}
+     */
+  String.prototype.capitalizeV2 = function capitalizeV2() {
+    const str = this.split(' ');
+    return str.map((v) => v.capitalize()).join(' ');
+  };
+  String.prototype.decodeJid = function decodeJid() {
+    if (/:\d+@/gi.test(this)) {
+      const decode = jidDecode(this) || {};
+      return (decode.user && decode.server && decode.user + '@' + decode.server || this).trim();
+    } else return this.trim();
+  };
+  /**
+     * number must be milliseconds
+     * @return {string}
+     */
+  Number.prototype.toTimeString = function toTimeString() {
+    // const milliseconds = this % 1000
+    const seconds = Math.floor((this / 1000) % 60);
+    const minutes = Math.floor((this / (60 * 1000)) % 60);
+    const hours = Math.floor((this / (60 * 60 * 1000)) % 24);
+    const days = Math.floor((this / (24 * 60 * 60 * 1000)));
+    return (
+      (days ? `${days} day(s) ` : '') +
+            (hours ? `${hours} hour(s) ` : '') +
+            (minutes ? `${minutes} minute(s) ` : '') +
+            (seconds ? `${seconds} second(s)` : '')
+    ).trim();
+  };
+  Number.prototype.getRandom = String.prototype.getRandom = Array.prototype.getRandom = getRandom;
+}
+
+
+function isNumber() {
+  const int = parseInt(this);
+  return typeof int === 'number' && !isNaN(int);
+}
+
+function getRandom() {
+  if (Array.isArray(this) || this instanceof String) return this[Math.floor(Math.random() * this.length)];
+  return Math.floor(Math.random() * this);
+}
+
+
+/**
+ * ??
+ * @link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Nullish_coalescing_operator
+ * @return {boolean}
+ */
+function nullish(args) {
+  return !(args !== null && args !== undefined);
+}

+ 218 - 0
lib/sticker.js

@@ -0,0 +1,218 @@
+import { dirname } from 'path'
+import { fileURLToPath } from 'url'
+import * as fs from 'fs'
+import * as path from 'path'
+import * as  crypto from 'crypto'
+import { ffmpeg } from './converter.js'
+import fluent_ffmpeg from 'fluent-ffmpeg'
+import { spawn } from 'child_process'
+import uploadFile from './uploadFile.js'
+import uploadImage from './uploadImage.js'
+import { fileTypeFromBuffer } from 'file-type'
+import webp from 'node-webpmux'
+import fetch from 'node-fetch'
+
+const __dirname = dirname(fileURLToPath(import.meta.url))
+const tmp = path.join(__dirname, '../tmp')
+/**
+ * Image to Sticker
+ * @param {Buffer} img Image Buffer
+ * @param {String} url Image URL
+ */
+function sticker2(img, url) {
+  return new Promise(async (resolve, reject) => {
+    try {
+      if (url) {
+        const res = await fetch(url)
+        if (res.status !== 200) throw await res.text()
+        img = await res.buffer()
+      }
+      const inp = path.join(tmp, +new Date + '.jpeg')
+      await fs.promises.writeFile(inp, img)
+      const ff = spawn('ffmpeg', [
+        '-y',
+        '-i', inp,
+        '-vf', 'scale=512:512:flags=lanczos:force_original_aspect_ratio=decrease,format=rgba,pad=512:512:(ow-iw)/2:(oh-ih)/2:color=#00000000,setsar=1',
+        '-f', 'png',
+        '-'
+      ])
+      ff.on('error', reject)
+      ff.on('close', async () => {
+        await fs.promises.unlink(inp)
+      })
+      const bufs = []
+      const [_spawnprocess, ..._spawnargs] = [...(module.exports.support.gm ? ['gm'] : module.exports.magick ? ['magick'] : []), 'convert', 'png:-', 'webp:-']
+      const im = spawn(_spawnprocess, _spawnargs)
+      im.on('error', e => conn.reply(m.chat, util.format(e), m))
+      im.stdout.on('data', chunk => bufs.push(chunk))
+      ff.stdout.pipe(im.stdin)
+      im.on('exit', () => {
+        resolve(Buffer.concat(bufs))
+      })
+    } catch (e) {
+      reject(e)
+    }
+  })
+}
+
+/**
+ * Image/Video to Sticker
+ * @param {Buffer} img Image/Video Buffer
+ * @param {String} url Image/Video URL
+ * @param {String} packname EXIF Packname
+ * @param {String} author EXIF Author
+ */
+async function sticker3(img, url, packname, author) {
+  url = url ? url : await uploadFile(img)
+  const res = await fetch('https://api.xteam.xyz/sticker/wm?' + new URLSearchParams(Object.entries({
+    url,
+    packname,
+    author
+  })))
+  return await res.buffer()
+}
+
+/**
+ * Image to Sticker
+ * @param {Buffer} img Image/Video Buffer
+ * @param {String} url Image/Video URL
+ */
+async function sticker4(img, url) {
+  if (url) {
+    const res = await fetch(url)
+    if (res.status !== 200) throw await res.text()
+    img = await res.buffer()
+  }
+  return await ffmpeg(img, [
+    '-vf', 'scale=512:512:flags=lanczos:force_original_aspect_ratio=decrease,format=rgba,pad=512:512:(ow-iw)/2:(oh-ih)/2:color=#00000000,setsar=1'
+  ], 'jpeg', 'webp')
+}
+
+async function sticker5(img, url, packname, author, categories = [''], extra = {}) {
+  const { Sticker } = await import('wa-sticker-formatter')
+  const stickerMetadata = {
+    type: 'default',
+    pack: packname,
+    author,
+    categories,
+    ...extra
+  }
+  return (new Sticker(img ? img : url, stickerMetadata)).toBuffer()
+}
+
+/**
+ * Convert using fluent-ffmpeg
+ * @param {string} img 
+ * @param {string} url 
+ */
+function sticker6(img, url) {
+  return new Promise(async (resolve, reject) => {
+    if (url) {
+      const res = await fetch(url)
+      if (res.status !== 200) throw await res.text()
+      img = await res.buffer()
+    }
+    const type = await fileTypeFromBuffer(img) || {
+      mime: 'application/octet-stream',
+      ext: 'bin'
+    }
+    if (type.ext == 'bin') reject(img)
+    const tmp = path.join(__dirname, `../tmp/${+ new Date()}.${type.ext}`)
+    const out = path.join(tmp + '.webp')
+    await fs.promises.writeFile(tmp, img)
+    // https://github.com/MhankBarBar/termux-wabot/blob/main/index.js#L313#L368
+    const Fffmpeg = /video/i.test(type.mime) ? fluent_ffmpeg(tmp).inputFormat(type.ext) : fluent_ffmpeg(tmp).input(tmp)
+    Fffmpeg
+      .on('error', function (err) {
+        console.error(err)
+        fs.promises.unlink(tmp)
+        reject(img)
+      })
+      .on('end', async function () {
+        fs.promises.unlink(tmp)
+        resolve(await fs.promises.readFile(out))
+      })
+      .addOutputOptions([
+        `-vcodec`, `libwebp`, `-vf`,
+        `scale='min(320,iw)':min'(320,ih)':force_original_aspect_ratio=decrease,fps=15, pad=320:320:-1:-1:color=white@0.0, split [a][b]; [a] palettegen=reserve_transparent=on:transparency_color=ffffff [p]; [b][p] paletteuse`
+      ])
+      .toFormat('webp')
+      .save(out)
+  })
+}
+/**
+ * Add WhatsApp JSON Exif Metadata
+ * Taken from https://github.com/pedroslopez/whatsapp-web.js/pull/527/files
+ * @param {Buffer} webpSticker 
+ * @param {String} packname 
+ * @param {String} author 
+ * @param {String} categories 
+ * @param {Object} extra 
+ * @returns 
+ */
+async function addExif(webpSticker, packname, author, categories = [''], extra = {}) {
+  const img = new webp.Image();
+  const stickerPackId = crypto.randomBytes(32).toString('hex');
+  const json = { 'sticker-pack-id': stickerPackId, 'sticker-pack-name': packname, 'sticker-pack-publisher': author, 'emojis': categories, ...extra };
+  const exifAttr = Buffer.from([0x49, 0x49, 0x2A, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x41, 0x57, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00]);
+  const jsonBuffer = Buffer.from(JSON.stringify(json), 'utf8');
+  const exif = Buffer.concat([exifAttr, jsonBuffer]);
+  exif.writeUIntLE(jsonBuffer.length, 14, 4);
+  await img.load(webpSticker)
+  img.exif = exif
+  return await img.save(null)
+}
+
+/**
+ * Image/Video to Sticker
+ * @param {Buffer} img Image/Video Buffer
+ * @param {String} url Image/Video URL
+ * @param {...String} 
+*/
+async function sticker(img, url, ...args) {
+  let lastError, stiker
+  for (const func of [
+    sticker3, global.support.ffmpeg && sticker6, sticker5,
+    global.support.ffmpeg && global.support.ffmpegWebp && sticker4,
+    global.support.ffmpeg && (global.support.convert || global.support.magick || global.support.gm) && sticker2,
+  ].filter(f => f)) {
+    try {
+      stiker = await func(img, url, ...args)
+      if (stiker.includes('html')) continue
+      if (stiker.includes('WEBP')) {
+        try {
+          return await addExif(stiker, ...args)
+        } catch (e) {
+          console.error(e)
+          return stiker
+        }
+      }
+      throw stiker.toString()
+    } catch (err) {
+      lastError = err
+      continue
+    }
+  }
+  console.error(lastError)
+  return lastError
+}
+
+const support = {
+  ffmpeg: true,
+  ffprobe: true,
+  ffmpegWebp: true,
+  convert: true,
+  magick: false,
+  gm: false,
+  find: false
+}
+
+export {
+  sticker,
+  sticker2,
+  sticker3,
+  sticker4,
+  sticker6,
+  addExif,
+  support
+}

+ 228 - 0
lib/store.js

@@ -0,0 +1,228 @@
+import {readFileSync, writeFileSync, existsSync} from 'fs';
+
+/**
+ * @type {import('@whiskeysockets/baileys')}
+ */
+const {initAuthCreds, BufferJSON, proto} = (await import('@whiskeysockets/baileys')).default;
+
+/**
+ * @param {import('@whiskeysockets/baileys').WASocket | import('@whiskeysockets/baileys').WALegacySocket}
+ */
+function bind(conn) {
+  if (!conn.chats) conn.chats = {};
+  /**
+     *
+     * @param {import('@whiskeysockets/baileys').Contact[]|{contacts:import('@whiskeysockets/baileys').Contact[]}} contacts
+     * @returns
+     */
+  function updateNameToDb(contacts) {
+    if (!contacts) return;
+    try {
+      contacts = contacts.contacts || contacts;
+      for (const contact of contacts) {
+        const id = conn.decodeJid(contact.id);
+        if (!id || id === 'status@broadcast') continue;
+        let chats = conn.chats[id];
+        if (!chats) chats = conn.chats[id] = {...contact, id};
+        conn.chats[id] = {
+          ...chats,
+          ...({
+            ...contact, id, ...(id.endsWith('@g.us') ?
+                            {subject: contact.subject || contact.name || chats.subject || ''} :
+                            {name: contact.notify || contact.name || chats.name || chats.notify || ''}),
+          } || {}),
+        };
+      }
+    } catch (e) {
+    //  console.error(e);
+    }
+  }
+  conn.ev.on('contacts.upsert', updateNameToDb);
+  conn.ev.on('groups.update', updateNameToDb);
+  conn.ev.on('contacts.set', updateNameToDb);
+  conn.ev.on('chats.set', async ({chats}) => {
+    try {
+      for (let {id, name, readOnly} of chats) {
+        id = conn.decodeJid(id);
+        if (!id || id === 'status@broadcast') continue;
+        const isGroup = id.endsWith('@g.us');
+        let chats = conn.chats[id];
+        if (!chats) chats = conn.chats[id] = {id};
+        chats.isChats = !readOnly;
+        if (name) chats[isGroup ? 'subject' : 'name'] = name;
+        if (isGroup) {
+          const metadata = await conn.groupMetadata(id).catch((_) => null);
+          if (name || metadata?.subject) chats.subject = name || metadata.subject;
+          if (!metadata) continue;
+          chats.metadata = metadata;
+        }
+      }
+    } catch (e) {
+     // console.error(e);
+    }
+  });
+  conn.ev.on('group-participants.update', async function updateParticipantsToDb({id, participants, action}) {
+    if (!id) return;
+    id = conn.decodeJid(id);
+    if (id === 'status@broadcast') return;
+    if (!(id in conn.chats)) conn.chats[id] = {id};
+    const chats = conn.chats[id];
+    chats.isChats = true;
+    const groupMetadata = await conn.groupMetadata(id).catch((_) => null);
+    if (!groupMetadata) return;
+    chats.subject = groupMetadata.subject;
+    chats.metadata = groupMetadata;
+  });
+
+  conn.ev.on('groups.update', async function groupUpdatePushToDb(groupsUpdates) {
+    try {
+      for (const update of groupsUpdates) {
+        const id = conn.decodeJid(update.id);
+        if (!id || id === 'status@broadcast') continue;
+        const isGroup = id.endsWith('@g.us');
+        if (!isGroup) continue;
+        let chats = conn.chats[id];
+        if (!chats) chats = conn.chats[id] = {id};
+        chats.isChats = true;
+        const metadata = await conn.groupMetadata(id).catch((_) => null);
+        if (metadata) chats.metadata = metadata;
+        if (update.subject || metadata?.subject) chats.subject = update.subject || metadata.subject;
+      }
+    } catch (e) {
+     // console.error(e);
+    }
+  });
+  conn.ev.on('chats.upsert', function chatsUpsertPushToDb(chatsUpsert) {
+    try {
+      const {id, name} = chatsUpsert;
+      if (!id || id === 'status@broadcast') return;
+      conn.chats[id] = {...(conn.chats[id] || {}), ...chatsUpsert, isChats: true};
+      const isGroup = id.endsWith('@g.us');
+      if (isGroup) conn.insertAllGroup().catch((_) => null);
+    } catch (e) {
+    //  console.error(e);
+    }
+  });
+  conn.ev.on('presence.update', async function presenceUpdatePushToDb({id, presences}) {
+    try {
+      const sender = Object.keys(presences)[0] || id;
+      const _sender = conn.decodeJid(sender);
+      const presence = presences[sender]['lastKnownPresence'] || 'composing';
+      let chats = conn.chats[_sender];
+      if (!chats) chats = conn.chats[_sender] = {id: sender};
+      chats.presences = presence;
+      if (id.endsWith('@g.us')) {
+        let chats = conn.chats[id];
+        if (!chats) chats = conn.chats[id] = {id};
+      }
+    } catch (e) {
+     // console.error(e);
+    }
+  });
+}
+
+const KEY_MAP = {
+  'pre-key': 'preKeys',
+  'session': 'sessions',
+  'sender-key': 'senderKeys',
+  'app-state-sync-key': 'appStateSyncKeys',
+  'app-state-sync-version': 'appStateVersions',
+  'sender-key-memory': 'senderKeyMemory',
+};
+
+/**
+ *
+ * @param {String} filename
+ * @param {import('pino').Logger} logger
+ * @returns
+ */
+function useSingleFileAuthState(filename, logger) {
+  let creds; let keys = {}; let saveCount = 0;
+  // save the authentication state to a file
+  const saveState = (forceSave) => {
+    logger?.trace('saving auth state');
+    saveCount++;
+    if (forceSave || saveCount > 5) {
+      writeFileSync(
+          filename,
+          // BufferJSON replacer utility saves buffers nicely
+          JSON.stringify({creds, keys}, BufferJSON.replacer, 2),
+      );
+      saveCount = 0;
+    }
+  };
+
+  if (existsSync(filename)) {
+    const result = JSON.parse(
+        readFileSync(filename, {encoding: 'utf-8'}),
+        BufferJSON.reviver,
+    );
+    creds = result.creds;
+    keys = result.keys;
+  } else {
+    creds = initAuthCreds();
+    keys = {};
+  }
+
+  return {
+    state: {
+      creds,
+      keys: {
+        get: (type, ids) => {
+          const key = KEY_MAP[type];
+          return ids.reduce(
+              (dict, id) => {
+                let value = keys[key]?.[id];
+                if (value) {
+                  if (type === 'app-state-sync-key') {
+                    value = proto.AppStateSyncKeyData.fromObject(value);
+                  }
+
+                  dict[id] = value;
+                }
+
+                return dict;
+              }, {},
+          );
+        },
+        set: (data) => {
+          for (const _key in data) {
+            const key = KEY_MAP[_key];
+            keys[key] = keys[key] || {};
+            Object.assign(keys[key], data[_key]);
+          }
+
+          saveState();
+        },
+      },
+    },
+    saveState,
+  };
+}
+function loadMessage(jid, id = null) {
+  let message = null;
+  // If only 1 param, first param is assumed to be id not jid
+  if (jid && !id) {
+    id = jid;
+    /** @type {(m: import('@whiskeysockets/baileys').proto.WebMessageInfo) => Boolean} */
+    const filter = (m) => m.key?.id == id;
+    const messages = {};
+    const messageFind = Object.entries(messages)
+        .find(([, msgs]) => {
+          return msgs.find(filter);
+        });
+    message = messageFind?.[1]?.find(filter);
+  } else {
+    // @ts-ignore
+    jid = jid?.decodeJid?.();
+    const messages = {};
+    if (!(jid in messages)) return null;
+    message = messages[jid].find((m) => m.key.id == id);
+  }
+  return message ? message : null;
+}
+export default {
+  bind,
+  useSingleFileAuthState,
+  loadMessage,
+};

+ 15 - 0
lib/tictactoe.d.ts

@@ -0,0 +1,15 @@
+export declare class TicTacToe {
+    /* X PlayerName */
+    playerX: string;
+    /* Y PlayerName */
+    playerY: string;
+    /* X if true, Y if false */
+    _currentTurn: boolean;
+    _x: number;
+    _y: number;
+    _turns: number;
+    constructor(playerX: string, playerY: string);
+    get board(): number;
+    turn(player, index: number): boolean;
+    turn(player, x: number, y: number): boolean;
+}

+ 95 - 0
lib/tictactoe.js

@@ -0,0 +1,95 @@
+class TicTacToe {
+  constructor(playerX = 'x', playerO = 'o') {
+    this.playerX = playerX;
+    this.playerO = playerO;
+    this._currentTurn = false;
+    this._x = 0;
+    this._o = 0;
+    this.turns = 0;
+  }
+
+  get board() {
+    return this._x | this._o;
+  }
+
+  get currentTurn() {
+    return this._currentTurn ? this.playerO : this.playerX;
+  }
+
+  get enemyTurn() {
+    return this._currentTurn ? this.playerX : this.playerO;
+  }
+
+  static check(state) {
+    for (const combo of [7, 56, 73, 84, 146, 273, 292, 448]) {
+      if ((state & combo) === combo) {
+        return !0;
+      }
+    }
+    return !1;
+  }
+
+  /**
+     * ```js
+     * TicTacToe.toBinary(1, 2) // 0b010000000
+     * ```
+     */
+  static toBinary(x = 0, y = 0) {
+    if (x < 0 || x > 2 || y < 0 || y > 2) throw new Error('invalid position');
+    return 1 << x + (3 * y);
+  }
+
+  /**
+     * @param player `0` is `X`, `1` is `O`
+     *
+     * - `-3` `Game Ended`
+     * - `-2` `Invalid`
+     * - `-1` `Invalid Position`
+     * - ` 0` `Position Occupied`
+     * - ` 1` `Sucess`
+     * @return {-3|-2|-1|0|1}
+     */
+  turn(player = 0, x = 0, y) {
+    if (this.board === 511) return -3;
+    let pos = 0;
+    if (y == null) {
+      if (x < 0 || x > 8) return -1;
+      pos = 1 << x;
+    } else {
+      if (x < 0 || x > 2 || y < 0 || y > 2) return -1;
+      pos = TicTacToe.toBinary(x, y);
+    }
+    if (this._currentTurn ^ player) return -2;
+    if (this.board & pos) return 0;
+    this[this._currentTurn ? '_o' : '_x'] |= pos;
+    this._currentTurn = !this._currentTurn;
+    this.turns++;
+    return 1;
+  }
+
+  /**
+     * @return {('X'|'O'|1|2|3|4|5|6|7|8|9)[]}
+     */
+  static render(boardX = 0, boardO = 0) {
+    const x = parseInt(boardX.toString(2), 4);
+    const y = parseInt(boardO.toString(2), 4) * 2;
+    return [...(x + y).toString(4).padStart(9, '0')].reverse().map((value, index) => value == 1 ? 'X' : value == 2 ? 'O' : ++index);
+  }
+
+  /**
+     * @return {('X'|'O'|1|2|3|4|5|6|7|8|9)[]}
+     */
+  render() {
+    return TicTacToe.render(this._x, this._o);
+  }
+
+  get winner() {
+    const x = TicTacToe.check(this._x);
+    const o = TicTacToe.check(this._o);
+    return x ? this.playerX : o ? this.playerO : false;
+  }
+}
+
+new TicTacToe().turn;
+
+export default TicTacToe;

+ 58 - 0
lib/tiktok.js

@@ -0,0 +1,58 @@
+import axios from 'axios';
+import cheerio from 'cheerio';
+
+const clean = (data) => {
+  let regex = /(<([^>]+)>)/gi;
+  data = data.replace(/(<br?\s?\/>)/gi, " \n");
+  return data.replace(regex, "");
+};
+
+async function shortener(url) {
+  return url;
+}
+
+export const Tiktok = async (query) => {
+  let response = await axios("https://lovetik.com/api/ajax/search", {
+    method: "POST",
+    data: new URLSearchParams(Object.entries({ query })),
+  });
+
+  const result = {}; 
+
+  result.creator = "YNTKTS";
+  result.title = clean(response.data.desc);
+  result.author = clean(response.data.author);
+  result.nowm = await shortener(
+    (response.data.links[0].a || "").replace("https", "http")
+  );
+  result.watermark = await shortener(
+    (response.data.links[1].a || "").replace("https", "http")
+  );
+  result.audio = await shortener(
+    (response.data.links[2].a || "").replace("https", "http")
+  );
+  result.thumbnail = await shortener(response.data.cover);
+  return result;
+}
+
+async function ttimg(link) {
+  try {
+    let url = `https://dlpanda.com/es?url=${link}&token=G7eRpMaa`;
+    let response = await axios.get(url);
+    const html = response.data;
+    const $ = cheerio.load(html);
+    let imgSrc = [];
+    $('div.col-md-12 > img').each((index, element) => {
+      imgSrc.push($(element).attr('src'));
+    });
+    if (imgSrc.length === 0) {
+      return { data: '*[❗] No se encontraron imágenes en el enlace proporcionado.*' };
+    }
+    return { data: imgSrc };
+  } catch (error) {
+    console.log(error); 
+    return { data: '*[❗] No se obtuvo respuesta de la página, intente más tarde.*' };
+  }
+}
+
+export { ttimg };

+ 66 - 0
lib/uploadFile.js

@@ -0,0 +1,66 @@
+import fetch from 'node-fetch';
+import {FormData, Blob} from 'formdata-node';
+import {fileTypeFromBuffer} from 'file-type';
+/**
+ * Upload epheremal file to file.io
+ * `Expired in 1 day`
+ * `100MB Max Filesize`
+ * @param {Buffer} buffer File Buffer
+ */
+const fileIO = async (buffer) => {
+  const {ext, mime} = await fileTypeFromBuffer(buffer) || {};
+  const form = new FormData();
+  const blob = new Blob([buffer.toArrayBuffer()], {type: mime});
+  form.append('file', blob, 'tmp.' + ext);
+  const res = await fetch('https://file.io/?expires=1d', { // 1 Day Expiry Date
+    method: 'POST',
+    body: form,
+  });
+  const json = await res.json();
+  if (!json.success) throw json;
+  return json.link;
+};
+
+/**
+ * Upload file to storage.restfulapi.my.id
+ * @param {Buffer|ReadableStream|(Buffer|ReadableStream)[]} inp File Buffer/Stream or Array of them
+ * @return {string|null|(string|null)[]}
+ */
+const RESTfulAPI = async (inp) => {
+  const form = new FormData();
+  let buffers = inp;
+  if (!Array.isArray(inp)) buffers = [inp];
+  for (const buffer of buffers) {
+    const blob = new Blob([buffer.toArrayBuffer()]);
+    form.append('file', blob);
+  }
+  const res = await fetch('https://storage.restfulapi.my.id/upload', {
+    method: 'POST',
+    body: form,
+  });
+  let json = await res.text();
+  try {
+    json = JSON.parse(json);
+    if (!Array.isArray(inp)) return json.files[0].url;
+    return json.files.map((res) => res.url);
+  } catch (e) {
+    throw json;
+  }
+};
+
+/**
+ *
+ * @param {Buffer} inp
+ * @return {Promise<string>}
+ */
+export default async function(inp) {
+  let err = false;
+  for (const upload of [RESTfulAPI, fileIO]) {
+    try {
+      return await upload(inp);
+    } catch (e) {
+      err = e;
+    }
+  }
+  if (err) throw err;
+}

+ 57 - 0
lib/uploadImage.js

@@ -0,0 +1,57 @@
+import fetch from 'node-fetch'
+import { FormData, Blob } from 'formdata-node'
+import { fileTypeFromBuffer } from 'file-type'
+
+/**
+ * Upload file to qu.ax
+ * Supported mimetypes:
+ * - `image/jpeg`
+ * - `image/jpg`
+ * - `image/png`
+ * - `video/mp4`
+ * - `video/webm`
+ * - `audio/mpeg`
+ * - `audio/wav`
+ * @param {Buffer} buffer File Buffer
+ * @return {Promise<string>}
+ */
+export default async (buffer) => {
+const { ext, mime } = await fileTypeFromBuffer(buffer)
+const form = new FormData()
+const blob = new Blob([buffer.toArrayBuffer()], { type: mime })
+form.append('files[]', blob, 'tmp.' + ext)
+const res = await fetch('https://qu.ax/upload.php', { method: 'POST', body: form })
+const result = await res.json()
+if (result && result.success) {
+return result.files[0].url
+} else {
+throw new Error('Failed to upload the file to qu.ax')
+}}
+
+/**
+ * Upload file to qu.ax
+ * Supported mimetypes:
+ * - `image/jpeg`
+ * - `image/jpg`
+ * - `image/png`
+ * - `video/mp4`
+ * - `video/webm`
+ * - `audio/mpeg`
+ * - `audio/wav`
+ * @param {Buffer} buffer File Buffer
+ * @return {Promise<string>}
+ */
+
+/*export default async (buffer) => {
+const {ext, mime} = await fileTypeFromBuffer(buffer)
+const form = new FormData()
+const blob = new Blob([buffer.toArrayBuffer()], {type: mime})
+form.append('file', blob, 'tmp.' + ext)
+const res = await fetch('https://telegra.ph/upload', {
+method: 'POST',
+body: form,
+})
+const img = await res.json()
+if (img.error) throw img.error
+return 'https://telegra.ph' + img[0].src
+}*/

+ 18 - 0
lib/validators.js

@@ -0,0 +1,18 @@
+// lib/validators.js
+export function luhnCheck(num) {
+  let sum = 0;
+  let shouldDouble = false;
+  
+  for (let i = num.length - 1; i >= 0; i--) {
+    let digit = parseInt(num.charAt(i), 10);
+    
+    if (shouldDouble) {
+      if ((digit *= 2) > 9) digit -= 9;
+    }
+    
+    sum += digit;
+    shouldDouble = !shouldDouble;
+  }
+  
+  return (sum % 10) === 0;
+}

+ 1497 - 0
lib/webp.js

@@ -0,0 +1,1497 @@
+'use strict';
+
+Object.defineProperty(exports, '__esModule', {
+  value: true,
+});
+exports.default = exports.constants = void 0;
+
+const _fs2 = _interopRequireDefault(require('fs'));
+
+const _util = require('util');
+
+const _path = require('path');
+
+function _interopRequireDefault(obj) {
+  return obj && obj.__esModule ? obj : {default: obj};
+}
+
+function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
+  try {
+    var info = gen[key](arg);
+    var value = info.value;
+  } catch (error) {
+    reject(error);
+    return;
+  }
+  if (info.done) {
+    resolve(value);
+  } else {
+    Promise.resolve(value).then(_next, _throw);
+  }
+}
+
+function _asyncToGenerator(fn) {
+  return function() {
+    const self = this;
+    const args = arguments;
+    return new Promise(function(resolve, reject) {
+      const gen = fn.apply(self, args);
+      function _next(value) {
+        asyncGeneratorStep(gen, resolve, reject, _next, _throw, 'next', value);
+      }
+      function _throw(err) {
+        asyncGeneratorStep(gen, resolve, reject, _next, _throw, 'throw', err);
+      }
+      _next(undefined);
+    });
+  };
+}
+
+function _defineProperty(obj, key, value) {
+  if (key in obj) {
+    Object.defineProperty(obj, key, {
+      value: value,
+      enumerable: true,
+      configurable: true,
+      writable: true,
+    });
+  } else {
+    obj[key] = value;
+  }
+  return obj;
+}
+
+function _classPrivateMethodGet(receiver, privateSet, fn) {
+  if (!privateSet.has(receiver)) {
+    throw new TypeError('attempted to get private field on non-instance');
+  }
+  return fn;
+}
+
+const fs = {
+  read: (0, _util.promisify)(_fs2.default.read),
+  write: (0, _util.promisify)(_fs2.default.write),
+  open: (0, _util.promisify)(_fs2.default.open),
+  close: (0, _util.promisify)(_fs2.default.close),
+};
+const nullByte = Buffer.alloc(1);
+nullByte[0] = 0;
+const constants = {
+  TYPE_LOSSY: 0,
+  TYPE_LOSSLESS: 1,
+  TYPE_EXTENDED: 2,
+};
+exports.constants = constants;
+
+function VP8Width(data) {
+  const n = (data[7] << 8) | data[6];
+  return n & 0b0011111111111111;
+}
+
+function VP8Height(data) {
+  const n = (data[9] << 8) | data[8];
+  return n & 0b0011111111111111;
+}
+
+function VP8LWidth(data) {
+  const n = (data[2] << 8) | data[1];
+  return (n & 0b0011111111111111) + 1;
+}
+
+function VP8LHeight(data) {
+  let n = (data[4] << 16) | (data[3] << 8) | data[2];
+  n = n >> 6;
+  return (n & 0b0011111111111111) + 1;
+}
+
+function doesVP8LHaveAlpha(data) {
+  return !!(data[4] & 0b00010000);
+}
+
+function createBasicChunk(name, data) {
+  const chunk = Buffer.alloc(8);
+  const size = data.length;
+  let out;
+  chunk.write(name, 0);
+  chunk.writeUInt32LE(size, 4);
+  out = [chunk, data];
+
+  if (size & 1) {
+    out[2] = nullByte;
+  }
+
+  return out;
+}
+
+const _convertToExtended = new WeakSet();
+
+const _demuxFrame = new WeakSet();
+
+const _readHeader = new WeakSet();
+
+const _readChunkHeader = new WeakSet();
+
+const _readChunkHeader_buf = new WeakSet();
+
+const _readChunk_raw = new WeakSet();
+
+const _readChunk_VP = new WeakSet();
+
+const _readChunk_VP8_buf = new WeakSet();
+
+const _readChunk_VP8L = new WeakSet();
+
+const _readChunk_VP8L_buf = new WeakSet();
+
+const _readChunk_VP8X = new WeakSet();
+
+const _readChunk_ANIM = new WeakSet();
+
+const _readChunk_ANMF = new WeakSet();
+
+const _readChunk_ALPH = new WeakSet();
+
+const _readChunk_ALPH_buf = new WeakSet();
+
+const _readChunk_ICCP = new WeakSet();
+
+const _readChunk_EXIF = new WeakSet();
+
+const _readChunk_XMP = new WeakSet();
+
+const _readChunk_Skip = new WeakSet();
+
+const _read = new WeakSet();
+
+class Image {
+  constructor() {
+    _read.add(this);
+
+    _readChunk_Skip.add(this);
+
+    _readChunk_XMP.add(this);
+
+    _readChunk_EXIF.add(this);
+
+    _readChunk_ICCP.add(this);
+
+    _readChunk_ALPH_buf.add(this);
+
+    _readChunk_ALPH.add(this);
+
+    _readChunk_ANMF.add(this);
+
+    _readChunk_ANIM.add(this);
+
+    _readChunk_VP8X.add(this);
+
+    _readChunk_VP8L_buf.add(this);
+
+    _readChunk_VP8L.add(this);
+
+    _readChunk_VP8_buf.add(this);
+
+    _readChunk_VP.add(this);
+
+    _readChunk_raw.add(this);
+
+    _readChunkHeader_buf.add(this);
+
+    _readChunkHeader.add(this);
+
+    _readHeader.add(this);
+
+    _demuxFrame.add(this);
+
+    _convertToExtended.add(this);
+
+    _defineProperty(this, 'data', null);
+
+    _defineProperty(this, 'loaded', false);
+
+    _defineProperty(this, 'path', '');
+  }
+
+  clear() {
+    this.data = null;
+    this.path = '';
+    this.loaded = false;
+  }
+
+  get width() {
+    if (!this.loaded) {
+      return undefined;
+    }
+
+    const d = this.data;
+    return d.extended ?
+      d.extended.width :
+      d.vp8l ?
+      d.vp8l.width :
+      d.vp8 ?
+      d.vp8.width :
+      undefined;
+  }
+
+  get height() {
+    if (!this.loaded) {
+      return undefined;
+    }
+
+    const d = this.data;
+    return d.extended ?
+      d.extended.height :
+      d.vp8l ?
+      d.vp8l.height :
+      d.vp8 ?
+      d.vp8.height :
+      undefined;
+  }
+
+  get type() {
+    return this.loaded ? this.data.type : undefined;
+  }
+
+  get hasAnim() {
+    return this.loaded ?
+      this.data.extended ?
+        this.data.extended.hasAnim :
+        false :
+      false;
+  }
+
+  get anim() {
+    return this.hasAnim ? this.data.anim : undefined;
+  }
+
+  get frameCount() {
+    return this.anim ? this.anim.frameCount : 0;
+  }
+
+  get iccp() {
+    return this.data.extended ?
+      this.data.extended.hasICCP ?
+        this.data.iccp.raw :
+        undefined :
+      undefined;
+  }
+
+  set iccp(raw) {
+    if (!this.data.extended) {
+      _classPrivateMethodGet(
+          this,
+          _convertToExtended,
+          _convertToExtended2,
+      ).call(this);
+    }
+
+    if (raw === undefined) {
+      this.data.extended.hasICCP = false;
+      delete this.data.iccp;
+    } else {
+      this.data.iccp = {
+        raw,
+      };
+      this.data.extended.hasICCP = true;
+    }
+  }
+
+  get exif() {
+    return this.data.extended ?
+      this.data.extended.hasEXIF ?
+        this.data.exif.raw :
+        undefined :
+      undefined;
+  }
+
+  set exif(raw) {
+    if (!this.data.extended) {
+      _classPrivateMethodGet(
+          this,
+          _convertToExtended,
+          _convertToExtended2,
+      ).call(this);
+    }
+
+    if (raw === undefined) {
+      this.data.extended.hasEXIF = false;
+      delete this.data.exif;
+    } else {
+      this.data.exif = {
+        raw,
+      };
+      this.data.extended.hasEXIF = true;
+    }
+  }
+
+  get xmp() {
+    return this.data.extended ?
+      this.data.extended.hasXMP ?
+        this.data.xmp.raw :
+        undefined :
+      undefined;
+  }
+
+  set xmp(raw) {
+    if (!this.data.extended) {
+      _classPrivateMethodGet(
+          this,
+          _convertToExtended,
+          _convertToExtended2,
+      ).call(this);
+    }
+
+    if (raw === undefined) {
+      this.data.extended.hasXMP = false;
+      delete this.data.xmp;
+    } else {
+      this.data.xmp = {
+        raw,
+      };
+      this.data.extended.hasXMP = true;
+    }
+  }
+
+  load(path) {
+    const _this = this;
+
+    return _asyncToGenerator(function* () {
+      _this.path = path;
+      _this.data = yield _classPrivateMethodGet(_this, _read, _read2).call(
+          _this,
+          path,
+      );
+      _this.loaded = true;
+    })();
+  }
+
+  demuxAnim(path, frame = -1, prefix = '#FNAME#') {
+    const _this2 = this;
+
+    return _asyncToGenerator(function* () {
+      let start = 0;
+      let end = _this2.frameCount;
+
+      if (end == 0) {
+        throw new Error('This WebP isn\'t an animation');
+      }
+
+      if (frame != -1) {
+        start = end = frame;
+      }
+
+      for (let i = start; i <= end; i++) {
+        yield _classPrivateMethodGet(_this2, _demuxFrame, _demuxFrame2).call(
+            _this2,
+            `${path}/${prefix}_${i}.webp`.replace(
+                /#FNAME#/g,
+                (0, _path.basename)(_this2.path, '.webp'),
+            ),
+            _this2.anim.frames[i],
+        );
+      }
+    })();
+  }
+
+  replaceFrame(path, frame) {
+    const _this3 = this;
+
+    return _asyncToGenerator(function* () {
+      if (!_this3.hasAnim) {
+        throw new Error('WebP isn\'t animated');
+      }
+
+      if (frame < 0 || frame >= _this3.frameCount) {
+        throw new Error(
+            `Frame index ${frame} out of bounds (0<=index<${_this3.frameCount})`,
+        );
+      }
+
+      const r = new Image();
+      yield r.load(path);
+
+      switch (r.type) {
+        case constants.TYPE_LOSSY:
+        case constants.TYPE_LOSSLESS:
+          break;
+
+        case constants.TYPE_EXTENDED:
+          if (r.hasAnim) {
+            throw new Error('Merging animations not currently supported');
+          }
+
+          break;
+
+        default:
+          throw new Error('Unknown WebP type');
+      }
+
+      switch (_this3.anim.frames[frame].type) {
+        case constants.TYPE_LOSSY:
+          if (_this3.anim.frames[frame].vp8.alpha) {
+            delete _this3.anim.frames[frame].alph;
+          }
+
+          delete _this3.anim.frames[frame].vp8;
+          break;
+
+        case constants.TYPE_LOSSLESS:
+          delete _this3.anim.frames[frame].vp8l;
+          break;
+
+        default:
+          throw new Error('Unknown frame type');
+      }
+
+      switch (r.type) {
+        case constants.TYPE_LOSSY:
+          _this3.anim.frames[frame].vp8 = r.data.vp8;
+          break;
+
+        case constants.TYPE_LOSSLESS:
+          _this3.anim.frames[frame].vp8l = r.data.vp8l;
+          break;
+
+        case constants.TYPE_EXTENDED:
+          if (r.data.vp8) {
+            _this3.anim.frames[frame].vp8 = r.data.vp8;
+
+            if (r.data.vp8.alpha) {
+              _this3.anim.frames[frame].alph = r.data.alph;
+            }
+          } else if (r.data.vp8l) {
+            _this3.anim.frames[frame].vp8l = r.data.vp8l;
+          }
+
+          break;
+      }
+
+      _this3.anim.frames[frame].width = r.width;
+      _this3.anim.frames[frame].height = r.height;
+    })();
+  }
+
+  muxAnim({path, bgColor = [255, 255, 255, 255], loops = 0} = {}) {
+    const _this4 = this;
+
+    return _asyncToGenerator(function* () {
+      return Image.muxAnim({
+        path,
+        bgColor,
+        loops,
+        frames: _this4.frames,
+      });
+    })();
+  }
+
+  static muxAnim({
+    path,
+    frames,
+    width = 0,
+    height = 0,
+    bgColor = [255, 255, 255, 255],
+    loops = 0,
+    delay = 100,
+    x = 0,
+    y = 0,
+    blend = true,
+    dispose = false,
+  } = {}) {
+    return _asyncToGenerator(function* () {
+      const header = Buffer.alloc(12);
+      let chunk = Buffer.alloc(18);
+      const out = [];
+      let img;
+      let alpha = false;
+      let size;
+      let _w = 0;
+      let _h = 0;
+
+      const _width = width - 1;
+      const _height = height - 1;
+
+      if (frames.length == 0) {
+        throw new Error('No frames to mux');
+      } else if (_width <= 0 || _width > 1 << 24) {
+        throw new Error('Width out of range');
+      } else if (_height <= 0 || _height > 1 << 24) {
+        throw new Error('Height out of range');
+      } else if (_height * _width > Math.pow(2, 32) - 1) {
+        throw new Error(`Width*height too large (${_width}, ${_height})`);
+      } else if (loops < 0 || loops >= 1 << 24) {
+        throw new Error('Loops out of range');
+      } else if (delay < 0 || delay >= 1 << 24) {
+        throw new Error('Delay out of range');
+      } else if (x < 0 || x >= 1 << 24) {
+        throw new Error('X out of range');
+      } else if (y < 0 || y >= 1 << 24) {
+        throw new Error('Y out of range');
+      }
+
+      header.write('RIFF', 0);
+      header.write('WEBP', 8);
+      chunk.write('VP8X', 0);
+      chunk.writeUInt32LE(10, 4);
+      chunk[8] |= 0b00000010;
+
+      if (width != 0) {
+        chunk.writeUIntLE(_width, 12, 3);
+      }
+
+      if (height != 0) {
+        chunk.writeUIntLE(_height, 15, 3);
+      }
+
+      out.push(header, chunk);
+      chunk = Buffer.alloc(14);
+      chunk.write('ANIM', 0);
+      chunk.writeUInt32LE(6, 4);
+      chunk.writeUInt8(bgColor[2], 8);
+      chunk.writeUInt8(bgColor[1], 9);
+      chunk.writeUInt8(bgColor[0], 10);
+      chunk.writeUInt8(bgColor[3], 11);
+      chunk.writeUInt16LE(loops, 12);
+      out.push(chunk);
+
+      for (let i = 0, l = frames.length; i < l; i++) {
+        const _delay =
+            typeof frames[i].delay === 'undefined' ? delay : frames[i].delay;
+        const _x = typeof frames[i].x === 'undefined' ? x : frames[i].x;
+        const _y = typeof frames[i].y === 'undefined' ? y : frames[i].y;
+        const _blend =
+            typeof frames[i].blend === 'undefined' ? blend : frames[i].blend;
+        const _dispose =
+            typeof frames[i].dispose === 'undefined' ?
+              dispose :
+              frames[i].dispose;
+        let size = 16;
+        let keepChunk = true;
+        let imgData;
+
+        if (delay < 0 || delay >= 1 << 24) {
+          throw new Error(`Delay out of range on frame ${i}`);
+        } else if (x < 0 || x >= 1 << 24) {
+          throw new Error(`X out of range on frame ${i}`);
+        } else if (y < 0 || y >= 1 << 24) {
+          throw new Error(`Y out of range on frame ${i}`);
+        }
+
+        chunk = Buffer.alloc(24);
+        chunk.write('ANMF', 0);
+        chunk.writeUIntLE(_x, 8, 3);
+        chunk.writeUIntLE(_y, 11, 3);
+        chunk.writeUIntLE(_delay, 20, 3);
+
+        if (!_blend) {
+          chunk[23] |= 0b00000010;
+        }
+
+        if (_dispose) {
+          chunk[23] |= 0b00000001;
+        }
+
+        if (frames[i].path) {
+          img = new Image();
+          yield img.load(frames[i].path);
+        } else {
+          img = {
+            data: frames[i],
+          };
+        }
+
+        chunk.writeUIntLE(img.data.width - 1, 14, 3);
+        chunk.writeUIntLE(img.data.height - 1, 17, 3);
+
+        switch (img.data.type) {
+          case constants.TYPE_LOSSY:
+            {
+              const c = img.data.vp8;
+              _w = c.width > _w ? c.width : _w;
+              _h = c.height > _h ? c.height : _h;
+              size += c.raw.length + 8;
+              imgData = createBasicChunk('VP8 ', c.raw);
+            }
+            break;
+
+          case constants.TYPE_LOSSLESS:
+            {
+              const c = img.data.vp8l;
+              _w = c.width > _w ? c.width : _w;
+              _h = c.height > _h ? c.height : _h;
+              size += c.raw.length + 8;
+
+              if (c.alpha) {
+                alpha = true;
+              }
+
+              imgData = createBasicChunk('VP8L', c.raw);
+            }
+            break;
+
+          case constants.TYPE_EXTENDED:
+            if (img.data.extended.hasAnim) {
+              const fr = img.data.anim.frames;
+              keepChunk = false;
+
+              if (img.data.extended.hasAlpha) {
+                alpha = true;
+              }
+
+              for (let i = 0, l = fr.length; i < l; i++) {
+                _w = fr[i].width + _x > _w ? fr[i].width + _x : _w;
+                _h = fr[i].height + _y > _h ? fr[i].height + _y : _h;
+                let b = Buffer.alloc(8);
+                b.write('ANMF', 0);
+                b.writeUInt32LE(fr[i].raw.length, 4);
+                out.push(b, fr[i].raw);
+
+                if (fr[i].raw.length & 1) {
+                  out.push(nullByte);
+                }
+
+                b = fr[i].raw;
+                b.writeUIntLE(_x, 0, 3);
+                b.writeUIntLE(_y, 3, 3);
+                b.writeUIntLE(_delay, 12, 3);
+
+                if (!_blend) {
+                  b[15] |= 0b00000010;
+                } else {
+                  b[15] &= 0b11111101;
+                }
+
+                if (_dispose) {
+                  b[15] |= 0b00000001;
+                } else {
+                  b[15] &= 0b11111110;
+                }
+              }
+            } else {
+              _w = img.data.extended.width > _w ? img.data.extended.width : _w;
+              _h =
+                img.data.extended.height > _h ? img.data.extended.height : _h;
+
+              if (img.data.vp8) {
+                imgData = [];
+
+                if (img.data.alph) {
+                  alpha = true;
+                  imgData.push(...createBasicChunk('ALPH', img.data.alph.raw));
+                  size += img.data.alph.raw.length + 8;
+                }
+
+                imgData.push(...createBasicChunk('VP8 ', img.data.vp8.raw));
+                size += img.data.vp8.raw.length + 8;
+              } else if (img.data.vp8l) {
+                imgData = createBasicChunk('VP8L', img.data.vp8l.raw);
+
+                if (img.data.vp8l.alpha) {
+                  alpha = true;
+                }
+
+                size += img.data.vp8l.raw.length + 8;
+              }
+            }
+
+            break;
+
+          default:
+            throw new Error('Unknown image type');
+        }
+
+        if (keepChunk) {
+          chunk.writeUInt32LE(size, 4);
+          out.push(chunk, ...imgData);
+        }
+      }
+
+      if (width == 0) {
+        out[1].writeUIntLE(_w - 1, 12, 3);
+      }
+
+      if (height == 0) {
+        out[1].writeUIntLE(_h - 1, 15, 3);
+      }
+
+      size = 4;
+
+      for (let i = 1, l = out.length; i < l; i++) {
+        size += out[i].length;
+      }
+
+      header.writeUInt32LE(size, 4);
+
+      if (alpha) {
+        out[1][8] |= 0b00010000;
+      }
+
+      const fp = yield fs.open(path, 'w');
+
+      for (let i = 0, l = out.length; i < l; i++) {
+        yield fs.write(fp, out[i], 0, undefined, undefined);
+      }
+
+      yield fs.close(fp);
+    })();
+  }
+}
+
+var _convertToExtended2 = function _convertToExtended2() {
+  if (!this.loaded) {
+    throw new Error('No image loaded');
+  }
+
+  this.data.type = constants.TYPE_EXTENDED;
+  this.data.extended = {
+    hasICC: false,
+    hasAlpha: false,
+    hasEXIF: false,
+    hasXMP: false,
+    width: this.vp8 ? this.vp8.width : this.vp8l ? this.vp8l.width : 1,
+    height: this.vp8 ? this.vp8.height : this.vp8l ? this.vp8l.height : 1,
+  };
+};
+
+var _demuxFrame2 = /* #__PURE__*/ (function() {
+  const _demuxFrame3 = _asyncToGenerator(function* (path, frame) {
+    const header = Buffer.alloc(12);
+    let size;
+    let chunk;
+    const out = [];
+    header.write('RIFF', 0);
+    header.write('WEBP', 8);
+    out.push(header);
+
+    if (
+      this.data.extended.hasICC ||
+      this.data.extended.hasEXIF ||
+      this.data.extended.hasXMP ||
+      (frame.vp8 && frame.vp8.alpha)
+    ) {
+      chunk = Buffer.alloc(18);
+      chunk.write('VP8X', 0);
+      chunk.writeUInt32LE(10, 4);
+
+      if (this.data.extended.hasICC) {
+        chunk[8] |= 0b00100000;
+      }
+
+      if ((frame.vp8l && frame.vp8l.alpha) || (frame.vp8 && frame.vp8.alpha)) {
+        chunk[8] |= 0b00010000;
+      }
+
+      if (this.data.extended.hasEXIF) {
+        chunk[8] |= 0b00001000;
+      }
+
+      if (this.data.extended.hasXMP) {
+        chunk[8] |= 0b00000100;
+      }
+
+      chunk.writeUIntLE(frame.width - 1, 12, 3);
+      chunk.writeUIntLE(frame.height - 1, 15, 3);
+      out.push(chunk);
+
+      if (this.data.extended.hasICC) {
+        out.push(...createBasicChunk('ICCP', this.data.extended.icc.raw));
+      }
+    }
+
+    if (frame.vp8l) {
+      out.push(...createBasicChunk('VP8L', frame.vp8l.raw));
+    } else if (frame.vp8) {
+      if (frame.vp8.alpha) {
+        out.push(...createBasicChunk('ALPH', frame.alph.raw));
+      }
+
+      out.push(...createBasicChunk('VP8 ', frame.vp8.raw));
+    } else {
+      throw new Error('Frame has no VP8/VP8L?');
+    }
+
+    if (this.type == constants.TYPE_EXTENDED) {
+      if (this.data.extended.hasEXIF) {
+        out.push(...createBasicChunk('EXIF', this.data.extended.exif.raw));
+      }
+
+      if (this.data.extended.hasXMP) {
+        out.push(...createBasicChunk('XMP ', this.data.extended.xmp.raw));
+      }
+    }
+
+    size = 4;
+
+    for (let i = 1, l = out.length; i < l; i++) {
+      size += out[i].length;
+    }
+
+    header.writeUInt32LE(size, 4);
+    const fp = yield fs.open(path, 'w');
+
+    for (let i = 0, l = out.length; i < l; i++) {
+      yield fs.write(fp, out[i], 0, undefined, undefined);
+    }
+
+    yield fs.close(fp);
+  });
+
+  function _demuxFrame2(_x2, _x3) {
+    return _demuxFrame3.apply(this, arguments);
+  }
+
+  return _demuxFrame2;
+})();
+
+const _readHeader2 = /* #__PURE__*/ (function() {
+  const _readHeader3 = _asyncToGenerator(function* (fd) {
+    const buf = Buffer.alloc(12);
+    const {bytesRead} = yield fs.read(fd, buf, 0, 12, undefined);
+
+    if (bytesRead != 12) {
+      throw new Error('Reached end of file while reading header');
+    }
+
+    if (buf.toString('utf8', 0, 4) != 'RIFF') {
+      throw new Error('Bad header (not RIFF)');
+    }
+
+    if (buf.toString('utf8', 8, 12) != 'WEBP') {
+      throw new Error('Bad header (not WEBP)');
+    }
+
+    return {
+      fileSize: buf.readUInt32LE(4),
+    };
+  });
+
+  function _readHeader2(_x4) {
+    return _readHeader3.apply(this, arguments);
+  }
+
+  return _readHeader2;
+})();
+
+const _readChunkHeader2 = /* #__PURE__*/ (function() {
+  const _readChunkHeader3 = _asyncToGenerator(function* (fd) {
+    const buf = Buffer.alloc(8);
+    const {bytesRead} = yield fs.read(fd, buf, 0, 8, undefined);
+
+    if (bytesRead == 0) {
+      return {
+        fourCC: '\x00\x00\x00\x00',
+        size: 0,
+      };
+    } else if (bytesRead < 8) {
+      throw new Error('Reached end of file while reading chunk header');
+    }
+
+    return {
+      fourCC: buf.toString('utf8', 0, 4),
+      size: buf.readUInt32LE(4),
+    };
+  });
+
+  function _readChunkHeader2(_x5) {
+    return _readChunkHeader3.apply(this, arguments);
+  }
+
+  return _readChunkHeader2;
+})();
+
+const _readChunkHeader_buf2 = function _readChunkHeader_buf2(buf, cursor) {
+  if (cursor >= buf.length) {
+    return {
+      fourCC: '\x00\x00\x00\x00',
+      size: 0,
+    };
+  }
+
+  return {
+    fourCC: buf.toString('utf8', cursor, cursor + 4),
+    size: buf.readUInt32LE(cursor + 4),
+  };
+};
+
+const _readChunk_raw2 = /* #__PURE__*/ (function() {
+  const _readChunk_raw3 = _asyncToGenerator(function* (n, fd, size) {
+    const buf = Buffer.alloc(size);
+    const discard = Buffer.alloc(1);
+    const {bytesRead} = yield fs.read(fd, buf, 0, size, undefined);
+
+    if (bytesRead != size) {
+      throw new Error(`Reached end of file while reading ${n} chunk`);
+    }
+
+    if (size & 1) {
+      yield fs.read(fd, discard, 0, 1, undefined);
+    }
+
+    return {
+      raw: buf,
+    };
+  });
+
+  function _readChunk_raw2(_x6, _x7, _x8) {
+    return _readChunk_raw3.apply(this, arguments);
+  }
+
+  return _readChunk_raw2;
+})();
+
+const _readChunk_VP2 = /* #__PURE__*/ (function() {
+  const _readChunk_VP3 = _asyncToGenerator(function* (fd, size) {
+    const buf = Buffer.alloc(size);
+    const discard = Buffer.alloc(1);
+    const {bytesRead} = yield fs.read(fd, buf, 0, size, undefined);
+
+    if (bytesRead != size) {
+      throw new Error('Reached end of file while reading VP8 chunk');
+    }
+
+    if (size & 1) {
+      yield fs.read(fd, discard, 0, 1, undefined);
+    }
+
+    return {
+      raw: buf,
+      width: VP8Width(buf, 8),
+      height: VP8Height(buf, 8),
+    };
+  });
+
+  function _readChunk_VP2(_x9, _x10) {
+    return _readChunk_VP3.apply(this, arguments);
+  }
+
+  return _readChunk_VP2;
+})();
+
+const _readChunk_VP8_buf2 = function _readChunk_VP8_buf2(buf, size, cursor) {
+  if (cursor >= buf.length) {
+    throw new Error('Reached end of buffer while reading VP8 chunk');
+  }
+
+  const raw = buf.slice(cursor, cursor + size);
+  return {
+    raw,
+    width: VP8Width(raw),
+    height: VP8Height(raw),
+  };
+};
+
+const _readChunk_VP8L2 = /* #__PURE__*/ (function() {
+  const _readChunk_VP8L3 = _asyncToGenerator(function* (fd, size) {
+    const buf = Buffer.alloc(size);
+    const discard = Buffer.alloc(1);
+    const {bytesRead} = yield fs.read(fd, buf, 0, size, undefined);
+
+    if (bytesRead != size) {
+      throw new Error('Reached end of file while reading VP8L chunk');
+    }
+
+    if (size & 1) {
+      yield fs.read(fd, discard, 0, 1, undefined);
+    }
+
+    return {
+      raw: buf,
+      alpha: doesVP8LHaveAlpha(buf, 0),
+      width: VP8LWidth(buf),
+      height: VP8LHeight(buf),
+    };
+  });
+
+  function _readChunk_VP8L2(_x11, _x12) {
+    return _readChunk_VP8L3.apply(this, arguments);
+  }
+
+  return _readChunk_VP8L2;
+})();
+
+const _readChunk_VP8L_buf2 = function _readChunk_VP8L_buf2(buf, size, cursor) {
+  if (cursor >= buf.length) {
+    throw new Error('Reached end of buffer while reading VP8L chunk');
+  }
+
+  const raw = buf.slice(cursor, cursor + size);
+  return {
+    raw,
+    alpha: doesVP8LHaveAlpha(raw),
+    width: VP8LWidth(raw),
+    height: VP8LHeight(raw),
+  };
+};
+
+const _readChunk_VP8X2 = /* #__PURE__*/ (function() {
+  const _readChunk_VP8X3 = _asyncToGenerator(function* (fd, size) {
+    const buf = Buffer.alloc(size);
+    const {bytesRead} = yield fs.read(fd, buf, 0, size, undefined);
+
+    if (bytesRead != size) {
+      throw new Error('Reached end of file while reading VP8X chunk');
+    }
+
+    return {
+      raw: buf,
+      hasICC: !!(buf[0] & 0b00100000),
+      hasAlpha: !!(buf[0] & 0b00010000),
+      hasEXIF: !!(buf[0] & 0b00001000),
+      hasXMP: !!(buf[0] & 0b00000100),
+      hasAnim: !!(buf[0] & 0b00000010),
+      width: buf.readUIntLE(4, 3) + 1,
+      height: buf.readUIntLE(7, 3) + 1,
+    };
+  });
+
+  function _readChunk_VP8X2(_x13, _x14) {
+    return _readChunk_VP8X3.apply(this, arguments);
+  }
+
+  return _readChunk_VP8X2;
+})();
+
+const _readChunk_ANIM2 = /* #__PURE__*/ (function() {
+  const _readChunk_ANIM3 = _asyncToGenerator(function* (fd, size) {
+    const buf = Buffer.alloc(size);
+    const {bytesRead} = yield fs.read(fd, buf, 0, size, undefined);
+
+    if (bytesRead != size) {
+      throw new Error('Reached end of file while reading ANIM chunk');
+    }
+
+    return {
+      raw: buf,
+      bgColor: buf.slice(0, 4),
+      loopCount: buf.readUInt16LE(4),
+    };
+  });
+
+  function _readChunk_ANIM2(_x15, _x16) {
+    return _readChunk_ANIM3.apply(this, arguments);
+  }
+
+  return _readChunk_ANIM2;
+})();
+
+const _readChunk_ANMF2 = /* #__PURE__*/ (function() {
+  const _readChunk_ANMF3 = _asyncToGenerator(function* (fd, size) {
+    const buf = Buffer.alloc(size);
+    const discard = Buffer.alloc(1);
+    const {bytesRead} = yield fs.read(fd, buf, 0, size, undefined);
+
+    if (bytesRead != size) {
+      throw new Error('Reached end of file while reading ANMF chunk');
+    }
+
+    if (size & 1) {
+      yield fs.read(fd, discard, 0, 1, undefined);
+    }
+
+    const out = {
+      raw: buf,
+      x: buf.readUIntLE(0, 3),
+      y: buf.readUIntLE(3, 3),
+      width: buf.readUIntLE(6, 3) + 1,
+      height: buf.readUIntLE(9, 3) + 1,
+      duration: buf.readUIntLE(12, 3),
+      blend: !(buf[15] & 0b00000010),
+      dispose: !!(buf[15] & 0b00000001),
+    };
+    let keepLooping = true;
+    let cursor = 16;
+
+    while (keepLooping) {
+      const header = _classPrivateMethodGet(
+          this,
+          _readChunkHeader_buf,
+          _readChunkHeader_buf2,
+      ).call(this, buf, cursor);
+      let t;
+
+      cursor += 8;
+
+      switch (header.fourCC) {
+        case 'VP8 ':
+          if (!out.vp8) {
+            out.type = constants.TYPE_LOSSY;
+            out.vp8 = _classPrivateMethodGet(
+                this,
+                _readChunk_VP8_buf,
+                _readChunk_VP8_buf2,
+            ).call(this, buf, header.size, cursor);
+          }
+
+          break;
+
+        case 'VP8L':
+          if (!out.vp8l) {
+            out.type = constants.TYPE_LOSSLESS;
+            out.vp8l = _classPrivateMethodGet(
+                this,
+                _readChunk_VP8L_buf,
+                _readChunk_VP8L_buf2,
+            ).call(this, buf, header.size, cursor);
+          }
+
+          break;
+
+        case 'ALPH':
+          if (out.vp8) {
+            out.alph = _classPrivateMethodGet(
+                this,
+                _readChunk_ALPH_buf,
+                _readChunk_ALPH_buf2,
+            ).call(this, buf, header.size, cursor);
+            out.vp8.alpha = true;
+          }
+
+          break;
+
+        case '\x00\x00\x00\x00':
+        default:
+          keepLooping = false;
+          break;
+      }
+
+      cursor += header.size + 1;
+
+      if (header.size & 1) {
+        cursor++;
+      }
+
+      if (cursor >= buf.length) {
+        keepLooping = false;
+      }
+    }
+
+    return out;
+  });
+
+  function _readChunk_ANMF2(_x17, _x18) {
+    return _readChunk_ANMF3.apply(this, arguments);
+  }
+
+  return _readChunk_ANMF2;
+})();
+
+const _readChunk_ALPH2 = /* #__PURE__*/ (function() {
+  const _readChunk_ALPH3 = _asyncToGenerator(function* (fd, size) {
+    return _classPrivateMethodGet(this, _readChunk_raw, _readChunk_raw2).call(
+        this,
+        'ALPH',
+        fd,
+        size,
+    );
+  });
+
+  function _readChunk_ALPH2(_x19, _x20) {
+    return _readChunk_ALPH3.apply(this, arguments);
+  }
+
+  return _readChunk_ALPH2;
+})();
+
+var _readChunk_ALPH_buf2 = function _readChunk_ALPH_buf2(buf, size, cursor) {
+  if (cusor >= buf.length) {
+    throw new Error('Reached end of buffer while reading ALPH chunk');
+  }
+
+  return {
+    raw: buf.slice(cursor, cursor + size),
+  };
+};
+
+const _readChunk_ICCP2 = /* #__PURE__*/ (function() {
+  const _readChunk_ICCP3 = _asyncToGenerator(function* (fd, size) {
+    return _classPrivateMethodGet(this, _readChunk_raw, _readChunk_raw2).call(
+        this,
+        'ICCP',
+        fd,
+        size,
+    );
+  });
+
+  function _readChunk_ICCP2(_x21, _x22) {
+    return _readChunk_ICCP3.apply(this, arguments);
+  }
+
+  return _readChunk_ICCP2;
+})();
+
+const _readChunk_EXIF2 = /* #__PURE__*/ (function() {
+  const _readChunk_EXIF3 = _asyncToGenerator(function* (fd, size) {
+    return _classPrivateMethodGet(this, _readChunk_raw, _readChunk_raw2).call(
+        this,
+        'EXIF',
+        fd,
+        size,
+    );
+  });
+
+  function _readChunk_EXIF2(_x23, _x24) {
+    return _readChunk_EXIF3.apply(this, arguments);
+  }
+
+  return _readChunk_EXIF2;
+})();
+
+const _readChunk_XMP2 = /* #__PURE__*/ (function() {
+  const _readChunk_XMP3 = _asyncToGenerator(function* (fd, size) {
+    return _classPrivateMethodGet(this, _readChunk_raw, _readChunk_raw2).call(
+        this,
+        'XML',
+        fd,
+        size,
+    );
+  });
+
+  function _readChunk_XMP2(_x25, _x26) {
+    return _readChunk_XMP3.apply(this, arguments);
+  }
+
+  return _readChunk_XMP2;
+})();
+
+const _readChunk_Skip2 = /* #__PURE__*/ (function() {
+  const _readChunk_Skip3 = _asyncToGenerator(function* (fd, size) {
+    const buf = Buffer.alloc(size);
+    const discard = Buffer.alloc(1);
+    const {bytesRead} = yield fs.read(fd, buf, 0, size, undefined);
+
+    if (bytesRead != size) {
+      throw new Error('Reached end of file while skipping chunk');
+    }
+
+    if (size & 1) {
+      yield fs.read(fd, discard, 0, 1, undefined);
+    }
+  });
+
+  function _readChunk_Skip2(_x27, _x28) {
+    return _readChunk_Skip3.apply(this, arguments);
+  }
+
+  return _readChunk_Skip2;
+})();
+
+var _read2 = /* #__PURE__*/ (function() {
+  const _read3 = _asyncToGenerator(function* (path) {
+    const fd = yield fs.open(path, 'r');
+    const out = {};
+    let keepLooping = true;
+    let first = true;
+    const {fileSize} = yield _classPrivateMethodGet(
+        this,
+        _readHeader,
+        _readHeader2,
+    ).call(this, fd);
+
+    while (keepLooping) {
+      const {fourCC, size} = yield _classPrivateMethodGet(
+          this,
+          _readChunkHeader,
+          _readChunkHeader2,
+      ).call(this, fd);
+
+      switch (fourCC) {
+        case 'VP8 ':
+          if (!out.vp8) {
+            out.vp8 = yield _classPrivateMethodGet(
+                this,
+                _readChunk_VP,
+                _readChunk_VP2,
+            ).call(this, fd, size);
+          } else {
+            yield _classPrivateMethodGet(
+                this,
+                _readChunk_Skip,
+                _readChunk_Skip2,
+            ).call(this, fd, size);
+          }
+
+          if (first) {
+            out.type = constants.TYPE_LOSSY;
+            keepLooping = false;
+          }
+
+          break;
+
+        case 'VP8L':
+          if (!out.vp8l) {
+            out.vp8l = yield _classPrivateMethodGet(
+                this,
+                _readChunk_VP8L,
+                _readChunk_VP8L2,
+            ).call(this, fd, size);
+          } else {
+            yield _classPrivateMethodGet(
+                this,
+                _readChunk_Skip,
+                _readChunk_Skip2,
+            ).call(this, fd, size);
+          }
+
+          if (first) {
+            out.type = constants.TYPE_LOSSLESS;
+            keepLooping = false;
+          }
+
+          break;
+
+        case 'VP8X':
+          if (!out.extended) {
+            out.type = constants.TYPE_EXTENDED;
+            out.extended = yield _classPrivateMethodGet(
+                this,
+                _readChunk_VP8X,
+                _readChunk_VP8X2,
+            ).call(this, fd, size);
+          } else {
+            yield _classPrivateMethodGet(
+                this,
+                _readChunk_Skip,
+                _readChunk_Skip2,
+            ).call(this, fd, size);
+          }
+
+          break;
+
+        case 'ANIM':
+          if (!out.anim) {
+            const {raw, bgColor, loopCount} = yield _classPrivateMethodGet(
+                this,
+                _readChunk_ANIM,
+                _readChunk_ANIM2,
+            ).call(this, fd, size);
+            out.anim = {
+              backgroundColor: [bgColor[2], bgColor[1], bgColor[0], bgColor[3]],
+              loopCount,
+              frames: [],
+            };
+            out.anim.raw = raw;
+          } else {
+            yield _classPrivateMethodGet(
+                this,
+                _readChunk_Skip,
+                _readChunk_Skip2,
+            ).call(this, fd, size);
+          }
+
+          break;
+
+        case 'ANMF':
+          {
+            const f = yield _classPrivateMethodGet(
+                this,
+                _readChunk_ANMF,
+                _readChunk_ANMF2,
+            ).call(this, fd, size);
+            out.anim.frames.push(f);
+          }
+          break;
+
+        case 'ALPH':
+          if (!out.alph) {
+            out.alph = yield _classPrivateMethodGet(
+                this,
+                _readChunk_ALPH,
+                _readChunk_ALPH2,
+            ).call(this, fd, size);
+          } else {
+            yield _classPrivateMethodGet(
+                this,
+                _readChunk_Skip,
+                _readChunk_Skip2,
+            ).call(this, fd, size);
+          }
+
+          break;
+
+        case 'ICCP':
+          if (!out.iccp) {
+            out.iccp = yield _classPrivateMethodGet(
+                this,
+                _readChunk_ICCP,
+                _readChunk_ICCP2,
+            ).call(this, fd, size);
+          } else {
+            yield _classPrivateMethodGet(
+                this,
+                _readChunk_Skip,
+                _readChunk_Skip2,
+            ).call(this, fd, size);
+          }
+
+          break;
+
+        case 'EXIF':
+          if (!out.exif) {
+            out.exif = yield _classPrivateMethodGet(
+                this,
+                _readChunk_EXIF,
+                _readChunk_EXIF2,
+            ).call(this, fd, size);
+          } else {
+            yield _classPrivateMethodGet(
+                this,
+                _readChunk_Skip,
+                _readChunk_Skip2,
+            ).call(this, fd, size);
+          }
+
+          break;
+
+        case 'XMP ':
+          if (!out.xmp) {
+            out.xmp = yield _classPrivateMethodGet(
+                this,
+                _readChunk_XMP,
+                _readChunk_XMP2,
+            ).call(this, fd, size);
+          } else {
+            yield _classPrivateMethodGet(
+                this,
+                _readChunk_Skip,
+                _readChunk_Skip2,
+            ).call(this, fd, size);
+          }
+
+          break;
+
+        case '\x00\x00\x00\x00':
+          keepLooping = false;
+          break;
+
+        default:
+          yield _classPrivateMethodGet(
+              this,
+              _readChunk_Skip,
+              _readChunk_Skip2,
+          ).call(this, fd, size);
+          break;
+      }
+
+      first = false;
+    }
+
+    if (out.type == constants.TYPE_EXTENDED && out.extended.hasAnim) {
+      out.anim.frameCount = out.anim.frames.length;
+    }
+
+    return out;
+  });
+
+  function _read2(_x29) {
+    return _read3.apply(this, arguments);
+  }
+
+  return _read2;
+})();
+
+const _default = {
+  TYPE_LOSSY: constants.TYPE_LOSSY,
+  TYPE_LOSSLESS: constants.TYPE_LOSSLESS,
+  TYPE_EXTENDED: constants.TYPE_EXTENDED,
+  Image,
+};
+exports.default = _default;

+ 171 - 0
lib/webp2mp4.js

@@ -0,0 +1,171 @@
+import { convert } from "./ezgif-convert.js"
+import { FormData, Blob } from 'formdata-node'
+import { fileTypeFromBuffer } from "file-type"
+import crypto from "crypto"
+
+const randomBytes = crypto.randomBytes(5).toString("hex");
+const urlRegex = /^(https?|ftp):\/\/[^\s/$.?#].[^\s]*$/;
+
+async function webp2mp4(source) {
+    const isUrl = typeof source === 'string' && urlRegex.test(source);
+ 
+    try {
+        return await convert({
+            type: 'webp-mp4',
+            ...(isUrl ? {
+                url: source
+            } : {
+                file: new Blob([source]),
+                filename: randomBytes + "." + (await fileTypeFromBuffer(source)).ext
+            })
+        });
+    } catch (error) {
+        console.error("Error converting to webp-mp4. Trying fallback types.");
+
+        try {
+            return await convert({
+                type: 'webp-avif',
+                ...(isUrl ? {
+                    url: source
+                } : {
+                    file: new Blob([source]),
+                    filename: randomBytes + "." + (await fileTypeFromBuffer(source)).ext
+                })
+            });
+        } catch (avifError) {
+            console.error("Error converting to webp-avif. Trying webp-gif.");
+
+            try {
+                return await convert({
+                    type: 'webp-gif',
+                    ...(isUrl ? {
+                        url: source
+                    } : {
+                        file: new Blob([source]),
+                        filename: randomBytes + "." + (await fileTypeFromBuffer(source)).ext
+                    })
+                });
+            } catch (gifError) {
+                console.error("Error converting to webp-gif. All fallback types failed.");
+                throw gifError;
+            }
+        }
+    }
+}
+
+async function webp2png(source) {
+    const isUrl = typeof source === 'string' && urlRegex.test(source);
+
+    try {
+        return await convert({
+            type: 'webp-png',
+            ...(isUrl ? {
+                url: source
+            } : {
+                file: new Blob([source]),
+                filename: randomBytes + "." + (await fileTypeFromBuffer(source)).ext
+            })
+        });
+    } catch (pngError) {
+        console.error("Error converting to webp-png. Trying webp-jpg.");
+
+        try {
+            return await convert({
+                type: 'webp-jpg',
+                ...(isUrl ? {
+                    url: source
+                } : {
+                    file: new Blob([source]),
+                    filename: randomBytes + "." + (await fileTypeFromBuffer(source)).ext
+                })
+            });
+        } catch (jpgError) {
+            console.error("Error converting to webp-jpg. All fallback types failed.");
+            throw jpgError;
+        }
+    }
+}
+
+export {
+    webp2mp4,
+    webp2png
+};
+
+/*import fetch from 'node-fetch';
+import {
+    FormData,
+    Blob
+} from 'formdata-node';
+import {
+    JSDOM
+} from 'jsdom';
+
+// @param {Buffer|String} source 
+
+async function webp2mp4(source) {
+    let form = new FormData()
+    let isUrl = typeof source === 'string' && /https?:\/\//.test(source)
+    const blob = !isUrl && new Blob([source.toArrayBuffer()])
+    form.append('new-image-url', isUrl ? blob : '')
+    form.append('new-image', isUrl ? '' : blob, 'image.webp')
+    let res = await fetch('https://ezgif.com/webp-to-mp4', {
+        method: 'POST',
+        body: form
+    })
+    let html = await res.text()
+    let {
+        document
+    } = new JSDOM(html).window
+    let form2 = new FormData()
+    let obj = {}
+    for (let input of document.querySelectorAll('form input[name]')) {
+        obj[input.name] = input.value
+        form2.append(input.name, input.value)
+    }
+    let res2 = await fetch('https://ezgif.com/webp-to-mp4/' + obj.file, {
+        method: 'POST',
+        body: form2
+    })
+    let html2 = await res2.text()
+    let {
+        document: document2
+    } = new JSDOM(html2).window
+    return new URL(document2.querySelector('div#output > p.outfile > video > source').src, res2.url).toString()
+}
+
+async function webp2png(source) {
+    let form = new FormData()
+    let isUrl = typeof source === 'string' && /https?:\/\//.test(source)
+    const blob = !isUrl && new Blob([source.toArrayBuffer()])
+    form.append('new-image-url', isUrl ? blob : '')
+    form.append('new-image', isUrl ? '' : blob, 'image.webp')
+    let res = await fetch('https://ezgif.com/webp-to-png', {
+        method: 'POST',
+        body: form
+    })
+    let html = await res.text()
+    let {
+        document
+    } = new JSDOM(html).window
+    let form2 = new FormData()
+    let obj = {}
+    for (let input of document.querySelectorAll('form input[name]')) {
+        obj[input.name] = input.value
+        form2.append(input.name, input.value)
+    }
+    let res2 = await fetch('https://ezgif.com/webp-to-png/' + obj.file, {
+        method: 'POST',
+        body: form2
+    })
+    let html2 = await res2.text()
+    let {
+        document: document2
+    } = new JSDOM(html2).window
+    return new URL(document2.querySelector('div#output > p.outfile > img').src, res2.url).toString()
+}
+
+export {
+    webp2mp4,
+    webp2png
+}
+// By @nm9h*/

+ 114 - 0
lib/welcome.js

@@ -0,0 +1,114 @@
+import {DOMImplementation, XMLSerializer} from 'xmldom';
+import JsBarcode from 'jsbarcode';
+import {JSDOM} from 'jsdom';
+import {readFileSync} from 'fs';
+import {join} from 'path';
+import {spawn} from 'child_process';
+
+const src = join(__dirname, '..', 'src');
+const _svg = readFileSync(join(src, 'welcome.svg'), 'utf-8');
+const barcode = (data) => {
+  const xmlSerializer = new XMLSerializer();
+  const document = new DOMImplementation().createDocument('http://www.w3.org/1999/xhtml', 'html', null);
+  const svgNode = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
+
+  JsBarcode(svgNode, data, {
+    xmlDocument: document,
+  });
+
+  return xmlSerializer.serializeToString(svgNode);
+};
+const imageSetter = (img, value) => img.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href', value);
+const textSetter = (el, value) => el.textContent = value;
+
+const {document: svg} = new JSDOM(_svg).window;
+/**
+ * Generate SVG Welcome
+ * @param {object} param0
+ * @param {string} param0.wid
+ * @param {string} param0.pp
+ * @param {string} param0.name
+ * @param {string} param0.text
+ * @param {string} param0.background
+ * @return {string}
+ */
+const genSVG = async ({
+  wid = '',
+  pp = join(src, 'avatar_contact.png'),
+  title = '',
+  name = '',
+  text = '',
+  background = '',
+} = {}) => {
+  const el = {
+    code: ['#_1661899539392 > g:nth-child(6) > image', imageSetter, toBase64(await toImg(barcode(wid.replace(/[^0-9]/g, '')), 'png'), 'image/png')],
+    pp: ['#_1661899539392 > g:nth-child(3) > image', imageSetter, pp],
+    text: ['#_1661899539392 > text.fil1.fnt0', textSetter, text],
+    title: ['#_1661899539392 > text.fil2.fnt1', textSetter, title],
+    name: ['#_1661899539392 > text.fil2.fnt2', textSetter, name],
+    bg: ['#_1661899539392 > g:nth-child(2) > image', imageSetter, background],
+  };
+  for (const [selector, set, value] of Object.values(el)) {
+    set(svg.querySelector(selector), value);
+  }
+  return svg.body.innerHTML;
+};
+
+const toImg = (svg, format = 'png') => new Promise((resolve, reject) => {
+  if (!svg) return resolve(Buffer.alloc(0));
+  const bufs = [];
+  const im = spawn('magick', ['convert', 'svg:-', format + ':-']);
+  im.on('error', (e) => reject(e));
+  im.stdout.on('data', (chunk) => bufs.push(chunk));
+  im.stdin.write(Buffer.from(svg));
+  im.stdin.end();
+  im.on('close', (code) => {
+    if (code !== 0) reject(code);
+    resolve(Buffer.concat(bufs));
+  });
+});
+
+const toBase64 = (buffer, mime) => `data:${mime};base64,${buffer.toString('base64')}`;
+
+/**
+ * Render SVG Welcome
+ * @param {object} param0
+ * @param {string} param0.wid
+ * @param {string} param0.pp
+ * @param {string} param0.name
+ * @param {string} param0.text
+ * @param {string} param0.background
+ * @return {Promise<Buffer>}
+ */
+const render = async ({
+  wid = '',
+  pp = toBase64(readFileSync(join(src, 'avatar_contact.png')), 'image/png'),
+  name = '',
+  title = '',
+  text = '',
+  background = toBase64(readFileSync(join(src, 'Aesthetic', 'Aesthetic_000.jpeg')), 'image/jpeg'),
+} = {}, format = 'png') => {
+  const svg = await genSVG({
+    wid, pp, name, text, background, title,
+  });
+  return await toImg(svg, format);
+};
+
+if (require.main === module) {
+  render({
+    wid: '1234567890',
+    // pp: '',
+    name: 'John Doe',
+    text: 'Lorem ipsum\ndot sit color',
+    title: 'grup testing',
+    // background: ''
+  }, 'jpg').then((result) => {
+    // console.log(result)
+    process.stdout.write(result);
+  });
+  // toImg(barcode('test')).then(result => {
+  //     // console.log(result)
+  //     process.stdout.write(result)
+
+  // })
+} else module.exports = render;

+ 74 - 0
lib/y2dl.js

@@ -0,0 +1,74 @@
+import {stat} from 'fs';
+import fetch from 'node-fetch';
+const sleep = async (ms) => new Promise((resolve) => setTimeout(resolve, ms));
+const bestFormat = (url, type) => new Promise(async (resolve, reject) => {
+  const at = await fetch('https://srvcdn8.2convert.me/api/json?url=' + url, {
+    method: 'GET',
+    headers: {
+      'origin': 'https://en1.y2mate.is',
+      'referer': 'https://en1.y2mate.is/',
+      'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36 OPR/99.0.0.0',
+    },
+  });
+  const json = await at.json();
+  if (json.error == true) reject(false);
+  const formats = json.formats;
+  if (type == 'audio') {
+    const formatau = formats.audio;
+    let format = formatau.find((format) => format.quality == 192);
+    if (!format) format = formatau.find((format) => format.quality == 128);
+    if (!format) format = formatau.find((format) => format.quality == 64);
+    if (!format) format = formatau.find((format) => format.quality == 48);
+    if (!format) return reject(false);
+    return resolve(format);
+  }
+  if (type == 'video') {
+    if (formats.video.length == 0) return reject(false);
+    const format = formats.video[formats.video.length - 1];
+    return resolve(format);
+  }
+});
+
+const getUrlDl = (url) => new Promise(async (resolve, reject) => {
+  const taskid = await fetch('https://srvcdn8.2convert.me/api/json', {
+    method: 'POST',
+    headers: {
+      'content-type': 'application/x-www-form-urlencoded; charset=UTF-8',
+      'origin': 'https://en1.y2mate.is',
+      'referer': 'https://en1.y2mate.is/',
+      'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36 OPR/99.0.0.0',
+    },
+    body: 'hash=' + encodeURIComponent(url),
+  });
+  const json = await taskid.json();
+  if (json.error) return reject(false);
+  // nsole.log(taskid)
+  /* ask for status every 1 second */
+  let status = false;
+  while (status == false) {
+    await sleep(1000);
+    const statusid = await fetch('https://srvcdn8.2convert.me/api/json/task', {
+      method: 'POST',
+      headers: {
+        'content-type': 'application/x-www-form-urlencoded; charset=UTF-8',
+        'origin': 'https://en1.y2mate.is',
+        'referer': 'https://en1.y2mate.is/',
+        'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36 OPR/99.0.0.0',
+      },
+      body: 'taskId=' + json.taskId,
+    });
+    const json2 = await statusid.json();
+    if (json2.error) return reject(false);
+    if (json2.status == 'finished') {
+      status = true;
+      resolve(json2);
+      break;
+    }
+    if (json2.status == 'error') return reject(false);
+  }
+});
+
+export {
+  bestFormat,
+  getUrlDl,
+};

+ 314 - 0
lib/youtubedl.js

@@ -0,0 +1,314 @@
+import axios from 'axios';
+import crypto from 'crypto';
+
+const ogmp3 = {
+  api: {
+    base: "https://api3.apiapi.lat",
+    endpoints: {
+      a: "https://api5.apiapi.lat",
+      b: "https://api.apiapi.lat",
+      c: "https://api3.apiapi.lat"
+    }
+  },
+
+  headers: {
+    'authority': 'api.apiapi.lat',
+    'content-type': 'application/json',
+    'origin': 'https://ogmp3.lat',
+    'referer': 'https://ogmp3.lat/',
+    'user-agent': 'Postify/1.0.0'
+  },
+ 
+  formats: {
+    video: ['240', '360', '480', '720', '1080'],
+    audio: ['64', '96', '128', '192', '256', '320']
+  },
+
+  default_fmt: {
+    video: '720',
+    audio: '320'
+  },
+
+  restrictedTimezones: new Set(["-330", "-420", "-480", "-540"]),
+
+  utils: {
+    hash: () => {
+      const array = new Uint8Array(16);
+      crypto.getRandomValues(array);
+      return Array.from(array, byte => byte.toString(16).padStart(2, "0")).join("");
+    },
+
+    encoded: (str) => {
+      let result = "";
+      for (let i = 0; i < str.length; i++) {
+        result += String.fromCharCode(str.charCodeAt(i) ^ 1);
+      }
+      return result;
+    },
+
+    enc_url: (url, separator = ",") => {
+      const codes = [];
+      for (let i = 0; i < url.length; i++) {
+        codes.push(url.charCodeAt(i));
+      }
+      return codes.join(separator).split(separator).reverse().join(separator);
+    }
+  },
+
+  isUrl: str => {
+    try {
+      const url = new URL(str);
+      const hostname = url.hostname.toLowerCase();
+      const b = [/^(.+\.)?youtube\.com$/, /^(.+\.)?youtube-nocookie\.com$/, /^youtu\.be$/];
+      return b.some(a => a.test(hostname)) && !url.searchParams.has("playlist");
+    } catch (_) {
+      return false;
+    }
+  },
+
+  youtube: url => {
+    if (!url) return null;
+    const b = [
+      /youtube\.com\/watch\?v=([a-zA-Z0-9_-]{11})/,
+      /youtube\.com\/embed\/([a-zA-Z0-9_-]{11})/,
+      /youtube\.com\/v\/([a-zA-Z0-9_-]{11})/,
+      /youtube\.com\/shorts\/([a-zA-Z0-9_-]{11})/,
+      /youtu\.be\/([a-zA-Z0-9_-]{11})/
+    ];
+    for (let a of b) {
+      if (a.test(url)) return url.match(a)[1];
+    }
+    return null;
+  },
+
+  request: async (endpoint, data = {}, method = 'post') => {
+    try {
+      const ae = Object.values(ogmp3.api.endpoints);
+      const be = ae[Math.floor(Math.random() * ae.length)];
+      
+      const fe = endpoint.startsWith('http') ? endpoint : `${be}${endpoint}`;
+
+      const { data: response } = await axios({
+        method,
+        url: fe,
+        data: method === 'post' ? data : undefined,
+        headers: ogmp3.headers
+      });
+      return {
+        status: true,
+        code: 200,
+        data: response
+      };
+    } catch (error) {
+      return {
+        status: false,
+        code: error.response?.status || 500,
+        error: error.message
+      };
+    }
+  },
+
+  async checkStatus(id) {
+    try {
+      const c = this.utils.hash();
+      const d = this.utils.hash();
+      const endpoint = `/${c}/status/${this.utils.encoded(id)}/${d}/`;
+
+      const response = await this.request(endpoint, {
+        data: id
+      });
+
+      return response;
+    } catch (error) {
+      return {
+        status: false,
+        code: 500,
+        error: error.message
+      };
+    }
+  },
+
+  async checkProgress(data) {
+    try {
+      let attempts = 0;
+      let maxAttempts = 300;
+
+      while (attempts < maxAttempts) {
+        attempts++;
+
+        const res = await this.checkStatus(data.i);
+        if (!res.status) {
+          await new Promise(resolve => setTimeout(resolve, 2000));
+          continue;
+        }
+
+        const stat = res.data;
+        if (stat.s === "C") {
+          return stat;
+        }
+
+        if (stat.s === "P") {
+          await new Promise(resolve => setTimeout(resolve, 2000));
+          continue;
+        }
+
+        return null;
+      }
+
+      return null;
+    } catch (error) {
+      return null;
+    }
+  },
+
+  download: async (link, format, type = 'video') => {
+    if (!link) {
+      return {
+        status: false,
+        code: 400,
+        error: "¿Que es lo que descarga? ingresa en link idiota"
+      };
+    }
+
+    if (!ogmp3.isUrl(link)) {
+      return {
+        status: false,
+        code: 400,
+        error: "Ese link es invalido pon en link de un video de youtube valido idiotas 🗿"
+      };
+    }
+
+    if (type !== 'video' && type !== 'audio') {
+      return {
+        status: false,
+        code: 400,
+        error: "Elejir video o audio?"
+      };
+    }
+
+    if (!format) {
+      format = type === 'audio' ? ogmp3.default_fmt.audio : ogmp3.default_fmt.video;
+    }
+
+    const valid_fmt = type === 'audio' ? ogmp3.formats.audio : ogmp3.formats.video;
+    if (!valid_fmt.includes(format)) {
+      return {
+        status: false,
+        code: 400,
+        error: `Formato ${format} no es valido para ${type} pero puedes elegir unos de estos: ${valid_fmt.join(', ')}`
+      };
+    }
+
+    const id = ogmp3.youtube(link);
+    if (!id) {
+      return {
+        status: false,
+        code: 400,
+        error: "Donde pito esta la ID del video? no puedo extraerlo hdp"
+      };
+    }
+
+    try {
+      let retries = 0;
+      const maxRetries = 20;
+
+      while (retries < maxRetries) {
+        retries++;
+        const c = ogmp3.utils.hash();
+        const d = ogmp3.utils.hash();
+        const req = {
+          data: ogmp3.utils.encoded(link),
+          format: type === 'audio' ? "0" : "1",
+          referer: "https://ogmp3.cc",
+          mp3Quality: type === 'audio' ? format : null,
+          mp4Quality: type === 'video' ? format : null,
+          userTimeZone: new Date().getTimezoneOffset().toString()
+        };
+
+        const resx = await ogmp3.request(
+          `/${c}/init/${ogmp3.utils.enc_url(link)}/${d}/`,
+          req
+        );
+
+        if (!resx.status) {
+          if (retries === maxRetries) return resx;
+          continue;
+        }
+
+        const data = resx.data;
+        if (data.le) {
+          return {
+            status: false,
+            code: 400,
+            error: "La duración del video es demasiado larga, amigo. El máximo es de 3 horas, no puedes superar eso, ¿entendido? 👍🏻"
+          };
+        }
+
+        if (data.i === "blacklisted") {
+          const limit = ogmp3.restrictedTimezones.has(new Date().getTimezoneOffset().toString()) ? 5 : 100;
+          return {
+            status: false,
+            code: 429,
+            error: `Limite de descargas diarias (${limit}) alcanzados, intente de nuevo mas tardes.`
+          };
+        }
+
+        if (data.e || data.i === "invalid") {
+          return {
+            status: false,
+            code: 400,
+            error: "El video no existe. No sé si fue eliminado o si YouTube lo restringió... no tengo idea 🤷🏻"
+          };
+        }
+
+        if (data.s === "C") {
+          return {
+            status: true,
+            code: 200,
+            result: {
+              title: data.t || "Kagak tau",
+              type: type,
+              format: format,
+              thumbnail: `https://i.ytimg.com/vi/${id}/maxresdefault.jpg`,
+              download: `${ogmp3.api.base}/${ogmp3.utils.hash()}/download/${ogmp3.utils.encoded(data.i)}/${ogmp3.utils.hash()}/`,
+              id: id,
+              quality: format
+            }
+          };
+        }
+
+        const prod = await ogmp3.checkProgress(data);
+        if (prod && prod.s === "C") {
+          return {
+            status: true,
+            code: 200,
+            result: {
+              title: prod.t || "Kagak tau",
+              type: type,
+              format: format,
+              thumbnail: `https://i.ytimg.com/vi/${id}/maxresdefault.jpg`,
+              download: `${ogmp3.api.base}/${ogmp3.utils.hash()}/download/${ogmp3.utils.encoded(prod.i)}/${ogmp3.utils.hash()}/`,
+              id: id,
+              quality: format
+            }
+          };
+        }
+      }
+
+      return {
+        status: false,
+        code: 500,
+        error: "Estoy exhausto.... Ya intenté hacer la solicitud varias veces y sigue sin funcionar, así que dejaré la solicitud para más tarde, ¡hasta luego! 🤨"
+      };
+
+    } catch (error) {
+      return {
+        status: false,
+        code: 500,
+        error: error.message
+      };
+    }
+  }
+};
+
+export { ogmp3 };

File diff suppressed because it is too large
+ 0 - 0
lib/yt-savetube.js


+ 584 - 0
main.js

@@ -0,0 +1,584 @@
+process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = '1'
+import './config.js' 
+import { createRequire } from 'module'
+import path, { join } from 'path'
+import {fileURLToPath, pathToFileURL} from 'url'
+import { platform } from 'process'
+import * as ws from 'ws'
+import fs, { watchFile, unwatchFile, writeFileSync, readdirSync, statSync, unlinkSync, existsSync, readFileSync, copyFileSync, watch, rmSync, readdir, stat, mkdirSync, rename } from 'fs';
+import { promises as fsPromises } from 'fs';
+import yargs from 'yargs'
+import { spawn } from 'child_process'
+import lodash from 'lodash'
+import chalk from 'chalk'
+import syntaxerror from 'syntax-error'
+import { format } from 'util'
+import pino from 'pino'
+import Pino from 'pino'
+import { Boom } from '@hapi/boom'
+import { makeWASocket, protoType, serialize } from './lib/simple.js'
+import {Low, JSONFile} from 'lowdb'
+import PQueue from 'p-queue'
+import store from './lib/store.js'
+import readline from 'readline'
+import NodeCache from 'node-cache' 
+import { startSubBots } from './plugins/jadibot.js';
+import pkg from 'google-libphonenumber'
+const { PhoneNumberUtil } = pkg
+const phoneUtil = PhoneNumberUtil.getInstance()
+const { makeInMemoryStore, DisconnectReason, useMultiFileAuthState, MessageRetryMap, fetchLatestBaileysVersion, makeCacheableSignalKeyStore } = await import('@whiskeysockets/baileys')
+const { CONNECTING } = ws
+const { chain } = lodash
+const PORT = process.env.PORT || process.env.SERVER_PORT || 3000
+protoType()
+serialize()
+global.__filename = function filename(pathURL = import.meta.url, rmPrefix = platform !== 'win32') {
+  return rmPrefix ? /file:\/\/\//.test(pathURL) ? fileURLToPath(pathURL) : pathURL : pathToFileURL(pathURL).toString();
+}; global.__dirname = function dirname(pathURL) {
+  return path.dirname(global.__filename(pathURL, true));
+}; global.__require = function require(dir = import.meta.url) {
+  return createRequire(dir);
+};
+//global.API = (name, path = '/', query = {}, apikeyqueryname) => (name in global.APIs ? global.APIs[name] : name) + path + (query || apikeyqueryname ? '?' + new URLSearchParams(Object.entries({...query, ...(apikeyqueryname ? {[apikeyqueryname]: global.APIKeys[name in global.APIs ? global.APIs[name] : name]} : {})})) : '')
+global.timestamp = { start: new Date }
+const __dirname = global.__dirname(import.meta.url);
+//const __dirname = join(fileURLToPath(import.meta.url), '..');
+global.opts = new Object(yargs(process.argv.slice(2)).exitProcess(false).parse());
+//global.prefix = new RegExp('^[' + (opts['prefix'] || '*/i!#$%+£¢€¥^°=¶∆×÷π√✓©®&.\\-.@').replace(/[|\\{}()[\]^$+*.\-\^]/g, '\\$&') + ']')
+
+//news
+const databasePath = path.join(__dirname, 'database');
+if (!fs.existsSync(databasePath)) fs.mkdirSync(databasePath);
+
+const paths = {
+users: path.join(databasePath, 'users'),
+chats: path.join(databasePath, 'chats'),
+settings: path.join(databasePath, 'settings'),
+msgs: path.join(databasePath, 'msgs'),
+sticker: path.join(databasePath, 'sticker'),
+stats: path.join(databasePath, 'stats'),
+};
+
+Object.values(paths).forEach(dir => {
+if (!fs.existsSync(dir)) fs.mkdirSync(dir);
+});
+
+const queue = new PQueue({ concurrency: 5 });
+
+global.db = {
+data: {
+users: {},
+chats: {},
+settings: {},
+msgs: {},
+sticker: {},
+stats: {},
+},
+};
+
+function getFilePath(category, id) {
+return path.join(paths[category], `${id}.json`);
+}
+
+async function readFile(category, id) {
+const filePath = getFilePath(category, id);
+const db = new Low(new JSONFile(filePath));
+await db.read();
+db.data = db.data || {};
+return db.data;
+}
+
+async function writeFile(category, id, data) {
+const filePath = getFilePath(category, id);
+const db = new Low(new JSONFile(filePath));
+await db.read();
+db.data = { ...db.data, ...data };    
+await db.write();
+}
+
+global.db.readData = async function (category, id) {
+if (!global.db.data[category][id]) {
+const data = await queue.add(() => readFile(category, id));
+global.db.data[category][id] = data;
+}
+return global.db.data[category][id];
+};
+
+global.db.writeData = async function (category, id, data) {
+global.db.data[category][id] = { ...global.db.data[category][id], ...data };
+await queue.add(() => writeFile(category, id, global.db.data[category][id]));
+};
+
+global.db.loadDatabase = async function () {
+const categories = ['users', 'chats', 'settings', 'msgs', 'sticker', 'stats'];
+const loadPromises = [];
+
+for (const category of categories) {
+const files = fs.readdirSync(paths[category]);
+for (const file of files) {
+const id = path.basename(file, '.json');
+if (category === 'users' && (id.includes('@newsletter') || id.includes('lid'))) continue;
+if (category === 'chats' && id.includes('@newsletter')) continue;
+
+loadPromises.push(queue.add(() => readFile(category, id)).then(data => {
+global.db.data[category][id] = data;
+}).catch(err => console.error(`Error cargando ${category}/${id}:`, err))
+);
+}}
+await Promise.all(loadPromises);
+console.log('Base de datos cargada');
+};
+
+global.db.save = async function () {
+const categories = ['users', 'chats', 'settings', 'msgs', 'sticker', 'stats'];
+
+for (const category of categories) {
+for (const [id, data] of Object.entries(global.db.data[category])) {
+if (Object.keys(data).length > 0) {
+if (category === 'users' && (id.includes('@newsletter') || id.includes('lid'))) continue;
+if (category === 'chats' && id.includes('@newsletter')) continue;
+
+await queue.add(() => writeFile(category, id, data))
+}}}};
+
+global.db.loadDatabase().then(() => {
+}).catch(err => console.error(err));
+
+/*global.db = new Low(/https?:\/\//.test(opts['db'] || '') ? new cloudDBAdapter(opts['db']) : new JSONFile('database.json'))
+global.DATABASE = global.db; 
+global.loadDatabase = async function loadDatabase() {
+if (global.db.READ) {
+return new Promise((resolve) => setInterval(async function() {
+if (!global.db.READ) {
+clearInterval(this);
+resolve(global.db.data == null ? global.loadDatabase() : global.db.data);
+}}, 1 * 1000));
+}
+if (global.db.data !== null) return;
+global.db.READ = true;
+await global.db.read().catch(console.error);
+global.db.READ = null;
+global.db.data = {
+users: {},
+chats: {},
+stats: {},
+msgs: {},
+sticker: {},
+settings: {},
+...(global.db.data || {}),
+};
+global.db.chain = chain(global.db.data);
+};
+loadDatabase();*/
+
+//if (global.conns instanceof Array) {console.log('Conexiones ya inicializadas...');} else {global.conns = [];}
+
+/* ------------------------------------------------*/
+
+global.creds = 'creds.json'
+global.authFile = `BotSession`
+global.authFileJB  = 'jadibts'
+global.rutaBot = join(__dirname, authFile)
+global.rutaJadiBot = join(__dirname, authFileJB)
+const respaldoDir = join(__dirname, 'BackupSession');
+const credsFile = join(global.rutaBot, global.creds);
+const backupFile = join(respaldoDir, global.creds);
+
+if (!fs.existsSync(rutaJadiBot)) {
+fs.mkdirSync(rutaJadiBot)}
+
+if (!fs.existsSync(respaldoDir)) fs.mkdirSync(respaldoDir);
+
+const {state, saveState, saveCreds} = await useMultiFileAuthState(global.authFile)
+const msgRetryCounterMap = new Map();
+const msgRetryCounterCache = new NodeCache({ stdTTL: 0, checkperiod: 0 });
+const userDevicesCache = new NodeCache({ stdTTL: 0, checkperiod: 0 });
+const {version} = await fetchLatestBaileysVersion()
+let phoneNumber = global.botNumberCode
+const methodCodeQR = process.argv.includes("qr")
+const methodCode = !!phoneNumber || process.argv.includes("code")
+const MethodMobile = process.argv.includes("mobile")
+let rl = readline.createInterface({
+input: process.stdin,
+output: process.stdout,
+terminal: true,
+})
+
+const question = (texto) => {
+rl.clearLine(rl.input, 0)
+return new Promise((resolver) => {
+rl.question(texto, (respuesta) => {
+rl.clearLine(rl.input, 0)
+resolver(respuesta.trim())
+})})
+}
+
+let opcion
+if (methodCodeQR) {
+opcion = '1'
+}
+if (!methodCodeQR && !methodCode && !fs.existsSync(`./${authFile}/creds.json`)) {
+do {
+let lineM = '⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ 》'
+opcion = await question(`╭${lineM}  
+┊ ${chalk.blueBright('╭┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅')}
+┊ ${chalk.blueBright('┊')} ${chalk.blue.bgBlue.bold.cyan('MÉTODO DE VINCULACIÓN')}
+┊ ${chalk.blueBright('╰┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅')}   
+┊ ${chalk.blueBright('╭┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅')}     
+┊ ${chalk.blueBright('┊')} ${chalk.green.bgMagenta.bold.yellow('¿CÓMO DESEA CONECTARSE?')}
+┊ ${chalk.blueBright('┊')} ${chalk.bold.redBright('⇢  Opción 1:')} ${chalk.greenBright('Código QR.')}
+┊ ${chalk.blueBright('┊')} ${chalk.bold.redBright('⇢  Opción 2:')} ${chalk.greenBright('Código de 8 digitos.')}
+┊ ${chalk.blueBright('╰┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅')}
+┊ ${chalk.blueBright('╭┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅')}     
+┊ ${chalk.blueBright('┊')} ${chalk.italic.magenta('Escriba sólo el número de')}
+┊ ${chalk.blueBright('┊')} ${chalk.italic.magenta('la opción para conectarse.')}
+┊ ${chalk.blueBright('╰┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅')} 
+╰${lineM}\n${chalk.bold.magentaBright('---> ')}`)
+if (!/^[1-2]$/.test(opcion)) {
+console.log(chalk.bold.redBright(`NO SE PERMITE NÚMEROS QUE NO SEAN ${chalk.bold.greenBright("1")} O ${chalk.bold.greenBright("2")}, TAMPOCO LETRAS O SÍMBOLOS ESPECIALES. ${chalk.bold.yellowBright("CONSEJO: COPIE EL NÚMERO DE LA OPCIÓN Y PÉGUELO EN LA CONSOLA.")}`))
+}} while (opcion !== '1' && opcion !== '2' || fs.existsSync(`./${authFile}/creds.json`))
+}
+
+console.info = () => {} 
+/*const connectionOptions = {
+logger: pino({ level: 'silent' }),
+printQRInTerminal: opcion == '1' ? true : methodCodeQR ? true : false,
+mobile: MethodMobile, 
+browser: opcion == '1' ? ['LoliBot-MD', 'Edge', '20.0.04'] : methodCodeQR ? ['LoliBot-MD', 'Edge', '20.0.04'] : ["Ubuntu", "Chrome", "20.0.04"],
+auth: {
+creds: state.creds,
+keys: makeCacheableSignalKeyStore(state.keys, Pino({ level: "fatal" }).child({ level: "fatal" })),
+},
+markOnlineOnConnect: false, 
+generateHighQualityLinkPreview: true, 
+syncFullHistory: false,
+getMessage: async (key) => {
+try {
+let jid = jidNormalizedUser(key.remoteJid);
+let msg = await store.loadMessage(jid, key.id);
+return msg?.message || "";
+} catch (error) {
+return "";
+}},
+msgRetryCounterCache: msgRetryCounterCache || new Map(),
+userDevicesCache: userDevicesCache || new Map(),
+//msgRetryCounterMap,
+defaultQueryTimeoutMs: undefined,
+cachedGroupMetadata: (jid) => global.conn.chats[jid] ?? {},
+version: [2, 3000, 1015901307],
+};*/
+
+const connectionOptions = {
+logger: pino({ level: 'silent' }),
+printQRInTerminal: opcion == '1' ? true : methodCodeQR ? true : false,
+mobile: MethodMobile, 
+auth: {
+creds: state.creds,
+keys: makeCacheableSignalKeyStore(state.keys, Pino({ level: "fatal" }).child({ level: "fatal" })),
+},
+browser: opcion == '1' ? ['KantuBot', 'Edge', '20.0.04'] : methodCodeQR ? ['KantuBot', 'Edge', '20.0.04'] : ["Ubuntu", "Chrome", "20.0.04"],
+version: version,
+generateHighQualityLinkPreview: true
+};
+    
+global.conn = makeWASocket(connectionOptions)
+
+if (!fs.existsSync(`./${authFile}/creds.json`)) {
+if (opcion === '2' || methodCode) {
+opcion = '2'
+if (!conn.authState.creds.registered) {
+let addNumber
+if (!!phoneNumber) {
+addNumber = phoneNumber.replace(/[^0-9]/g, '')
+} else {
+do {
+phoneNumber = await question(chalk.bgBlack(chalk.bold.greenBright("\n\n✳️ Escriba su número\n\nEjemplo: 5491168xxxx\n\n\n\n")))
+phoneNumber = phoneNumber.replace(/\D/g,'')
+if (!phoneNumber.startsWith('+')) {
+phoneNumber = `+${phoneNumber}`
+}
+} while (!await isValidPhoneNumber(phoneNumber))
+rl.close()
+addNumber = phoneNumber.replace(/\D/g, '')
+setTimeout(async () => {
+let codeBot = await conn.requestPairingCode(addNumber)
+codeBot = codeBot?.match(/.{1,4}/g)?.join("-") || codeBot
+console.log(chalk.bold.white(chalk.bgMagenta(`CÓDIGO DE VINCULACIÓN:`)), chalk.bold.white(chalk.white(codeBot)))
+}, 2000)
+}}}
+}
+
+conn.isInit = false
+conn.well = false
+
+if (!opts['test']) {
+setInterval(async () => {
+if (global.db.data) await global.db.save();
+if (opts['autocleartmp'] && (global.support || {}).find) {
+const tmpDirs = [os.tmpdir(), 'tmp', "jadibts"];
+tmpDirs.forEach(dir => {
+cp.spawn('find', [dir, '-amin', '2', '-type', 'f', '-delete']);
+})}}, 30 * 1000)}
+if (opts['server']) (await import('./server.js')).default(global.conn, PORT)
+
+//respaldo de la sesión
+function manageCredentials(action) {
+const credsFile = join(global.rutaBot, global.creds);
+const backupFile = join(respaldoDir, global.creds);
+if (action === 'backup' && existsSync(credsFile)) {
+copyFileSync(credsFile, backupFile);
+console.log(`[✅] Respaldo creado en ${backupFile}`);
+} else if (action === 'restore' && existsSync(backupFile)) {
+copyFileSync(backupFile, credsFile);
+console.log(`[✅] creds.json restaurado desde el respaldo`);
+}
+}
+
+setInterval(() => manageCredentials('backup'), 5 * 60 * 1000);
+
+//tmp
+async function cleanUp(type) {
+const targets = {
+tmp: join(__dirname, 'tmp'),
+session: './BotSession',
+subbots: './jadibts/'
+};
+if (type === 'tmp') {
+const files = readdirSync(targets.tmp);
+files.forEach(file => unlinkSync(join(targets.tmp, file)));
+console.log(chalk.cyan(`┏━━━━━━⪻♻️ AUTO-CLEAR 🗑️⪼━━━━━━•\n┃→ ARCHIVOS DE LA CARPETA TMP ELIMINADOS\n┗━━━━━━━━━━━━━━━━━━━━━━━━━━━•`));
+} else if (type === 'session' || type === 'subbots') {
+const dir = targets[type];
+const files = readdirSync(dir).filter(f => f.startsWith('pre-key-'));
+const threshold = Date.now() - (24 * 60 * 60 * 1000);
+for (const file of files) {
+const filePath = join(dir, file);
+const { mtimeMs } = statSync(filePath);
+if (mtimeMs < threshold) await unlinkSync(filePath);
+}
+console.log(chalk.bold.cyanBright(`\n╭» 🔵 ${type} 🔵\n│→ SESIONES NO ESENCIALES ELIMINADAS\n╰― ― ― ― ― ― ― ― ― ― ― ― ― ― ― ― ― ― ― 🗑️♻️`));
+}}
+
+setInterval(() => cleanUp('tmp'), 1000 * 60 * 3);
+setInterval(() => { cleanUp('session'); cleanUp('subbots'); }, 1000 * 60 * 10);
+
+async function connectionUpdate(update) {  
+const {connection, lastDisconnect, isNewLogin} = update
+global.stopped = connection
+if (isNewLogin) conn.isInit = true
+const code = lastDisconnect?.error?.output?.statusCode || lastDisconnect?.error?.output?.payload?.statusCode
+if (code && code !== DisconnectReason.loggedOut && conn?.ws.socket == null) {
+await global.reloadHandler(true).catch(console.error)
+//console.log(await global.reloadHandler(true).catch(console.error));
+global.timestamp.connect = new Date
+}
+if (global.db.data == null) loadDatabase()
+if (update.qr != 0 && update.qr != undefined || methodCodeQR) {
+if (opcion == '1' || methodCodeQR) {
+console.log(chalk.cyan('✅ ESCANEA EL CÓDIGO QR EXPIRA EN 45 SEGUNDOS ✅.'))
+}}
+if (connection == 'open') {
+console.log(chalk.bold.greenBright('\n▣─────────────────────────────···\n│\n│❧ 𝙲𝙾𝙽𝙴𝙲𝚃𝙰𝙳𝙾 𝙲𝙾𝚁𝚁𝙴𝙲𝚃𝙰𝙼𝙴𝙽𝚃𝙴 𝙰𝙻 𝚆𝙷𝙰𝚃𝚂𝙰𝙿𝙿 ✅\n│\n▣─────────────────────────────···'))
+await joinChannels(conn)
+}
+let reason = new Boom(lastDisconnect?.error)?.output?.statusCode
+if (connection === 'close') {
+if (reason === DisconnectReason.badSession) {
+conn.logger.error(`[ ⚠ ] Sesión incorrecta, por favor elimina la carpeta ${global.authFile} y escanea nuevamente.`);
+} else if (reason === DisconnectReason.connectionClosed) {
+conn.logger.warn(`[ ⚠ ] Conexión cerrada, reconectando...`);
+manageCredentials('restore');
+await global.reloadHandler(true).catch(console.error)
+} else if (reason === DisconnectReason.connectionLost) {
+conn.logger.warn(`[ ⚠ ] Conexión perdida con el servidor, reconectando...`);
+manageCredentials('restore');
+await global.reloadHandler(true).catch(console.error)
+} else if (reason === DisconnectReason.connectionReplaced) {
+conn.logger.error(`[ ⚠ ] Conexión reemplazada, se ha abierto otra nueva sesión. Por favor, cierra la sesión actual primero.`);
+} else if (reason === DisconnectReason.loggedOut) {
+conn.logger.error(`[ ⚠ ] Conexion cerrada, por favor elimina la carpeta ${global.authFile} y escanea nuevamente.`);
+await global.reloadHandler(true).catch(console.error)
+} else if (reason === DisconnectReason.restartRequired) {
+conn.logger.info(`[ ⚠ ] Reinicio necesario, reinicie el servidor si presenta algún problema.`);
+await global.reloadHandler(true).catch(console.error)
+} else if (reason === DisconnectReason.timedOut) {
+conn.logger.warn(`[ ⚠ ] Tiempo de conexión agotado, reconectando...`);
+await global.reloadHandler(true).catch(console.error) //process.send('reset')
+} else {
+conn.logger.warn(`[ ⚠ ] Razón de desconexión desconocida. ${reason || ''}: ${connection || ''}`);
+}}}
+
+process.on('uncaughtException', console.error);
+
+let isInit = true;
+let handler = await import('./handler.js');
+global.reloadHandler = async function(restatConn) {
+try {
+const Handler = await import(`./handler.js?update=${Date.now()}`).catch(console.error);
+if (Object.keys(Handler || {}).length) handler = Handler;
+} catch (e) {
+console.error(e);
+}
+if (restatConn) {
+const oldChats = global.conn.chats;
+try {
+global.conn.ws.close();
+} catch { }
+conn.ev.removeAllListeners();
+global.conn = makeWASocket(connectionOptions, {chats: oldChats});
+isInit = true;
+}
+if (!isInit) {
+conn.ev.off('messages.upsert', conn.handler);
+conn.ev.off('group-participants.update', conn.participantsUpdate);
+conn.ev.off('groups.update', conn.groupsUpdate);
+conn.ev.off('message.delete', conn.onDelete);
+conn.ev.off('call', conn.onCall);
+conn.ev.off('connection.update', conn.connectionUpdate);
+conn.ev.off('creds.update', conn.credsUpdate);
+}
+
+conn.welcome = 'HOLAA!! @user\n\n『Bienvenido A *@subject*』\n\n_`Recuerda leer las reglas del grupo para no tener ningun problema 🐣`_'
+conn.bye = 'Bueno, se fue @user 👋\n\nQue lo atropelle un tren 👻`'
+conn.spromote = 'Hey @user ya forma parte de staff 👑'
+conn.sdemote = '@user ya no eres admins'
+conn.sDesc = 'La descripción ha sido cambiada a \n@desc'
+conn.sSubject = 'El nombre del grupo ha sido cambiado a \n@group'
+conn.sIcon = 'El icono del grupo ha sido cambiado'
+conn.sRevoke = 'El enlace del grupo ha sido cambiado a \n@revoke'
+conn.handler = handler.handler.bind(global.conn);
+conn.participantsUpdate = handler.participantsUpdate.bind(global.conn);
+conn.groupsUpdate = handler.groupsUpdate.bind(global.conn);
+conn.onDelete = handler.deleteUpdate.bind(global.conn);
+conn.onCall = handler.callUpdate.bind(global.conn);
+conn.connectionUpdate = connectionUpdate.bind(global.conn);
+conn.credsUpdate = saveCreds.bind(global.conn, true);
+conn.ev.on('messages.upsert', conn.handler);
+conn.ev.on('group-participants.update', conn.participantsUpdate);
+conn.ev.on('groups.update', conn.groupsUpdate);
+conn.ev.on('message.delete', conn.onDelete);
+conn.ev.on('call', conn.onCall);
+conn.ev.on('connection.update', conn.connectionUpdate);
+conn.ev.on('creds.update', conn.credsUpdate);
+isInit = false
+return true
+}
+
+//Arranque nativo para subbots
+await startSubBots();
+
+/*const pluginFolder = global.__dirname(join(__dirname, './plugins/index'));
+const pluginFilter = (filename) => /\.js$/.test(filename);
+global.plugins = {};
+async function filesInit() {
+for (const filename of readdirSync(pluginFolder).filter(pluginFilter)) {
+try {
+const file = global.__filename(join(pluginFolder, filename));
+const module = await import(file);
+global.plugins[filename] = module.default || module;
+} catch (e) {
+conn.logger.error(e);
+delete global.plugins[filename];
+}}}
+filesInit().then((_) => Object.keys(global.plugins)).catch(console.error)*/
+
+const pluginFolder = global.__dirname(join(__dirname, './plugins/index'))
+const pluginFilter = (filename) => /\.js$/.test(filename)
+global.plugins = {}
+async function filesInit() {
+for (const filename of readdirSync(pluginFolder).filter(pluginFilter)) {
+try {
+const file = global.__filename(join(pluginFolder, filename))
+const module = await import(file)
+global.plugins[filename] = module.default || module
+} catch (e) {
+conn.logger.error(e)
+delete global.plugins[filename]
+}}}
+filesInit().then((_) => Object.keys(global.plugins)).catch(console.error)
+
+global.reload = async (_ev, filename) => {
+if (pluginFilter(filename)) {
+const dir = global.__filename(join(pluginFolder, filename), true)
+if (filename in global.plugins) {
+if (existsSync(dir)) conn.logger.info(` SE ACTULIZADO - '${filename}' CON ÉXITO`)
+else {
+conn.logger.warn(`SE ELIMINO UN ARCHIVO : '${filename}'`)
+return delete global.plugins[filename];
+}
+} else conn.logger.info(`SE DETECTO UN NUEVO PLUGINS : '${filename}'`)
+const err = syntaxerror(readFileSync(dir), filename, {
+sourceType: 'module',
+allowAwaitOutsideFunction: true,
+});
+if (err) conn.logger.error(`SE DETECTO UN ERROR DE SINTAXIS | SYNTAX ERROR WHILE LOADING '${filename}'\n${format(err)}`);
+else {
+try {
+const module = (await import(`${global.__filename(dir)}?update=${Date.now()}`));
+global.plugins[filename] = module.default || module;
+} catch (e) {
+conn.logger.error(`HAY UN ERROR REQUIERE EL PLUGINS '${filename}\n${format(e)}'`);
+} finally {
+global.plugins = Object.fromEntries(Object.entries(global.plugins).sort(([a], [b]) => a.localeCompare(b)));
+}}}};
+Object.freeze(global.reload);
+watch(pluginFolder, global.reload);
+await global.reloadHandler();
+async function _quickTest() {
+const test = await Promise.all([
+spawn('ffmpeg'),
+spawn('ffprobe'),
+spawn('ffmpeg', ['-hide_banner', '-loglevel', 'error', '-filter_complex', 'color', '-frames:v', '1', '-f', 'webp', '-']),
+spawn('convert'),
+spawn('magick'),
+spawn('gm'),
+spawn('find', ['--version']),
+].map((p) => {
+return Promise.race([
+new Promise((resolve) => {
+p.on('close', (code) => {
+resolve(code !== 127);
+});
+}),
+new Promise((resolve) => {
+p.on('error', (_) => resolve(false));
+})]);
+}));
+
+const [ffmpeg, ffprobe, ffmpegWebp, convert, magick, gm, find] = test;
+const s = global.support = {ffmpeg, ffprobe, ffmpegWebp, convert, magick, gm, find};
+Object.freeze(global.support);
+}
+
+function redefineConsoleMethod(methodName, filterStrings) {
+const originalConsoleMethod = console[methodName]
+console[methodName] = function() {
+const message = arguments[0]
+if (typeof message === 'string' && filterStrings.some(filterString => message.includes(atob(filterString)))) {
+arguments[0] = ""
+}
+originalConsoleMethod.apply(console, arguments)
+}}
+
+_quickTest().then(() => conn.logger.info('Ƈᴀʀɢᴀɴᴅᴏ....\n'))
+.catch(console.error)
+
+async function isValidPhoneNumber(number) {
+try {
+number = number.replace(/\s+/g, '')
+// Si el número empieza con '+521' o '+52 1', quitar el '1'
+if (number.startsWith('+521')) {
+number = number.replace('+521', '+52'); // Cambiar +521 a +52
+} else if (number.startsWith('+52') && number[4] === '1') {
+number = number.replace('+52 1', '+52'); // Cambiar +52 1 a +52
+}
+const parsedNumber = phoneUtil.parseAndKeepRawInput(number)
+return phoneUtil.isValidNumber(parsedNumber)
+} catch (error) {
+return false
+}}
+
+async function joinChannels(conn) {
+for (const channelId of Object.values(global.ch)) {
+await conn.newsletterFollow(channelId).catch(() => {})
+}}

BIN
media/Menu1.jpg


BIN
media/Menu2.jpg


BIN
media/Menu3.jpg


BIN
media/Menu4.jpg


BIN
media/a.mp3


BIN
menu.jpg


+ 93 - 0
package.json

@@ -0,0 +1,93 @@
+{
+"name": "LoliBot-MD",
+"version": "1.9.5", 
+"description": "Super Bot WhatsApp",
+"main": "index.js",
+"type": "module",
+    
+"directories": {
+"lib": "lib",
+"src": "src",
+"plugins": "plugins" },
+    
+"scripts": {
+"start": "node index.js",
+"qr": "node index.js qr",
+"code": "node index.js code",
+"test": "node test.js",
+"test2": "nodemon index.js" },
+    
+"homepage": "https://github.com/elrebelde21/LoliBot-MD",
+"author": {
+"name": "elrebelde21" },
+    
+"repository": {
+"type": "git",
+"url": "git+https://github.com/elrebelde21/LoliBot-MD.git" },
+
+"bugs": {
+"url": "https://github.com/elrebelde21/LoliBot-MD/issues" },
+"license": "GPL-3.0-or-later",
+"dependencies": {
+"@whiskeysockets/baileys": "github:elrebelde21/baileys",
+"@adiwajshing/keyed-db": "^0.2.4",
+"@bochilteam/scraper": "^5.0.1",
+"@vitalets/google-translate-api": "^8.0.0",
+"awesome-phonenumber": "^3.4.0",
+"axios": "^1.7.9",
+"hispamemes": "^1.0.7",
+"archiver": "^7.0.1",
+"acrcloud": "^1.4.0",
+"form-data": "^4.0.0",
+"cfonts": "^3.3.0",
+"chalk": "^5.4.1",
+"url-file-size": "^1.0.5-1",
+"cheerio": "1.0.0-rc.12", 
+"colors": "1.4.0",
+"express": "^4.18.1",
+"file-type": "^18.0.0",
+"fluent-ffmpeg": "^2.1.2",
+"formdata-node": "^5.0.0",
+"@shineiichijo/marika": "^2.0.6",
+"google-libphonenumber": "3.2.38",
+"human-readable": "^0.2.1",
+"jsdom": "^20.0.1",
+"node-os-utils": "^1.3.6",
+"club-atticus": "1.1.3",
+"link-preview-js": "^3.0.0",
+"lodash": "^4.17.21",
+"lowdb": "^3.0.0",
+"mongoose": "^6.6.5",
+"p-queue": "^8.1.0",
+"node-fetch": "^3.2.10",
+"node-gtts": "^2.0.2",
+"node-webpmux": "^3.1.3",
+"perf_hooks": "^0.0.1",
+"pino": "^8.6.1",
+"pino-pretty": "^9.1.1",
+"qrcode": "^1.5.1",
+"qrcode-terminal": "^0.12.0",
+"readline": "^1.3.0",
+"similarity": "^1.2.1",
+"g-i-s": "^2.1.6",
+"socket.io": "^4.5.2",
+"syntax-error": "^1.4.0",
+"terminal-image": "^2.0.0",
+"url-regex-safe": "^3.0.0",
+"emoji-api": "^2.0.1",
+"translate-google-api": "^1.0.4",
+"yt-search": "^2.12.1",
+"openai": "^3.3.0",
+"megajs": "^1.1.3",
+"mime-types": "^2.1.35",
+"fuzzysort": "^1.0.0", 
+"api-dylux": "^1.8.3",
+"diskusage": "^1.2.0",
+"yargs": "^17.6.0",
+"@hiudyy/ytdl": "^0.2.3",   
+"ytdl-core": "latest"    
+},
+"optionalDependencies": {
+"wa-sticker-formatter": "^4.3.2",
+"moment-timezone": "^0.5.37"
+}}

+ 118 - 0
plugins/_allantilink.js

@@ -0,0 +1,118 @@
+import fetch from 'node-fetch'  
+
+const isLinkTik = /tiktok.com/i 
+const isLinkYt = /youtube.com|youtu.be/i 
+const isLinkTel = /telegram.com|t.me/i 
+const isLinkFb = /facebook.com|fb.me/i 
+const isLinkIg = /instagram.com/i 
+const isLinkTw = /twitter.com|x.com/i 
+const isLinkDc = /discord.com|discord.gg/i 
+const isLinkTh = /threads.net/i 
+const isLinkTch = /twitch.tv/i
+  
+let handler = m => m
+handler.before = async function (m, { conn, isAdmin, isBotAdmin, isOwner, isROwner }) {
+if (!m.isGroup) return 
+if (!isAdmin || !isOwner || !isROwner || m.fromMe || !isBotAdmin) return
+
+let chat = global.db.data.chats[m.chat]
+let bot = global.db.data.settings[this.user.jid] || {}
+let delet = m.key.participant
+let bang = m.key.id
+let toUser = `${m.sender.split("@")[0]}`
+let aa = toUser + '@s.whatsapp.net'
+    
+const isAntiLinkTik = isLinkTik.exec(m.text)
+const isAntiLinkYt = isLinkYt.exec(m.text)
+const isAntiLinkTel = isLinkTel.exec(m.text)
+const isAntiLinkFb = isLinkFb.exec(m.text)
+const isAntiLinkIg = isLinkIg.exec(m.text)
+const isAntiLinkTw = isLinkTw.exec(m.text)
+const isAntiLinkDc = isLinkDc.exec(m.text)
+const isAntiLinkTh = isLinkTh.exec(m.text)
+const isAntiLinkTch = isLinkTch.exec(m.text)
+ 
+if (chat.antiTiktok && isAntiLinkTik) {  
+//if (chat.delete) return //conn.sendMessage(m.chat, { text: mid.mAdvertencia + mid.mAntiDelete }, { quoted: m })  
+if (isBotAdmin) {
+await conn.reply(m.chat, `*「 ANTILINK DETECTADO 」*\n@${toUser} 🤨 Rompiste las reglas del Grupo sera eliminado....`, null, { mentions: [aa] })
+await conn.sendMessage(m.chat, { delete: { remoteJid: m.chat, fromMe: false, id: bang, participant: delet }})
+let remove = await conn.groupParticipantsUpdate(m.chat, [m.sender], 'remove')
+if (remove[0].status === '404') return
+}}
+    
+if (chat.antiYoutube && isAntiLinkYt) {
+//if (chat.delete) return //conn.sendMessage(m.chat, { text: mid.mAdvertencia + mid.mAntiDelete }, { quoted: m })  
+if (isBotAdmin) {
+await conn.reply(m.chat, `*「 ANTILINK DETECTADO 」*\n@${toUser} 🤨 Rompiste las reglas del Grupo sera eliminado....`, null, { mentions: [aa] })
+await conn.sendMessage(m.chat, { delete: { remoteJid: m.chat, fromMe: false, id: bang, participant: delet }})
+let remove = await conn.groupParticipantsUpdate(m.chat, [m.sender], 'remove')
+if (remove[0].status === '404') return
+}}
+    
+if (chat.antiTelegram && isAntiLinkTel) {
+//if (chat.delete) return //conn.sendMessage(m.chat, { text: mid.mAdvertencia + mid.mAntiDelete }, { quoted: m })   
+if (isBotAdmin) {
+await conn.reply(m.chat, `*「 ANTILINK DETECTADO 」*\n@${toUser} 🤨 Rompiste las reglas del Grupo sera eliminado....`, null, { mentions: [aa] })
+await conn.sendMessage(m.chat, { delete: { remoteJid: m.chat, fromMe: false, id: bang, participant: delet }})
+let remove = await conn.groupParticipantsUpdate(m.chat, [m.sender], 'remove')
+if (remove[0].status === '404') return
+}}
+    
+if (chat.antiFacebook && isAntiLinkFb) {
+//if (chat.delete) return //conn.sendMessage(m.chat, { text: mid.mAdvertencia + mid.mAntiDelete }, { quoted: m })  
+if (isBotAdmin) {
+await conn.reply(m.chat, `*「 ANTILINK DETECTADO 」*\n@${toUser} 🤨 Rompiste las reglas del Grupo sera eliminado....`, null, { mentions: [aa] })
+await conn.sendMessage(m.chat, { delete: { remoteJid: m.chat, fromMe: false, id: bang, participant: delet }})
+let remove = await conn.groupParticipantsUpdate(m.chat, [m.sender], 'remove')
+if (remove[0].status === '404') return 
+}}
+    
+if (chat.antiInstagram && isAntiLinkIg) {
+//if (chat.delete) return //conn.sendMessage(m.chat, { text: mid.mAdvertencia + mid.mAntiDelete }, { quoted: m })  
+if (isBotAdmin) {
+await conn.reply(m.chat, `*「 ANTILINK DETECTADO 」*\n@${toUser} 🤨 Rompiste las reglas del Grupo sera eliminado....`, null, { mentions: [aa] })
+await conn.sendMessage(m.chat, { delete: { remoteJid: m.chat, fromMe: false, id: bang, participant: delet }})
+let remove = await conn.groupParticipantsUpdate(m.chat, [m.sender], 'remove')
+if (remove[0].status === '404') return 
+}}
+    
+if (chat.antiTwitter && isAntiLinkTw) {
+//if (chat.delete) return //conn.sendMessage(m.chat, { text: mid.mAdvertencia + mid.mAntiDelete }, { quoted: m })  
+if (isBotAdmin) {
+await conn.reply(m.chat, `*「 ANTILINK DETECTADO 」*\n@${toUser} 🤨 Rompiste las reglas del Grupo sera eliminado....`, null, { mentions: [aa] })
+await conn.sendMessage(m.chat, { delete: { remoteJid: m.chat, fromMe: false, id: bang, participant: delet }})
+let remove = await conn.groupParticipantsUpdate(m.chat, [m.sender], 'remove')
+if (remove[0].status === '404') return
+}}
+
+if (chat.antiDiscord && isAntiLinkDc) {
+//if (chat.delete) return //conn.sendMessage(m.chat, { text: mid.mAdvertencia + mid.mAntiDelete }, { quoted: m })  
+if (isBotAdmin) {
+await conn.reply(m.chat, `*「 ANTILINK DETECTADO 」*\n@${toUser} 🤨 Rompiste las reglas del Grupo sera eliminado....`, null, { mentions: [aa] })
+await conn.sendMessage(m.chat, { delete: { remoteJid: m.chat, fromMe: false, id: bang, participant: delet }})
+let remove = await conn.groupParticipantsUpdate(m.chat, [m.sender], 'remove')
+if (remove[0].status === '404') return
+}}
+
+if (chat.antiThreads && isAntiLinkTh) {
+//if (chat.delete) return conn.sendMessage(m.chat, { text: mid.mAdvertencia + mid.mAntiDelete }, { quoted: m })  
+if (isBotAdmin) {
+await conn.reply(m.chat, `*「 ANTILINK DETECTADO 」*\n@${toUser} 🤨 Rompiste las reglas del Grupo sera eliminado....`, null, { mentions: [aa] })
+await conn.sendMessage(m.chat, { delete: { remoteJid: m.chat, fromMe: false, id: bang, participant: delet }})
+let remove = await conn.groupParticipantsUpdate(m.chat, [m.sender], 'remove')
+if (remove[0].status === '404') return
+}}
+
+if (chat.antiTwitch && isAntiLinkTch) {
+//if (chat.delete) return conn.sendMessage(m.chat, { text: mid.mAdvertencia + mid.mAntiDelete }, { quoted: m })  
+if (isBotAdmin) {
+await conn.reply(m.chat, `*「 ANTILINK DETECTADO 」*\n@${toUser} 🤨 Rompiste las reglas del Grupo sera eliminado....`, null, { mentions: [aa] })
+await conn.sendMessage(m.chat, { delete: { remoteJid: m.chat, fromMe: false, id: bang, participant: delet }})
+let remove = await conn.groupParticipantsUpdate(m.chat, [m.sender], 'remove')
+if (remove[0].status === '404') return
+}}
+
+return !0
+}
+export default handler

+ 33 - 0
plugins/_antiArabe.js

@@ -0,0 +1,33 @@
+let handler = m => m;
+
+handler.before = async function (m, { conn }) {
+const prefijosProhibidos = ['91', '92', '222', '93', '265', '61', '62', '966', '229', '40', '49', '20', '963', '967', '234', '210', '212'];
+const bot = global.db.data.settings[conn.user.jid] || {};
+const senderNumber = m.sender.split('@')[0];
+const user = global.db.data.users[m.sender]
+const text = (m.text || '').toLowerCase();
+
+if (["120363371008200788@newsletter", "120363371008200788@newsletter"].includes(m.chat)) return;
+if (m.fromMe) return;
+if (!bot.anticommand) return;
+
+const allowedCommands = ['piedra', 'papel', 'tijera', 'menu', 'estado', 'bots', 'serbot', 'jadibot', 'code'];
+if (allowedCommands.some(cmd => text.includes(cmd))) {
+if (user.banned && m.text.includes('PIEDRA') || m.text.includes('PAPEL') || m.text.includes('TIJERA') ||  m.text.includes('code') ||  m.text.includes('estado') || m.text.includes('bots') ||  m.text.includes('serbot') || m.text.includes('jadibot')) {
+user.banned = false;
+}
+return !0; 
+}
+
+if (user.banned) return !1;
+const esProhibido = prefijosProhibidos.some(prefijo => senderNumber.startsWith(prefijo));
+if (esProhibido) {
+user.banned = true;
+console.log(`⚠️ Usuarios baneado ${m.sender}`)
+await conn.reply(m.chat, `⚠️ @${m.sender.split`@`[0]} ha sido baneado.\nPor orden de mi owner no puedes usar el bot.\n\nPARA USAR EL BOT HAZTE UN SUB BOT CON:\n/jadibot\n\n⚠️ \`\`\`Serás Baneados\`\`\` ⚠️`, m, { mentions: [m.sender] });
+return !1;
+}
+return !0;
+};
+
+export default handler;

+ 27 - 0
plugins/_antifakes.js

@@ -0,0 +1,27 @@
+let handler = m => m;
+
+handler.before = async function (m, { conn, isAdmin, isBotAdmin, isOwner, isROwner }) {
+if (!m.isGroup) return !1;
+let chat = global.db.data.chats[m.chat];
+let bot = global.db.data.settings[conn.user.jid] || {};
+    
+if (isBotAdmin && chat.antifake && !isAdmin && !isOwner && !isROwner) {
+const fkontak = {"key": { "participants": "0@s.whatsapp.net", "remoteJid": "status@broadcast", "fromMe": false, "id": "Halo" }, "message": { "contactMessage": { "vcard": `BEGIN:VCARD\nVERSION:3.0\nN:Sy;Bot;;;\nFN:y\nitem1.TEL;waid=${m.sender.split('@')[0]}:${m.sender.split('@')[0]}\nitem1.X-ABLabel:Ponsel\nEND:VCARD` } }, "participant": "0@s.whatsapp.net" };
+
+const prefijosProhibidos = ['91', '92', '222', '93', '265', '61', '62', '966', '229', '40', '49', '20', '963', '967', '234', '210', '212'];
+
+const senderNumber = m.sender.split('@')[0]; 
+if (prefijosProhibidos.some(prefijo => senderNumber.startsWith(prefijo))) {
+let texto = `*@${senderNumber}* En este grupo no está permitido el uso de números con prefijos prohibidos, será expulsado...`;
+
+try {
+await conn.reply(m.chat, texto, fkontak, m);
+let response = await conn.groupParticipantsUpdate(m.chat, [m.sender], 'remove');
+if (response[0].status === "404") return; 
+} catch (error) {
+console.error(`Error al expulsar a ${senderNumber}:`, error);
+}}}
+return !0;
+};
+
+export default handler;

+ 59 - 0
plugins/_antilink.js

@@ -0,0 +1,59 @@
+import ws from 'ws';
+
+export async function before(m, { conn, isAdmin, isBotAdmin, isOwner, isROwner, participants }) {
+if (!m.isGroup) return;
+if (isAdmin || isOwner || m.fromMe || isROwner) return;
+let chat = global.db.data.chats[m.chat];
+let delet = m.key.participant;
+let bang = m.key.id;
+const user = `@${m.sender.split`@`[0]}`;
+const groupAdmins = participants.filter(p => p.admin);
+const listAdmin = groupAdmins.map((v, i) => `*» ${i + 1}. @${v.id.split('@')[0]}*`).join('\n');
+let bot = global.db.data.settings[this.user.jid] || {};
+
+let linkRegex1 = /chat.whatsapp.com\/([0-9A-Za-z]{20,24})|5chat-whatzapp\.vercel\.app/i;
+let linkRegex2 = /whatsapp.com\/channel\/([0-9A-Za-z]{20,24})/i;
+
+const isGroupLink = linkRegex1.exec(m.text) || linkRegex2.exec(m.text);
+const grupo = `https://chat.whatsapp.com`;
+
+const allBots = [conn, ...global.conns.filter((conn) => conn.user && conn.ws.socket && conn.ws.socket.readyState !== ws.CLOSED)];
+
+const isThisBotAdmin = isBotAdmin;
+const botAdmins = allBots.filter(bot => {
+const botParticipants = participants.find(p => p.id === bot.user.jid);
+return botParticipants && botParticipants.admin;
+});
+
+let shouldAct = false;
+if (botAdmins.length > 0) {
+shouldAct = isThisBotAdmin && botAdmins.some(bot => bot.user.jid === conn.user.jid);
+} else if (allBots.length > 1) {
+const firstBot = allBots[0]; 
+shouldAct = conn.user.jid === firstBot.user.jid;
+} else {
+return; 
+}
+
+if (!shouldAct) return;
+        
+if (isAdmin && chat.antiLink && m.text.includes(grupo)) return m.reply('*El AntiLink Esta activo pero que salvarte eres admin 😎!*');
+
+if (chat.antiLink && isGroupLink && !isAdmin) {
+if (isBotAdmin) {
+const linkThisGroup = `https://chat.whatsapp.com/${await this.groupInviteCode(m.chat)}`;
+if (m.text.includes(linkThisGroup)) return;
+}
+
+await conn.sendMessage(m.chat, { text: `*「 ANTILINK DETECTADO 」*\n\n${user} 🤨 Rompiste las reglas del Grupo sera eliminado....`, mentions: [m.sender] }, { quoted: m, ephemeralExpiration: 24*60*100, disappearingMessagesInChat: 24*60*100 });
+
+if (!isBotAdmin) return conn.sendMessage(m.chat, { text: `*Te salvarte gil, no soy admin no te puedo eliminar*`, mentions: [...groupAdmins.map(v => v.id)] }, { quoted: m });
+if (isBotAdmin) {
+await conn.sendMessage(m.chat, { delete: { remoteJid: m.chat, fromMe: false, id: bang, participant: delet } });
+let responseb = await conn.groupParticipantsUpdate(m.chat, [m.sender], 'remove');
+if (responseb[0].status === "404") return;
+}} else if (!bot.restrict) {
+return m.reply('*𝙀𝙡 𝙥𝙧𝙤𝙥𝙞𝙚𝙩𝙖𝙧𝙞𝙤 𝙙𝙚𝙡 𝙗𝙤𝙩 𝙣𝙤 𝙩𝙞𝙚𝙣𝙚 𝙖𝙘𝙩𝙞𝙫𝙖𝙙𝙤 𝙚𝙡 𝙧𝙚𝙨𝙩𝙧𝙞𝙘𝙞𝙤𝙣 (𝙚𝙣𝙖𝙗𝙡𝙚 𝙧𝙚𝙨𝙩𝙧𝙞𝙘𝙩) 𝙘𝙤𝙣𝙩𝙖𝙘𝙩𝙚 𝙘𝙤𝙣 𝙚𝙡 𝙥𝙖𝙧𝙖 𝙦𝙪𝙚 𝙡𝙤𝙨 𝙝𝙖𝙗𝙞𝙡𝙞𝙩𝙚*');
+}
+return !0;
+}

+ 62 - 0
plugins/_antilink2.js

@@ -0,0 +1,62 @@
+let linkRegex = /https:/i
+export async function before(m, { isAdmin, isBotAdmin, text }) {
+  if (m.isBaileys && m.fromMe)
+    return !0
+  if (!m.isGroup) return !1
+  
+  // Asegurarse de que chat existe y tiene un valor predeterminado
+  let chat = global.db.data.chats[m.chat] || {};
+  
+  let delet = m.key.participant
+  let bang = m.key.id
+  const user = `@${m.sender.split`@`[0]}`;
+  
+  // Asegurarse de que bot tiene un valor predeterminado
+  let bot = global.db.data.settings[this.user.jid] || {};
+  
+  const isGroupLink = linkRegex.exec(m.text)
+  
+  // Comprobar si chat.antiLink2 existe antes de usarlo
+  if (chat && chat.antiLink2 && isGroupLink && !isAdmin) {
+    if (isBotAdmin) {
+      try {
+        const linkThisGroup = `https://chat.whatsapp.com/${await this.groupInviteCode(m.chat)}`
+        const linkThisGroup2 = `https://www.youtube.com/`
+        const linkThisGroup3 = `https://youtu.be/`
+        if (m.text.includes(linkThisGroup)) return !0
+        if (m.text.includes(linkThisGroup2)) return !0
+        if (m.text.includes(linkThisGroup3)) return !0
+      } catch (e) {
+        console.error('Error al obtener el código de invitación del grupo', e);
+      }
+    }    
+    
+    await conn.sendMessage(m.chat, {
+      text: `*「 ANTILINK DETECTADO 」*\n\n${user} 🤨 Rompiste las reglas del Grupo sera eliminado....`, 
+      mentions: [m.sender]
+    }, {quoted: m})
+    
+    if (!isBotAdmin) return m.reply('*Te salvarte gil, no soy admin no te puedo eliminar*')  
+    
+    if (isBotAdmin) {
+      try {
+        await conn.sendMessage(m.chat, { 
+          delete: { 
+            remoteJid: m.chat, 
+            fromMe: false, 
+            id: bang, 
+            participant: delet 
+          }
+        })
+        
+        let responseb = await conn.groupParticipantsUpdate(m.chat, [m.sender], 'remove')
+        if (responseb[0].status === "404") return
+      } catch (e) {
+        console.error('Error al eliminar mensaje o participante', e);
+      }
+    } else if (!bot.restrict) {
+      return m.reply('*𝙀𝙡 𝙥𝙧𝙤𝙥𝙞𝙚𝙩𝙖𝙧𝙞𝙤 𝙙𝙚𝙡 𝙗𝙤𝙩 𝙣𝙤 𝙩𝙞𝙚𝙣𝙚 𝙖𝙘𝙩𝙞𝙫𝙖𝙙𝙤 𝙚𝙡 𝙧𝙚𝙨𝙩𝙧𝙞𝙘𝙘𝙞𝙤́𝙣 (𝙚𝙣𝙖𝙗𝙡𝙚 𝙧𝙚𝙨𝙩𝙧𝙞𝙘𝙩) 𝙘𝙤𝙣𝙩𝙖𝙘𝙩𝙚 𝙘𝙤𝙣 𝙚𝙡 𝙥𝙖𝙧𝙖 𝙦𝙪𝙚 𝙡𝙤𝙨 𝙝𝙖𝙗𝙞𝙡𝙞𝙩𝙚*')
+    }
+  }
+  return !0
+} 

+ 114 - 0
plugins/_antiprivado.js

@@ -0,0 +1,114 @@
+import ws from 'ws';
+
+// Caché local para metadatos de grupos
+const groupMetadataCache = {};
+
+export async function before(m, { conn, isAdmin, isBotAdmin, isOwner, isROwner }) {
+  try {
+    // Verificar que chat existe antes de usarlo
+    let chat = global.db.data.chats[m.chat] || {};
+    let user = global.db.data.users[m.sender] || {};
+    let setting = global.db.data.settings[this.user.jid] || {};
+    
+    // Usar setting con verificación
+    let prefixRegex = new RegExp('^[' + (setting.prefix || '').replace(/[|\\{}()[\]^$+*.\-\^]/g, '\\$&') + ']');
+    
+    const users = [...new Set([...global.conns.filter((conn) => conn.user && conn.ws.socket && conn.ws.socket.readyState !== ws.CLOSED).map((conn) => conn)])];
+    
+    // ===== IMPLEMENTACIÓN CON CACHÉ PARA EVITAR RATE LIMITS =====
+    let participants = [];
+    if (m.isGroup) {
+      // Verificar si ya tenemos el metadata en caché
+      if (groupMetadataCache[m.chat] && (Date.now() - groupMetadataCache[m.chat].timestamp < 60000)) {
+        // Usar caché si existe y no ha expirado (60 segundos)
+        participants = groupMetadataCache[m.chat].participants;
+      } else {
+        try {
+          // Si no está en caché o expiró, hacer la llamada a la API
+          const metadata = await conn.groupMetadata(m.chat).catch(e => ({}));
+          if (metadata && metadata.participants) {
+            participants = metadata.participants;
+            // Guardar en caché con timestamp
+            groupMetadataCache[m.chat] = {
+              participants: metadata.participants,
+              timestamp: Date.now()
+            };
+          }
+        } catch (e) {
+          console.error('Error al obtener metadata del grupo:', e);
+          // En caso de error, usar los datos que ya tengamos
+          participants = (conn.chats[m.chat] || {}).participants || [];
+        }
+      }
+    }
+    
+    // Optimizar las búsquedas con Map para mejor rendimiento
+    const participantsMap = new Map(participants.map(p => [p.id, p]));
+    
+    const mainBotInGroup = participantsMap.has(global.conn.user.jid);
+    
+    // Verificar que chat.primaryBot existe antes de acceder
+    const primaryBot = chat.primaryBot || null;
+    const primaryBotConnected = primaryBot ? users.some(conn => conn.user.jid === primaryBot) : false;
+    const primaryBotInGroup = primaryBot ? participantsMap.has(primaryBot) : false;
+      
+    if (!global.db.data.users[m.sender]) global.db.data.users[m.sender] = {};
+    if (!global.db.data.users[m.sender].mensaje) global.db.data.users[m.sender].mensaje = {};
+    if (!global.db.data.users[m.sender].mensaje[m.chat]) global.db.data.users[m.sender].mensaje[m.chat] = 0;
+    global.db.data.users[m.sender].mensaje[m.chat]++;
+
+    if (m.isGroup) {
+      if (primaryBot) {
+        if (primaryBotConnected && primaryBotInGroup) {
+          if (this.user.jid !== primaryBot) throw !1; 
+        }
+        else if (mainBotInGroup) {
+          if (this.user.jid !== global.conn.user.jid) throw !1;
+        }
+      }
+    }
+
+    if (m.fromMe) return
+    if (m.isGroup) return !1
+    if (!m.message) return !0 
+    if (["120363371008200788@newsletter", "120363371008200788@newsletter"].includes(m.chat)) return;
+    
+    // Usar expresiones regulares para comprobaciones más eficientes
+    const allowedTerms = /PIEDRA|PAPEL|TIJERA|menu|estado|code|Code|bots|serbot|jadibot|reg|verificar|Serbot|Jadibot|jadibot code|serbot code|jadibot --code|serbot --code/i;
+    if (m.text && allowedTerms.test(m.text)) return !0;
+    
+    if (!user.warnPv) user.warnPv = false;
+
+    // Verificar que setting existe antes de usar antiPrivate
+    if (setting && setting.antiPrivate && !isOwner && !isROwner) {
+      if (user.warnPv) {
+        console.log(`[AntiPrivate]`);
+        throw !1; 
+      }
+
+      if (!user.warnPv) {
+        // Verificar que nna2 está definido, o usar un valor predeterminado
+        const nna2 = global.nna2 || 'https://chat.whatsapp.com/grupo_oficial';
+        m.reply(`Hola, está prohibido usar los comandos en privado...\n\n*\`🔰 SI QUIERES HACERTE UN SUB BOT, USA LOS SIGUIENTES COMANDOS:\`*\n/serbot\n/code\n\n> _*Para usar mis funciones, únete al grupo oficial 👇*_\n${nna2}`);
+        user.warnPv = true;
+        throw !1; 
+      }
+    }
+
+    if (m.text && prefixRegex.test(m.text)) {
+      this.sendPresenceUpdate('composing', m.chat)
+      this.readMessages([m.key])
+          
+      let usedPrefix = m.text.match(prefixRegex)[0]
+      let command = m.text.slice(usedPrefix.length).trim().split(' ')[0]
+    }
+  } catch (error) {
+    // Si el error es rate-limit, manejarlo silenciosamente
+    if (error.message && error.message.includes('rate-overlimit')) {
+      console.log('[RATE LIMIT] Detectado rate limit en _antiprivado.js, esperando...');
+      return !1; // Continuar sin bloquear la ejecución
+    }
+    // Para otros errores, lanzarlos normalmente
+    throw error;
+  }
+}

+ 30 - 0
plugins/_antitrabas.js

@@ -0,0 +1,30 @@
+//By @NeKosmic || https://github.com/NeKosmic/ //
+
+import * as fs from 'fs'
+
+export async function before(m, { conn, isAdmin, isBotAdmin, usedPrefix }) {
+if (m.isBaileys && m.fromMe) return !0
+if (!m.isGroup) return !1
+m.isBot = m.id.startsWith('BAE5') && m.id.length === 16 || m.id.startsWith('3EB0') && m.id.length === 12 || m.id.startsWith('3EB0') && (m.id.length === 20 || m.id.length === 22) || m.id.startsWith('B24E') && m.id.length === 20;
+if (m.isBot) return
+let chat = global.db.data.chats[m.chat]
+let bot = global.db.data.settings[this.user.jid] || {}
+let delet = m.key.participant
+let bang = m.key.id
+let name = await conn.getName(m.sender)
+let fakemek = {key: {participant: "0@s.whatsapp.net","remoteJid": "0@s.whatsapp.net"},"message": {"groupInviteMessage": {"groupJid": "5217121649714-5217121649714@g.us","inviteCode": "m","groupName": "P", "caption": '𝙺𝚊𝚗𝚝𝚞 - 𝙱𝚘𝚝', 'jpegThumbnail': null}}}
+if (chat.antiTraba && m.text.length > 5000) { //Cantidad máxima de caracteres aceptados en un mensaje//
+if (isAdmin) return conn.sendMessage(m.chat, { text: `⚠️El administrador @${m.sender.split("@")[0]} acaba de enviar un texto que contiene muchos caracteres -.-!`, mentions: [m.sender] }, { quoted: fakemek })
+conn.sendButton(m.chat, `*[ ! ] Se detecto un mensaje que contiene muchos caracteres [ ! ]*\n`, `${isBotAdmin ? '' : 'No soy administrador, no puedo hacer nada :/'}`, null, [['ᴅᴇsᴀᴄᴛɪᴠᴀ ᴀɴᴛɪᴛʀᴀʙᴀ', `/disable antitraba`]], null, null, m)
+//await conn.sendButton(m.chat, `*[ ! ] Se detecto un mensaje que contiene muchos caracteres [ ! ]*\n`, `${isBotAdmin ? '' : 'No soy administrador, no puedo hacer nada :/'}`, author, ['[  ]', usedPrefix+'apagar antitraba'], fakemek )
+if (isBotAdmin) {
+conn.sendMessage(m.chat, { delete: { remoteJid: m.chat, fromMe: false, id: bang, participant: delet }})
+setTimeout(() => { 
+conn.sendMessage(m.chat, { text: `Marcar el chat como leido ✓\n${"\n".repeat(400)}\n• El número : wa.me/${m.sender.split("@")[0]}\n• Alias : ${name}\n‼️Acaba de enviar un texto que contiene muchos caracteres que puede ocasionar fallos en los dispositivos`, mentions: [m.sender] }, { quoted: fakemek })
+}, 0)
+setTimeout(() => { 
+conn.groupParticipantsUpdate(m.chat, [m.sender], 'remove')
+}, 1000)} else if (!bot.restrict) return m.reply(`Este comando esta desactivado por mi jefe`)
+}
+return !0
+} 

+ 142 - 0
plugins/_autodetec.js

@@ -0,0 +1,142 @@
+let WAMessageStubType = (await import(global.baileys)).default
+import { readdirSync, unlinkSync, existsSync, promises as fs, rmSync } from 'fs';
+import path from 'path';
+export async function before(m, { conn, participants, groupMetadata}) {
+if (!m.messageStubType || !m.isGroup) return
+let pp = await conn.profilePictureUrl(m.messageStubParameters[0], 'image').catch(_ => 'https://telegra.ph/file/2a1d71ab744b55b28f1ae.jpg')
+let img = await (await fetch(`${pp}`)).buffer()
+let usuario = `@${m.sender.split`@`[0]}` 
+let fkontak = { "key": { "participants":"0@s.whatsapp.net", "remoteJid": "status@broadcast", "fromMe": false, "id": "Halo" }, "message": { "contactMessage": { "vcard": `BEGIN:VCARD\nVERSION:3.0\nN:Sy;Bot;;;\nFN:y\nitem1.TEL;waid=${m.sender.split('@')[0]}:${m.sender.split('@')[0]}\nitem1.X-ABLabel:Ponsel\nEND:VCARD` }}, "participant": "0@s.whatsapp.net" }
+let chat = global.db.data.chats[m.chat]
+let users = participants.map(u => conn.decodeJid(u.id))
+const groupAdmins = participants.filter(p => p.admin)
+const listAdmin = groupAdmins.map((v, i) => `*» ${i + 1}. @${v.id.split('@')[0]}*`).join('\n')
+
+/*if (chat.detect && m.messageStubType == 2) {
+const chatId = m.isGroup ? m.chat : m.sender;
+const uniqid = chatId.split('@')[0];
+const sessionPath = './BotSession/';
+const files = await fs.readdir(sessionPath);
+let filesDeleted = 0;
+for (const file of files) {
+if (file.includes(uniqid)) {
+await fs.unlink(path.join(sessionPath, file));
+filesDeleted++;
+console.log(`⚠️ Eliminacion session (PreKey) que provocan el undefined el chat`)}}
+
+} else*/ if (chat.detect && m.messageStubType == 21) {
+await this.sendMessage(m.chat, { text: `${usuario} \`𝙃𝘼𝙎 𝘾𝘼𝙈𝘽𝙄𝘼𝘿𝙊 𝙀𝙇 𝙉𝙊𝙈𝘽𝙍𝙀́ 𝘿𝙀𝙇 𝙂𝙍𝙐𝙋𝙊 𝘼:\`\n\n> *${m.messageStubParameters[0]}*`, mentions: [m.sender], mentions: [...groupAdmins.map(v => v.id)] }, { quoted: fkontak, ephemeralExpiration: 24*60*100, disappearingMessagesInChat: 24*60*100}) 
+} else if (chat.detect && m.messageStubType == 22) {
+await this.sendMessage(m.chat, { text: `${usuario} \`𝙃𝘼𝙎 𝘾𝘼𝙈𝘽𝙄𝘼𝘿𝙊 𝙇𝘼𝙎 𝙁𝙊𝙏𝙊 𝘿𝙀𝙇 𝙂𝙍𝙐𝙋𝙊\``, mentions: [m.sender] }, { quoted: fkontak, ephemeralExpiration: 24*60*100, disappearingMessagesInChat: 24*60*100}) 
+} else if (chat.detect && m.messageStubType == 24) {
+await this.sendMessage(m.chat, { text: `${usuario} 𝙉𝙐𝙀𝙑𝘼 𝘿𝙀𝙎𝘾𝙍𝙄𝙋𝘾𝙄𝙊𝙉 𝘿𝙀𝙇 𝙂𝙍𝙐𝙋𝙊 𝙀𝙎:\n\n${m.messageStubParameters[0]}`, mentions: [m.sender] }, { quoted: fkontak, ephemeralExpiration: 24*60*100, disappearingMessagesInChat: 24*60*100})
+} else if (chat.detect && m.messageStubType == 25) {
+await this.sendMessage(m.chat, { text: `🔒 𝘼𝙃𝙊𝙍𝘼 *${m.messageStubParameters[0] == 'on' ? '𝙎𝙊𝙇𝙊 𝘼𝘿𝙈𝙄𝙉𝙎' : '𝙏𝙊𝘿𝙊𝙎'}* 𝙋𝙐𝙀𝘿𝙀 𝙀𝘿𝙄𝙏𝘼𝙍 𝙇𝘼 𝙄𝙉𝙁𝙊𝙍𝙈𝘼𝘾𝙄𝙊𝙉 𝘿𝙀𝙇 𝙂𝙍𝙐𝙋𝙊`, mentions: [m.sender] }, { quoted: fkontak, ephemeralExpiration: 24*60*100, disappearingMessagesInChat: 24*60*100})
+} else if (chat.detect && m.messageStubType == 26) {
+await this.sendMessage(m.chat, { text: `𝙀𝙇 𝙂𝙍𝙐𝙋𝙊 *${m.messageStubParameters[0] == 'on' ? '𝙀𝙎𝙏𝘼 𝘾𝙀𝙍𝙍𝘼𝘿𝙊 🔒' : '𝙀𝙎𝙏𝘼 𝘼𝘽𝙄𝙀𝙍𝙏𝙊 🔓'}*\n ${m.messageStubParameters[0] == 'on' ? '𝙎𝙊𝙇𝙊 𝙇𝙊𝙎 𝘼𝘿𝙈𝙄𝙉𝙎 𝙋𝙐𝙀𝘿𝙀𝙉 𝙀𝙎𝘾𝙍𝙄𝘽𝙄𝙍' : '𝙔𝘼 𝙋𝙐𝙀𝘿𝙀𝙉 𝙀𝙎𝘾𝙍𝙄𝘽𝙄𝙍 𝙏𝙊𝘿𝙊𝙎'} 𝙀𝙉 𝙀𝙎𝙏𝙀 𝙂𝙍𝙐𝙋𝙊`, mentions: [m.sender] }, { quoted: fkontak, ephemeralExpiration: 24*60*100, disappearingMessagesInChat: 24*60*100})
+} else if (chat.welcome && m.messageStubType == 27 && this.user.jid != global.conn.user.jid) { 
+let subject = groupMetadata.subject
+let descs = groupMetadata.desc || "*ᴜɴ ɢʀᴜᴘᴏ ɢᴇɴɪᴀ😸*\n *sɪɴ ʀᴇɢʟᴀ 😉*";
+let userName = `${m.messageStubParameters[0].split`@`[0]}`;
+let defaultWelcome = `┏━━━━━━━━━━━━\n┃──〘 *WELCOME* 〙──\n┃━━━━━━━━━━━━\n┃ *Hola @${userName} 👋 Bienvenido a*\n┃ *_${subject} ✨_*\n┃ *_🥳 Disfruta de tu_*\n┃ *_estadía en el grupo 🥳_*\n┃\n┗━━━━━━━━━━━`;
+let textWel = chat.sWelcome ? chat.sWelcome
+.replace(/@user/g, `@${userName}`)
+.replace(/@group/g, subject) 
+.replace(/@desc/g, descs)
+: defaultWelcome;
+        
+await this.sendMessage(m.chat, { text: textWel, 
+contextInfo:{
+forwardingScore: 9999999,
+isForwarded: true, 
+mentionedJid:[m.sender, m.messageStubParameters[0]],
+externalAdReply: {
+showAdAttribution: true,
+renderLargerThumbnail: true,
+thumbnailUrl: pp, 
+title: "BIENVENID@ 😄",
+body: [wm, ' ' + wm + '😊', '🌟'].getRandom(),
+containsAutoReply: true,
+mediaType: 1, 
+sourceUrl: [nna, nna2, yt].getRandom()}}}, { quoted: fkontak }) 
+} else if (chat.welcome && (m.messageStubType == 28 || m.messageStubType == 32) && this.user.jid != global.conn.user.jid ) {
+let subject = groupMetadata.subject;
+let userName = `${m.messageStubParameters[0].split`@`[0]}`;
+let defaultBye = `┏━━━━━━━━━━━━\n┃──〘 *ADIOS* 〙───\n┃━━━━━━━━━━━━\n┃ *_☠ Se fue @${userName}_* \n┃ *_Que dios lo bendiga️_* \n┃ *_Y lo atropelle un tren 😇_*\n┗━━━━━━━━━━`;
+let textBye = chat.sBye ? chat.sBye
+.replace(/@user/g, `@${userName}`)
+.replace(/@group/g, subject)
+: defaultBye;
+await this.sendMessage(m.chat, { text: textBye, 
+contextInfo:{
+forwardingScore: 9999999,
+isForwarded: true, 
+mentionedJid:[m.sender, m.messageStubParameters[0]],
+externalAdReply: {
+showAdAttribution: true,
+renderLargerThumbnail: true,
+thumbnailUrl: pp, 
+title: "BYE 👋",
+body: [wm, ' ' + wm + '😊', '🌟'].getRandom(),
+containsAutoReply: true,
+mediaType: 1, 
+sourceUrl: [nna, nna2, nnaa, yt, md].getRandom()}}}, { quoted: fkontak }) 
+} else if (chat.detect && m.messageStubType == 29) {
+let subject = groupMetadata.subject;
+let defaultPromote = `@${m.messageStubParameters[0].split`@`[0]} 𝘼𝙃𝙊𝙍𝘼 𝙀𝙎 𝘼𝘿𝙈𝙄𝙉 𝙀𝙉 𝙀𝙎𝙏𝙀 𝙂𝙍𝙐𝙋𝙊\n\n😼🫵𝘼𝘾𝘾𝙄𝙊𝙉 𝙍𝙀𝘼𝙇𝙄𝙕𝘼𝘿𝘼 𝙋𝙊𝙍: ${usuario}`
+let textAdm = chat.sPromote ? chat.sPromote
+.replace(/@user/g, `@${m.messageStubParameters[0].split`@`[0]}`)
+.replace(/@autor/g, `${usuario}`)
+.replace(/@group/g, subject) 
+: defaultPromote;
+await this.sendMessage(m.chat, { text: textAdm, mentions: [m.sender, m.messageStubParameters[0], ...groupAdmins.map(v => v.id)] }, { quoted: fkontak, ephemeralExpiration: 24*60*100, disappearingMessagesInChat: 24*60*100})
+} else if (chat.detect && m.messageStubType == 30) {
+let subject = groupMetadata.subject;
+let defaultDemote = `@${m.messageStubParameters[0].split`@`[0]} 𝘿𝙀𝙅𝘼 𝘿𝙀 𝙎𝙀𝙍 𝘼𝘿𝙈𝙄𝙉 𝙀𝙉 𝙀𝙎𝙏𝙀 𝙂𝙍𝙐𝙋𝙊\n\n😼🫵𝘼𝘾𝘾𝙄𝙊𝙉 𝙍𝙀𝘼𝙇𝙄𝙕𝘼𝘿𝘼 𝙋𝙊𝙍: ${usuario}`
+let textAdmin = chat.sDemote ? chat.sDemote
+.replace(/@user/g, `@${m.messageStubParameters[0].split`@`[0]}`)
+.replace(/@autor/g, `${usuario}`)
+.replace(/@group/g, subject) 
+: defaultDemote;
+await this.sendMessage(m.chat, { text: textAdmin, mentions: [m.sender, m.messageStubParameters[0], ...groupAdmins.map(v => v.id)] }, { quoted: fkontak, ephemeralExpiration: 24*60*100, disappearingMessagesInChat: 24*60*100})
+} else if (chat.detect && m.messageStubType === 172 && m.messageStubParameters.length > 0) {
+const rawUser = m.messageStubParameters[0];
+const users = rawUser.split('@')[0];
+const prefijosProhibidos = ['+91', '+92', '+222', '+93', '+265', '+61', '+62', '+966', '+229', '+40', '+49', '+20', '+963', '+967', '+234', '+210', '+212'];
+const usersConPrefijo = users.startsWith('+') ? users : `+${users}`;
+
+if (chat.antifake) {
+const esProhibido = prefijosProhibidos.some(prefijo => {
+const coincide = usersConPrefijo.startsWith(prefijo);
+return coincide;
+});
+
+if (esProhibido) {
+try {
+await conn.groupRequestParticipantsUpdate(m.chat, [rawUser], 'reject');
+console.log(`Solicitud de ${usersConPrefijo} rechazada por prefijo prohibido.`);
+} catch (error) {
+console.error(`Error al rechazar la solicitud de ${usersConPrefijo}:`, error);
+}} else {
+try {
+await conn.groupRequestParticipantsUpdate(m.chat, [rawUser], 'approve');
+console.log(`Solicitud de ${usersConPrefijo} aprobada (no tiene prefijo prohibido).`);
+} catch (error) {
+console.error(`Error al aprobar la solicitud de ${usersConPrefijo}:`, error);
+}}} else {
+try {
+await conn.groupRequestParticipantsUpdate(m.chat, [rawUser], 'approve');
+console.log(`Solicitud de ${usersConPrefijo} aprobada (antifake desactivado).`);
+} catch (error) {
+console.error(`Error al aprobar la solicitud de ${usersConPrefijo}:`, error);
+}}
+return; /*
+} if (chat.detect && m.messageStubType == 72) {
+await this.sendMessage(m.chat, { text: `${usuario} 𝘾𝘼𝙈𝘽𝙄𝙊 𝙇𝘼𝙎 𝘿𝙐𝙍𝘼𝘾𝙄𝙊𝙉 𝘿𝙀𝙇 𝙇𝙊𝙎 𝙈𝙀𝙉𝙎𝘼𝙅𝙀 𝙏𝙀𝙈𝙋𝙊𝙍𝘼𝙇𝙀𝙎 𝘼 *@${m.messageStubParameters[0]}*`, mentions: [m.sender] }, { quoted: fkontak, ephemeralExpiration: 24*60*100, disappearingMessagesInChat: 24*60*100})
+}  else if (chat.detect && m.messageStubType == 123) {
+await this.sendMessage(m.chat, { text: `${usuario} *𝘿𝙀𝙎𝘼𝘾𝙏𝙄𝙑𝙊́* 𝙇𝙊𝙎 𝙈𝙀𝙉𝙎𝘼𝙅𝙀 𝙏𝙀𝙈𝙋𝙊𝙍𝘼𝙇.`, mentions: [m.sender] }, { quoted: fkontak, ephemeralExpiration: 24*60*100, disappearingMessagesInChat: 24*60*100})*/
+} else {
+console.log({messageStubType: m.messageStubType,
+messageStubParameters: m.messageStubParameters,
+type: WAMessageStubType[m.messageStubType], 
+})}}

+ 89 - 0
plugins/_autolevelup.js

@@ -0,0 +1,89 @@
+//import db from '../lib/database.js'
+import { canLevelUp } from '../lib/levelling.js'
+
+export async function before(m, { conn }) {
+  let who = m.mentionedJid && m.mentionedJid[0] ? m.mentionedJid[0] : m.fromMe ? conn.user.jid : m.sender
+ let ppch = await conn.profilePictureUrl(who, 'image').catch(_ => imageUrl.getRandom()) 
+let user = global.db.data.users[m.sender]
+let chat = global.db.data.chats[m.chat]
+if (!chat.autolevelup) return !0
+let before = user.level * 1
+while (canLevelUp(user.level, user.exp, global.multiplier))
+user.level++
+user.role = global.rpg.role(user.level).name
+if (before !== user.level) {
+    
+conn.reply(m.chat, [`*「 FELICIDADES 🤜🤛 」*\n\nSubiste de nivel sigue asi 👏\n\n*• NIVEL:* ${before} ⟿ ${user.level}\n*• RANGO:* ${user.role}\n\n_*Para ver tu XP en tiempo real coloca el comando #level*_`, `@${m.sender.split`@`[0]} Ohhh pa has alcanzado el siguiente nivel\n*• NIVEL:* ${before} ⟿ ${user.level}\n\n_*Para ver quien es esta el top coloca el comando #lb*_`, `Que pro @${m.sender.split`@`[0]} has alcanzado un nuevo nivel  👻\n\n*• Nuevo nivel:* ${user.level}\n*• Nivel anterior:* ${before}\n`].getRandom(), m, {contextInfo: {externalAdReply :{ mediaUrl: null, mediaType: 1, description: null, title: wm, body: ' 💫 𝐒𝐮𝐩𝐞𝐫 𝐁𝐨𝐭 𝐃𝐞 𝐖𝐡𝐚𝐭𝐬𝐚𝐩𝐩 🥳 ', previewType: 0, thumbnail: img.getRandom(), sourceUrl: redes.getRandom()}}})  
+
+let niv = `*${m.pushName || 'Anónimo'}* Obtiene un nuevo nivel 🥳
+
+*• Nivel anterior:* ${before} 
+*• Nivel actúal :* ${user.level}
+*• Rol:* ${user.role}
+*• Bot:* ${wm}`
+let nivell = `*${m.pushName || 'Anónimo'} Haz subido un nuevo nivel 🥳*
+
+> _*• NIVEL:* ${before} ⟿ ${user.level}_`
+let nivelll = `🥳 ${m.pushName || 'Anónimo'} Que pro Acaba de alcanzar un nuevo nivel 🥳
+
+*• Nivel:* ${before} ⟿ ${user.level}
+*• Rango:* ${user.role}
+*• Bot:* ${wm}`
+await global.conn.sendMessage(global.ch.ch1, { text: [niv, nivell, nivelll].getRandom(), contextInfo: {
+externalAdReply: {
+title: "【 🔔 Notificación General 🔔 】",
+body: '¡Haz subido de nivel 🥳!',
+thumbnailUrl: ppch, 
+sourceUrl: redes.getRandom(),
+mediaType: 1,
+showAdAttribution: false,
+renderLargerThumbnail: false
+}}}, { quoted: null })
+}}		
+
+global.rpg = {
+emoticon(text) {
+text = text.toLowerCase();
+const mapping = {
+role: '🏅',
+level: '⬆️'
+};
+for (const key in mapping) {
+if (text.includes(key)) return mapping[key];
+}
+return '';
+},
+_roles: null,
+
+generateRoles() {
+if (this._roles) return this._roles; 
+const ranks = ['NOVATO(A)', 'APRENDIS', 'EXPLORADOR(A)', 'MAESTRO(A)', 'IRON', 'PLATA', 'ORO', 'Bard', 'Necromancer', 'Warlock', 'Wizard', 'Sage', 'Priest', 'Rogue', 'Brawler', 'Archer', 'Sniper', 'Ninja', 'Samurai', 'Berserker', 'Legend', 'Champion', 'Grandmaster', 'Elder', 'Immortal', 'Nephalem', 'Eternal', 'Neptune', 'Pluto', 'Eris', 'Ascension', 'Elysium', 'Ether', 'Gaea', 'Hades', 'DIAMANTE', 'PRO EN KANTUBOT', 'SUPER PRO', 'LEGENDARIO(A)', 'Nova', 'LEYENDA', 'ESTELAR', 'TOP ASTRAL', 'ÉLITE GLOBAL'];
+    
+const subLevels = ['V', 'IV', 'III', 'II', 'I'];
+let roles = [];
+let currentLevel = 0;
+const step = 1; 
+
+ranks.forEach(rank => {
+subLevels.forEach(numeral => {
+roles.push({
+name: `${rank} ${numeral}`,
+level: currentLevel
+});
+currentLevel += step; 
+});
+});
+
+roles.sort((a, b) => b.level - a.level);
+this._roles = roles;
+return roles;
+},
+
+role(level) {
+level = parseInt(level, 10);
+if (isNaN(level)) return { name: '', level: '' };
+const roles = this.generateRoles();
+const foundRole = roles.find(r => level >= r.level);
+return foundRole || roles[roles.length - 1];
+}
+};

+ 84 - 0
plugins/_autoresponder.js

@@ -0,0 +1,84 @@
+import axios from 'axios';
+import fetch from 'node-fetch';
+import translate from '@vitalets/google-translate-api';
+import { sticker } from '../lib/sticker.js';
+import { perplexity } from '../lib/scraper.js';
+
+//let handler = m => m;
+//handler.all = async function (m, {conn}) {
+export async function before(m, { conn }) {
+let user = global.db.data.users[m.sender]
+let chat = global.db.data.chats[m.chat];
+let setting = global.db.data.settings[this.user.jid]
+let prefixRegex = new RegExp('^[' + setting.prefix.replace(/[|\\{}()[\]^$+*.\-\^]/g, '\\$&') + ']');
+
+//if (prefixRegex.test(m.text)) return true;
+if (m.mentionedJid.includes(this.user.jid)) {
+//if (m.mentionedJid.includes(this.user.jid) || (m.quoted && m.quoted.sender === this.user.jid)) {
+if (chat.simi) return;
+if (m.text.includes('PIEDRA') || m.text.includes('PAPEL') || m.text.includes('TIJERA') ||  m.text.includes('menu') ||  m.text.includes('estado') || m.text.includes('bots') ||  m.text.includes('serbot') || m.text.includes('jadibot') || m.text.includes('Video') || m.text.includes('Audio') || m.text.includes('audio') || m.text.includes('Bot') || m.text.includes('bot') || m.text.includes('Exp') || m.text.includes('diamante') || m.text.includes('kantucoins') || m.text.includes('Diamante') || m.text.includes('Kantucoins')) return !0
+if (["120363371008200788@newsletter", "120363371008200788@newsletter"].includes(m.chat)) return;
+await this.sendPresenceUpdate('composing', m.chat);
+
+async function luminsesi(q, username, logic) {
+try {
+const response = await axios.post("https://luminai.my.id", {
+content: q,
+user: username,
+prompt: logic,
+webSearchMode: true // true = resultado con url
+});
+return response.data.result;
+} catch (error) {
+console.error(error);
+}}
+
+async function perplexityIA(q, logic) {
+      try {
+        let response = await perplexity.chat([
+          { role: 'system', content: logic || syms1 },
+          { role: 'user', content: q }
+        ], 'sonar-pro');
+        if (response.status) {
+          return response.result.response;
+        } else {
+          throw new Error(`Error en Perplexity: ${response.result.error}`);
+        }
+      } catch (error) {
+        console.error('Error en Perplexity:', error);
+        return null;
+      }
+    }
+
+let query = m.text;
+let username = `${m.pushName}`;
+let txtDefault = await fetch('https://raw.githubusercontent.com/crxsmods/text/refs/heads/main/text-chatgpt').then(v => v.text());
+//await fetch('https://raw.githubusercontent.com/Skidy89/chat-gpt-jailbreak/main/Text.txt').then(v => v.text());
+let syms1 = chat.sAutorespond ? chat.sAutorespond : txtDefault
+
+if (!chat.autorespond) return 
+if (m.fromMe) return
+let result
+if (!result || result.trim().length === 0) {
+result = await perplexityIA(query, syms1);
+}
+    
+if (!result || result.trim().length === 0) {
+result = await luminsesi(query, username, syms1);
+result = result.replace(/Maaf, terjadi kesalahan saat memproses permintaan Anda/g, '').trim();
+result = result.replace(/Generated by BLACKBOX\.AI.*?https:\/\/www\.blackbox\.ai/g, '').trim();
+result = result.replace(/and for API requests replace https:\/\/www\.blackbox\.ai with https:\/\/api\.blackbox\.ai/g, '').trim();
+}
+
+if (result && result.trim().length > 0) {
+await this.reply(m.chat, result, m);
+await this.readMessages([m.key])
+} else {
+let gpt = await fetch(`${apis}/ia/gptprompt?text=${m.text}?&prompt=${syms1}`) 
+let res = await gpt.json()
+await this.reply(m.chat, res.data, m)
+}}
+return true;
+}
+
+//export default handler;

+ 35 - 0
plugins/_autosticker.js

@@ -0,0 +1,35 @@
+import {sticker} from '../lib/sticker.js';
+const handler = (m) => m;
+
+handler.all = async function(m) {
+const chat = db.data.chats[m.chat];
+const user = db.data.users[m.sender];
+
+if (chat.autosticker && m.isGroup) {
+const q = m;
+let stiker = false;
+const mime = (q.msg || q).mimetype || q.mediaType || '';
+if (/webp/g.test(mime)) return;
+if (/image/g.test(mime)) {
+const img = await q.download?.();
+if (!img) return;
+stiker = await sticker(img, false, packname, author);
+} else if (/video/g.test(mime)) {
+if (/video/g.test(mime)) if ((q.msg || q).seconds > 8) return await m.reply(`*⚠️ El video solo puede durar 8 seg*`);
+const img = await q.download();
+if (!img) return;
+stiker = await sticker(img, false, packname, author);
+} else if (m.text.split(/\n| /i)[0]) {
+if (isUrl(m.text)) stiker = await sticker(false, m.text.split(/\n| /i)[0], packname, author);
+else return;
+}
+if (stiker) {
+await conn.sendFile(m.chat, stiker, null, null, fake, {asSticker: true});
+}}
+return !0;
+};
+export default handler;
+
+const isUrl = (text) => {
+return text.match(new RegExp(/^https?:\/\/(www\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_+.~#?&/=]*)(jpe?g|gif|png|mp4)/, 'gi'));
+};

+ 26 - 0
plugins/_cmdWithMedia.js

@@ -0,0 +1,26 @@
+const { proto, generateWAMessage, areJidsSameUser } = (await import('@whiskeysockets/baileys')).default
+
+export async function all(m, chatUpdate) {
+  if (m.isBaileys) return;
+  if (!m.message) return;
+  if (!m.msg.fileSha256) return;
+  if (!(Buffer.from(m.msg.fileSha256).toString('base64') in global.db.data.sticker)) return;
+
+  const hash = global.db.data.sticker[Buffer.from(m.msg.fileSha256).toString('base64')];
+  const {text, mentionedJid} = hash;
+  const messages = await generateWAMessage(m.chat, {text: text, mentions: mentionedJid}, {
+    userJid: this.user.id,
+    quoted: m.quoted && m.quoted.fakeObj,
+  });
+  messages.key.fromMe = m.isBaileys || (m.sender === m.conn?.user?.jid)
+  messages.key.id = m.key.id
+  messages.pushName = m.pushName
+  if (m.isGroup) messages.participant = m.sender
+  const msg = {
+    ...chatUpdate,
+    messages: [proto.WebMessageInfo.fromObject(messages)],
+    type: 'append',
+  };
+  this.ev.emit('messages.upsert', msg);
+}
+ 

+ 90 - 0
plugins/_fakeReply.js

@@ -0,0 +1,90 @@
+import fetch from 'node-fetch'
+
+//let handler = m => m
+//handler.all = async function (m) {
+export async function before(m, { conn, text }) {	
+let who = m.mentionedJid && m.mentionedJid[0] ? m.mentionedJid[0] : m.fromMe ? this.user.jid : m.sender
+let pp = await this.profilePictureUrl(who, 'image').catch(_ => "https://telegra.ph/file/33bed21a0eaa789852c30.jpg")
+		
+global.canalIdGB = ["120363371008200788@newsletter", "120363178718483875@newsletter", "120363371008200788@newsletter"]
+global.canalNombreGB = ["ᴋᴀɴᴛᴜ - ʙᴏᴛ 🔥", "𝑫𝒆𝒗 𝑩𝒚 𝑪𝒓𝒙𝒔𝑴𝒐𝒅𝒔 💎", "𝐊𝐚𝐧𝐭𝐮 - 𝐁𝐨𝐭 ⚡"]
+global.channelRD = await getRandomChannel()
+
+global.fkontak = { "key": { "participants":"0@s.whatsapp.net", "remoteJid": "status@broadcast", "fromMe": false, "id": "Halo" }, "message": { "contactMessage": { "vcard": `BEGIN:VCARD\nVERSION:3.0\nN:Sy;Bot;;;\nFN:y\nitem1.TEL;waid=${m.sender.split('@')[0]}:${m.sender.split('@')[0]}\nitem1.X-ABLabel:Ponsel\nEND:VCARD` }}, "participant": "0@s.whatsapp.net" }
+	
+global.rpl = { contextInfo: { externalAdReply: { mediaUrl: nna, mediaType: 'VIDEO', description: 'Actualización/novedades', title: packname, body: 'Canal update', thumbnailUrl: pp, sourceUrl: [nna, nna2, nnaa].getRandom() }}} 
+   	
+global.fake = { contextInfo: { mentionedJid: await this.parseMention(text), forwardingScore: 1, isForwarded: true, forwardedNewsletterMessageInfo: { newsletterJid: channelRD.id, serverMessageId: '', newsletterName: channelRD.name }}}
+   
+global.fake2 = { contextInfo: { mentionedJid: null, forwardingScore: 1, isForwarded: true, forwardedNewsletterMessageInfo: { newsletterJid: channelRD.id, serverMessageId: '', newsletterName: channelRD.name }, externalAdReply: { title: wm, body: vs, mediaType: 1, renderLargerThumbnail: false, previewType: `PHOTO`, thumbnailUrl: pp, sourceUrl: redes.getRandom() }}}
+   
+global.rpyp = { contextInfo: { externalAdReply: { mediaUrl: md, mediaType: 'VIDEO', description: 'GitHub', title: 'GitHub', body: 'ˢᶦ ᵗᵉ ᵃᵍʳᵃᵈᵃ ᵉˡ ᴮᵒᵗ ᵃᵖᵒʸᵃʳᵐᵉ ᶜᵒⁿ ᵘⁿᵃ 🌟', thumbnailUrl: pp, sourceUrl: md }}}
+	
+//⊱ ━━━━━.⋅ RPG ⋅.━━━━ ⊰
+
+global.flaaa = [
+'https://flamingtext.com/net-fu/proxy_form.cgi?&imageoutput=true&script=water-logo&script=water-logo&fontsize=90&doScale=true&scaleWidth=800&scaleHeight=500&fontsize=100&fillTextColor=%23000&shadowGlowColor=%23000&backgroundColor=%23000&text=',
+'https://flamingtext.com/net-fu/proxy_form.cgi?&imageoutput=true&script=crafts-logo&fontsize=90&doScale=true&scaleWidth=800&scaleHeight=500&text=',
+'https://flamingtext.com/net-fu/proxy_form.cgi?&imageoutput=true&script=amped-logo&doScale=true&scaleWidth=800&scaleHeight=500&text=',
+'https://www6.flamingtext.com/net-fu/proxy_form.cgi?&imageoutput=true&script=sketch-name&doScale=true&scaleWidth=800&scaleHeight=500&fontsize=100&fillTextType=1&fillTextPattern=Warning!&text=',
+'https://www6.flamingtext.com/net-fu/proxy_form.cgi?&imageoutput=true&script=sketch-name&doScale=true&scaleWidth=800&scaleHeight=500&fontsize=100&fillTextType=1&fillTextPattern=Warning!&fillColor1Color=%23f2aa4c&fillColor2Color=%23f2aa4c&fillColor3Color=%23f2aa4c&fillColor4Color=%23f2aa4c&fillColor5Color=%23f2aa4c&fillColor6Color=%23f2aa4c&fillColor7Color=%23f2aa4c&fillColor8Color=%23f2aa4c&fillColor9Color=%23f2aa4c&fillColor10Color=%23f2aa4c&fillOutlineColor=%23f2aa4c&fillOutline2Color=%23f2aa4c&backgroundColor=%23101820&text=']
+
+global.cmenut = '❖––––––『'
+global.cmenub = '┊✦ '
+global.cmenuf = '╰━═┅═━––––––๑\n'
+global.cmenua = '\n⌕ ❙❘❙❙❘❙❚❙❘❙❙❚❙❘❙❘❙❚❙❘❙❙❚❙❘❙❙❘❙❚❙❘ ⌕\n     '
+global.dmenut = '*❖─┅──┅〈*'
+global.dmenub = '*┊»*'
+global.dmenub2 = '*┊*'
+global.dmenuf = '*╰┅────────┅✦*'
+global.htjava = '⫹⫺'
+global.htki = '*⭑•̩̩͙⊱•••• ☪*'
+global.htka = '*☪ ••••̩̩͙⊰•⭑*'
+global.comienzo = '• • ◕◕════'
+global.fin = '════◕◕ • •'
+global.botdate = `⫹⫺ Date :  ${moment.tz('America/Los_Angeles').format('DD/MM/YY')}` //Asia/Jakarta
+global.bottime = `𝗧 𝗜 𝗠 𝗘 : ${moment.tz('America/Los_Angeles').format('HH:mm:ss')}`//America/Los_Angeles
+global.fgif = {
+key: {
+participant : '0@s.whatsapp.net'},
+message: { 
+"videoMessage": { 
+"title": wm,
+"h": `Hmm`,
+'seconds': '999999999', 
+'gifPlayback': 'true', 
+'caption': bottime,
+'jpegThumbnail': fs.readFileSync('./media/Menu3.jpg')
+}}}
+
+/*----------------------[ SALIDA DEL GRUPO ]-----------------------*/
+if (!m.isGroup) return
+let chats = global.db.data.chats[m.chat]
+if (!chats.expired) return !0
+if (+new Date() > chats.expired) {
+await this.reply(m.chat, [`*${this.user.name}* ᴹᵉ ᵛᵒʸ ᵈᵉˡ ᵉˡ ᵍʳᵘᵖᵒ ᶠᵘᵉ ᵘⁿ ᵍᵘˢᵗᵒ ᵉˢᵗᵃ ᵃᵠᵘᶦ́ ˢᶦ ᵠᵘᶦᵉʳᵉˢ ᵠᵘᵉ ᵛᵘᵉˡᵛᵃ ᵁˢᵉʳ ᵈᵉ ⁿᵘᵉᵛᵒ ᵉˡ ᶜᵒᵐᵃⁿᵈᵒ`, `Bueno me voy de este grupo de mrd, no me agregue a grupo ptm`, `*${this.user.name}* me voy de este grupito culiado nada interesante yo queria ver teta y son puro gays aca 🤣`].getRandom()) 
+await this.groupLeave(m.chat)
+chats.expired = null
+}
+
+/*----------------------[ FIN DE PREMIUM ]-----------------------*/
+for (const user of Object.values(global.db.data.users)) {
+if (user.premiumTime != 0 && user.premium) {
+if (new Date() * 1 >= user.premiumTime) {
+user.premiumTime = 0;
+user.premium = false;
+const JID = Object.keys(global.db.data.users).find((key) => global.db.data.users[key] === user);
+const usuarioJid = JID.split`@`[0];
+const textoo = `*⚠️ @${usuarioJid} 𝚃𝚄 𝚃𝙸𝙴𝙼𝙿𝙾 𝙲𝙾𝙼𝙾 𝚄𝚂𝚄𝙰𝚁𝙸𝙾 𝙿𝚁𝙴𝙼𝙸𝚄𝙼 𝙷𝙰 𝙴𝚇𝙿𝙸𝚁𝙰𝙳𝙾, 𝚈𝙰 𝙽𝙾 𝙴𝚁𝙴𝚂 𝚄𝙽 𝚄𝚂𝚄𝙰𝚁𝙸𝙾 𝙿𝚁𝙴𝙼𝙸𝚄𝙼*`;
+await this.sendMessage(JID, {text: textoo, mentions: [JID]}, {quoted: ''});
+}}}}
+ 
+//export default handler
+
+ 
+async function getRandomChannel() {
+let randomIndex = Math.floor(Math.random() * canalIdGB.length)
+let id = canalIdGB[randomIndex]
+let nombre = canalNombreGB[randomIndex]
+return { id, nombre }
+} 	

+ 33 - 0
plugins/_simsimi.js

@@ -0,0 +1,33 @@
+import fetch from 'node-fetch';
+const handler = (m) => m;
+
+handler.before = async (m) => {
+const chat = global.db.data.chats[m.chat];
+if (chat.simi) {
+if (/^.*false|disnable|(turn)?off|0/i.test(m.text)) return;
+let textodem = m.text;
+if (m.text.includes('serbot') || m.text.includes('bots')|| m.text.includes('jadibot')|| m.text.includes('menu')|| m.text.includes('play')|| m.text.includes('play2') || m.text.includes('playdoc') || m.text.includes('tiktok') || m.text.includes('facebook') || m.text.includes('menu2') ||  m.text.includes('infobot') || m.text.includes('estado') ||  m.text.includes('ping') ||  m.text.includes('instalarbot') ||  m.text.includes('sc') || m.text.includes('sticker') ||  m.text.includes('s') || m.text.includes('wm') ||  m.text.includes('qc')) return
+if (m.fromMe) return
+try {
+await conn.sendPresenceUpdate('composing', m.chat)
+let gpt = await fetch(`${apis}/tools/simi?text=${encodeURIComponent(textodem)}`)
+let res = await gpt.json() 
+await m.reply(res.data.message) 
+} catch {
+/*SI DA ERROR USARA ESTA OTRA OPCION DE API DE IA QUE RECUERDA EL NOMBRE DE LA PERSONA*/
+if (textodem.includes('Hola')) textodem = textodem.replace('Hola', 'Hello');
+if (textodem.includes('hola')) textodem = textodem.replace('hola', 'hello');
+if (textodem.includes('HOLA')) textodem = textodem.replace('HOLA', 'HELLO');
+const reis = await fetch('https://translate.googleapis.com/translate_a/single?client=gtx&sl=auto&tl=en&dt=t&q=' + textodem);
+const resu = await reis.json();
+const nama = m.pushName || '1';
+const api = await fetch('http://api.brainshop.ai/get?bid=153868&key=rcKonOgrUFmn5usX&uid=' + nama + '&msg=' + resu[0][0][0]);
+const res = await api.json();
+const reis2 = await fetch('https://translate.googleapis.com/translate_a/single?client=gtx&sl=auto&tl=es&dt=t&q=' + res.cnt);
+const resu2 = await reis2.json()
+await m.reply(resu2[0][0][0])}
+return !0;
+}
+return true;
+};
+export default handler;

+ 171 - 0
plugins/_templateResponse.js

@@ -0,0 +1,171 @@
+// @type {import('@whiskeysockets/baileys')}
+
+const { proto, generateWAMessage, areJidsSameUser, decryptPollVote, } = (await import('@whiskeysockets/baileys')).default;
+export async function before(m, chatUpdate) {
+if (m.isBaileys) {
+return
+}
+if (!m.message) {
+return
+}
+if (!(m.message.buttonsResponseMessage || m.message.templateButtonReplyMessage || m.message.listResponseMessage || m.message.interactiveResponseMessage)) {
+return
+}
+let id
+if (m.message.buttonsResponseMessage) {
+id = m.message.buttonsResponseMessage.selectedButtonId
+} else if (m.message.templateButtonReplyMessage) {
+id = m.message.templateButtonReplyMessage.selectedId
+} else if (m.message.listResponseMessage) {
+id = m.message.listResponseMessage.singleSelectReply?.selectedRowId;
+} else if (m.message.interactiveResponseMessage) {
+id = JSON.parse(m.message.interactiveResponseMessage.nativeFlowResponseMessage.paramsJson).id
+}
+const text = m.message.buttonsResponseMessage?.selectedDisplayText || m.message.templateButtonReplyMessage?.selectedDisplayText || m.message.listResponseMessage?.title
+let isIdMessage = false
+let usedPrefix
+for (const name in global.plugins) {
+const plugin = global.plugins[name]
+if (!plugin) {
+continue
+}
+if (plugin.disabled) {
+continue
+}
+if (!opts['restrict']) {
+if (plugin.tags && plugin.tags.includes('admin')) {
+continue
+}}
+if (typeof plugin !== 'function') {
+continue
+}
+if (!plugin.command) {
+continue
+}
+const str2Regex = (str) => str.replace(/[|\\{}()[\]^$+*?.]/g, '\\$&')
+const _prefix = plugin.customPrefix ? plugin.customPrefix : this.prefix ? this.prefix : global.prefix
+const match = (_prefix instanceof RegExp ? [[_prefix.exec(id), _prefix]] : Array.isArray(_prefix) ? _prefix.map((p) => {
+const re = p instanceof RegExp ? p : new RegExp(str2Regex(p));
+return [re.exec(id), re]
+}) :
+typeof _prefix === 'string' ?
+[[new RegExp(str2Regex(_prefix)).exec(id), new RegExp(str2Regex(_prefix))]] :
+[[[], new RegExp]]
+).find((p) => p[1])
+if ((usedPrefix = (match[0] || '')[0])) {
+const noPrefix = id.replace(usedPrefix, '')
+let [command] = noPrefix.trim().split` `.filter((v) => v)
+command = (command || '').toLowerCase()
+const isId = plugin.command instanceof RegExp ?
+plugin.command.test(command) :
+Array.isArray(plugin.command) ?
+plugin.command.some((cmd) => cmd instanceof RegExp ?
+cmd.test(command) :
+cmd === command,
+) :
+typeof plugin.command === 'string' ?
+plugin.command === command :
+false
+if (!isId) {
+continue
+}
+isIdMessage = true
+}}
+const messages = await generateWAMessage(m.chat, {text: isIdMessage ? id : text, mentions: m.mentionedJid}, {
+userJid: this.user.id,
+quoted: m.quoted && m.quoted.fakeObj,
+})
+messages.key.fromMe = areJidsSameUser(m.sender, this.user.id)
+messages.key.id = m.key.id
+messages.pushName = m.name
+if (m.isGroup) {
+messages.key.participant = messages.participant = m.sender
+}
+const msg = {
+...chatUpdate,
+messages: [proto.WebMessageInfo.fromObject(messages)].map((v) => (v.conn = this, v)),
+type: 'append',
+}
+this.ev.emit('messages.upsert', msg)
+}
+
+/*const {
+  proto,
+  generateWAMessage,
+  areJidsSameUser
+} = (await import('@whiskeysockets/baileys')).default
+export async function all(m, chatUpdate) {
+  try {
+    if (m.isBaileys) return
+    if (!m.message) return
+    if (!(m.message.buttonsResponseMessage || m.message.templateButtonReplyMessage || m.message.listResponseMessage ||
+        m.message.interactiveResponseMessage)) return
+    let id = m.message.buttonsResponseMessage?.selectedButtonId || m.message.templateButtonReplyMessage?.selectedId ||
+      m.message.listResponseMessage?.singleSelectReply?.selectedRowId || JSON.parse(m.message
+        .interactiveResponseMessage?.nativeFlowResponseMessage?.paramsJson)?.id
+    let text = m.message.buttonsResponseMessage?.selectedDisplayText || m.message.templateButtonReplyMessage
+      ?.selectedDisplayText || m.message.listResponseMessage?.title || m.message.interactiveResponseMessage?.body
+      ?.text
+    let isIdMessage = false,
+      usedPrefix
+    for (let name in plugins) {
+      let plugin = plugins[name]
+      if (!plugin) continue
+      if (plugin.disabled) continue
+      if (!opts['restrict'])
+        if (plugin.tags && plugin.tags.includes('admin')) continue
+      if (typeof plugin !== 'function') continue
+      if (!plugin.command) continue
+      const str2Regex = str => str.replace(/[|\\{}()[\]^$+*?.]/g, '\\$&')
+      let _prefix = plugin.customPrefix ? plugin.customPrefix : this.prefix ? this.prefix : prefix
+      let match = (_prefix instanceof RegExp ? // RegExp Mode?
+        [
+          [_prefix.exec(id), _prefix]
+        ] : Array.isArray(_prefix) ? // Array?
+        _prefix.map(p => {
+          let re = p instanceof RegExp ? // RegExp in Array?
+            p : new RegExp(str2Regex(p))
+          return [re.exec(id), re]
+        }) : typeof _prefix === 'string' ? // String?
+        [
+          [new RegExp(str2Regex(_prefix)).exec(id), new RegExp(str2Regex(_prefix))]
+        ] : [
+          [
+            [], new RegExp
+          ]
+        ]).find(p => p[1])
+      if ((usedPrefix = (match[0] || '')[0])) {
+        let noPrefix = id.replace(usedPrefix, '')
+        let [command] = noPrefix.trim().split(' ').filter(v => v)
+        command = (command || '').toLowerCase()
+        let isId = plugin.command instanceof RegExp ? // RegExp Mode?
+          plugin.command.test(command) : Array.isArray(plugin.command) ? // Array?
+          plugin.command.some(cmd => cmd instanceof RegExp ? // RegExp in Array?
+            cmd.test(command) : cmd === command) : typeof plugin.command === 'string' ? // String?
+          plugin.command === command : false
+        if (!isId) continue
+        isIdMessage = true
+      }
+    }
+    let messages = await generateWAMessage(m.chat, {
+      text: isIdMessage ? id : text,
+      mentions: m.mentionedJid
+    }, {
+      userJid: this.user.id,
+      quoted: m.quoted?.fakeObj
+    })
+    messages.key.fromMe = areJidsSameUser(m.sender, this.user.id)
+    messages.key.id = m.key.id
+    messages.pushName = m.name
+    if (m.isGroup) messages.key.participant = messages.participant = m.sender
+    let msg = {
+      ...chatUpdate,
+      messages: [proto.WebMessageInfo.fromObject(messages)].map(v => (v.conn = this, v)),
+      type: 'append'
+    }
+    this.ev.emit('messages.upsert', msg)
+  } catch (error) {
+    console.error('Error in processing message:', error);
+  }
+}
+*/

+ 275 - 0
plugins/adult-comandos+18.js

@@ -0,0 +1,275 @@
+import axios from "axios";
+import fetch from "node-fetch";
+import moment from 'moment-timezone';
+import fs from "fs"
+const handler = async (m, {command, conn}) => {
+let porn = 'https://qu.ax/bXMB.webp'
+let porn2 = 'https://qu.ax/TxtQ.webp'
+const fakee2 = { contextInfo: { mentionedJid: null, forwardingScore: 1, isForwarded: true, forwardedNewsletterMessageInfo: { newsletterJid: channelRD.id, serverMessageId: '', newsletterName: channelRD.name }, externalAdReply: { title: "🥵 CONTENIDO +18🥵", body: "No alto para menores..", mediaType: 1, renderLargerThumbnail: false, previewType: `PHOTO`, thumbnail: imagen3, sourceUrl: redes.getRandom() }}}
+if (!db.data.chats[m.chat].modohorny && m.isGroup) {
+handler.limit = false
+conn.sendFile(m.chat, [porn, porn2].getRandom(), 'sticker.webp', '', m, true, { contextInfo: { 'forwardingScore': 200, 'isForwarded': false, externalAdReply:{ showAdAttribution: false, title: `ᴸᵒˢ ᶜᵒᵐᵃⁿᵈᵒ ʰᵒʳⁿʸ ᵉˢᵗᵃ ᵈᵉˢᵃᶜᵗᶦᵛᵃᵈᵒ ᵖᵃʳᵃ ᵃᶜᵗᶦᵛᵃʳ ᵘˢᵃʳ:`, body: '#enable modohorny', mediaType: 2, sourceUrl: md, thumbnail: imagen3}}}, { quoted: m, ephemeralExpiration: 24*60*100, disappearingMessagesInChat: 24*60*100})
+return
+}
+const horarioNsfw = db.data.chats[m.chat].horarioNsfw
+const now = moment.tz('America/Argentina/Buenos_Aires');
+const currentTime = now.format('HH:mm');
+
+if (horarioNsfw) {
+const { inicio, fin } = horarioNsfw;
+const inicioTime = moment(inicio, 'HH:mm').tz('America/Argentina/Buenos_Aires');
+const finTime = moment(fin, 'HH:mm').tz('America/Argentina/Buenos_Aires');
+const currentMoment = moment(currentTime, 'HH:mm').tz('America/Argentina/Buenos_Aires');
+let isWithinTimeRange = false;
+if (inicioTime.isAfter(finTime)) {
+if (currentMoment.isBetween(inicioTime, moment('23:59', 'HH:mm').tz('America/Argentina/Buenos_Aires')) || 
+currentMoment.isBetween(moment('00:00', 'HH:mm').tz('America/Argentina/Buenos_Aires'), finTime)) {
+isWithinTimeRange = true;
+}} else {
+if (currentMoment.isBetween(inicioTime, finTime)) {
+isWithinTimeRange = true;
+}}
+if (!isWithinTimeRange) {
+handler.limit = false
+conn.sendFile(m.chat, [porn, porn2].getRandom(), 'sticker.webp', '', m, true, { contextInfo: { 'forwardingScore': 200, 'isForwarded': false, externalAdReply:{ showAdAttribution: false, title: `ᴱˢᵗᵉ ᶜᵒᵐᵃⁿᵈᵒ ˢᵒˡᵒ ᶠᵘⁿᶜᶦᵒⁿᵃ ᵉˡ ʰᵒʳᵃʳᶦᵒ ʰᵃᵇᶦˡᶦᵗᵃᵈᵒ ᵉˡ ᵍʳᵘᵖᵒ:`, body: `${inicio} a ${fin}`, mediaType: 2, sourceUrl: md, thumbnail: imagen3}}}, { quoted: m, ephemeralExpiration: 24*60*100, disappearingMessagesInChat: 24*60*100})
+return
+}}
+ 
+if (command == 'videos') {  
+conn.sendFile(m.chat, `${apis}/nsfw/tiktok`, 'error.mp4', "😘", m, null, fakee2);
+}
+ 
+if (command == 'hentai') {
+conn.sendFile(m.chat, "https://delirius-nsfw.onrender.com/media/h/bdsm", 'error.jpg', "🥵", m, null, fakee2);
+//conn.sendFile(m.chat, "https://delirius-nsfw.onrender.com/media/h/bdsm", null, " 🥵", null, null, { viewOnce: true }, m, null, fake)
+//conn.sendButton(m.chat, '🥵', botname, "https://delirius-nsfw.onrender.com/media/h/bdsm", [['🔄 𝐒𝐈𝐆𝐔𝐈𝐄𝐍𝐓𝐄 🔄', `/${command}`]], null, null, m)
+}
+
+if (command == 'nsfwloli') {
+let nsfw = JSON.parse(fs.readFileSync('./src/nsfw/nsfwloli.json'))
+conn.sendFile(m.chat, nsfw.url, null, "🥵", null, null, { viewOnce: true }, m, null, fake)
+//conn.sendButton(m.chat, '🥵', botname, result.url, [['🔄 𝐒𝐈𝐆𝐔𝐈𝐄𝐍𝐓𝐄 🔄', `/${command}`]], null, null, m)
+}
+
+if (command == 'china') {
+conn.sendFile(m.chat, `${apis}/nsfw/corean`, 'error.jpg', "🥵", m, null, fakee2, { viewOnce: true }, null)
+//conn.sendButton(m.chat, '*Te gustó 😏*', botname, "https://deliriusapi-official.vercel.app/api/china", [['🔄 𝐒𝐈𝐆𝐔𝐈𝐄𝐍𝐓𝐄 🔄', `/${command}`]], null, null, m)
+}
+
+if (command == 'boobs') {
+conn.sendFile(m.chat, `${apis}/nsfw/boobs`, null, "Upa la paja 😱", null, null, { viewOnce: true }, m, null, fake)
+//conn.sendButton(m.chat, '*Upa la paja*', botname, "https://deliriusapi-official.vercel.app/api/boobs", [['🔄 𝐒𝐈𝐆𝐔𝐈𝐄𝐍𝐓𝐄 🔄', `/${command}`]], null, null, m)
+}
+
+if (command == 'hentai2') {
+let hentai = JSON.parse(fs.readFileSync('./src/nsfw/neko.json'))
+let hentairesult = hentai.getRandom()
+conn.sendFile(m.chat, hentairesult, null, "Upa la paja 😱", null, null, { viewOnce: true }, m, null, fake)
+//conn.sendButton(m.chat, '🥵', botname, hentairesult, [['🔄 𝐒𝐈𝐆𝐔𝐈𝐄𝐍𝐓𝐄 🔄', `/${command}`]], null, null, m)
+}
+ 
+if (command == 'porno') {
+//conn.sendButton(m.chat, '🥵 Uff pa una pajita 🥵', botname, "https://delirius-nsfw.onrender.com/media/r/ass", [['🔄 𝐒𝐈𝐆𝐔𝐈𝐄𝐍𝐓𝐄 🔄', `/${command}`]], null, null, m)
+conn.sendFile(m.chat, `${apis}/nsfw/girls`, null, "🥵 Uff pa una pajita 🥵", null, null, { viewOnce: true }, m, null, fakee2)
+}
+
+if (command == 'tetas') {
+const resError = (await axios.get(`https://raw.githubusercontent.com/elrebelde21/NovaBot-MD/master/src/nsfw/tetas.json`)).data;
+let res = await conn.getFile(`https://api-fgmods.ddns.net/api/nsfw/boobs?apikey=fg-dylux`).data;
+if (res == '' || !res || res == null) res = await resError[Math.floor(resError.length * Math.random())];
+conn.sendFile(m.chat, res, 'error.jpg', "🥵 dame lechita de hay 🥵", m, null, fakee2);
+//conn.sendButton(m.chat, `🥵 dame lechita de hay 🥵`, botname, res, [['🔄 𝐒𝐈𝐆𝐔𝐈𝐄𝐍𝐓𝐄 🔄', `/${command}`]], null, null, m)
+//conn.sendFile(m.chat, res, 'thumbnail.jpg', `listo`, m)
+}
+
+  if (command == 'pornololi') {
+    const res = (await axios.get(`https://raw.githubusercontent.com/BrunoSobrino/TheMystic-Bot-MD/master/src/JSON/nsfwloli.json`)).data;
+    const haha = await res[Math.floor(res.length * Math.random())];
+    conn.sendFile(m.chat, haha, 'error.jpg', "🥵", m, null, fakee2);
+  }
+
+if (command == 'nsfwfoot') {
+    const res = (await axios.get(`https://raw.githubusercontent.com/BrunoSobrino/TheMystic-Bot-MD/master/src/JSON/nsfwfoot.json`)).data;
+    const haha = await res[Math.floor(res.length * Math.random())];
+    conn.sendFile(m.chat, haha, null, `_${command}_`, null, null, { viewOnce: true }, m, null, fake)
+    //conn.sendMessage(m.chat, {image: {url: haha}, caption: `_${command}_`.trim()}, {quoted: m});
+  }
+
+  if (command == 'nsfwass') {
+    const res = (await axios.get(`https://raw.githubusercontent.com/BrunoSobrino/TheMystic-Bot-MD/master/src/JSON/nsfwass.json`)).data;
+    const haha = await res[Math.floor(res.length * Math.random())];
+    conn.sendFile(m.chat, haha, null, `🥵 Upa la paja 🥵`, null, null, { viewOnce: true }, m, null, fake)
+  }
+
+  if (command == 'nsfwbdsm') {
+    const res = (await axios.get(`https://raw.githubusercontent.com/BrunoSobrino/TheMystic-Bot-MD/master/src/JSON/nsfwbdsm.json`)).data;
+    const haha = await res[Math.floor(res.length * Math.random())];
+    conn.sendFile(m.chat, haha, null, `_${command}_`, null, null, { viewOnce: true }, m, null, fake)
+  }
+
+  if (command == 'nsfwcum') {
+    const res = (await axios.get(`https://raw.githubusercontent.com/BrunoSobrino/TheMystic-Bot-MD/master/src/JSON/nsfwcum.json`)).data;
+    const haha = await res[Math.floor(res.length * Math.random())];
+    conn.sendFile(m.chat, haha, null, `_${command}_`, null, null, { viewOnce: true }, m, null, fake)
+  }
+
+  if (command == 'nsfwero') {
+    const res = (await axios.get(`https://raw.githubusercontent.com/BrunoSobrino/TheMystic-Bot-MD/master/src/JSON/nsfwero.json`)).data;
+    const haha = await res[Math.floor(res.length * Math.random())];
+    conn.sendFile(m.chat, haha, null, `_${command}_`, null, null, { viewOnce: true }, m, null, fake)
+  }
+
+  if (command == 'nsfwfemdom') {
+    const res = (await axios.get(`https://raw.githubusercontent.com/BrunoSobrino/TheMystic-Bot-MD/master/src/JSON/nsfwfemdom.json`)).data;
+    const haha = await res[Math.floor(res.length * Math.random())];
+    conn.sendFile(m.chat, haha, null, `_${command}_`, null, null, { viewOnce: true }, m, null, fake)
+  }
+
+  if (command == 'nsfwglass') {
+    const res = (await axios.get(`https://raw.githubusercontent.com/BrunoSobrino/TheMystic-Bot-MD/master/src/JSON/nsfwglass.json`)).data;
+    const haha = await res[Math.floor(res.length * Math.random())];
+    conn.sendFile(m.chat, haha, null, `_${command}_`, null, null, { viewOnce: true }, m, null, fake)
+  }
+  
+if (command == 'nsfworgy') {
+    const res = (await axios.get(`https://raw.githubusercontent.com/BrunoSobrino/TheMystic-Bot-MD/master/src/JSON/nsfworgy.json`)).data;
+    const haha = await res[Math.floor(res.length * Math.random())];
+    conn.sendFile(m.chat, haha, null, `_${command}_`, null, null, { viewOnce: true }, m, null, fake)
+  }
+  
+  if (command == 'booty') {
+    const resError = (await axios.get(`https://raw.githubusercontent.com/BrunoSobrino/TheMystic-Bot-MD/master/src/JSON/booty.json`)).data;
+    let res = await conn.getFile(`https://api-fgmods.ddns.net/api/nsfw/ass?apikey=fg-dylux`).data;
+    if (res == '' || !res || res == null) res = await resError[Math.floor(resError.length * Math.random())];
+    conn.sendFile(m.chat, res, null, `_${command}_`, null, null, { viewOnce: true }, m, null, fake)
+  }
+
+  if (command == 'ecchi') {
+    const res = (await axios.get(`https://raw.githubusercontent.com/BrunoSobrino/TheMystic-Bot-MD/master/src/JSON/ecchi.json`)).data;
+    const url = await res[Math.floor(res.length * Math.random())];
+    conn.sendFile(m.chat, url, null, `_${command}_`, null, null, { viewOnce: true }, m, null, fake)
+  }
+
+  if (command == 'furro') {
+    const res = (await axios.get(`https://raw.githubusercontent.com/BrunoSobrino/TheMystic-Bot-MD/master/src/JSON/furro.json`)).data;
+    const url = await res[Math.floor(res.length * Math.random())];
+    conn.sendFile(m.chat, url, null, `_y este furro?_`, null, null, { viewOnce: true }, m, null, fake)
+  }
+
+  if (command == 'trapito') {
+    const res = await fetch(`https://api.waifu.pics/nsfw/trap`);
+    const json = await res.json();
+    const url = json.url;
+    conn.sendFile(m.chat, url, null, `_oh no un trapito😱 _`, null, null, { viewOnce: true }, m, null, fake)
+  }
+
+  if (command == 'imagenlesbians') {
+    const resError = (await axios.get(`https://raw.githubusercontent.com/BrunoSobrino/TheMystic-Bot-MD/master/src/JSON/imagenlesbians.json`)).data;
+    let res = await conn.getFile(`https://api-fgmods.ddns.net/api/nsfw/lesbian?apikey=fg-dylux`).data;
+    if (res == '' || !res || res == null) res = await resError[Math.floor(resError.length * Math.random())];
+    conn.sendFile(m.chat, res, null, `_${command}_`, null, null, { viewOnce: true }, m, null, fake)
+  }
+
+  if (command == 'panties') {
+    const res = (await axios.get(`https://raw.githubusercontent.com/BrunoSobrino/TheMystic-Bot-MD/master/src/JSON/panties.json`)).data;
+    const url = await res[Math.floor(res.length * Math.random())];
+    conn.sendFile(m.chat, url, null, `_${command}_`, null, null, { viewOnce: true }, m, null, fake)
+  }
+
+  if (command == 'pene') {
+    const resError = (await axios.get(`https://raw.githubusercontent.com/BrunoSobrino/TheMystic-Bot-MD/master/src/JSON/pene.json`)).data;
+    let res = await conn.getFile(`https://api-fgmods.ddns.net/api/nsfw/penis?apikey=fg-dylux`).data;
+    if (res == '' || !res || res == null) res = await resError[Math.floor(resError.length * Math.random())];
+    conn.sendFile(m.chat, res, null, `_${command}_`, null, null, { viewOnce: true }, m, null, fake)
+  }
+
+  if (command == 'randomxxx') {
+    const rawjsonn = ['https://raw.githubusercontent.com/BrunoSobrino/TheMystic-Bot-MD/master/src/JSON/tetas.json', 'https://raw.githubusercontent.com/BrunoSobrino/TheMystic-Bot-MD/master/src/JSON/booty.json', 'https://raw.githubusercontent.com/BrunoSobrino/TheMystic-Bot-MD/master/src/JSON/imagenlesbians.json', 'https://raw.githubusercontent.com/BrunoSobrino/TheMystic-Bot-MD/master/src/JSON/panties.json', 'https://raw.githubusercontent.com/BrunoSobrino/TheMystic-Bot-MD/master/src/JSON/porno.json'];
+    const rawjson = await rawjsonn[Math.floor(rawjsonn.length * Math.random())];
+    const res = (await axios.get(rawjson)).data;
+    const url = await res[Math.floor(res.length * Math.random())];
+    conn.sendFile(m.chat, url, null, `_${command}_`, null, null, { viewOnce: true }, m, null, fake)
+  }
+
+  if (command == 'yaoi') {
+    const res = await fetch(`https://nekobot.xyz/api/image?type=yaoi`);
+    const json = await res.json();
+    const url = json.message;
+    conn.sendFile(m.chat, url, null, `_${command}_`, null, null, { viewOnce: true }, m, null, fake)
+  }
+
+  if (command == 'yaoi2') {
+    const res = await fetch(`https://purrbot.site/api/img/nsfw/yaoi/gif`);
+    const json = await res.json();
+    const url = json.link;
+    conn.sendFile(m.chat, url, null, `_${command}_`, null, null, { viewOnce: true }, m, null, fake)
+  }
+
+  if (command == 'yuri') {
+    const res = (await axios.get(`https://raw.githubusercontent.com/BrunoSobrino/TheMystic-Bot-MD/master/src/JSON/yuri.json`)).data;
+    const url = await res[Math.floor(res.length * Math.random())];
+    conn.sendFile(m.chat, url, null, `_${command}_`, null, null, { viewOnce: true }, m, null, fake)
+  }
+ 
+if (command == 'pechos') {
+const res = (await axios.get(`https://raw.githubusercontent.com/elrebelde21/NovaBot-MD/master/src/nsfw/pechos.json`)).data;
+const url = await res[Math.floor(res.length * Math.random())];
+conn.sendFile(m.chat, url, 'error.jpg', "Lindo pechos para dame lechita 🥵", m, null, fakee2);
+//conn.sendButton(m.chat, `Lindo pechos para dame lechita 🥵`, botname, url, [['🔄 𝐒𝐈𝐆𝐔𝐈𝐄𝐍𝐓𝐄 🔄', `/${command}`]], null, null, m) 
+}
+
+  if (command == 'yuri2') {
+    const resError = (await axios.get(`https://raw.githubusercontent.com/BrunoSobrino/TheMystic-Bot-MD/master/src/JSON/yuri.json`)).data;
+    const res = await fetch(`https://purrbot.site/api/img/nsfw/yuri/gif`);
+    const json = await res.json();
+    let url = json.link;
+    if (url == '' || !url || url == null) url = await resError[Math.floor(resError.length * Math.random())];
+    conn.sendFile(m.chat, url, null, `_${command}_`, null, null, { viewOnce: true }, m, null, fake)
+  }
+
+if (command == 'hentaisearch' || command == 'searchhentai') {
+if (!text) throw '*⚠️ 𝙸𝙽𝙶𝚁𝙴𝚂𝙰 𝙴𝙻 𝙽𝙾𝙼𝙱𝚁𝙴 𝙳𝙴 𝙰𝙻𝙶𝚄𝙽 𝙷𝙴𝙽𝚃𝙰𝙸 𝙰 𝙱𝚄𝚂𝙲𝙰𝚁*';
+const searchResults = await searchHentai(text);
+let teks = searchResults.result.map((v, i) => `${i+1}. *_${v.title}_*
+↳ 📺 *_Vistas:_* ${v.views}
+↳ 🎞️ *_Link:_* ${v.url}`).join('\n\n');
+let randomThumbnail;
+if (searchResults.result.length > 0) {
+const randomIndex = Math.floor(Math.random() * searchResults.result.length);
+randomThumbnail = searchResults.result[randomIndex].thumbnail;
+} else {
+randomThumbnail = 'https://pictures.hentai-foundry.com/e/Error-Dot/577798/Error-Dot-577798-Zero_Two.png';
+teks = '*[❗] 𝙽𝙾 𝚂𝙴 𝙷𝙰𝙽 𝙴𝙽𝙲𝙾𝙽𝚃𝚁𝙰𝙳𝙾 𝚁𝙴𝚂𝚄𝙻𝚃𝙰𝙳𝙾𝚂*';
+}
+conn.sendFile(m.chat, randomThumbnail, 'error.jpg', teks, fake, m);
+}}
+handler.help = ['nsfwloli', 'nsfwfoot', 'nsfwass', 'nsfwbdsm', 'nsfwcum', 'nsfwero', 'nsfwfemdom', 'nsfwfoot', 'nsfwglass', 'nsfworgy', 'yuri', 'yuri2', 'yaoi', 'yaoi2', 'panties', 'tetas', 'booty', 'ecchi', 'furro', 'hentai', 'trapito', 'imagenlesbians', 'pene', 'porno', 'randomxxx', 'pechos', 'hentai', 'hentai2', 'nsfwloli', 'porno', 'tetas', 'china', 'boobs'];
+handler.tags = ['nsfw'];
+handler.command = ['nsfwloli', 'nsfwfoot', 'nsfwass', 'nsfwbdsm', 'nsfwcum', 'nsfwero', 'nsfwfemdom', 'nsfwfoot', 'nsfwglass', 'nsfworgy', 'yuri', 'yuri2', 'yaoi', 'yaoi2', 'panties', 'tetas', 'booty', 'ecchi', 'furro', 'hentai', 'trapito', 'imagenlesbians', 'pene', 'porno', 'randomxxx', 'pechos', 'hentai', 'hentai2', 'nsfwloli', 'porno', 'tetas', 'china', 'boobs', 'hentaisearch', 'searchhentai', 'videos']
+handler.limit = ["2", "3", "4", "6", "8"].getRandom()
+handler.register = true
+export default handler
+
+async function searchHentai(search) {
+  return new Promise((resolve, reject) => {
+    axios.get('https://hentai.tv/?s=' + search).then(async ({data}) => {
+      const $ = cheerio.load(data);
+      const result = {};
+      const res = [];
+      result.coder = 'rem-comp';
+      result.result = res;
+      result.warning = 'It is strictly forbidden to reupload this code, copyright © 2022 by rem-comp';
+      $('div.flex > div.crsl-slde').each(function(a, b) {
+        const _thumbnail = $(b).find('img').attr('src');
+        const _title = $(b).find('a').text().trim();
+        const _views = $(b).find('p').text().trim();
+        const _url = $(b).find('a').attr('href');
+        const hasil = {thumbnail: _thumbnail, title: _title, views: _views, url: _url};
+        res.push(hasil);
+      });
+      resolve(result);
+    }).catch((err) => {
+      console.log(err);
+    });
+  });
+}

+ 178 - 0
plugins/adult-comandos-menu.js

@@ -0,0 +1,178 @@
+import { xpRange } from "../lib/levelling.js";
+var handler = async (m, {conn, usedPrefix, usedPrefix: _p, text, args, isAdmin}) => {
+let porn = 'https://qu.ax/bXMB.webp'
+let porn2 = 'https://qu.ax/TxtQ.webp'
+if (!db.data.chats[m.chat].modohorny && m.isGroup) return conn.sendFile(m.chat, [porn, porn2].getRandom(), 'sticker.webp', '', m, true, { contextInfo: { 'forwardingScore': 200, 'isForwarded': false, externalAdReply:{ showAdAttribution: false, title: `ᴸᵒˢ ᶜᵒᵐᵃⁿᵈᵒ ʰᵒʳⁿʸ ᵉˢᵗᵃ ᵈᵉˢᵃᶜᵗᶦᵛᵃᵈᵒ ᵖᵃʳᵃ ᵃᶜᵗᶦᵛᵃʳ ᵘˢᵃʳ:`, body: '#enable modohorny', mediaType: 2, sourceUrl: md, thumbnail: imagen3}}}, { quoted: m, ephemeralExpiration: 24*60*100, disappearingMessagesInChat: 24*60*100})
+
+let {exp, limit, level, role} = global.db.data.users[m.sender];
+let {min, xp, max} = xpRange(level, global.multiplier);
+
+let d = new Date(new Date() + 3600000);
+let locale = "es";
+let weton = ["Pahing", "Pon", "Wage", "Kliwon", "Legi"][Math.floor(d / 84600000) % 5];
+let week = d.toLocaleDateString(locale, {weekday: "long"});
+let date = d.toLocaleDateString(locale, {day: "numeric",
+month: "long",
+year: "numeric",
+});
+let dateIslamic = Intl.DateTimeFormat(locale + "-TN-u-ca-islamic", {day: "numeric",
+month: "long",
+year: "numeric",
+}).format(d);
+let time = d.toLocaleTimeString(locale, {hour: "numeric",
+minute: "numeric",
+second: "numeric",
+});
+let _uptime = process.uptime() * 1000;
+let _muptime;
+if (process.send) {
+process.send("uptime");
+_muptime =
+(await new Promise((resolve) => {
+process.once("message", resolve);
+setTimeout(resolve, 1000)})) * 1000;
+}
+let {money} = global.db.data.users[m.sender];
+let muptime = clockString(_muptime);
+let uptime = clockString(_uptime);
+let totalreg = Object.keys(global.db.data.users).length;
+let rtotalreg = Object.values(global.db.data.users).filter((user) => user.registered == true).length;
+let replace = {"%": "%",
+p: _p,
+uptime,
+muptime,
+me: conn.getName(conn.user.jid),
+exp: exp - min,
+maxexp: xp,
+totalexp: exp,
+xp4levelup: max - exp,
+level,
+limit,
+weton,
+week,
+date,
+dateIslamic,
+time,
+totalreg,
+rtotalreg,
+role,
+readmore: readMore,
+};
+text = text.replace(new RegExp(`%(${Object.keys(replace).sort((a, b) => b.length - a.length).join`|`})`, "g"), (_, name) => "" + replace[name]);
+
+let pp = "./Menu2.jpg";
+let who = m.mentionedJid && m.mentionedJid[0] ? m.mentionedJid[0] : m.fromMe ? conn.user.jid : m.sender;
+let username = conn.getName(who);
+//let user = global.db.data.users[m.sender]
+//user.registered = false
+
+let menu = `Hola ${username} pajin 🤓
+
+┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈
+😏😏😏😏😏😏😏😏😏
+◉ *EXPERIENCIA | EXP ➺ ${exp}*
+◉ *NIVEL | LEVEL ➺ ${level}*
+┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈
+◉ *FECHA ➺ ${week}, ${date}*
+◉ *USUARIOS | USERS ➺ ${Object.keys(global.db.data.users).length}* 
+😏😏😏😏😏😏😏😏😏
+┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈
+
+*Comandos para ver pornito 🔞*
+*Usar bajo tu responsabilidad*
+*NOTA: No sea pajero*
+*NSFW ✅*
+
+◉ ${usedPrefix}pack
+◉ ${usedPrefix}pack2
+◉ ${usedPrefix}pack3
+◉ ${usedPrefix}pack4
+◉ ${usedPrefix}china
+◉ ${usedPrefix}boobs
+◉ ${usedPrefix}videoxxx
+◉ ${usedPrefix}videolesbixxx
+◉ ${usedPrefix}tetas
+◉ ${usedPrefix}booty
+◉ ${usedPrefix}ecchi
+◉ ${usedPrefix}furro
+◉ ${usedPrefix}pussy
+◉ ${usedPrefix}panties
+◉ ${usedPrefix}pene
+◉ ${usedPrefix}porno
+◉ ${usedPrefix}randomxxx
+◉ ${usedPrefix}pechos
+◉ ${usedPrefix}yuri
+◉ ${usedPrefix}yuri2
+◉ ${usedPrefix}trapito
+◉ ${usedPrefix}hentai
+◉ ${usedPrefix}pornololi
+◉ ${usedPrefix}pornoorgy
+◉ ${usedPrefix}pornofoot
+◉ ${usedPrefix}pornoass
+◉ ${usedPrefix}pornouniform
+◉ ${usedPrefix}pornobdsm
+◉ ${usedPrefix}pornocum
+◉ ${usedPrefix}pornonetorare
+◉ ${usedPrefix}pornofeet
+◉ ${usedPrefix}pornoero
+◉ ${usedPrefix}pornofemdom
+◉ ${usedPrefix}pornoglass
+◉ ${usedPrefix}pornosuccubus
+◉ ${usedPrefix}pornochupada
+◉ ${usedPrefix}pornomuslos
+  
+> El yaoi es pa las chicas no solo los hombre se divierten 🤓`.trim();
+
+if (/^hornymenu|menu18|menucaliente$/i.test(m.text)) {   
+conn.sendMessage(m.chat, { image: { url: "https://telegra.ph/file/c0b57f22c3fce1c2b5e72.jpg", }, caption: menu, 
+contextInfo: {
+externalAdReply: {
+title: `🥵🔥 𝐌𝐎𝐃𝐎-𝐂𝐀𝐋𝐈𝐄𝐍𝐓𝐄 🔥🥵`,
+sourceUrl: nna, 
+mediaType: 1,
+showAdAttribution: true,
+thumbnailUrl: "https://telegra.ph/file/361c821b05575733b1bb5.jpg",
+}}}, { quoted: m })
+}
+
+if (/^sethorario|nwfshorario|hornyHorario$/i.test(m.text)) {   
+//handler.group = true
+if (!isAdmin) return await m.reply(`⚠️ *Solo los admins pueden usar este comando.*`)
+const args = m.text.split(' ').slice(1); 
+if (args.length < 2) return conn.reply(m.chat, '⚠️ Por favor ingresa la hora de inicio y fin en formato HH:MM, por ejemplo: 23:00 - 06:00.', m);
+let inicio, fin;
+const regex1 = /^(\d{2}:\d{2})\s*-\s*(\d{2}:\d{2})$/; 
+const regex2 = /^(\d{2}:\d{2})\s*a\s*(\d{2}:\d{2})$/; 
+const regex3 = /^(\d{2}:\d{2})\s*,\s*(\d{2}:\d{2})$/;
+let match;
+if (match = args.join(' ').match(regex1)) {
+inicio = match[1];
+fin = match[2];
+} else if (match = args.join(' ').match(regex2)) {
+inicio = match[1];
+fin = match[2];
+} else if (match = args.join(' ').match(regex3)) {
+inicio = match[1];
+fin = match[2];
+} else {
+return conn.reply(m.chat, '⚠️ Formato de horario incorrecto. Por favor usa uno de los siguientes formatos: HH:MM - HH:MM o HH:MM, HH:MM.', m);
+}
+db.data.chats[m.chat].horarioNsfw = { inicio, fin };
+return conn.reply(m.chat, `Horario establecido: ${inicio} a ${fin}`, m);
+}
+}
+handler.help = ["menu18", "hornymenu", "nwfshorario"]
+handler.tags = ["main"];
+handler.command = /^(hornymenu|menu18|menucaliente|sethorario|nwfshorario|hornyHorario)$/i;
+handler.register = true
+handler.exp = 70;
+export default handler;
+
+const more = String.fromCharCode(8206);
+const readMore = more.repeat(4001);
+function clockString(ms) {
+  let h = isNaN(ms) ? "--" : Math.floor(ms / 3600000);
+  let m = isNaN(ms) ? "--" : Math.floor(ms / 60000) % 60;
+  let s = isNaN(ms) ? "--" : Math.floor(ms / 1000) % 60;
+  return [h, m, s].map((v) => v.toString().padStart(2, 0)).join(":");
+}

+ 226 - 0
plugins/adult-pack_vid.js

@@ -0,0 +1,226 @@
+import fetch from 'node-fetch';
+import moment from 'moment-timezone';
+const handler = async (m, {conn, command, usedPrefix}) => {
+const fakee2 = { contextInfo: { mentionedJid: null, forwardingScore: 1, isForwarded: true, forwardedNewsletterMessageInfo: { newsletterJid: channelRD.id, serverMessageId: '', newsletterName: channelRD.name }, externalAdReply: { title: "🥵 CONTENIDO +18🥵", body: "No alto para menores..", mediaType: 1, renderLargerThumbnail: false, previewType: `PHOTO`, thumbnail: imagen3, sourceUrl: redes.getRandom() }}}
+let porn = 'https://qu.ax/bXMB.webp'
+let porn2 = 'https://qu.ax/TxtQ.webp'
+if (!db.data.chats[m.chat].modohorny && m.isGroup) {
+handler.limit = false
+conn.sendFile(m.chat, [porn, porn2].getRandom(), 'sticker.webp', '', m, true, { contextInfo: { 'forwardingScore': 200, 'isForwarded': false, externalAdReply:{ showAdAttribution: false, title: `ᴸᵒˢ ᶜᵒᵐᵃⁿᵈᵒ ʰᵒʳⁿʸ ᵉˢᵗᵃ ᵈᵉˢᵃᶜᵗᶦᵛᵃᵈᵒ ᵖᵃʳᵃ ᵃᶜᵗᶦᵛᵃʳ ᵘˢᵃʳ:`, body: '#enable modohorny', mediaType: 2, sourceUrl: md, thumbnail: imagen3}}}, { quoted: m, ephemeralExpiration: 24*60*100, disappearingMessagesInChat: 24*60*100})
+return
+}
+const horarioNsfw = db.data.chats[m.chat].horarioNsfw
+const now = moment.tz('America/Argentina/Buenos_Aires'); 
+const currentTime = now.format('HH:mm'); 
+
+if (horarioNsfw) {
+const { inicio, fin } = horarioNsfw;
+const inicioTime = moment(inicio, 'HH:mm').tz('America/Argentina/Buenos_Aires');
+const finTime = moment(fin, 'HH:mm').tz('America/Argentina/Buenos_Aires');
+const currentMoment = moment(currentTime, 'HH:mm').tz('America/Argentina/Buenos_Aires');
+let isWithinTimeRange = false;
+if (inicioTime.isAfter(finTime)) {
+if (currentMoment.isBetween(inicioTime, moment('23:59', 'HH:mm').tz('America/Argentina/Buenos_Aires')) || 
+currentMoment.isBetween(moment('00:00', 'HH:mm').tz('America/Argentina/Buenos_Aires'), finTime)) {
+isWithinTimeRange = true;
+}} else {
+if (currentMoment.isBetween(inicioTime, finTime)) {
+isWithinTimeRange = true;
+}}
+if (!isWithinTimeRange) {
+handler.limit = false
+conn.sendFile(m.chat, [porn, porn2].getRandom(), 'sticker.webp', '', m, true, { contextInfo: { 'forwardingScore': 200, 'isForwarded': false, externalAdReply:{ showAdAttribution: false, title: `ᴱˢᵗᵉ ᶜᵒᵐᵃⁿᵈᵒ ˢᵒˡᵒ ᶠᵘⁿᶜᶦᵒⁿᵃ ᵉˡ ʰᵒʳᵃʳᶦᵒ ʰᵃᵇᶦˡᶦᵗᵃᵈᵒ ᵉˡ ᵍʳᵘᵖᵒ:`, body: `${inicio} a ${fin}`, mediaType: 2, sourceUrl: md, thumbnail: imagen3}}}, { quoted: m, ephemeralExpiration: 24*60*100, disappearingMessagesInChat: 24*60*100})
+return
+}
+//.catch(m.reply(`*[ ALTO HAY PAJIN ]*n\nLos comando +18 solo funcióna el horario habilitado el grupo:* ${inicio} a ${fin}`))   
+}
+
+switch (command) {
+case 'pack':
+const url = await pack[Math.floor(Math.random() * pack.length)];
+conn.sendFile(m.chat, url, 'error.jpg', "_🥵 aqui tiene mi Pack 😏_", m, null, fakee2);
+//conn.sendButton(m.chat, '_🥵 aqui tiene mi Pack 😏_', botname, url, [['🥵 𝐒𝐈𝐆𝐔𝐈𝐄𝐍𝐓𝐄 🥵', `/${command}`]], null, null, m)
+break;
+case 'pack2':
+const url2 = await packgirl[Math.floor(Math.random() * packgirl.length)];
+conn.sendFile(m.chat, url2, 'error.jpg', "_🥵 aqui tiene mi Pack 😏_", m, null, fakee2);
+//conn.sendButton(m.chat, '_🥵 aqui tiene mi Pack 😏_', botname, url2, [['🥵 𝐒𝐈𝐆𝐔𝐈𝐄𝐍𝐓𝐄 🥵', `/${command}`]], null, null, m)
+break;
+case 'pack3':
+const url3 = await packmen[Math.floor(Math.random() * packmen.length)];
+conn.sendFile(m.chat, url3, 'error.jpg', "_🥵 aqui tiene mi Pack 😏_", m, null, fakee2);
+//conn.sendButton(m.chat, '_🥵 aqui tiene mi Pack 😏_', botname, url3, [['🥵 𝐒𝐈𝐆𝐔𝐈𝐄𝐍𝐓𝐄 🥵', `/${command}`]], null, null, m) 
+break;
+case 'girls': case 'pack4':
+conn.sendFile(m.chat, `${apis}/api/girls`, 'error.jpg', "🥵", m, null, fakee2);
+//conn.sendButton(m.chat, '🥵', botname, "https://delirius-api-oficial.vercel.app/api/girls", [['🔄 𝐒𝐈𝐆𝐔𝐈𝐄𝐍𝐓𝐄 🔄', `/${command}`]], null, null, m)
+break
+case 'videoxxx': case 'vídeoxxx':
+const url4 = await videosxxxc[Math.floor(Math.random() * videosxxxc.length)];
+await conn.sendFile(m.chat, url4, 'error.jpg', "_*ᴅɪsғʀᴜᴛᴀ ᴅᴇʟ ᴠɪᴅᴇᴏ 🥵_", m, null, fakee2);
+//conn.sendButton(m.chat, '_*ᴅɪsғʀᴜᴛᴀ ᴅᴇʟ ᴠɪᴅᴇᴏ 🥵*_', botname, url4, [['🥵 𝐒𝐈𝐆𝐔𝐈𝐄𝐍𝐓𝐄 🥵', `/${command}`]], null, null, m)       
+break;
+case 'videoxxxlesbi': case 'videolesbixxx': case 'pornolesbivid': case 'pornolesbianavid': case 'pornolesbiv': case 'pornolesbianav': case 'pornolesv':
+const url5 = await videosxxxc2[Math.floor(Math.random() * videosxxxc2.length)];
+await conn.sendFile(m.chat, url5, 'error.jpg', "_*ᴅɪsғʀᴜᴛᴀ ᴅᴇʟ ᴠɪᴅᴇᴏ 🥵_", m, null, fakee2);
+//conn.sendButton(m.chat, '_*ᴅɪsғʀᴜᴛᴀ ᴅᴇʟ ᴠɪᴅᴇᴏ 🥵*_', botname, url5, [['🥵 𝐒𝐈𝐆𝐔𝐈𝐄𝐍𝐓𝐄 🥵', `/${command}`]], null, null, m)   
+break;
+}};
+handler.help = ['pack', 'pack2', 'pack3', 'pack4', 'videoxxx', 'videoxxxlesbi', 'girls', 'pornolesbiv'];
+handler.tags = ['nsfw'];
+handler.command = /^(pack|pack2|pack3|videoxxx|vídeoxxx|videoxxxlesbi|videolesbixxx|pornolesbivid|pornolesbianavid|pornolesbiv|pornolesbianav|pornolesv|girls|pack4)$/i;
+handler.limit = 2
+handler.register = true
+export default handler;
+
+global.pack = [
+  'https://telegra.ph/file/957fe4031132ef90b66ec.jpg',
+  'https://telegra.ph/file/c4b85bd53030cb648382f.jpg',
+  'https://telegra.ph/file/df56f8a76145df9c923ad.jpg',
+  'https://telegra.ph/file/d5d1c2c710c4b5ee8bc6c.jpg',
+  'https://telegra.ph/file/d0c0cd47e87535373ab68.jpg',
+  'https://telegra.ph/file/651a5a9dc96c97c8ef8fc.jpg',
+  'https://telegra.ph/file/f857ae461ceab18c38de2.jpg',
+  'https://telegra.ph/file/5d2a2aeff5e6fbd229eff.jpg',
+  'https://telegra.ph/file/b93573531f898ea875dd0.jpg',
+  'https://telegra.ph/file/c798b3959f84d345b0f25.jpg',
+  'https://telegra.ph/file/de820647f8cabce533557.jpg',
+  'https://telegra.ph/file/e105097d5fadf3e522eb5.jpg',
+  'https://telegra.ph/file/8592e352a9ee6c7244737.jpg',
+  'https://telegra.ph/file/bb9c7d879b7dc1d86a2ce.jpg',
+  'https://telegra.ph/file/83f108601e6105446ad1f.jpg',
+  'https://telegra.ph/file/2a6bff14e53ed2533ad25.jpg',
+  'https://telegra.ph/file/e37d74aeccc5bdfd6be3e.jpg',
+  'https://telegra.ph/file/ca984650af06b951e961d.jpg',
+  'https://telegra.ph/file/ebb3ac7f7498dd09f6afc.jpg',
+  'https://telegra.ph/file/6192305a24ffb8fa30942.jpg',
+  'https://telegra.ph/file/ee67c17d0043b98dc757e.jpg',
+  'https://telegra.ph/file/6ae756b686cd2b5950721.jpg',
+  'https://telegra.ph/file/b1e1da38d897d117c2aa9.jpg',
+  'https://telegra.ph/file/6b759437dc8b863c2fa19.jpg',
+  'https://telegra.ph/file/960d8c268aecb5eb117f0.jpg',
+  'https://telegra.ph/file/d0dd518bdd147cb10b0b5.jpg',
+  'https://telegra.ph/file/31f2d59b5cd68ec5acb21.jpg',
+  'https://telegra.ph/file/14ab9bd02f24e0f1a1a03.jpg',
+  'https://telegra.ph/file/e02bf6bc9227f7f8b7e2a.jpg',
+  'https://telegra.ph/file/ab55fca1d6b602b1a69df.jpg',
+  'https://telegra.ph/file/42105cac3666b37da3d1c.jpg',
+];
+global.packgirl = [
+  'https://telegra.ph/file/c0da7289bee2d97048feb.jpg',
+  'https://telegra.ph/file/b8564166f9cac4d843db3.jpg',
+  'https://telegra.ph/file/fdefd621a17712be15e0e.jpg',
+  'https://telegra.ph/file/6e1a6dcf1c91bf62d3945.jpg',
+  'https://telegra.ph/file/0224c1ecf6b676dda3ac0.jpg',
+  'https://telegra.ph/file/b71b8f04772f1b30355f1.jpg',
+  'https://telegra.ph/file/6561840400444d2d27d0c.jpg',
+  'https://telegra.ph/file/37e445df144e1dfcdb744.jpg',
+  'https://telegra.ph/file/155b6ac6757bdd9cd05f9.jpg',
+  'https://telegra.ph/file/2255a8a013540c2820a2b.jpg',
+  'https://telegra.ph/file/450e901ac153765f095c5.jpg',
+  'https://telegra.ph/file/f18e421a70810015be505.jpg',
+  'https://telegra.ph/file/d3d190691ec399431434e.jpg',
+  'https://telegra.ph/file/1fd2b897a1dbc3fdc2a70.jpg',
+  'https://telegra.ph/file/607d54a909035bca7444f.jpg',
+  'https://telegra.ph/file/818ba7c0ae82876b190b6.jpg',
+  'https://telegra.ph/file/0f2bb426951b4a8fe1e5a.jpg',
+  'https://telegra.ph/file/7e895b5b933226a07558a.jpg',
+  'https://telegra.ph/file/f9d9f0da337512a1b1882.jpg',
+  'https://telegra.ph/file/09ff5bfce02f1f78e3861.jpg',
+  'https://telegra.ph/file/4ad840d401ab1f90444df.jpg',
+  'https://telegra.ph/file/7b4bdcad3dde870355c94.jpg',
+  'https://telegra.ph/file/f69a5beaca50fc52a4a71.jpg',
+  'https://telegra.ph/file/411d7cdee24669e167adb.jpg',
+  'https://telegra.ph/file/36a63288e27e88e2f8e10.jpg',
+  'https://telegra.ph/file/1ac7657a5e7b354cd9991.jpg',
+  'https://telegra.ph/file/14161eab0c1d919dc3218.jpg',
+  'https://telegra.ph/file/810411b9128fe11dd639a.jpg',
+  'https://telegra.ph/file/5fe7e98533754b007e7a1.jpg',
+];
+global.packmen = [
+  'https://telegra.ph/file/bf303b19b9834f90e9617.jpg',
+  'https://telegra.ph/file/36ef2b807251dfccd17c2.jpg',
+  'https://telegra.ph/file/bcc34403d16de829ea5d2.jpg',
+  'https://telegra.ph/file/5c6b7615662fb53a39e53.jpg',
+  'https://telegra.ph/file/1a8183eff48671ea265c2.jpg',
+  'https://telegra.ph/file/f9745dcd22f67cbc62e08.jpg',
+  'https://telegra.ph/file/02219f503317b0596e101.jpg',
+  'https://telegra.ph/file/470c8ec30400a73d03207.jpg',
+  'https://telegra.ph/file/c94fa8ed20f2c0cf16786.jpg',
+  'https://telegra.ph/file/1b02a1ca6a39e741faec7.jpg',
+  'https://telegra.ph/file/eea58bf7043fd697cdb43.jpg',
+  'https://telegra.ph/file/ee3db7facdfe73c8df05a.jpg',
+  'https://telegra.ph/file/d45b4e4af4f2139507f8c.jpg',
+  'https://telegra.ph/file/d176e7fc8720f98f6b182.jpg',
+  'https://telegra.ph/file/ce1e072829d1fa5d99f5f.jpg',
+  'https://telegra.ph/file/a947933701be6d579c958.jpg',
+  'https://telegra.ph/file/9027e5a464ec88e8ab5c1.jpg',
+  'https://telegra.ph/file/049a8c611a838ea2f6daa.jpg',
+  'https://telegra.ph/file/37b35fbc7e2ee73482ee1.jpg',
+  'https://telegra.ph/file/9bcfade24ae85cd417f06.jpg',
+  'https://telegra.ph/file/ac0c711585f4300c54355.jpg',
+];
+global.videosxxxc = [
+  'https://telegra.ph/file/4a270d9945ac46f42d95c.mp4',
+  'https://telegra.ph/file/958c11e84d271e783ea3f.mp4',
+  'https://telegra.ph/file/f753759342337c4012b3f.mp4',
+  'https://telegra.ph/file/379cee56c908dd536dd33.mp4',
+  'https://telegra.ph/file/411d8f59a5cefc2a1d227.mp4',
+  'https://telegra.ph/file/ee2cf1b359d6eef50d7b7.mp4',
+  'https://telegra.ph/file/1e316b25c787f94a0f8fd.mp4',
+  'https://telegra.ph/file/c229d33edce798cde0ca4.mp4',
+  'https://telegra.ph/file/b44223e72dd7e80e415f2.mp4',
+  'https://telegra.ph/file/61486d45a8a3ea95a7c86.mp4',
+  'https://telegra.ph/file/76ba0dc2a07f491756377.mp4',
+  'https://telegra.ph/file/831bb88f562bef3f1a15d.mp4',
+  'https://telegra.ph/file/ee2cf1b359d6eef50d7b7.mp4',
+  'https://telegra.ph/file/598857924f3a29ffd37ae.mp4',
+  'https://telegra.ph/file/528caef6ea950ec45aeef.mp4',
+  'https://telegra.ph/file/4a270d9945ac46f42d95c.mp4',
+  'https://telegra.ph/file/958c11e84d271e783ea3f.mp4',
+  'https://telegra.ph/file/f753759342337c4012b3f.mp4',
+  'https://telegra.ph/file/379cee56c908dd536dd33.mp4',
+  'https://telegra.ph/file/411d8f59a5cefc2a1d227.mp4',
+  'https://telegra.ph/file/76ba0dc2a07f491756377.mp4',
+  'https://telegra.ph/file/831bb88f562bef3f1a15d.mp4',
+];
+
+global.videosxxxc2 = [
+  'https://l.top4top.io/m_2257y4pyl0.mp4',
+  'https://c.top4top.io/m_2274woesg0.mp4',
+  'https://k.top4top.io/m_2257pdwjy0.mp4',
+  'https://a.top4top.io/m_2257qulmx0.mp4',
+  'https://a.top4top.io/m_2257vxzr62.mp4',
+  'https://b.top4top.io/m_2257wjmbh3.mp4',
+  'https://b.top4top.io/m_2257sen2a1.mp4',
+  'https://c.top4top.io/m_2257hpo9v3.mp4',
+  'https://e.top4top.io/m_2257pye7u1.mp4',
+  'https://c.top4top.io/m_2257p7xg14.mp4',
+  'https://c.top4top.io/m_2257p4v9i3.mp4',
+  'https://l.top4top.io/m_2257jvkrv3.mp4',
+  'https://b.top4top.io/m_2257pl7wh1.mp4',
+  'https://e.top4top.io/m_2257fiwnp2.mp4',
+  'https://b.top4top.io/m_22578b1nk1.mp4',
+  'https://k.top4top.io/m_22572gv7q1.mp4',
+  'https://i.top4top.io/m_2257pu90l2.mp4',
+  'https://d.top4top.io/m_2257vcwiw3.mp4',
+  'https://j.top4top.io/m_2258joebc2.mp4',
+  'https://g.top4top.io/m_2258kvnba4.mp4',
+  'https://f.top4top.io/m_2258nm8pe1.mp4',
+  'https://g.top4top.io/m_2258af7bc2.mp4',
+  'https://l.top4top.io/m_2258f0ci92.mp4',
+  'https://j.top4top.io/m_2258ehqpb2.mp4',
+  'https://h.top4top.io/m_2258pckkf3.mp4',
+  'https://e.top4top.io/m_225857rs20.mp4',
+  'https://k.top4top.io/m_225863kpa0.mp4',
+  'https://j.top4top.io/m_2258s6we62.mp4',
+  'https://i.top4top.io/m_2258if6l13.mp4',
+  'https://b.top4top.io/m_2258lmd2h1.mp4',
+  'https://j.top4top.io/m_2258a9oah2.mp4',
+  'https://i.top4top.io/m_22588w3xh0.mp4',
+  'https://g.top4top.io/m_225885lm14.mp4',
+  'https://e.top4top.io/m_2258buxc30.mp4',
+  'https://e.top4top.io/m_2258fvra62.mp4',
+  'https://l.top4top.io/m_22588mx7k4.mp4',
+  'https://g.top4top.io/m_2258zhldg1.mp4',
+];

+ 95 - 0
plugins/adult-xnxxdl.js

@@ -0,0 +1,95 @@
+import fetch from 'node-fetch';
+import cheerio from 'cheerio';
+import moment from 'moment-timezone';
+const handler = async (m, {conn, args, command, usedPrefix}) => {
+let porn = 'https://qu.ax/bXMB.webp'
+let porn2 = 'https://qu.ax/TxtQ.webp'
+if (!db.data.chats[m.chat].modohorny && m.isGroup) {
+handler.limit = false
+conn.sendFile(m.chat, [porn, porn2].getRandom(), 'sticker.webp', '', m, true, { contextInfo: { 'forwardingScore': 200, 'isForwarded': false, externalAdReply:{ showAdAttribution: false, title: `ᴸᵒˢ ᶜᵒᵐᵃⁿᵈᵒ ʰᵒʳⁿʸ ᵉˢᵗᵃ ᵈᵉˢᵃᶜᵗᶦᵛᵃᵈᵒ ᵖᵃʳᵃ ᵃᶜᵗᶦᵛᵃʳ ᵘˢᵃʳ:`, body: '#enable modohorny', mediaType: 2, sourceUrl: md, thumbnail: imagen3}}}, { quoted: m, ephemeralExpiration: 24*60*100, disappearingMessagesInChat: 24*60*100})
+return
+}
+const horarioNsfw = db.data.chats[m.chat].horarioNsfw
+const now = moment.tz('America/Argentina/Buenos_Aires'); 
+const currentTime = now.format('HH:mm'); 
+
+if (horarioNsfw) {
+const { inicio, fin } = horarioNsfw;
+const inicioTime = moment(inicio, 'HH:mm').tz('America/Argentina/Buenos_Aires');
+const finTime = moment(fin, 'HH:mm').tz('America/Argentina/Buenos_Aires');
+const currentMoment = moment(currentTime, 'HH:mm').tz('America/Argentina/Buenos_Aires');
+let isWithinTimeRange = false;
+if (inicioTime.isAfter(finTime)) {
+if (currentMoment.isBetween(inicioTime, moment('23:59', 'HH:mm').tz('America/Argentina/Buenos_Aires')) || 
+currentMoment.isBetween(moment('00:00', 'HH:mm').tz('America/Argentina/Buenos_Aires'), finTime)) {
+isWithinTimeRange = true;
+}} else {
+if (currentMoment.isBetween(inicioTime, finTime)) {
+isWithinTimeRange = true;
+}}
+if (!isWithinTimeRange) {
+handler.limit = false
+conn.sendFile(m.chat, [porn, porn2].getRandom(), 'sticker.webp', '', m, true, { contextInfo: { 'forwardingScore': 200, 'isForwarded': false, externalAdReply:{ showAdAttribution: false, title: `ᴱˢᵗᵉ ᶜᵒᵐᵃⁿᵈᵒ ˢᵒˡᵒ ᶠᵘⁿᶜᶦᵒⁿᵃ ᵉˡ ʰᵒʳᵃʳᶦᵒ ʰᵃᵇᶦˡᶦᵗᵃᵈᵒ ᵉˡ ᵍʳᵘᵖᵒ:`, body: `${inicio} a ${fin}`, mediaType: 2, sourceUrl: md, thumbnail: imagen3}}}, { quoted: m, ephemeralExpiration: 24*60*100, disappearingMessagesInChat: 24*60*100})
+return
+}}
+  
+if (!args[0]) throw `*⚠️ ¿Que esta buscando pajin? ingresa un enlace valido de xnxx*\n\n*Aqui te recomiendo uno ejemplo:* ${usedPrefix + command} https://www.xnxx.com/video-14lcwbe8/rubia_novia_follada_en_cuarto_de_bano*`;
+try {
+m.react(`⌛`) 
+let xnxxLink = '';
+if (args[0].includes('xnxx')) {
+xnxxLink = args[0];
+} else {
+const index = parseInt(args[0]) - 1;
+if (index >= 0) {
+if (Array.isArray(global.videoListXXX) && global.videoListXXX.length > 0) {
+const matchingItem = global.videoListXXX.find((item) => item.from === m.sender);
+if (matchingItem) {
+if (index < matchingItem.urls.length) {
+xnxxLink = matchingItem.urls[index];
+} else {
+throw `*⚠️ ɴᴏ sᴇ ᴇɴᴄᴏɴᴛʀᴏ́ ᴜɴ ᴇɴʟᴀᴄᴇ ᴘᴀʀᴀ ᴇsᴇ ɴᴜ́ᴍᴇʀᴏ, ᴘᴏʀ ғᴀᴠᴏʀ ɪɴɢʀᴇsᴇ ᴜɴ ɴᴜ́ᴍᴇʀᴏ ᴇɴᴛʀᴇ ᴇʟ  1 ʏ ᴇʟ ${matchingItem.urls.length}*`;
+}} else {
+throw `*⚠️ ᴘᴀʀᴀ ᴘᴏᴅᴇʀ ᴜsᴀʀ ᴇsᴛᴇ ᴄᴏᴍᴀɴᴅᴏ ᴅᴇ ᴇsᴛᴀ ғᴏʀᴍᴀ (${usedPrefix + command} <numero>), ᴘᴏʀ ғᴀᴠᴏʀ ʀᴇᴀʟɪᴢᴀʀ ʟᴀ ʙᴜ́sǫᴜᴇᴅᴀ ᴅᴇ ᴠɪᴅᴇᴏs ᴄᴏɴ ᴇʟ ᴄᴏᴍᴀɴᴅᴏ: ${usedPrefix}xnxxsearch <texto>*`;
+}} else {
+throw `*⚠️ ᴘᴀʀᴀ ᴘᴏᴅᴇʀ ᴜsᴀʀ ᴇsᴛᴇ ᴄᴏᴍᴀɴᴅᴏ ᴅᴇ ᴇsᴛᴀ ғᴏʀᴍᴀ (${usedPrefix + command} <numero>), ᴘᴏʀ ғᴀᴠᴏʀ ʀᴇᴀʟɪᴢᴀʀ ʟᴀ ʙᴜ́sǫᴜᴇᴅᴀ ᴅᴇ ᴠɪᴅᴇᴏs ᴄᴏɴ ᴇʟ ᴄᴏᴍᴀɴᴅᴏ: ${usedPrefix}xnxxsearch <texto>*`;
+}}}
+const res = await xnxxdl(xnxxLink);
+const json = await res.result.files;
+conn.sendMessage(m.chat, {document: {url: json.high}, mimetype: 'video/mp4', fileName: res.result.title}, {quoted: m});
+m.react(`🔥`) 
+} catch {
+throw `*⚠️ ¿Que esta buscando pajin? ingresa un enlace valido de xnxx*\n\n*Aqui te recomiendo uno algo similar a estos:* ${usedPrefix + command} https://www.xnxx.com/video-14lcwbe8/rubia_novia_follada_en_cuarto_de_bano`;
+handler.limit = false
+}};
+handler.help = ['xnxxdl']
+handler.tags = ['nsfw'];
+handler.command = /^(xnxxdl)$/i;
+handler.limit = ["10", "12", "15", "16", "18", "25"].getRandom()
+handler.register = true
+export default handler;
+
+async function xnxxdl(URL) {
+  return new Promise((resolve, reject) => {
+    fetch(`${URL}`, {method: 'get'}).then((res) => res.text()).then((res) => {
+      const $ = cheerio.load(res, {xmlMode: false});
+      const title = $('meta[property="og:title"]').attr('content');
+      const duration = $('meta[property="og:duration"]').attr('content');
+      const image = $('meta[property="og:image"]').attr('content');
+      const videoType = $('meta[property="og:video:type"]').attr('content');
+      const videoWidth = $('meta[property="og:video:width"]').attr('content');
+      const videoHeight = $('meta[property="og:video:height"]').attr('content');
+      const info = $('span.metadata').text();
+      const videoScript = $('#video-player-bg > script:nth-child(6)').html();
+      const files = {
+        low: (videoScript.match('html5player.setVideoUrlLow\\(\'(.*?)\'\\);') || [])[1],
+        high: videoScript.match('html5player.setVideoUrlHigh\\(\'(.*?)\'\\);' || [])[1],
+        HLS: videoScript.match('html5player.setVideoHLS\\(\'(.*?)\'\\);' || [])[1],
+        thumb: videoScript.match('html5player.setThumbUrl\\(\'(.*?)\'\\);' || [])[1],
+        thumb69: videoScript.match('html5player.setThumbUrl169\\(\'(.*?)\'\\);' || [])[1],
+        thumbSlide: videoScript.match('html5player.setThumbSlide\\(\'(.*?)\'\\);' || [])[1],
+        thumbSlideBig: videoScript.match('html5player.setThumbSlideBig\\(\'(.*?)\'\\);' || [])[1]};
+      resolve({status: 200, result: {title, URL, duration, image, videoType, videoWidth, videoHeight, info, files}});
+    }).catch((err) => reject({code: 503, status: false, result: err}));
+  });
+}

+ 102 - 0
plugins/adult-xnxxsearch.js

@@ -0,0 +1,102 @@
+import fetch from 'node-fetch';
+import moment from 'moment-timezone';
+const handler = async (m, {text, usedPrefix, command}) => {
+let porn = 'https://qu.ax/bXMB.webp'
+let porn2 = 'https://qu.ax/TxtQ.webp'
+if (!db.data.chats[m.chat].modohorny && m.isGroup) {
+handler.limit = false
+conn.sendFile(m.chat, [porn, porn2].getRandom(), 'sticker.webp', '', m, true, { contextInfo: { 'forwardingScore': 200, 'isForwarded': false, externalAdReply:{ showAdAttribution: false, title: `ᴸᵒˢ ᶜᵒᵐᵃⁿᵈᵒ ʰᵒʳⁿʸ ᵉˢᵗᵃ ᵈᵉˢᵃᶜᵗᶦᵛᵃᵈᵒ ᵖᵃʳᵃ ᵃᶜᵗᶦᵛᵃʳ ᵘˢᵃʳ:`, body: '#enable modohorny', mediaType: 2, sourceUrl: md, thumbnail: imagen3}}}, { quoted: m, ephemeralExpiration: 24*60*100, disappearingMessagesInChat: 24*60*100})
+return
+}
+const horarioNsfw = db.data.chats[m.chat].horarioNsfw
+const now = moment.tz('America/Argentina/Buenos_Aires'); 
+const currentTime = now.format('HH:mm'); 
+
+if (horarioNsfw) {
+const { inicio, fin } = horarioNsfw;
+const inicioTime = moment(inicio, 'HH:mm').tz('America/Argentina/Buenos_Aires');
+const finTime = moment(fin, 'HH:mm').tz('America/Argentina/Buenos_Aires');
+const currentMoment = moment(currentTime, 'HH:mm').tz('America/Argentina/Buenos_Aires');
+let isWithinTimeRange = false;
+if (inicioTime.isAfter(finTime)) {
+if (currentMoment.isBetween(inicioTime, moment('23:59', 'HH:mm').tz('America/Argentina/Buenos_Aires')) || 
+currentMoment.isBetween(moment('00:00', 'HH:mm').tz('America/Argentina/Buenos_Aires'), finTime)) {
+isWithinTimeRange = true;
+}} else {
+if (currentMoment.isBetween(inicioTime, finTime)) {
+isWithinTimeRange = true;
+}}
+if (!isWithinTimeRange) {
+handler.limit = false
+conn.sendFile(m.chat, [porn, porn2].getRandom(), 'sticker.webp', '', m, true, { contextInfo: { 'forwardingScore': 200, 'isForwarded': false, externalAdReply:{ showAdAttribution: false, title: `ᴱˢᵗᵉ ᶜᵒᵐᵃⁿᵈᵒ ˢᵒˡᵒ ᶠᵘⁿᶜᶦᵒⁿᵃ ᵉˡ ʰᵒʳᵃʳᶦᵒ ʰᵃᵇᶦˡᶦᵗᵃᵈᵒ ᵉˡ ᵍʳᵘᵖᵒ:`, body: `${inicio} a ${fin}`, mediaType: 2, sourceUrl: md, thumbnail: imagen3}}}, { quoted: m, ephemeralExpiration: 24*60*100, disappearingMessagesInChat: 24*60*100})
+return
+}}
+
+if (!text) throw `*⚠️ Que esta buscando Pajín? usar el comando de esta forma*\n*• Ejemplo:* ${usedPrefix + command} Con mi prima*`;
+try {
+const vids_ = {
+from: m.sender,
+urls: [],
+};
+if (!global.videoListXXX) {
+global.videoListXXX = [];
+}
+if (global.videoListXXX[0]?.from == m.sender) {
+global.videoListXXX.splice(0, global.videoListXXX.length);
+}
+const res = await xnxxsearch(text);
+const json = res.result;
+let cap = `*🔍 RESULTADOS DE LA BUSQUEDA:* ${text.toUpperCase()}\n\n`;
+let count = 1;
+for (const v of json) {
+const linkXXX = v.link;
+vids_.urls.push(linkXXX);
+cap += `*[${count}]*\n• *🎬 Titulo:* ${v.title}\n• *🔗 Link:* ${v.link}\n• *❗ Info:* ${v.info}`;
+cap += '\n\n' + '••••••••••••••••••••••••••••••••' + '\n\n';
+count++;
+}
+m.reply(cap);
+global.videoListXXX.push(vids_);
+} catch (e) {
+m.reply(`\`\`\`⚠️ OCURRIO UN ERROR ⚠️\`\`\`\n\n> *Reporta el siguiente error a mi creador con el comando:*#report\n\n>>> ${e} <<<< `)       
+console.log(e) 
+handler.limit = false
+}};
+handler.help = ['xnxxsearch'].map((v) => v + ' <query>');
+handler.tags = ['nsfw'];
+handler.command = /^xnxxsearch|xnxxs$/i;
+handler.limit = ["10", "12", "15", "16", "18", "25"].getRandom()
+handler.register = true
+export default handler;
+
+async function xnxxsearch(query) {
+  return new Promise((resolve, reject) => {
+    const baseurl = 'https://www.xnxx.com';
+    fetch(`${baseurl}/search/${query}/${Math.floor(Math.random() * 3) + 1}`, {method: 'get'}).then((res) => res.text()).then((res) => {
+      const $ = cheerio.load(res, {xmlMode: false});
+      const title = [];
+      const url = [];
+      const desc = [];
+      const results = [];
+      $('div.mozaique').each(function(a, b) {
+        $(b).find('div.thumb').each(function(c, d) {
+          url.push(baseurl + $(d).find('a').attr('href').replace('/THUMBNUM/', '/'));
+        });
+      });
+      $('div.mozaique').each(function(a, b) {
+        $(b).find('div.thumb-under').each(function(c, d) {
+          desc.push($(d).find('p.metadata').text());
+          $(d).find('a').each(function(e, f) {
+            title.push($(f).attr('title'));
+          });
+        });
+      });
+      for (let i = 0; i < title.length; i++) {
+        results.push({title: title[i], info: desc[i], link: url[i]});
+      }
+      resolve({code: 200, status: true, result: results});
+    }).catch((err) => reject({code: 503, status: false, result: err}));
+  });
+}
+
+

+ 29 - 0
plugins/afk-_afk.js

@@ -0,0 +1,29 @@
+export function before(m) {
+const user = global.db.data.users[m.sender];
+if (user.afk > -1) {
+m.reply(`『 DEJASTE DE ESTA AFK 』
+
+${user.afkReason ? '*🔸️ ʀᴀᴢᴏɴ :* ' + user.afkReason : ''}*
+*🔸 ᴇsᴛᴜᴠᴏ ɪɴᴀᴄᴛɪᴠᴏ ᴅᴜʀᴀɴᴛᴇ:* ${(new Date - user.afk).toTimeString()}*`.trim());
+user.afk = -1;
+user.afkReason = '';
+}
+const jids = [...new Set([...(m.mentionedJid || []), ...(m.quoted ? [m.quoted.sender] : [])])];
+for (const jid of jids) {
+const user = global.db.data.users[jid];
+if (!user) {
+continue;
+}
+const afkTime = user.afk;
+if (!afkTime || afkTime < 0) {
+continue;
+}
+const reason = user.afkReason || '';
+m.reply(`『 💤 NO LOS ETIQUETE 💤 』
+> *ᴇsᴛᴇ ᴜsᴜᴀʀɪᴏ ǫᴜᴇ ᴍᴇɴᴄɪᴏɴᴀs ᴇsᴛᴀ ᴀғᴋ*
+
+*🔸 ${reason ? 'ᴍᴏᴛɪᴠᴏ ᴅᴇ ɪɴᴀᴄᴛɪᴠɪᴅᴀᴅ (ᴀғᴋ): ' + reason : 'ᴍᴏᴛɪᴠᴏ ᴅᴇ ɪɴᴀᴄᴛɪᴠɪᴅᴀᴅ (ᴀғᴋ): Paja xD\n> _El usuario no especificó un motivo_'}*
+*🔸 ᴛɪᴇᴍᴘᴏ ᴛʀᴀɴsᴄᴜʀʀɪᴅᴏ ᴅᴇ ɪɴᴀᴄᴛɪᴠɪᴅᴀᴅ (ᴀғᴋ): ${(new Date - afkTime).toTimeString()}*`.trim());
+}
+return true;
+}

+ 17 - 0
plugins/afk-afk.js

@@ -0,0 +1,17 @@
+const handler = async (m, {text}) => {
+const user = global.db.data.users[m.sender];
+user.afk = + new Date;
+user.afkReason = text;
+m.reply(`『 AFK 』
+
+> ᴇsᴛᴇ ᴜsᴜᴀʀɪᴏ : ${conn.getName(m.sender)} ᴇsᴛᴀ ɪɴᴀᴄᴛɪᴠᴏ. 
+
+\`💤 NO LOS ETIQUETE 💤\`
+*☣️ ᴍᴏᴛɪᴠᴏs :* ${text ? ': ' + text : 'paja'}`);
+};
+handler.help = ['afk [alasan]'];
+handler.tags = ['econ'];
+handler.command = /^afk$/i;
+handler.money = 75
+handler.register = true
+export default handler;

+ 46 - 0
plugins/audio-efectos.js

@@ -0,0 +1,46 @@
+import { unlinkSync, readFileSync } from 'fs'
+import { join } from 'path'
+import { exec } from 'child_process'
+
+let handler = async (m, { conn, args, __dirname, usedPrefix, command }) => {
+try {
+let q = m.quoted ? m.quoted : m
+let mime = ((m.quoted ? m.quoted : m.msg).mimetype || '')
+let set
+if (/bass/.test(command)) set = '-af equalizer=f=94:width_type=o:width=2:g=30'
+if (/blown/.test(command)) set = '-af acrusher=.1:1:64:0:log'
+if (/deep/.test(command)) set = '-af atempo=4/4,asetrate=44500*2/3'
+if (/earrape/.test(command)) set = '-af volume=12'
+if (/fast/.test(command)) set = '-filter:a "atempo=1.63,asetrate=44100"'
+if (/fat/.test(command)) set = '-filter:a "atempo=1.6,asetrate=22100"'
+if (/nightcore/.test(command)) set = '-filter:a atempo=1.06,asetrate=44100*1.25'
+if (/reverse/.test(command)) set = '-filter_complex "areverse"'
+if (/robot/.test(command)) set = '-filter_complex "afftfilt=real=\'hypot(re,im)*sin(0)\':imag=\'hypot(re,im)*cos(0)\':win_size=512:overlap=0.75"'
+if (/slow/.test(command)) set = '-filter:a "atempo=0.7,asetrate=44100"'
+if (/smooth/.test(command)) set = '-filter:v "minterpolate=\'mi_mode=mci:mc_mode=aobmc:vsbmc=1:fps=120\'"'
+if (/tupai|squirrel|chipmunk/.test(command)) set = '-filter:a "atempo=0.5,asetrate=65100"'
+if (/audio/.test(mime)) {
+let ran = getRandom('.mp3')
+let filename = join(__dirname, '../tmp/' + ran)
+let media = await q.download(true)
+exec(`ffmpeg -i ${media} ${set} ${filename}`, async (err, stderr, stdout) => {
+await unlinkSync(media)
+if (err) throw `_*Error!*_`
+let buff = await readFileSync(filename)
+conn.sendFile(m.chat, buff, ran, null, m, true, {
+type: 'audioMessage', 
+ptt: true 
+})})
+} else throw `⚡ 𝙍𝙚𝙨𝙥𝙤𝙣𝙙𝙖𝙣 𝙖𝙡 𝙖𝙪𝙙𝙞𝙤 𝙤 𝙣𝙤𝙩𝙖 𝙙𝙚𝙡 𝙫𝙤𝙯 𝙥𝙖𝙧𝙖 𝙢𝙤𝙙𝙞𝙛𝙞𝙘𝙖𝙧 𝙪𝙨𝙚 𝙚𝙨𝙩𝙚 𝙘𝙤𝙢𝙖𝙣𝙙𝙤 *${usedPrefix + command}*`
+} catch (e) {
+m.reply(`\`\`\`⚠️ OCURRIO UN ERROR ⚠️\`\`\`\n\n> *Reporta el siguiente error a mi creador con el comando:*#report\n\n>>> ${e} <<<< `)       
+console.log(e) 
+}}
+handler.help = ['bass', 'blown', 'deep', 'earrape', 'fast', 'fat', 'nightcore', 'reverse', 'robot', 'slow', 'smooth', 'tupai'].map(v => v + ' [vn]')
+handler.tags = ['efec']
+handler.command = /^(bass|blown|deep|earrape|fas?t|nightcore|reverse|robot|slow|smooth|tupai|squirrel|chipmunk)$/i
+handler.register = true
+export default handler
+
+const getRandom = (ext) => {
+return `${Math.floor(Math.random() * 10000)}${ext}`}

+ 52 - 0
plugins/buscador-animeinfo.js

@@ -0,0 +1,52 @@
+import translate from '@vitalets/google-translate-api';
+import {Anime} from '@shineiichijo/marika';
+const client = new Anime();
+const handler = async (m, {conn, text, usedPrefix}) => {
+if (!text) return m.reply(`*⚠️ INGRESE EL NOMBRE DE ALGUN ANIME A BUSCAR*`);
+m.react("✨") 
+try {
+const anime = await client.searchAnime(text);
+const result = anime.data[0];
+const resultes = await translate(`${result.background}`, {to: 'es', autoCorrect: true});
+const resultes2 = await translate(`${result.synopsis}`, {to: 'es', autoCorrect: true});
+const AnimeInfo = `🟢 • *ᴛɪ́ᴛᴜʟᴏ:* ${result.title}
+🎋 • *ғᴏʀᴍᴀᴛᴏ:* ${result.type}
+📈 • *ᴇsᴛᴀᴅᴏ:* ${result.status.toUpperCase().replace(/\_/g, ' ')}
+🍥 • *ᴇᴘɪsᴏᴅɪᴏs ᴛᴏᴛᴀʟᴇs:* ${result.episodes}
+🎈 • *ᴅᴜʀᴀᴄɪᴏ́ɴ: ${result.duration}*
+✨ • *ʙᴀsᴀᴅᴏ ᴇɴ:* ${result.source.toUpperCase()}
+💫 • *ᴇsᴛʀᴇɴᴀᴅᴏ:* ${result.aired.from}
+🎗 • *ғɪɴᴀʟɪᴢᴀᴅᴏ:* ${result.aired.to}
+🎐 • *ᴘᴏᴘᴜʟᴀʀɪᴅᴀᴅ:* ${result.popularity}
+🎏 • *ғᴀᴠᴏʀɪᴛᴏs:* ${result.favorites}
+🎇 • *ᴄʟᴀsɪғɪᴄᴀᴄɪᴏ́ɴ:* ${result.rating}
+🏅 • *ʀᴀɴɢᴏ:* ${result.rank}
+♦ • *ᴛʀᴀɪʟᴇʀ:* ${result.trailer.url}
+🌐 • *ᴜʀʟ:* ${result.url}
+🎆 • *ʙᴀᴄᴋɢʀᴏᴜɴᴅ:* ${resultes.text}
+❄ • *ʀɪɴɢᴋᴀsᴀɴ:* ${resultes2.text}`;
+conn.sendFile(m.chat, result.images.jpg.image_url, 'error.jpg', AnimeInfo, m, null, fake);
+m.react("✅") 
+} catch (error) {   
+try {
+const res = await fetch(`https://deliriussapi-oficial.vercel.app/search/animesearch?q=${encodeURIComponent(text)}`);
+const data = await res.json();
+if (data && data.data && data.data.length > 0) {
+const result = data.data[0];
+const AnimeInfo = `*• Título:* ${result.title}\n` +
+`*• Tipo:* ${result.type}\n` +
+`*• Episodios:* ${result.episode}\n` +
+`*• Puntuación:* ${result.score}\n` +
+`*• URL:* ${result.url}`;
+await conn.sendFile(m.chat, result.image, 'anime.jpg', AnimeInfo, m, null, fake);
+m.react("✅") 
+}} catch (e) {
+m.reply(`\`\`\`⚠️ OCURRIO UN ERROR ⚠️\`\`\`\n\n> *Reporta el siguiente error a mi creador con el comando:*#report\n\n>>> ${e} <<<< `)       
+console.log(e) 
+m.react("❌") 
+}}}
+handler.help = ['animeinfo']
+handler.tags = ['buscadores']
+handler.command = /^(anime|animeinfo)$/i;
+handler.register = true
+export default handler;

+ 37 - 0
plugins/buscador-wikipedia.js

@@ -0,0 +1,37 @@
+import axios from 'axios';
+import fetch from 'node-fetch';
+import cheerio from 'cheerio';
+async function wikipedia(querry) {
+try {
+const link = await axios.get(`https://es.wikipedia.org/wiki/${querry}`);
+const $ = cheerio.load(link.data);
+const judul = $('#firstHeading').text().trim();
+const thumb = $('#mw-content-text').find('div.mw-parser-output > div:nth-child(1) > table > tbody > tr:nth-child(2) > td > a > img').attr('src') || `//i.ibb.co/nzqPBpC/http-error-404-not-found.png`;
+const isi = [];
+$('#mw-content-text > div.mw-parser-output').each(function(rayy, Ra) {
+const penjelasan = $(Ra).find('p').text().trim();
+isi.push(penjelasan)});
+for (const i of isi) {
+const data = {status: link.status,
+result: {judul: judul,
+thumb: 'https:' + thumb,
+isi: i}};
+return data;
+}} catch (err) {
+const notFond = {status: link.status,
+Pesan: eror};
+return notFond;
+}}
+const handler = async (m, {conn, text, usedPrefix, command}) => {
+if (!text) throw `*⚠️ ᴇsᴛᴀs ᴜsᴀɴᴅᴏ ᴍᴀʟ ᴇʟ ᴄᴏᴍᴀɴᴅᴏ!!*\n*ᴜsᴏ ᴄᴏʀʀᴇᴄᴛᴏ:*\n*${usedPrefix + command} 𝙿𝚊𝚕𝚊𝚋𝚛𝚊 𝚌𝚕𝚊𝚟𝚎 𝚊 𝚋𝚞𝚜𝚌𝚊𝚛*\n\n*• ᴇᴊᴇᴍᴘʟᴏ:*\n*${usedPrefix + command} Estrellas*`;
+wikipedia(`${text}`).then((res) => {
+m.reply(`*ᴀǫᴜɪ ᴛɪᴇɴᴇs ʟᴀ ɪɴғᴏʀᴍᴀᴄɪᴏ́ɴ ᴇɴᴄᴏɴᴛʀᴀᴅᴀ:*\n\n` + res.result.isi)}).catch(() => {
+m.reply('*⚠️ ɴᴏ sᴇ ᴇɴᴄᴏɴᴛʀᴏ ɴɪɴɢᴜɴᴀ ɪɴғᴏʀᴍᴀᴄɪᴏ́ɴ, ᴘʀᴜᴇʙᴀ ǫᴜᴇ ʜᴀʏᴀs ᴇsᴄʀɪᴛᴏ ᴜɴᴀ sᴏʟᴀ ᴘᴀʟᴀʙʀᴀ ʏ ʟᴏ ʜᴀʏᴀs ᴇsᴄʀɪᴛᴏ ᴄᴏʀʀᴇᴄᴛᴀᴍᴇɴᴛᴇ*');
+});
+};
+handler.help = ['wikipedia'].map((v) => v + ' <apa>');
+handler.tags = ['buscadores'];
+handler.command = /^(wiki|wikipedia)$/i;
+handler.register = true
+handler.limit = 1
+export default handler;

+ 370 - 0
plugins/chatbot.js

@@ -0,0 +1,370 @@
+import { perplexity } from '../lib/scraper.js';
+const antiSpam = new Map();
+
+export async function before(m, { conn }) {
+    let fkontak = {
+        "key": {
+            "participants": "0@s.whatsapp.net",
+            "remoteJid": "status@broadcast",
+            "fromMe": false,
+            "id": "Halo"
+        },
+        "message": {
+            "contactMessage": {
+                "vcard": `BEGIN:VCARD
+VERSION:3.0
+N:Sy;Bot;;;
+FN:y
+item1.TEL;waid=${m.sender.split('@')[0]}:${m.sender.split('@')[0]}
+item1.X-ABLabel:Ponsel
+END:VCARD`
+            }
+        },
+        "participant": "0@s.whatsapp.net"
+    };
+
+    if (
+        m.id.startsWith('NJX-') ||
+        (m.id.startsWith('BAE5') && m.id.length === 16) ||
+        (m.id.startsWith('3EB0') && m.id.length === 12) ||
+        (m.id.startsWith('3EB0') && (m.id.length === 20 || m.id.length === 22)) ||
+        (m.id.startsWith('B24E') && m.id.length === 20) ||
+        m.id.startsWith('FizzxyTheGreat-')
+    ) return;
+
+    let setting = global.db.data.settings[this.user.jid];
+    let chat = global.db.data.chats[m.chat];
+    let name = conn.getName(m.sender);
+    const user = `@${m.sender.split('@')[0]}`;
+
+    if (chat.isBanned) return;
+    if (m.fromMe) return;
+    if (m.chat === "120363371008200788@newsletter") return;
+    if (m.chat === "120363371008200788@newsletter") return;
+
+    let vn = 'https://qu.ax/eGdW.mp3';
+    let bot = `${pickRandom([
+        `*Hola ${user} soy un bot el que puedo ayudar? 👉👈*`,
+        `Aqui estoy`,
+        `bot tu abuela`,
+        `que quiere?`,
+        `No dispoble 🫣`,
+        `Hola aqui estoy soy tu botsito sexy el que puedo ayudar uwu`
+    ])}`.trim();
+    let txt = `*Pagas una fortuna para streaming.*
+
+> *Tenemos streaming variado. Es muy barato y todos pueden comprar.*
+
+💎 \`\`\`W E B\`\`\`
+
+💻 *Página:*
+https://hackstorex.com
+
+💥 *BUSCAS SCRIPTS YA HECHOS PARA CREAR TUS PÁGINAS WEB?*
+
+⚡ *WEB*
+
+> https://MexSpin.fun
+
+🗣📲 *Contacto:*
+> 5217121649714`;
+
+    // Detectar palabras clave incluyendo Kantu y Kantubot
+    if (
+        m.text.includes('bot') ||
+        m.text.includes('Bot') ||
+        m.text.includes('simsimi') ||
+        m.text.includes('simi') ||
+        m.text.includes('alexa') ||
+        m.text.includes('kantu') ||
+        m.text.includes('Kantu') ||
+        m.text.includes('kantubot') ||
+        m.text.includes('Kantubot')
+    ) {
+        if (
+            m.text.includes('jadibot') ||
+            m.text.includes('bots') ||
+            m.text.includes('serbot') ||
+            m.text.includes('instalarbot') ||
+            m.text.includes('infobot')
+        ) return;
+
+        const lastMessageTime = antiSpam.get(m.sender) || 0;
+        const currentTime = Date.now();
+        if (currentTime - lastMessageTime < 9000) throw !0;
+
+        if (/^¿que es un bot\?|Que es un bot\?|que es un bot\?|que es un bot$/i.test(m.text)) {
+            return conn.reply(
+                m.chat,
+                `\`☆::¿${await tr("QUE ES UN BOT DE WHATSAPP?")}::☆\`
+
+> 𝐔𝐧 𝐁𝐨𝐭 𝐞𝐬 𝐮𝐧𝐚 𝐢𝐧𝐭𝐞𝐥𝐢𝐠𝐞𝐧𝐜𝐢𝐚 𝐚𝐫𝐭𝐢𝐟𝐢𝐜𝐢𝐚𝐥 𝐪𝐮𝐞 𝐫𝐞𝐚𝐥𝐢𝐳𝐚 𝐭𝐚𝐫𝐞𝐚𝐬 𝐪𝐮𝐞 𝐥𝐞 𝐢𝐧𝐝𝐢𝐪𝐮𝐞 𝐜𝐨𝐧 𝐜𝐨𝐦𝐚𝐧𝐝𝐨𝐬, 𝐞𝐧 𝐞𝐥 𝐜𝐚𝐬𝐨 𝐝𝐞 𝐖𝐡𝐚𝐭𝐬𝐀𝐩𝐩 𝐩𝐮𝐞𝐝𝐞𝐬 𝐜𝐫𝐞𝐚𝐫 𝐬𝐭𝐢𝐜𝐤𝐞𝐫𝐬, 𝐝𝐞𝐬𝐜𝐚𝐫𝐠𝐚𝐫 𝐦𝐮́𝐬𝐢𝐜𝐚, 𝐯𝐢𝐝𝐞𝐨𝐬, 𝐜𝐫𝐞𝐚𝐫 𝐥𝐨𝐠𝐨𝐬 𝐩𝐞𝐫𝐬𝐨𝐧𝐚𝐥𝐢𝐳𝐚𝐝𝐨𝐬 𝐲 𝐦𝐮𝐜𝐡𝐨 𝐦𝐚𝐬, 𝐞𝐬𝐭𝐨 𝐝𝐞 𝐟𝐨𝐫𝐦𝐚 𝐚𝐮𝐭𝐨𝐦𝐚𝐭𝐢𝐳𝐚𝐝𝐚, 𝐨 𝐬𝐞𝐚 𝐪𝐮𝐞 𝐮𝐧 𝐡𝐮𝐦𝐚𝐧𝐨 𝐧𝐨 𝐢𝐧𝐭𝐞𝐫𝐟𝐢𝐞𝐫𝐞 𝐞𝐧 𝐞𝐥 𝐩𝐫𝐨𝐜𝐞𝐬𝐨. 𝐏𝐚𝐫𝐚 𝐯𝐞𝐫 𝐞𝐥 𝐦𝐞𝐧𝐮́ 𝐝𝐞 𝐜𝐨𝐦𝐚𝐧𝐝𝐨𝐬 𝐩𝐮𝐞𝐝𝐞𝐬 𝐮𝐬𝐚𝐫: #menu
+
+>「 ᴋᴀɴᴛᴜ - ʙᴏᴛ 」`,
+                m
+            );
+        }
+
+        if (/^Quiero un bot|como obtengo un bot\?|Quiero un bot\?|quiero un bot|solicitó bot|solicito bot|Necesito un bot|necesito un bot$/i.test(m.text)) {
+            return conn.reply(
+                m.chat,
+                `\`⚡ ¿${await tr("Quieres un bot para tu grupo?")}\`
+
+Puedes solicitarlo *GRATIS* escribiendo a mi creador Crxs
+
+
+
+\`⚡ ¿El bot estará activo 24/7?\`
+> _*Sí, nuestro bot está alojado en un servidor de pago para mantenerlo activo 24/7.*_
+
+> 「 ᴋᴀɴᴛᴜ - ʙᴏᴛ 」`,
+                m,
+                {
+                    contextInfo: {
+                        externalAdReply: {
+                            mediaUrl: null,
+                            mediaType: 1,
+                            description: null,
+                            title: `Hola ${name} 👋`,
+                            body: wm,
+                            previewType: 0,
+                            thumbnail: img.getRandom(),
+                            sourceUrl: redes.getRandom()
+                        }
+                    }
+                }
+            );
+        }
+
+        try {
+            let prefixRegex = new RegExp(
+                '^[' +
+                    setting.prefix.replace(/[|\\{}()[\]^$+*.\-\^]/g, '\\$&') +
+                    ']'
+            );
+            let hasPrefixWithKeyword =
+                prefixRegex.test(m.text) &&
+                m.text.match(
+                    new RegExp(
+                        '^[' +
+                            setting.prefix.replace(/[|\\{}()[\]^$+*.\-\^]/g, '\\$&') +
+                            '](?:bot|Bot|simsimi|simi|alexa|kantu|Kantu|kantubot|Kantubot)'
+                    )
+                );
+            let hasKeywordWithoutPrefix =
+                (
+                    m.text.includes('bot') ||
+                    m.text.includes('Bot') ||
+                    m.text.includes('simsimi') ||
+                    m.text.includes('simi') ||
+                    m.text.includes('alexa') ||
+                    m.text.includes('kantu') ||
+                    m.text.includes('Kantu') ||
+                    m.text.includes('kantubot') ||
+                    m.text.includes('Kantubot')
+                ) && !prefixRegex.test(m.text);
+            if (!hasPrefixWithKeyword && !hasKeywordWithoutPrefix) return;
+            let query = m.text;
+            if (hasPrefixWithKeyword) {
+                query = m.text
+                    .replace(prefixRegex, '')
+                    .replace(
+                        /^(?:bot|Bot|simsimi|simi|alexa|kantu|Kantu|kantubot|Kantubot)/i,
+                        ''
+                    )
+                    .trim();
+            } else if (hasKeywordWithoutPrefix) {
+                const keywordRegex = /^(?:bot|Bot|simsimi|simi|alexa|kantu|Kantu|kantubot|Kantubot)\s+/i;
+                if (keywordRegex.test(m.text)) {
+                    query = m.text.replace(keywordRegex, '').trim();
+                } else {
+                    query = m.text.trim();
+                }
+            }
+            if (!query) return;
+
+            conn.sendPresenceUpdate('composing', m.chat);
+            antiSpam.set(m.sender, currentTime);
+
+            async function luminsesi(q, username, logic) {
+                try {
+                    const response = await axios.post('https://luminai.my.id', {
+                        content: q,
+                        user: username,
+                        prompt: logic,
+                        webSearchMode: true
+                    });
+                    return response.data.result;
+                } catch (error) {
+                    console.error(error);
+                }
+            }
+
+            async function perplexityIA(q, logic) {
+                try {
+                    let response = await perplexity.chat(
+                        [
+                            { role: 'system', content: logic || syms1 },
+                            { role: 'user', content: q }
+                        ],
+                        'sonar-pro'
+                    );
+                    if (response.status) {
+                        return response.result.response;
+                    } else {
+                        throw new Error(`Error en Perplexity: ${response.result.error}`);
+                    }
+                } catch (error) {
+                    console.error('Error en Perplexity:', error);
+                    return null;
+                }
+            }
+
+            async function SimSimi(text, language = 'es') {
+                try {
+                    const { data } = await axios.post(
+                        'https://api.simsimi.vn/v1/simtalk',
+                        new URLSearchParams({ text, lc: language }).toString(),
+                        {
+                            headers: {
+                                'Content-Type': 'application/x-www-form-urlencoded',
+                                'User-Agent':
+                                    'Mozilla/5.0 (Windows NT 10.0; Win64; x64)'
+                            }
+                        }
+                    );
+                    return data.message;
+                } catch (error) {
+                    console.error(error);
+                    return null;
+                }
+            }
+
+            let username = `${m.pushName}`;
+            let syms1 = await fetch(
+                'https://raw.githubusercontent.com/crxsmods/text2/refs/heads/main/text-chatgpt'
+            ).then(v => v.text());
+
+            let result;
+            if (!result || result.trim().length === 0) {
+                result = await perplexityIA(query, syms1);
+            }
+
+            if (!result || result.trim().length === 0) {
+                result = await SimSimi(query);
+            }
+
+            if (!result || result.trim().length === 0) {
+                result = await luminsesi(query, username, syms1);
+                result = result
+                    .replace(
+                        /Maaf, terjadi kesalahan saat memproses permintaan Anda/g,
+                        ''
+                    )
+                    .trim();
+                result = result
+                    .replace(
+                        /Generated by BLACKBOX\.AI.*?https:\/\/www\.blackbox\.ai/g,
+                        ''
+                    )
+                    .trim();
+                result = result
+                    .replace(
+                        /and for API requests replace https:\/\/www\.blackbox\.ai with https:\/\/api\.blackbox\.ai/g,
+                        ''
+                    )
+                    .trim();
+            }
+
+            if (result && result.trim().length > 0) {
+                await conn.reply(m.chat, result, m);
+                antiSpam.set(m.sender, Date.now());
+            }
+        } catch (e) {
+            try {
+                let gpt = await fetch(`${apis}/tools/simi?text=${m.text}`);
+                let res = await gpt.json();
+                await m.reply(res.data.message);
+                antiSpam.set(m.sender, Date.now());
+            } catch (e) {
+                return m.reply(
+                    [
+                        `Simsimi esta durmiendo no molesta 🥱`,
+                        `Callarte`,
+                        `Api simsimi caida`,
+                        `Simsimi esta ocupado cojieron con tu hermana vuelva mas tarde 🥵`,
+                        `NO MOLESTE PUTA`,
+                        `No hay señar`,
+                        `No estoy disponible`
+                    ].getRandom()
+                );
+                console.log(e);
+            }
+        }
+    }
+
+    if (/^infohost|hosting$/i.test(m.text)) {
+        await conn.sendMessage(
+            m.chat,
+            {
+                text: txt,
+                contextInfo: {
+                    forwardingScore: 9999999,
+                    isForwarded: false,
+                    externalAdReply: {
+                        showAdAttribution: true,
+                        containsAutoReply: true,
+                        title: `💎 KANTU BOT 💎`,
+                        body: `By CrxsMods`,
+                        previewType: 'PHOTO',
+                        thumbnailUrl:
+                            'https://cdn.dorratz.com/files/1739136628132.jpg',
+                        sourceUrl: nna
+                    }
+                }
+            },
+            { quoted: m }
+        );
+    }
+
+    if (/^todo bien$/i.test(m.text)) {
+        conn.reply(m.chat, `𝑩𝒊𝒆𝒏 𝒄𝒂𝒑𝒐 😎 𝒚 𝒕𝒖`, m);
+    }
+
+    if (/^e$/i.test(m.text)) {
+        conn.reply(
+            m.chat,
+            `𝑸𝒖𝒆 𝒃𝒖𝒆𝒏𝒐 𝒔𝒂𝒃𝒆𝒓 𝒍𝒂 𝒍𝒆𝒕𝒓𝒂 𝒆`,
+            m
+        );
+    }
+
+    if (/^@5217121649714|CrxsMods$/i.test(m.text)) {
+        conn.reply(
+            m.chat,
+            `*_[ ⚠ ️] No etiquetes a mi creador, si tiene alguna consulta o dudas, hablarle al privado_*`,
+            m
+        );
+    }
+
+    if (/^reglas$/i.test(m.text)) {
+        m.reply(
+            [
+                `\`🌐 REGLAS DEL BOT 🌐\`\n\n* *No hacer spam de comandos*\n\nUsar los comando cada 5 segundos, de lo contrario el bot se puede satura, o numero del bot puede irse a support por spam.\n\n* *No estar enviando link del grupos al bot para que se una*\n\nHablar con mi creador y el lo une a tu grupo, si apoyar nuestras redes sociales:\n${yt}\n${md}\n\n* *No llamar al bot, ni al creador*\n\nSi lo haces, seras baneado del bot y bloqueado`,
+                `\`⚠️ 𝙍𝙀𝙂𝙇𝘼𝙎 ⚠️\`
+
+* 𝐏𝐫𝐨𝐡𝐢𝐛𝐢𝐝𝐨 𝐥𝐥𝐚𝐦𝐚𝐫 𝐚𝐥 𝐁𝐨𝐭
+* 𝐏𝐫𝐨𝐡𝐢𝐛𝐢𝐝𝐨 𝐒𝐩𝐚𝐦 𝐚𝐥 𝐁𝐨𝐭
+* 𝐍𝐨 𝐚𝐠𝐫𝐞𝐠𝐚𝐫 𝐚𝐥 𝐁𝐨𝐭
+* 𝐑𝐞𝐬𝐩𝐞𝐭𝐚 𝐥𝐨𝐬 𝐭𝐞𝐫𝐦𝐢𝐧𝐨𝐬 𝐲 𝐜𝐨𝐧𝐝𝐢𝐜𝐢𝐨𝐧𝐞𝐬`
+            ].getRandom() + `\n\n>「 ᴋᴀɴᴛᴜ - ʙᴏᴛ 」`
+        );
+    }
+    return !0;
+}
+
+//export default handler
+
+function pickRandom(list) {
+    return list[Math.floor(Math.random() * list.length)];
+}

+ 605 - 0
plugins/config-on y off.js

@@ -0,0 +1,605 @@
+import fetch from 'node-fetch'
+import fs from 'fs' 
+let handler = async (m, { conn, usedPrefix, command, args, isOwner, isAdmin, isROwner, text }) => { 
+//try{
+let chat = global.db.data.chats[m.chat]
+let user = global.db.data.users[m.sender]
+let bot = global.db.data.settings[conn.user.jid] || {}
+let toUser = `${m.sender.split("@")[0]}`
+let aa = toUser + '@s.whatsapp.net'
+let listSections = []    
+listSections.push({ title: '『 FUNCIÓN PARA ADMINS 』',
+rows: [{ header: `🎉 BIENVENIDA ${m.isGroup ? chat.welcome ? '✅' : '❌' : `⚠️`}`, title: "", id: `${usedPrefix + command} welcome`, description: `Mensaje de Bienvenida para nuevos Miembros en Grupos\n` }, 
+{ header: `🔗 ANTI ENLACES ${m.isGroup ? chat.antilink ? '✅' : '❌' : `⚠️`}`, title: "", id: `${usedPrefix + command} antilink`, description: `Eliminar Personas que envíen enlaces de Grupos de WhatsApp\n` },
+{ header: `🔗 ANTI ENLACES 2 ${m.isGroup ? chat.antilink ? '✅' : '❌' : `⚠️`}`, title: "", id: `${usedPrefix + command} antilink2`, description: `Eliminar Personas que envíen enlaces que contengan https\n` }, 
+{ header: `🔗 ANTI TRABA ${m.isGroup ? chat.antilink ? '✅' : '❌' : `⚠️`}`, title: "", id: `${usedPrefix + command} antitraba`, description: `El Bot detecta textos largos que podrian ser virus y causar lag en el chat y elimina al usuario.\n` }, 
+{ header: `🔗 ANTI TIKTOK ${m.isGroup ? chat.antilink ? '✅' : '❌' : `⚠️`}`, title: "", id: `${usedPrefix + command} antitiktok`, description: `Eliminar Personas que envíen enlaces de TikTok\n` }, 
+{ header: `🔗 ANTI YOUTUBE ${m.isGroup ? chat.antilink ? '✅' : '❌' : `⚠️`}`, title: "", id: `${usedPrefix + command} antiyoutube`, description: `Eliminar Personas que envíen enlaces de YouTube\n` }, 
+{ header: `🔗 ANTI TELEGRAM ${m.isGroup ? chat.antilink ? '✅' : '❌' : `⚠️`}`, title: "", id: `${usedPrefix + command} antitelegram`, description: `Eliminar Personas que envíen enlaces de Telegram\n` }, 
+{ header: `🔗 ANTI FACEBOOK ${m.isGroup ? chat.antilink ? '✅' : '❌' : `⚠️`}`, title: "", id: `${usedPrefix + command} antifacebook`, description: `Eliminar Personas que envíen enlaces de Facebbok\n` }, 
+{ header: `🔗 ANTI INSTAGRAM ${m.isGroup ? chat.antilink ? '✅' : '❌' : `⚠️`}`, title: "", id: `${usedPrefix + command} antiinstagram`, description: `Eliminar Personas que envíen enlaces de Instagram\n` }, 
+{ header: `🔗 ANTI TWITTER ${m.isGroup ? chat.antilink ? '✅' : '❌' : `⚠️`}`, title: "", id: `${usedPrefix + command} antitwitter`, description: `Eliminar Personas que envíen enlaces de Twitter\n` }, 
+{ header: `🔗 ANTI DISCORD ${m.isGroup ? chat.antilink ? '✅' : '❌' : `⚠️`}`, title: "", id: `${usedPrefix + command} antidiscord`, description: `Eliminar Personas que envíen enlaces de Discord\n` }, 
+{ header: `🔗 ANTI TREADS ${m.isGroup ? chat.antilink ? '✅' : '❌' : `⚠️`}`, title: "", id: `${usedPrefix + command} antithreads`, description: `Eliminar Personas que envíen enlaces de Threas\n` },
+{ header: `🟢 ANTIFAKE ${m.isGroup ? chat.antilink ? '✅' : '❌' : `⚠️`}`, title: "", id: `${usedPrefix + command} antifake`, description: `ᶦⁿᵍʳᵉˢᵒ ᵈᵉ ⁿᵘᵐᵉʳᵒ ᶠᵃᵏᵉ (ᵛᶦʳᵗᵘᵃˡᵉˢ), ˢᵉʳᵃⁿ ᵉˣᵖˡᵘˢᵃᵈᵒ ᵃᵘᵗᵒᵐᵃ́ᵗᶦᶜᵃᵐᵉⁿᵗᵉ ᵈᵉˡ ᴳʳᵘᵖᵒ...\n` }, 
+{ header: `🔔 AVISOS ${m.isGroup ? chat.antilink ? '✅' : '❌' : `⚠️`}`, title: "", id: `${usedPrefix + command} detect`, description: `Avisos de acciones dentro del Grupo\n` }, 
+{ header: `🪄 STICKERS AUTOMÁTICOS ${m.isGroup ? chat.antilink ? '✅' : '❌' : `⚠️`}`, title: "", id: `${usedPrefix + command} autosticker`, description: `Los vídeos, Gif, imágenes, enlaces jpg o jpeg; Se convertirán en Stickers Automáticamente\n` }, 
+{ header: `🗑️ ANTI ELIMINAR ${m.isGroup ? chat.antilink ? '✅' : '❌' : `⚠️`}`, title: "", id: `${usedPrefix + command} antidelete`, description: `Todo mensaje eliminado será reenviado al Chat o Grupo\n` }, 
+{ header: `🔞 MODO CALIENTE ${m.isGroup ? chat.antilink ? '✅' : '❌' : `⚠️`}`, title: "", id: `${usedPrefix + command} modohorny`, description: `Mostrar contenido para Adulto en los Chats\n` }, 
+{ header: `🔊 AUDIOS ${m.isGroup ? chat.antilink ? '✅' : '❌' : `⚠️`}`, title: "", id: `${usedPrefix + command} audios`, description: `Habilitar el envio automático de Audios a todos\n` }, 
+{ header: `🆙 NIVEL AUTOMÁTICO ${m.isGroup ? chat.antilink ? '✅' : '❌' : `⚠️`}`, title: "", id: `${usedPrefix + command} autolevelup`, description: `Sube de nivel a todos de manera automática; (Aplica recompensas por subir de Nivel)\n` }, 
+{ header: `🙃 CHATBOT ${m.isGroup ? chat.antilink ? '✅' : '❌' : `⚠️`}`, title: "", id: `${usedPrefix + command} chatbot`, description: `El bot empezar a hablar con todos el grupo.\n` }, 
+{ header: `🛂 MODO ADMIN ${m.isGroup ? chat.antilink ? '✅' : '❌' : `⚠️`}`, title: "", id: `.${usedPrefix + command} modoadmin`, description: `Solo los Admins podrán usar el Bot en Grupos\n` }, 
+{ header: `『 FUNCIÓN SOLO PARA OWNER 』\n`, title: `🔰 ANTI PRIVADO ${m.isGroup ? chat.antilink ? '✅' : '❌' : `⚠️`}`, id: `${usedPrefix + command} antiprivado`, description: `Bloquea a la persoma que usen el bot en privado\n` }, 
+{ header: `🚫 ANTI LLAMADAS ${m.isGroup ? chat.antilink ? '✅' : '❌' : `⚠️`}`, title: "", id: `${usedPrefix + command} anticall`, description: `Bloquea a Personas que hagan llamadas\n` }, 
+{ header: `⛔ RESTRINGIR ${m.isGroup ? chat.antilink ? '✅' : '❌' : `⚠️`}`, title: "", id: `${usedPrefix + command} restrict`, description: `Habilitar función para agregar o eliminar personas en Grupos\n` }, 
+{ header: `⚜️ SOLO PRIVADOS ${m.isGroup ? chat.antilink ? '✅' : '❌' : `⚠️`}`, title: "", id: `${usedPrefix + command} pconly`, description: `Permitir que solo se use en Chats Privados\n` }, 
+{ header: `⚜️ SOLO GRUPOS ${m.isGroup ? chat.antilink ? '✅' : '❌' : `⚠️`}`, title: "", id: `${usedPrefix + command} gconly`, description: `Permitir que solo se use en Chats Grupales\n` }, 
+{ header: `✅ LECTURA AUTOMÁTICA ${m.isGroup ? chat.antilink ? '✅' : '❌' : `⚠️`}`, title: "", id: `${usedPrefix + command} autoread`, description: `Dejar los mensajes o chats como Leídos.\n` }, 
+{ header: `🌐 MODO PÚBLICO ${m.isGroup ? chat.antilink ? '✅' : '❌' : `⚠️`}`, title: "", id: `${usedPrefix + command} public`, description: `Habilitar función para que todos puedan usar KantuBot.\n` }]
+});
+let textoo = `*\`⧼⧼⧼ CONFIGURACIÓN ⧽⧽⧽\`*
+
+> *Seleccione una opción de la lista*
+> *Para empezar a Configurar*
+
+● *Avisos de la Configuracion:*
+✅ ⇢ *Función Activada*
+❌ ⇢ *Función Desactivada*
+⚠️ ⇢ *Este Chat no es un Grupo*
+
+*\`『 FUNCIÓN PARA ADMINS 』\`*
+
+🎉 BIENVENIDA ${m.isGroup ? chat.welcome ? '✅' : '❌' : `⚠️`}
+• Mensaje de Bienvenida para nuevos Miembros en Grupos
+• ${usedPrefix + command} welcome 
+
+🔗 ANTI ENLACES ${m.isGroup ? chat.antilink ? '✅' : '❌' : `⚠️`}
+• Eliminar Personas que envíen enlaces de Grupos de WhatsApp
+• ${usedPrefix + command} antilink
+
+🔗 ANTI ENLACES 2 ${m.isGroup ? chat.antilink ? '✅' : '❌' : `⚠️`}
+• Eliminar Personas que envíen enlaces que contengan https
+• ${usedPrefix + command} antilink2
+
+🔗 ANTI TRABA ${m.isGroup ? chat.antilink ? '✅' : '❌' : `⚠️`}
+• El Bot detecta textos largos que podrían ser virus y causar lag en el chat y elimina al usuario.
+• ${usedPrefix + command} antitraba
+
+🔗 ANTI TIKTOK ${m.isGroup ? chat.antilink ? '✅' : '❌' : `⚠️`}
+• Eliminar Personas que envíen enlaces de TikTok
+• ${usedPrefix + command} antitiktok
+
+🔗 ANTI YOUTUBE ${m.isGroup ? chat.antilink ? '✅' : '❌' : `⚠️`}
+• Eliminar Personas que envíen enlaces de YouTube
+• ${usedPrefix + command} antiyoutube
+
+🔗 ANTI TELEGRAM ${m.isGroup ? chat.antilink ? '✅' : '❌' : `⚠️`}
+• Eliminar Personas que envíen enlaces de Telegram
+• ${usedPrefix + command} antitelegram
+
+🔗 ANTI FACEBOOK ${m.isGroup ? chat.antilink ? '✅' : '❌' : `⚠️`}
+• Eliminar Personas que envíen enlaces de Facebook
+• ${usedPrefix + command} antifacebook
+
+🔗 ANTI INSTAGRAM ${m.isGroup ? chat.antilink ? '✅' : '❌' : `⚠️`}
+• Eliminar Personas que envíen enlaces de Instagram
+• ${usedPrefix + command} antiinstagram
+
+🔗 ANTI TWITTER ${m.isGroup ? chat.antilink ? '✅' : '❌' : `⚠️`}
+• Eliminar Personas que envíen enlaces de Twitter
+• ${usedPrefix + command} antitwitter
+
+🔗 ANTI DISCORD ${m.isGroup ? chat.antilink ? '✅' : '❌' : `⚠️`}
+• Eliminar Personas que envíen enlaces de Discord
+• ${usedPrefix + command} antidiscord
+
+🔗 ANTI THREADS ${m.isGroup ? chat.antilink ? '✅' : '❌' : `⚠️`}
+• Eliminar Personas que envíen enlaces de Threads
+• ${usedPrefix + command} antithreads
+
+🟢 ANTIFAKE ${m.isGroup ? chat.antilink ? '✅' : '❌' : `⚠️`}
+• Ingreso de número fake (virtuales), serán expulsados automáticamente del Grupo.
+• ${usedPrefix + command} antifake
+
+🔔 AVISOS ${m.isGroup ? chat.antilink ? '✅' : '❌' : `⚠️`}
+• Avisos de acciones dentro del Grupo
+• ${usedPrefix + command} detect
+
+🪄 STICKERS AUTOMÁTICOS ${m.isGroup ? chat.antilink ? '✅' : '❌' : `⚠️`}
+• Los vídeos, GIF, imágenes, enlaces jpg o jpeg; se convertirán en Stickers automáticamente.
+• ${usedPrefix + command} autosticker
+
+🗑️ ANTI ELIMINAR ${m.isGroup ? chat.antilink ? '✅' : '❌' : `⚠️`}
+• Todo mensaje eliminado será reenviado al Chat o Grupo.
+• ${usedPrefix + command} antidelete
+
+🔞 MODO CALIENTE ${m.isGroup ? chat.antilink ? '✅' : '❌' : `⚠️`}
+• Mostrar contenido para Adultos en los Chats.
+• ${usedPrefix + command} modohorny
+
+🔊 AUDIOS ${m.isGroup ? chat.antilink ? '✅' : '❌' : `⚠️`}
+• Habilitar el envío automático de Audios a todos.
+• ${usedPrefix + command} audios
+
+🆙 NIVEL AUTOMÁTICO ${m.isGroup ? chat.antilink ? '✅' : '❌' : `⚠️`}
+• Sube de nivel a todos de manera automática; (Aplica recompensas por subir de nivel).
+• ${usedPrefix + command} autolevelup
+
+🙃 CHATBOT ${m.isGroup ? chat.antilink ? '✅' : '❌' : `⚠️`}
+• El bot comenzará a hablar con todos en el grupo.
+• ${usedPrefix + command} chatbot
+
+🛂 MODO ADMIN ${m.isGroup ? chat.antilink ? '✅' : '❌' : `⚠️`}
+• Solo los Admins podrán usar el Bot en Grupos.
+• ${usedPrefix + command} modoadmin
+
+
+*\`『 FUNCIÓN SOLO PARA OWNER 』\`"
+
+🔰 ANTI PRIVADO ${m.isGroup ? chat.antilink ? '✅' : '❌' : `⚠️`}
+• Bloquea a las personas que usen el bot en privado.
+• ${usedPrefix + command} antiprivado
+
+🚫 ANTI LLAMADAS ${m.isGroup ? chat.antilink ? '✅' : '❌' : `⚠️`}
+• Bloquea a personas que hagan llamadas.
+• ${usedPrefix + command} anticall
+
+⛔ RESTRINGIR ${m.isGroup ? chat.antilink ? '✅' : '❌' : `⚠️`}
+• Habilitar función para agregar o eliminar personas en Grupos.
+• ${usedPrefix + command} restrict
+
+⚜️ SOLO PRIVADOS ${m.isGroup ? chat.antilink ? '✅' : '❌' : `⚠️`}
+• Permitir que solo se use en Chats Privados.
+• ${usedPrefix + command} pconly
+
+⚜️ SOLO GRUPOS ${m.isGroup ? chat.antilink ? '✅' : '❌' : `⚠️`}
+• Permitir que solo se use en Chats Grupales.
+• ${usedPrefix + command} gconly
+
+✅ LECTURA AUTOMÁTICA ${m.isGroup ? chat.antilink ? '✅' : '❌' : `⚠️`}
+• Dejar los mensajes o chats como Leídos.
+• ${usedPrefix + command} autoread
+
+🌐 MODO PÚBLICO ${m.isGroup ? chat.antilink ? '✅' : '❌' : `⚠️`}
+• Habilitar función para que todos puedan usar el bot.
+• ${usedPrefix + command} public
+
+> ${wm}`        
+let isEnable = /true|enable|(turn)?on|1/i.test(command)
+let type = (args[0] || '').toLowerCase()
+let isAll = false, isUser = false
+switch (type) {
+case 'welcome': case 'bienvenida':
+if (!m.isGroup) {
+if (!isOwner) {
+global.dfail('group', m, conn)
+throw false
+}
+} else if (!isAdmin) {
+global.dfail('admin', m, conn)
+throw false
+}
+chat.welcome = isEnable
+break
+    
+case 'detect': case 'avisos':
+if (!m.isGroup) {
+if (!isOwner) {
+global.dfail('group', m, conn)
+throw false
+}
+} else if (!isAdmin) {
+global.dfail('admin', m, conn)
+throw false
+}
+chat.detect = isEnable
+break
+		
+case 'antidelete': case 'antieliminar': case 'delete':
+if (m.isGroup) {
+if (!(isAdmin || isOwner)) {
+global.dfail('admin', m, conn)
+throw false
+}}
+chat.delete = isEnable
+break
+    
+case 'public': case 'publico':
+isAll = true
+if (!isROwner) {
+global.dfail('rowner', m, conn)
+throw false
+}
+global.opts['self'] = !isEnable
+break
+    
+case 'antilink': case 'antienlace':
+if (m.isGroup) {
+if (!(isAdmin || isOwner)) {
+global.dfail('admin', m, conn)
+throw false
+}}
+chat.antiLink = isEnable
+break
+    
+case 'antilink2': case 'antienlace2':
+if (m.isGroup) {
+if (!(isAdmin || isOwner)) {
+global.dfail('admin', m, conn)
+throw false
+}}
+chat.antiLink2 = isEnable 
+break
+		
+case 'antitiktok': case 'antitk': case 'antitik':
+if (m.isGroup) {
+if (!(isAdmin || isOwner)) {
+global.dfail('admin', m, conn)
+throw false
+}}
+chat.antiTiktok = isEnable 
+break
+		
+case 'antiyoutube': case 'antiyt':
+if (m.isGroup) {
+if (!(isAdmin || isOwner)) {
+global.dfail('admin', m, conn)
+throw false
+}}
+chat.antiYoutube = isEnable 
+break
+		
+case 'antitelegram': case 'antitl': case 'antitele': case 'antitg': case 'antitel':
+if (m.isGroup) {
+if (!(isAdmin || isOwner)) {
+global.dfail('admin', m, conn)
+throw false
+}}
+chat.antiTelegram = isEnable 
+break
+		
+case 'antifacebook': case 'antifb': case 'antifbook':
+if (m.isGroup) {
+if (!(isAdmin || isOwner)) {
+global.dfail('admin', m, conn)
+throw false
+}}
+chat.antiFacebook = isEnable 
+break
+		
+case 'antiinstagram': case 'antinstagram': case 'antiig': case 'antig': case 'antiinsta': case 'antinsta':
+if (m.isGroup) {
+if (!(isAdmin || isOwner)) {
+global.dfail('admin', m, conn)
+throw false
+}}
+chat.antiInstagram = isEnable 
+break
+		
+case 'antitwitter': case 'antitw': case 'antitwit': case 'antitwter': case 'antitwiter': case 'antix':
+if (m.isGroup) {
+if (!(isAdmin || isOwner)) {
+global.dfail('admin', m, conn)
+throw false
+}}
+chat.antiTwitter = isEnable 
+break
+
+case 'antidiscord':
+if (m.isGroup) {
+if (!(isAdmin || isOwner)) {
+global.dfail('admin', m, conn)
+throw false
+}}
+chat.antiDiscord = isEnable 
+break
+
+case 'antithreads':
+if (m.isGroup) {
+if (!(isAdmin || isOwner)) {
+global.dfail('admin', m, conn)
+throw false
+}}
+chat.antiThreads = isEnable 
+break
+
+case 'antitwitch':
+if (m.isGroup) {
+if (!(isAdmin || isOwner)) {
+global.dfail('admin', m, conn)
+throw false
+}}
+chat.antiTwitch = isEnable 
+break
+    
+case 'modohorny': case 'modocaliente': case 'modehorny':
+if (m.isGroup) {
+if (!(isAdmin || isOwner)) {
+global.dfail('admin', m, conn)
+throw false
+}}
+chat.modohorny = isEnable          
+break
+    
+case 'stickers':
+if (m.isGroup) {
+if (!(isAdmin || isOwner)) {
+global.dfail('admin', m, conn)
+throw false
+}}
+chat.stickers = isEnable          
+break
+    
+case 'game': case 'juegos': case 'fun':
+if (m.isGroup) {
+if (!(isAdmin || isOwner)) {
+global.dfail('admin', m, conn)
+throw false
+}}
+chat.game = isEnable          
+break
+    
+case 'ruleta': case 'game2':
+if (m.isGroup) {
+if (!(isAdmin || isOwner)) {
+global.dfail('admin', m, conn)
+throw false
+}}
+chat.game2 = isEnable          
+break
+    
+case 'temporal':
+isAll = true
+if (!isOwner) {
+global.dfail('owner', m, conn)
+throw false
+}
+bot.temporal = isEnable
+break
+		
+case 'autolevelup': case 'autonivel': case 'nivelautomatico':
+if (m.isGroup) {
+if (!(isAdmin || isOwner)) {
+global.dfail('admin', m, conn)
+throw false
+}}
+chat.autolevelup = isEnable          
+break
+    
+case 'autosticker':
+if (m.isGroup) {
+if (!(isAdmin || isOwner)) {
+global.dfail('admin', m, conn)
+throw false
+}}
+chat.autosticker = isEnable          
+break
+    
+case 'reaction': case 'reaccion': case 'emojis': case 'antiemojis': case 'reacciones': case 'reaciones':
+if (m.isGroup) {
+if (!(isAdmin || isOwner)) {
+global.dfail('admin', m, conn)
+throw false
+}}
+chat.reaction = isEnable          
+break
+		
+case 'antitoxic': case 'antitoxicos': case 'antimalos':
+if (m.isGroup) {
+if (!(isAdmin || isOwner)) {
+global.dfail('admin', m, conn)
+throw false
+}}
+chat.antitoxic = isEnable
+break
+    
+case 'audios':
+if (m.isGroup) {
+if (!(isAdmin || isOwner)) {
+global.dfail('admin', m, conn)
+throw false
+}}
+chat.audios = isEnable          
+break
+    
+case 'antiver': case 'modover': case 'modoobservar': case 'modobservar': case 'antiviewonce':
+if (m.isGroup) {
+if (!(isAdmin || isOwner)) {
+global.dfail('admin', m, conn)
+throw false
+}}
+chat.antiver = isEnable 
+break
+		
+case 'antiinternacional': case 'antinternacional': case 'antinternational': case 'antifake': case 'antifalsos': case 'antivirtuales': case 'antiextranjeros':		
+if (m.isGroup) {
+if (!(isAdmin || isOwner)) {
+global.dfail('admin', m, conn)
+throw false
+}}
+chat.antifake = isEnable          
+break
+		
+case 'jadibot': case 'modojadibot': case 'serbot': case 'modoserbot': 
+isAll = true
+if (!isROwner) {
+global.dfail('rowner', m, conn)
+throw false
+}
+bot.jadibotmd = isEnable
+break 
+    
+case 'restrict': case 'restringir':
+isAll = true
+if (!isOwner) {
+global.dfail('owner', m, conn)
+throw false
+}
+bot.restrict = isEnable
+break
+
+case 'antiporn': case 'antiporno':
+if (m.isGroup) {
+if (!(isAdmin || isOwner)) {
+global.dfail('admin', m, conn)
+throw false
+}}
+chat.antiPorn = isEnable          
+break
+    
+case 'nyimak':
+isAll = true
+if (!isROwner) {
+global.dfail('rowner', m, conn)
+throw false
+}
+global.opts['nyimak'] = isEnable
+break
+    
+case 'autoread': case 'autovisto':
+isAll = true
+if (!isROwner) {
+global.dfail('rowner', m, conn)
+throw false
+}
+bot.autoread2 = isEnable    
+global.opts['autoread'] = isEnable  
+break
+    
+case 'anticall': case 'antillamar':
+isAll = true
+if (!isOwner) {
+global.dfail('rowner', m, conn)
+throw false
+}
+bot.antiCall = isEnable
+break
+		
+case 'antispam':
+isAll = true
+if (!isOwner) {
+global.dfail('owner', m, conn)
+throw false
+}
+bot.antiSpam = isEnable
+break
+
+case 'antispam2':
+isAll = true
+if (!isOwner) {
+global.dfail('owner', m, conn)
+throw false
+}
+bot.antiSpam2 = isEnable
+break
+
+case 'modoadmin': case 'soloadmin': case 'modeadmin':
+if (m.isGroup) {
+if (!(isAdmin || isOwner)) {
+global.dfail('admin', m, conn)
+throw false
+}}
+chat.modoadmin = isEnable          
+break    
+   
+case 'pconly': case 'privateonly': case 'soloprivados':
+isAll = true
+if (!isOwner) {
+global.dfail('rowner', m, conn)
+throw false
+}
+global.opts['pconly'] = isEnable
+break
+    
+case 'gconly': case 'grouponly': case 'sologrupos':
+isAll = true
+if (!isOwner) {
+global.dfail('rowner', m, conn)
+throw false
+}
+global.opts['gconly'] = isEnable
+break
+case 'antiprivado': case 'antiprivate':
+case 'privado':
+isAll = true
+if (!isOwner) {
+global.dfail('rowner', m, conn)
+throw false
+}
+bot.antiPrivate = isEnable
+break
+case 'antitrabas': case 'antitraba': case 'antilag':
+if (m.isGroup) {
+if (!(isAdmin || isOwner)) {
+global.dfail('admin', m, conn)
+throw false
+}}
+chat.antiTraba = isEnable
+break
+
+case 'autorespond': case 'autoresponder':
+if (m.isGroup) {
+if (!(isAdmin || isOwner)) {
+global.dfail('admin', m, conn)
+throw false
+}}
+chat.autorespond = isEnable 
+break		
+case 'simi': case 'chatbot':
+if (m.isGroup) {
+if (!(isAdmin || isOwner)) {
+global.dfail('admin', m, conn)
+throw false
+}}
+chat.simi = isEnable
+break 
+		
+case 'anticommand': case 'antiarabe': case 'antiarabe2': case 'AntiCommand':
+isAll = true
+if (!isOwner) {
+global.dfail('rowner', m, conn)
+throw false
+}
+bot.anticommand = isEnable
+break 
+		
+case 'modoia': case 'chatgpt': case 'ia':
+isAll = true;
+if (!isOwner) {
+global.dfail('owner', m, conn);
+throw false;
+}
+bot.modoia = isEnable;      
+break;      
+      
+case 'swonly': case 'statusonly':
+isAll = true
+if (!isOwner) {
+global.dfail('rowner', m, conn)
+throw false
+}
+global.opts['swonly'] = isEnable
+break
+default:
+if (!/[01]/.test(command)) return await m.reply(textoo) 
+//conn.sendList(m.chat, texto, wm, `AJUSTES`, null, listSections, m)
+throw false
+}
+await m.reply(`🗂️ ʟᴀ ᴏᴘᴄɪᴏɴ ${type} ᴘᴀʀᴀ ${isAll ? 'ᴇsᴛᴇ ʙᴏᴛ' : isUser ? '' : 'ᴇsᴛᴇ ᴄʜᴀᴛ'} ғᴜᴇ ${isEnable ? 'ᴀᴄᴛɪᴠᴀᴅᴏ' : 'ᴅᴇsᴀᴄᴛɪᴠᴀᴅᴏ'} `) 
+/*conn.sendButton(m.chat, `╭┄〔 *${wm}* 〕┄⊱
+┆🗂️ ᴏᴘᴄɪᴏɴ: ${type} 
+┆——————«•»——————
+┆🎚️ ᴇsᴛᴀᴅᴏ: ${isEnable ? 'ᴀᴄᴛɪᴠᴀᴅᴏ' : 'ᴅᴇsᴀᴄᴛɪᴠᴀᴅᴏ'}
+┆——————«•»——————
+┆📣 ᴘᴀʀᴀ: ${isAll ? 'ᴇsᴛᴇ ʙᴏᴛ' : isUser ? '' : 'ᴇsᴛᴇ ᴄʜᴀᴛ'} 
+╰━━━⊰ 𓃠 ${vs} ⊱━━━━დ`, wm, null, [[`${isEnable ? `Desactivar` : `Activar`}`, `${isEnable ? `.off ${type}` : `.on ${type}`}`]], null, null, m)*/
+}; 
+handler.help = ['en', 'dis'].map(v => v + 'able <option>')
+handler.tags = ['nable']
+handler.command = /^((en|dis)able|(tru|fals)e|(turn)?o(n|ff)|[01])$/i
+handler.register = true
+export default handler;
+
+const more = String.fromCharCode(8206)
+const readMore = more.repeat(4001)

+ 32 - 0
plugins/convertidor-toanime.js

@@ -0,0 +1,32 @@
+import uploadImage from '../lib/uploadImage.js';
+const handler = async (m, {conn, text, args, usedPrefix, command}) => {
+const q = m.quoted ? m.quoted : m;
+const mime = (q.msg || q).mimetype || q.mediaType || '';
+if (!/image/g.test(mime)) throw '⚠️ ¿𝐇𝐞𝐲 𝐧𝐨 𝐬𝐚𝐛𝐞𝐬 𝐜𝐨𝐦𝐨 𝐮𝐬𝐚𝐫 𝐞𝐬𝐭𝐞 𝐜𝐨𝐦𝐚𝐧𝐝𝐨 𝐩𝐞𝐧𝐝𝐞𝐣𝐨? 𝐫𝐞𝐬𝐩𝐨𝐧𝐝𝐞 𝐚 𝐮𝐧𝐚 𝐢𝐦𝐚𝐠𝐞𝐧';
+m.react(`⌛`) 
+const data = await q.download?.();
+const image = await uploadImage(data);
+try {
+const anime = `https://api.lolhuman.xyz/api/imagetoanime?apikey=${lolkeysapi}&img=${image}`;
+await conn.sendFile(m.chat, anime, 'error.jpg', null, m, null, fake);
+m.react(`✅`) 
+} catch (i) {
+try {
+const anime2 = `https://api.zahwazein.xyz/photoeditor/jadianime?url=${image}&apikey=${keysxxx}`;
+await conn.sendFile(m.chat, anime2, 'error.jpg', null, m, null, fake);
+m.react(`✅`)  
+} catch (a) {
+try {
+const anime3 = `https://api.caliph.biz.id/api/animeai?img=${image}&apikey=caliphkey`;
+await conn.sendFile(m.chat, anime3, 'error.jpg', null, m, null, fake);
+m.react(`✅`)         
+} catch (e) {
+m.reply(`\`\`\`⚠️ OCURRIO UN ERROR ⚠️\`\`\`\n\n> *Reporta el siguiente error a mi creador con el comando:*#report\n\n>>> ${e} <<<< `)       
+console.log(e) 
+m.react(`❌`) 
+}}}};
+handler.help = ['toanime'];
+handler.tags = ['convertidor']
+handler.command = /^(jadianime|toanime)$/i;
+handler.register = true
+export default handler;

+ 16 - 0
plugins/convertidor-togifaud.js

@@ -0,0 +1,16 @@
+/* 𝐂𝐑𝐄𝐀𝐃𝐎 𝐏𝐎𝐑 https://github.com/BrunoSobrino */
+
+const handler = async (m, {conn, usedPrefix, command}) => {
+if (!m.quoted) throw `*⚠️ 𝐑𝐞𝐬𝐩𝐨𝐧𝐝𝐞 𝐚 𝐮𝐧 𝐯𝐢𝐝𝐞𝐨 𝐪𝐮𝐞 𝐝𝐞𝐬𝐞𝐞 𝐜𝐨𝐧𝐯𝐞𝐫𝐭𝐢𝐫 𝐞𝐧 𝐠𝐢𝐟 𝐜𝐨𝐧 𝐚𝐮𝐝𝐢𝐨*`;
+const q = m.quoted || m;
+const mime = (q.msg || q).mimetype || '';
+if (!/(mp4)/.test(mime)) throw `*⚠️ 𝐄𝐥 𝐭𝐢𝐩𝐨 𝐝𝐞 𝐚𝐫𝐜𝐡𝐢𝐯𝐨 ${mime} 𝐧𝐨 𝐞𝐬 𝐜𝐨𝐫𝐫𝐞𝐜𝐭𝐨, 𝐫𝐞𝐬𝐩𝐨𝐧𝐝𝐚 𝐚 𝐮𝐧 𝐯𝐢𝐝𝐞𝐨 𝐪𝐮𝐞 𝐝𝐞𝐬𝐬𝐞 𝐜𝐨𝐧𝐯𝐞𝐫𝐭𝐢𝐫 𝐞𝐧 𝐠𝐢𝐟 𝐜𝐨𝐧 𝐚𝐮𝐝𝐢𝐨*`;
+m.reply(global.wait);
+const media = await q.download();
+conn.sendMessage(m.chat, {video: media, gifPlayback: true, caption: '*ᴀϙᴜɪ ᴇsᴛᴀ sᴜ ɢɪғ ᴄᴏɴ ᴀᴜᴅɪᴏ*'}, {quoted: m});
+};
+handler.help = ['togif'];
+handler.tags = ['convertidor']
+handler.command = ['togifaud', 'togif'];
+handler.register = true
+export default handler;

+ 17 - 0
plugins/convertidor-toimg.js

@@ -0,0 +1,17 @@
+import {webp2png} from '../lib/webp2mp4.js';
+const handler = async (m, {conn, usedPrefix, command}) => {
+const notStickerMessage = `*⚠️ 𝐑𝐞𝐬𝐩𝐨𝐧𝐝𝐞 𝐚 𝐮𝐧 𝐬𝐭𝐢𝐜𝐤𝐞𝐫 𝐪𝐮𝐞 𝐝𝐞𝐬𝐞𝐞 𝐜𝐨𝐧𝐯𝐞𝐫𝐭𝐢𝐫 𝐞𝐧 𝐢𝐦𝐚𝐠𝐞𝐧 𝐜𝐨𝐧 𝐞𝐥 𝐬𝐢𝐠𝐮𝐢𝐞𝐧𝐭𝐞 𝐜𝐨𝐦𝐚𝐧𝐝𝐨:* ${usedPrefix + command}`;
+if (!m.quoted) throw notStickerMessage;
+m.reply(`Euu flaco 🥴\n\n> *Convirtiendo tu Sticker a Imagen 🔄*`) 
+const q = m.quoted || m;
+const mime = q.mediaType || '';
+if (!/sticker/.test(mime)) throw notStickerMessage;
+const media = await q.download();
+const out = await webp2png(media).catch((_) => null) || Buffer.alloc(0);
+await conn.sendFile(m.chat, out, 'error.png', null, m, null, fake);
+};
+handler.help = ['toimg (reply)'];
+handler.tags = ['convertidor']
+handler.command = ['toimg', 'jpg', 'img'];
+handler.register = true
+export default handler;

+ 17 - 0
plugins/convertidor-tomp3.js

@@ -0,0 +1,17 @@
+import {toAudio} from '../lib/converter.js';
+const handler = async (m, {conn, usedPrefix, command}) => {
+const q = m.quoted ? m.quoted : m;
+const mime = (q || q.msg).mimetype || q.mediaType || '';
+if (!/video|audio/.test(mime)) throw `*⚠️ ¿𝐘 𝐞𝐥 𝐯𝐢𝐝𝐞𝐨? 𝐑𝐞𝐬𝐩𝐨𝐧𝐝𝐞 𝐚 𝐮𝐧 𝐯𝐢𝐝𝐞𝐨 𝐨 𝐧𝐨𝐭𝐚 𝐝𝐞 𝐯𝐨𝐳 𝐩𝐚𝐫𝐚 𝐜𝐨𝐧𝐯𝐞𝐫𝐭𝐢𝐫 𝐚 𝐌𝐏𝟑*`;
+const media = await q.download();
+if (!media) throw '*⚠️ 𝐎𝐂𝐔𝐑𝐑𝐈𝐎́ 𝐔𝐍 𝐄𝐑𝐑𝐎𝐑 𝐍𝐎𝐒𝐄 𝐐𝐔𝐄 𝐏𝐀𝐒𝐎? 𝐓𝐔 𝐒𝐀𝐁𝐄𝐒?* :)';
+m.reply(`Calmaoooo estoy procesando 😎\n\n> *Convirtiendo de MP4 a MP3 🔄*`) 
+  const audio = await toAudio(media, 'mp4');
+if (!audio.data) throw '*⚠️ 𝐓𝐑𝐄𝐌𝐄𝐍𝐃𝐎 ¿𝐍𝐨 𝐬𝐚𝐛𝐞𝐬 𝐮𝐬𝐚𝐫 𝐞𝐥 𝐜𝐨𝐦𝐚𝐧𝐝𝐨? 𝐫𝐞𝐬𝐩𝐨𝐧𝐝𝐞𝐫 𝐚 𝐮𝐧 𝐯𝐢𝐝𝐞𝐨 𝐨 𝐧𝐨𝐭𝐚 𝐝𝐞 𝐯𝐨𝐳 𝐛𝐨𝐛𝐨*';
+conn.sendMessage(m.chat, {audio: audio.data, mimetype: 'audio/mpeg', fake, }, {quoted: m});
+};
+handler.help = ['tomp3'];
+handler.tags = ['convertidor']
+handler.command = /^to(mp3|audio)$/i;
+handler.register = true
+export default handler;

+ 16 - 0
plugins/convertidor-tourl.js

@@ -0,0 +1,16 @@
+import uploadFile from '../lib/uploadFile.js';
+import uploadImage from '../lib/uploadImage.js';
+const handler = async (m) => {
+const q = m.quoted ? m.quoted : m;
+const mime = (q.msg || q).mimetype || '';
+if (!mime) throw '*⚠️ ¿𝐘 𝐋𝐀 𝐈𝐌𝐀𝐆𝐄𝐍? 𝐑𝐞𝐬𝐩𝐨𝐧𝐝𝐞 𝐚 𝐮𝐧𝐚 𝐢𝐦𝐚𝐠𝐞𝐧 𝐨 𝐯𝐢𝐝𝐞𝐨 𝐞𝐥 𝐜𝐮𝐚𝐥 𝐬𝐞𝐫𝐚 𝐜𝐨𝐧𝐯𝐞𝐫𝐭𝐢𝐝𝐨 𝐚 𝐞𝐧𝐥𝐚𝐜𝐞*';
+const media = await q.download();
+const isTele = /image\/(png|jpe?g|gif)|video\/mp4/.test(mime);
+const link = await (isTele ? uploadImage : uploadFile)(media);
+m.reply(link);
+};
+handler.help = ['tourl <reply image>'];
+handler.tags = ['convertidor']
+handler.command = /^(upload|tourl)$/i;
+handler.register = true
+export default handler;

+ 24 - 0
plugins/convertidor-tovideo.js

@@ -0,0 +1,24 @@
+import {webp2mp4} from '../lib/webp2mp4.js';
+import {ffmpeg} from '../lib/converter.js';
+const handler = async (m, {conn, usedPrefix, command}) => {
+if (!m.quoted) throw `*⚠️ 𝐑𝐄𝐒𝐏𝐎𝐍𝐃𝐄 𝐀 𝐔𝐍 𝐒𝐓𝐈𝐂𝐊𝐄𝐑 𝐐𝐔𝐄 𝐃𝐄𝐒𝐒𝐄 𝐂𝐎𝐍𝐕𝐄𝐑𝐓𝐈𝐑 𝐄𝐍 𝐕𝐈𝐃𝐄𝐎 𝐂𝐎𝐍 𝐄𝐋 𝐂𝐎𝐌𝐀𝐍𝐃𝐎: ${usedPrefix + command}*`;
+const mime = m.quoted.mimetype || '';
+if (!/webp/.test(mime)) throw `*⚠️ 𝐑𝐄𝐒𝐏𝐎𝐍𝐃𝐄 𝐀 𝐔𝐍 𝐒𝐓𝐈𝐂𝐊𝐄𝐑 𝐐𝐔𝐄 𝐃𝐄𝐒𝐒𝐄 𝐂𝐎𝐍𝐕𝐄𝐑𝐓𝐈𝐑 𝐄𝐍 𝐕𝐈𝐃𝐄𝐎 𝐂𝐎𝐍 𝐄𝐋 𝐂𝐎𝐌𝐀𝐍𝐃𝐎: ${usedPrefix + command}*`;
+const media = await m.quoted.download();
+let out = Buffer.alloc(0);
+if (/webp/.test(mime)) {
+out = await webp2mp4(media);
+} else if (/audio/.test(mime)) {
+out = await ffmpeg(media, ['-filter_complex', 'color',
+'-pix_fmt', 'yuv420p',
+'-crf', '51',
+'-c:a', 'copy',
+'-shortest', 
+], 'mp3', 'mp4')}
+await conn.sendFile(m.chat, out, 'error.mp4', '*✅ 𝐄𝐱𝐢𝐭𝐨*', m, null, fake, 0, {thumbnail: out});
+};
+handler.help = ['tovideo'];
+handler.tags = ['convertidor']
+handler.command = ['tovideo', 'tomp4', 'mp4', 'togif'];
+handler.register = true
+export default handler;

+ 43 - 0
plugins/convertidor-tts.js

@@ -0,0 +1,43 @@
+import gtts from 'node-gtts';
+import {readFileSync, unlinkSync} from 'fs';
+import {join} from 'path';
+const defaultLang = 'es';
+const handler = async (m, {conn, args, usedPrefix, command}) => {
+let lang = args[0];
+let text = args.slice(1).join(' ');
+if ((args[0] || '').length !== 2) {
+lang = defaultLang;
+text = args.join(' ');
+}
+if (!text && m.quoted?.text) text = m.quoted.text;
+conn.sendPresenceUpdate('recording', m.chat)   
+let res;
+try {
+res = await tts(text, lang);
+} catch (e) {
+m.reply(e + '');
+text = args.join(' ');
+if (!text) throw `*⚠️ 𝐄𝐬𝐜𝐫𝐢𝐛𝐞 𝐮𝐧 𝐭𝐞𝐱𝐭𝐨 𝐪𝐮𝐞 𝐪𝐮𝐢𝐞𝐫𝐚 𝐜𝐨𝐧𝐯𝐞𝐫𝐭𝐢𝐫 𝐚 𝐧𝐨𝐭𝐚 𝐝𝐞 𝐯𝐨𝐳, 𝐄𝐣𝐞𝐦𝐩𝐥𝐨:* ${usedPrefix + command} es Hola negros`;
+res = await tts(text, defaultLang);
+} finally {
+if (res) conn.sendFile(m.chat, res, 'tts.opus', null, m, null, fake, true);
+}};
+handler.help = ['tts <lang> <teks>'];
+handler.tags = ['convertidor']
+handler.command = /^g?tts$/i;
+handler.register = true
+export default handler;
+
+function tts(text, lang = 'es') {
+console.log(lang, text);
+return new Promise((resolve, reject) => {
+try {
+const tts = gtts(lang);
+const filePath = join(global.__dirname(import.meta.url), '../tmp', (1 * new Date) + '.wav');
+tts.save(filePath, text, () => {
+resolve(readFileSync(filePath));
+unlinkSync(filePath);
+});
+} catch (e) {
+reject(e);
+}})}

+ 99 - 0
plugins/descargas-consejos.js

@@ -0,0 +1,99 @@
+import translate from '@vitalets/google-translate-api'
+import fetch from 'node-fetch'
+import axios from "axios"
+
+let handler = async (m, { conn, usedPrefix, command }) => {
+try { 
+if (command == 'consejo' || command == 'advice') { 
+let img = 'https://img.freepik.com/vector-premium/caracter-gato-ilustracion-hoja-trebol_75474-1263.jpg'
+let list = global.motivation 
+let contenido = list[Math.floor(Math.random() * list.length)]
+let result = await translate(`${contenido}`, { to: "es", autoCorrect: true })
+let texto = `
+*╭━━・☘️・━━━━・☘️・━━⬣*
+
+*ღ _${result.text}_*
+
+*╰━━・☘️・━━━━・☘️・━━⬣*`
+//conn.sendButton(m.chat, texto.trim(), botname, img, [['✨ 𝐒𝐈𝐆𝐔𝐈𝐄𝐍𝐓𝐄 ✨', `/${command}`]], null, null, m)}
+conn.sendFile(m.chat, img,  'error.jpg', texto.trim(), fkontak, false, fake)} 
+//await conn.sendButton(m.chat, texto.trim(), wm, img, [[lenguajeGB.smsConj(), `${usedPrefix + command}`], [lenguajeGB.smsConMenu(), `${usedPrefix}menu`]], m, frep)}   
+  
+if (command == 'frase2' || command == 'phrase2') { 
+let img = 'https://superpet.pe/blog/wp-content/uploads/2022/05/nombres-para-gatos-blancos.jpg'  
+let list = (await axios.get(`https://raw.githubusercontent.com/GataNina-Li/GataBot-MD/master/src/JSON/frase2.json`)).data  
+let contenido = await list[Math.floor(list.length * Math.random())]
+let frase = contenido.motivasi
+let frase2 = await translate(`${frase}`, { to: "es", autoCorrect: true })
+let texto = `
+*╭━━・☘️・━━━━・☘️・━━⬣*
+
+*ღ ${frase2.text}*
+
+*╰━━・☘️・━━━━・☘️・━━⬣*`
+conn.sendFile(m.chat, img,  'error.jpg', texto.trim(), fkontak, false, fake)} 
+//await conn.sendButton(m.chat, texto.trim(), wm, img, [[lenguajeGB.smsFras(), `${usedPrefix + command}`], [lenguajeGB.smsConMenu(), `${usedPrefix}menu`]], m, frep)} 
+} catch (e) {
+await m.react(`❌`) 
+m.reply(`\`\`\`⚠️ OCURRIO UN ERROR ⚠️\`\`\`\n\n> *Reporta el siguiente error a mi creador con el comando:*#report\n\n>>> ${e} <<<< `)       
+console.log(e)}}
+handler.help = ['consejo']
+handler.tags = ['downloader']
+handler.command = ['consejo', 'advice', 'frase2', 'phrase2']
+handler.register = true
+handler.limit = 1
+handler.level = 2
+export default handler
+
+global.motivation = [
+  "Jangan bicara, bertindak saja. Jangan katakan, tunjukkan saja. Jangan janji, buktikan saja.",
+  "Jangan pernah berhenti melakukan yang terbaik hanya karena seseorang tidak memberi Anda penghargaan.",
+  "Bekerja saat mereka tidur. Belajar saat mereka berpesta. Hemat sementara mereka menghabiskan. Hiduplah seperti mimpi mereka.",
+  "Kunci sukses adalah memusatkan pikiran sadar kita pada hal-hal yang kita inginkan, bukan hal-hal yang kita takuti.",
+  "Jangan takut gagal. Ketakutan berada di tempat yang sama tahun depan seperti Anda saat ini.",
+  "Jika kita terus melakukan apa yang kita lakukan, kita akan terus mendapatkan apa yang kita dapatkan.",
+  "Jika Anda tidak dapat mengatasi stres, Anda tidak akan mengelola kesuksesan.",
+  "Bersikap keras kepala tentang tujuan Anda dan fleksibel tentang metode Anda.",
+  "Kerja keras mengalahkan bakat ketika bakat tidak bekerja keras.",
+  "Ingatlah bahwa pelajaran terbesar dalam hidup biasanya dipelajari dari saat-saat terburuk dan dari kesalahan terburuk.",
+  "Hidup bukan tentang menunggu badai berlalu, tetapi belajar menari di tengah hujan.",
+  "Jika rencananya tidak berhasil, ubah rencananya bukan tujuannya.",
+  "Jangan takut kalau hidupmu akan berakhir; takutlah kalau hidupmu tak pernah dimulai.",
+  "Orang yang benar-benar hebat adalah orang yang membuat setiap orang merasa hebat.",
+  "Pengalaman adalah guru yang berat karena dia memberikan tes terlebih dahulu, kemudian pelajarannya.",
+  "Mengetahui seberapa banyak yang perlu diketahui adalah awal dari belajar untuk hidup.",
+  "Sukses bukanlah akhir, kegagalan tidak fatal. Yang terpenting adalah keberanian untuk melanjutkan.",
+  "Lebih baik gagal dalam orisinalitas daripada berhasil meniru.",
+  "Berani bermimpi, tapi yang lebih penting, berani melakukan tindakan di balik impianmu.",
+  "Tetapkan tujuan Anda tinggi-tinggi, dan jangan berhenti sampai Anda mencapainya.",
+  "Kembangkan kesuksesan dari kegagalan. Keputusasaan dan kegagalan adalah dua batu loncatan paling pasti menuju sukses.",
+  "Jenius adalah satu persen inspirasi dan sembilan puluh sembilan persen keringat.",
+  "Sukses adalah tempat persiapan dan kesempatan bertemu.",
+  "Ketekunan gagal 19 kali dan berhasil pada kesempatam yang ke-20.",
+  "Jalan menuju sukses dan jalan menuju kegagalan hampir persis sama.",
+  "Sukses biasanya datang kepada mereka yang terlalu sibuk mencarinya.",
+  "Jangan tunda pekerjaanmu sampai besok, sementara kau bisa mengerjakannya hari ini.",
+  "20 tahun dari sekarang, kau mungkin lebih kecewa dengan hal-hal yang tidak sempat kau lakukan alih-alih yang sudah.",
+  "Jangan habiskan waktumu memukuli tembok dan berharap bisa mengubahnya menjadi pintu.",
+  "Kesempatan itu mirip seperti matahari terbit. Kalau kau menunggu terlalu lama, kau bisa melewatkannya.",
+  "Hidup ini terdiri dari 10 persen apa yang terjadi padamu dan 90 persen bagaimana caramu menyikapinya.",
+  "Ada tiga cara untuk mencapai kesuksesan tertinggi: Cara pertama adalah bersikap baik. Cara kedua adalah bersikap baik. Cara ketiga adalah menjadi baik.",
+  "Alasan nomor satu orang gagal dalam hidup adalah karena mereka mendengarkan teman, keluarga, dan tetangga mereka.",
+  "Waktu lebih berharga daripada uang. Kamu bisa mendapatkan lebih banyak uang, tetapi kamu tidak bisa mendapatkan lebih banyak waktu.",
+  "Penetapan tujuan adalah rahasia masa depan yang menarik.",
+  "Saat kita berusaha untuk menjadi lebih baik dari kita, segala sesuatu di sekitar kita juga menjadi lebih baik.",
+  "Pertumbuhan dimulai ketika kita mulai menerima kelemahan kita sendiri.",
+  "Janganlah pernah menyerah ketika Anda masih mampu berusaha lagi. Tidak ada kata berakhir sampai Anda berhenti mencoba.",
+  "Kemauan adalah kunci sukses. Orang-orang sukses, berusaha keras apa pun yang mereka rasakan dengan menerapkan keinginan mereka untuk mengatasi sikap apatis, keraguan atau ketakutan.",
+  "Janganlah pernah menyerah ketika Anda masih mampu berusaha lagi. Tidak ada kata berakhir sampai Anda berhenti mencoba.",
+  "Kemauan adalah kunci sukses. Orang-orang sukses, berusaha keras apa pun yang mereka rasakan dengan menerapkan keinginan mereka untuk mengatasi sikap apatis, keraguan atau ketakutan.",
+  "Hal pertama yang dilakukan orang sukses adalah memandang kegagalan sebagai sinyal positif untuk sukses.",
+  "Ciri khas orang sukses adalah mereka selalu berusaha keras untuk mempelajari hal-hal baru.",
+  "Sukses adalah mendapatkan apa yang kamu inginkan, kebahagiaan menginginkan apa yang kamu dapatkan.",
+  "Orang pesimis melihat kesulitan di setiap kesempatan. Orang yang optimis melihat peluang dalam setiap kesulitan.",
+  "Keraguan membunuh lebih banyak mimpi daripada kegagalan.",
+  "Lakukan apa yang harus kamu lakukan sampai kamu dapat melakukan apa yang ingin kamu lakukan.",
+  "Optimistis adalah salah satu kualitas yang lebih terkait dengan kesuksesan dan kebahagiaan daripada yang lain.",
+  "Penghargaan paling tinggi bagi seorang pekerja keras bukanlah apa yang dia peroleh dari pekerjaan itu, tapi seberapa berkembang ia dengan kerja kerasnya itu.",
+  "Cara terbaik untuk memulai adalah dengan berhenti berbicara dan mulai melakukan.",
+  "Kegagalan tidak akan pernah menyusul jika tekad untuk sukses cukup kuat."]

+ 99 - 0
plugins/descargas-drive.js

@@ -0,0 +1,99 @@
+import fetch from 'node-fetch';
+const userCaptions = new Map();
+const userRequests = {};
+
+let handler = async (m, { conn, args, usedPrefix, command }) => {
+if (!args[0]) throw `⚠️ ${await tr("Ingrese una Url de Drive")}\n• ${await tr("Ejemplo")}: ${usedPrefix + command} https://drive.google.com/file/d/Kantu`;
+
+if (userRequests[m.sender]) {
+conn.reply(m.chat, `⏳ *${await tr("Hey")} @${m.sender.split('@')[0]}* ${await tr("*Espera...* Ya hay una solicitud en proceso. Por favor, espera a que termine antes de hacer otra...")}`, userCaptions.get(m.sender) || m)
+return;
+}
+userRequests[m.sender] = true;
+m.react("📥");
+try {
+const waitMessageSent = conn.reply(m.chat, `*⌛ ${await tr("Calma")} 🫡 ${await tr("clack, Ya estoy enviado el archivo")} 🚀*\n*${await tr("Si no le llega el archivo es debido a que es muy pesado")}*`, m)
+userCaptions.set(m.sender, waitMessageSent);
+const downloadAttempts = [
+async () => {
+const api = await fetch(`https://api.siputzx.my.id/api/d/gdrive?url=${args[0]}`);
+const data = await api.json();
+return { url: data.data.download,
+filename: data.data.name,
+};
+},
+async () => {
+const api = await fetch(`https://apis.davidcyriltech.my.id/gdrive?url=${args[0]}`);
+const data = await api.json();
+return { url: data.download_link,
+filename: data.name,
+}},
+];
+
+let fileData = null;
+
+for (const attempt of downloadAttempts) {
+try {
+fileData = await attempt();
+if (fileData) break; // Si se obtiene un resultado, salir del bucle
+} catch (err) {
+console.error(`Error in attempt: ${err.message}`);
+continue; // Si falla, intentar con la siguiente API
+}}
+
+if (!fileData) {
+throw new Error(await tr('No se pudo descargar el archivo desde ninguna API'));
+}
+
+const { url, filename } = fileData;
+const mimetype = getMimetype(filename);
+await conn.sendMessage(m.chat, { document: { url: url }, mimetype: mimetype, fileName: filename, caption: null }, { quoted: m });
+await m.react("✅");
+} catch (e) {
+m.react(`❌`);
+m.reply(`\`\`\`⚠️ ${await tr("OCURRIO UN ERROR")} ⚠️\`\`\`\n\n> *${await tr("Reporta el siguiente error a mi creador con el comando:")}* #report\n\n>>> ${e} <<<< `)    
+console.log(e);
+} finally {
+delete userRequests[m.sender];
+}
+};
+handler.help = ['drive'].map(v => v + ' <url>');
+handler.tags = ['downloader'];
+handler.command = /^(drive|drivedl|dldrive|gdrive)$/i;
+handler.register = true;
+handler.limit = 3;
+
+export default handler;
+
+const getMimetype = (fileName) => {
+  const extension = fileName.split('.').pop().toLowerCase();
+  const mimeTypes = {
+    'pdf': 'application/pdf',
+    'mp4': 'video/mp4',
+    'jpg': 'image/jpeg',
+    'jpeg': 'image/jpeg',
+    'png': 'image/png',
+    'zip': 'application/zip',
+    'doc': 'application/msword',
+    'docx': 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
+    'xls': 'application/vnd.ms-excel',
+    'xlsx': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
+    'ppt': 'application/vnd.ms-powerpoint',
+    'pptx': 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
+    'txt': 'text/plain',
+    'mp3': 'audio/mpeg',
+    'apk': 'application/vnd.android.package-archive',
+    'rar': 'application/x-rar-compressed',
+    '7z': 'application/x-7z-compressed',
+    'mkv': 'video/x-matroska',
+    'avi': 'video/x-msvideo',
+    'mov': 'video/quicktime',
+    'wmv': 'video/x-ms-wmv',
+    'flv': 'video/x-flv',
+    'gif': 'image/gif',
+    'webp': 'image/webp',
+    'ogg': 'audio/ogg',
+    'wav': 'audio/wav',
+  };
+  return mimeTypes[extension] || 'application/octet-stream'; // Tipo por defecto
+};

+ 25 - 0
plugins/descargas-gitclone.js

@@ -0,0 +1,25 @@
+import fetch from 'node-fetch'
+const regex = /(?:https|git)(?::\/\/|@)github\.com[\/:]([^\/:]+)\/(.+)/i
+let handler = async (m, { args, usedPrefix, command }) => {
+if (!args[0]) return conn.reply(m.chat, `⚠️*𝙄𝙣𝙜𝙧𝙚𝙨𝙚 𝙪𝙣 𝙚𝙣𝙡𝙖𝙘𝙚 𝙙𝙚 𝙂𝙞𝙩𝙝𝙪𝙗*\n• *𝙀𝙟 :* ${usedPrefix + command} ${md}`, m, {contextInfo: {externalAdReply :{ mediaUrl: null, mediaType: 1, description: null, title: mg, body: ' 💫 𝐒𝐮𝐩𝐞𝐫 𝐁𝐨𝐭 𝐃𝐞 𝐖𝐡𝐚𝐭𝐬𝐚𝐩𝐩 🥳 ', previewType: 0, thumbnail: img.getRandom(), sourceUrl: redes.getRandom()}}})    
+if (!regex.test(args[0])) return conn.reply(m.chat, `⚠️ 𝙚𝙨𝙤 𝙣𝙤 𝙚𝙨 𝙪𝙣 𝙚𝙣𝙡𝙖𝙘𝙚 𝙙𝙚 𝙜𝙞𝙩𝙝𝙪𝙗 𝙗𝙤𝙡𝙪𝙙𝙤 🤡`, m, {contextInfo: {externalAdReply :{ mediaUrl: null, mediaType: 1, description: null, title: iig, body: ' 💫 𝐒𝐮𝐩𝐞𝐫 𝐁𝐨𝐭 𝐃𝐞 𝐖𝐡𝐚𝐭𝐬𝐚𝐩𝐩 🥳 ', previewType: 0, thumbnail: img.getRandom(), sourceUrl: redes.getRandom()}}})
+try {   
+let [_, user, repo] = args[0].match(regex) || []
+repo = repo.replace(/.git$/, '')
+let url = `https://api.github.com/repos/${user}/${repo}/zipball`
+let filename = (await fetch(url, { method: 'HEAD' })).headers.get('content-disposition').match(/attachment; filename=(.*)/)[1]
+conn.reply(m.chat, `*⌛ 𝐂𝐚𝐥𝐦𝐚 ✋ 𝐂𝐥𝐚𝐜𝐤, 𝐘𝐚 𝐞𝐬𝐭𝐨𝐲 𝐄𝐧𝐯𝐢𝐚𝐝𝐨 𝐞𝐥 𝐚𝐫𝐜𝐡𝐢𝐯𝐨 🚀*\n*𝐒𝐢 𝐧𝐨 𝐥𝐞 𝐥𝐥𝐞𝐠𝐚 𝐞𝐥 𝐚𝐫𝐜𝐡𝐢𝐯𝐨 𝐞𝐬 𝐝𝐞𝐛𝐢𝐝𝐨 𝐚 𝐪𝐮𝐞 𝐞𝐥 𝐑𝐞𝐩𝐨𝐬𝐢𝐭𝐨𝐫𝐢𝐨 𝐞𝐬 𝐦𝐮𝐲 𝐩𝐞𝐬𝐚𝐝𝐨*`, m, {contextInfo: {externalAdReply :{ mediaUrl: null, mediaType: 1, description: null, title: wm, body: ' 💫 𝐒𝐮𝐩𝐞𝐫 𝐁𝐨𝐭 𝐃𝐞 𝐖𝐡𝐚𝐭𝐬𝐚𝐩𝐩 🥳 ', previewType: 0, thumbnail: img.getRandom(), sourceUrl: redes.getRandom()}}})   
+conn.sendFile(m.chat, url, filename, null, m, null, fake)
+handler.limit = 2
+} catch (e) { 
+m.reply(`\`\`\`⚠️ OCURRIO UN ERROR ⚠️\`\`\`\n\n> *Reporta el siguiente error a mi creador con el comando:*#report\n\n>>> ${e} <<<< `)       
+console.log(e) 
+handler.limit = 0 //❌No gastada diamante si el comando falla
+}}
+handler.help = ['gitclone <url>']
+handler.tags = ['downloader']
+handler.command = /gitclone|clonarepo|clonarrepo|repoclonar/i
+handler.register = true
+//handler.limit = 2
+handler.level = 2
+export default handler

+ 86 - 0
plugins/descargas-ig.js

@@ -0,0 +1,86 @@
+import fetch from 'node-fetch';
+import axios from 'axios';
+import {instagramdl} from '@bochilteam/scraper';
+import {fileTypeFromBuffer} from 'file-type';
+ 
+const handler = async (m, {conn, args, command, usedPrefix}) => {
+const datas = global
+if (!args[0]) throw `⚠️ Ingresa el enlace del vídeo de Instagram junto al comando.\n\nEjemplo: *${usedPrefix + command}* https://www.instagram.com/p/C60xXk3J-sb/?igsh=YzljYTk1ODg3Zg==`
+await m.react('⌛')
+try {
+const res = await fetch(`https://api.siputzx.my.id/api/d/igdl?url=${args}`);
+const data = await res.json();
+const fileType = data.data[0].url.includes('.webp') ? 'image' : 'video'; 
+const downloadUrl = data.data[0].url;
+if (fileType === 'image') {
+await conn.sendFile(m.chat, downloadUrl, 'ig.jpg', '_*Aqui tiene tu imagen de Instagram*', m, null, fake);
+m.react('✅');
+} else if (fileType === 'video') {
+await conn.sendFile(m.chat, downloadUrl, 'ig.mp4', '*Aqui esta el video de Instagram*', m, null, fake);
+m.react('✅');
+}
+} catch {   
+try {
+const res = await fetch(`${APIs.fgmods.url}/downloader/igdl?url=${args}&apikey=${APIs.fgmods.key}`);
+const data = await res.json();
+if (!data || !data.result || data.result.length === 0) return m.react("❌");  
+const result = data.result[0];  
+const thumbnail = result.thumbnail;  
+const downloadUrl = result.url;  
+if (!downloadUrl) return m.react("❌");
+if (thumbnail && downloadUrl) {
+if (downloadUrl.endsWith('.jpg') || downloadUrl.endsWith('.png')) {
+await conn.sendFile(m.chat, downloadUrl, 'ig.jpg', '_*Aqui tiene tu imagen de Instagram*', m, null, fake);
+m.react('✅');  
+} else if (downloadUrl.endsWith('.mp4')) {
+await conn.sendFile(m.chat, downloadUrl, 'ig.mp4', '**Aqui esta el video de Instagram*', m, null, fake);
+m.react('✅');  
+}} else {
+m.react("❌");  
+}} catch {   
+try {
+const apiUrl = `${apis}/download/instagram?url=${encodeURIComponent(args[0])}`;
+const apiResponse = await fetch(apiUrl);
+const delius = await apiResponse.json();
+if (!delius || !delius.data || delius.data.length === 0) return m.react("❌");
+const downloadUrl = delius.data[0].url;
+const fileType = delius.data[0].type;
+if (!downloadUrl) return m.react("❌");
+
+if (fileType === 'image') {
+await conn.sendFile(m.chat, downloadUrl, 'ig.jpg', '_*Aqui tiene tu imagen de Instagram*', m, null, fake);
+m.react('✅')
+} else if (fileType === 'video') {
+await conn.sendFile(m.chat, downloadUrl, 'ig.mp4', '*Aqui esta el video de Instagram*', m, null, fake);
+m.react('✅')
+} else {
+return m.react("❌"); 
+}} catch {   
+try {
+const resultssss = await instagramdl(args[0]);
+const shortUrl3 = await (await fetch(`https://tinyurl.com/api-create.php?url=${args[0]}`)).text();
+const txt4 = `_${shortUrl3}_`.trim();
+for (const {url} of resultssss) await conn.sendFile(m.chat, url, 'error.mp4', txt4, m, null, fake);
+await m.react('✅')
+} catch (e) {
+await m.react('❌')
+console.log(e)
+handler.limit = 0
+}}}}}
+handler.help = ['instagram *<link ig>*']
+handler.tags = ['downloader']
+handler.command = /^(instagramdl|instagram|igdl|ig|instagramdl2|instagram2|igdl2|ig2|instagramdl3|instagram3|igdl3|ig3)$/i
+handler.limit = 1
+handler.register = true 
+export default handler;
+
+const getBuffer = async (url, options) => {
+options = options || {};
+const res = await axios({method: 'get', url, headers: {'DNT': 1, 'Upgrade-Insecure-Request': 1}, ...options, responseType: 'arraybuffer'});
+const buffer = Buffer.from(res.data, 'binary');
+const detectedType = await fileTypeFromBuffer(buffer);
+if (!detectedType || (detectedType.mime !== 'image/jpeg' && detectedType.mime !== 'image/png' && detectedType.mime !== 'video/mp4')) {
+return null;
+}
+return { buffer, detectedType };
+};

+ 47 - 0
plugins/descargas-igstalk.js

@@ -0,0 +1,47 @@
+import fg from 'api-dylux'
+let handler= async (m, { conn, args, text, usedPrefix, command }) => {
+if (!args[0]) throw `⚠️ Ingrese el Username de Instagram\n\n*• Ejemplo:* ${usedPrefix + command} GataDios` 
+m.react("⌛");
+try {
+const apiUrl = `https://deliriussapi-oficial.vercel.app/tools/igstalk?username=${encodeURIComponent(args[0])}`;
+const apiResponse = await fetch(apiUrl);
+const delius = await apiResponse.json();
+if (!delius || !delius.data) return m.react("❌");
+const profile = delius.data;
+const txt = `👤 *Perfil de Instagram*:
+🔹 *Nombre de usuario*: ${profile.username}
+🔹 *Nombre completo*: ${profile.full_name}
+🔹 *Biografía*: ${profile.biography}
+🔹 *Verificado*: ${profile.verified ? 'Sí' : 'No'}
+🔹 *Cuenta privada*: ${profile.private ? 'Sí' : 'No'}
+🔹 *Seguidores*: ${profile.followers}
+🔹 *Seguidos*: ${profile.following}
+🔹 *Publicaciones*: ${profile.posts}
+🔹 *URL*: ${profile.url}`;
+
+await conn.sendFile(m.chat, profile.profile_picture, 'insta_profile.jpg', txt, m, null, fake);
+ m.react("✅");
+} catch (e2) {
+try {     
+let res = await fg.igStalk(args[0])
+let te = `👤 *Perfil de Instagram*:
+*• Nombre:* ${res.name} 
+*• Username:* ${res.username}
+*• Seguidores:* ${res.followersH}
+*• Siguiendo:* ${res.followingH}
+*• Bio:* ${res.description}
+*• Posts:* ${res.postsH}
+*• Link* : https://instagram.com/${res.username.replace(/^@/, '')}`
+await conn.sendFile(m.chat, res.profilePic, 'igstalk.png', te, m, null, fake)
+m.react("⌛");     
+} catch (e) {
+await m.react(`❌`) 
+m.reply(`\`\`\`⚠️ OCURRIO UN ERROR ⚠️\`\`\`\n\n> *Reporta el siguiente error a mi creador con el comando:*#report\n\n>>> ${e} <<<< `)       
+console.log(e)
+}}}
+handler.help = ['igstalk']
+handler.tags = ['downloader']
+handler.command = ['igstalk', 'igsearch', 'instagramsearch'] 
+handler.register = true
+handler.limit = 1
+export default handler

+ 19 - 0
plugins/descargas-imagen.js

@@ -0,0 +1,19 @@
+import {googleImage} from '@bochilteam/scraper';
+const handler = async (m, {conn, text, usedPrefix, command}) => {
+if (!text) return m.reply(`𝗤𝘂𝗲 𝗯𝘂𝘀𝗰𝗮𝗿? 🤔️ 𝙪𝘀𝙖𝙧 𝙙𝙚 𝙡𝙖 𝙨𝙞𝙜𝙪𝙞𝙚𝙣𝙩𝙚 𝙢𝙖𝙣𝙚𝙧𝙖\n• 𝗘𝗷𝗲𝗺𝗽𝗹𝗼\n*${usedPrefix + command} Kantu*`) 
+if (m.text.includes('gore') || m.text.includes('cp')|| m.text.includes('porno')|| m.text.includes('Gore')|| m.text.includes('rule')|| m.text.includes('CP') || m.text.includes('Rule34') || m.text.includes('xxx')) throw '🙄 No voy a buscar tu pendejadas....'
+try {
+const res = await googleImage(text);
+const image = await res.getRandom();
+const link = image;
+conn.sendFile(m.chat, link, 'error.jpg', `_🔎 𝙍𝙚𝙨𝙪𝙡𝙩𝙖𝙙𝙤𝙨 𝙙𝙚: ${text}_`, m, null, fake);
+//conn.sendButton(m.chat, ``, botname, link, [['🔄 𝐒𝐈𝐆𝐔𝐈𝐄𝐍𝐓𝐄 🔄', `/${command} ${text}`]], null, null, m, null, fake)
+} catch (e) {
+console.log(e) 
+}}
+handler.help = ['gimage <query>', 'imagen <query>'];
+handler.tags = ['buscadores'];
+handler.command = /^(gimage|image|imagen)$/i;
+handler.register = true 
+handler.limit = 1
+export default handler;

+ 116 - 0
plugins/descargas-mediafire.js

@@ -0,0 +1,116 @@
+import axios from 'axios';
+import fetch from 'node-fetch';
+import cheerio from 'cheerio';
+import {mediafiredl} from '@bochilteam/scraper';
+import fg from 'api-dylux'
+let free = 150 
+let prem = 500
+
+const handler = async (m, {conn, args, usedPrefix, command}) => {
+let sticker = 'https://qu.ax/Wdsb.webp'
+if (!args[0]) throw `⚠️ 𝙄𝙣𝙜𝙧𝙚𝙨𝙚 𝙪𝙣 𝙀𝙣𝙡𝙖𝙘𝙚 𝙫𝙖𝙡𝙞𝙙𝙤 𝙙𝙚𝙡 𝙢𝙚𝙙𝙞𝙖𝙛𝙞𝙧𝙚 𝙀𝙟:*\n${usedPrefix + command} https://www.mediafire.com/file/sd9hl31vhhzf76v/KantuBot`
+m.react(`🚀`) 
+try {
+const res = await fetch(`https://api.agatz.xyz/api/mediafire?url=${args}`);
+const data = await res.json();
+const file = data.data[0];
+const caption = `┏━━『 𝐌𝐄𝐃𝐈𝐀𝐅𝐈𝐑𝐄 』━━•
+┃❥ 𝐍𝐨𝐦𝐛𝐫𝐞 :
+┃${file.nama}
+┃——————«•»——————
+┃❥ 𝐏𝐞𝐬𝐨 :
+┃${file.size}
+┃——————«•»——————
+┃❥ 𝐓𝐢𝐩𝐨 :
+┃${file.mime}
+╰━━━⊰ 𓃠 ${vs} ⊱━━━━•
+
+> ⏳ ᴱˢᵖᵉʳᵉ ᵘⁿ ᵐᵒᵐᵉⁿᵗᵒ ᵉⁿ ˡᵒˢ ᵠᵘᵉ ᵉⁿᵛᶦᵒˢ ˢᵘˢ ᵃʳᶜʰᶦᵛᵒˢ`.trim();
+m.reply(caption);
+conn.sendFile(m.chat, file.link, file.nama, '', m, null, {
+  mimetype: file.mime,
+  asDocument: true,
+});
+m.react(`✅`);
+} catch {
+try {
+const res = await fetch(`${APIs.fgmods.url}/downloader/mediafire?url=${args}&apikey=${APIs.fgmods.key}`);
+const data = await res.json();
+const fileData = data.result;
+const caption = `┏━━『 𝐌𝐄𝐃𝐈𝐀𝐅𝐈𝐑𝐄 』━━•
+┃❥ 𝐍𝐨𝐦𝐛𝐫𝐞 : ${fileData.title}
+┃❥ 𝐏𝐞𝐬𝐨 : ${fileData.filesize}
+┃❥ 𝐓𝐢𝐩𝐨 : ${fileData.mimetype}
+╰━━━⊰ 𓃠 ${vs} ⊱━━━━•`.trim();
+await conn.sendFile(m.chat, fileData.url, fileData.title, caption, m, null, {mimetype: fileData.mimetype, asDocument: true });
+m.react('✅'); 
+} catch {
+try {
+const res = await fetch(`https://api.siputzx.my.id/api/d/mediafire?url=${args}`);
+const data = await res.json();
+if (!data.status || !data.data) return 
+const fileDataArray = data.data;
+for (const fileData of fileDataArray) {
+const caption = `┏━━『 𝐌𝐄𝐃𝐈𝐀𝐅𝐈𝐑𝐄 』━━•
+┃❥ 𝐍𝐨𝐦𝐛𝐫𝐞 : ${fileData.filename}
+┃❥ 𝐏𝐞𝐬𝐨 : ${fileData.size}
+┃❥ 𝐓𝐢𝐩𝐨 : ${fileData.mime}
+╰━━━⊰ 𓃠 ${vs} ⊱━━━━•
+> ⏳ ᴱˢᵖᵉʳᵉ ᵘⁿ ᵐᵒᵐᵉⁿᵗᵒ ᵉⁿ ˡᵒˢ ᵠᵘᵉ ᵉⁿᵛᶦᵒˢ ˢᵘˢ ᵃʳᶜʰᶦᵛᵒˢ
+`.trim(); 
+await conn.sendFile(m.chat, fileData.link, fileData.filename, caption, m, null, {mimetype: fileData.mime, asDocument: true });
+m.react('✅'); 
+}
+} catch {
+try {
+const res = await fetch(`${apis}/api/mediafire?url=${args[0]}`);
+if (!res.ok) throw new Error(`HTTP error! status: ${res.status}`);
+const data = await res.json();
+const fileDataArray = data.data;
+fileDataArray.forEach((fileData) => {
+const caption = `┏━━『 𝐌𝐄𝐃𝐈𝐀𝐅𝐈𝐑𝐄 』━━•\n┃❥ 𝐍𝐨𝐦𝐛𝐫𝐞 :\n┃${fileData.filename}\n┃——————«•»——————\n┃❥ 𝐏𝐞𝐬𝐨 :\n┃${fileData.size}\n\n┃——————«•»——————\n┃❥ 𝐓𝐢𝐩𝐨 :\n┃${fileData.mime}\n╰━━━⊰ 𓃠 ${vs} ⊱━━━━•\n\n> ⏳ ᴱˢᵖᵉʳᵉ ᵘⁿ ᵐᵒᵐᵉⁿᵗᵒ ᵉⁿ ˡᵒˢ ᵠᵘᵉ ᵉⁿᵛᶦᵒˢ ˢᵘˢ ᵃʳᶜʰᶦᵛᵒˢ`.trim();
+m.reply(caption);
+conn.sendFile(m.chat, fileData.link, fileData.filename, '', m, null, {mimetype: fileData.mime, asDocument: true, 
+});
+m.react(`✅`);
+});
+} catch {
+try {
+const resEX = await mediafiredl(args[0]);
+const captionES = `┏━━『 𝐌𝐄𝐃𝐈𝐀𝐅𝐈𝐑𝐄 』━━•\n┃❥ 𝐍𝐨𝐦𝐛𝐫𝐞 :\n┃${resEX.filename}\n┃——————«•»——————\n┃❥ 𝐏𝐞𝐬𝐨 :\n┃ ${resEX.filesizeH}\n\n┃——————«•»——————\n┃❥ 𝐓𝐢𝐩𝐨 :\n┃${resEX.ext}\n\n╰━━━⊰ 𓃠 ${vs} ⊱━━━━•\n\n> ⏳ ᴱˢᵖᵉʳᵉ ᵘⁿ ᵐᵒᵐᵉⁿᵗᵒ ᵉⁿ ˡᵒˢ ᵠᵘᵉ ᵉⁿᵛᶦᵒˢ ˢᵘˢ ᵃʳᶜʰᶦᵛᵒˢ`.trim();
+m.reply(captionES);
+await conn.sendFile(m.chat, resEX.url, resEX.filename, '', m, null, {mimetype: resEX.ext, asDocument: true});
+m.react(`✅`)     
+} catch {
+try {
+const res = await mediafireDl(args[0]);
+const {name, size, date, mime, link} = res;
+const caption = `┏━━『 𝐌𝐄𝐃𝐈𝐀𝐅𝐈𝐑𝐄 』━━•\n┃❥ 𝐍𝐨𝐦𝐛𝐫𝐞 :\n┃${name}\n┃——————«•»——————\n┃❥ 𝐏𝐞𝐬𝐨 :\n┃${size}\n\n┃——————«•»——————\n┃❥ 𝐓𝐢𝐩𝐨 :\n┃${mime}\n\n╰━━━⊰ 𓃠 ${vs} ⊱━━━━•\n\n> ⏳ ᴱˢᵖᵉʳᵉ ᵘⁿ ᵐᵒᵐᵉⁿᵗᵒ ᵉⁿ ˡᵒˢ ᵠᵘᵉ ᵉⁿᵛᶦᵒˢ ˢᵘˢ ᵃʳᶜʰᶦᵛᵒˢ`.trim();
+await m.reply(caption);
+await conn.sendFile(m.chat, link, name, '', m, null, {mimetype: mime, asDocument: true});      
+m.react(`✅`) 
+} catch (e) {
+conn.sendFile(m.chat, sticker, 'error.webp', '', m, null, fake)
+m.react(`❌`) 
+console.error(e);
+handler.limit = false
+}}}}}}}
+handler.help = ['mediafire', 'mediafiredl'];
+handler.tags = ['downloader'];
+handler.command = /^(mediafire|mediafiredl|dlmediafire)$/i
+handler.register = true
+handler.limit = 3
+export default handler;
+
+async function mediafireDl(url) {
+  const res = await axios.get(`https://www-mediafire-com.translate.goog/${url.replace('https://www.mediafire.com/', '')}?_x_tr_sl=en&_x_tr_tl=fr&_x_tr_hl=en&_x_tr_pto=wapp`);
+  const $ = cheerio.load(res.data);
+  const link = $('#downloadButton').attr('href');
+  const name = $('body > main > div.content > div.center > div > div.dl-btn-cont > div.dl-btn-labelWrap > div.promoDownloadName.notranslate > div').attr('title').replaceAll(' ', '').replaceAll('\n', '');
+  const date = $('body > main > div.content > div.center > div > div.dl-info > ul > li:nth-child(2) > span').text();
+  const size = $('#downloadButton').text().replace('Download', '').replace('(', '').replace(')', '').replace('\n', '').replace('\n', '').replace('                         ', '').replaceAll(' ', '');
+  let mime = '';
+  const rese = await axios.head(link);
+  mime = rese.headers['content-type'];
+  return {name, size, date, mime, link};
+}

+ 93 - 0
plugins/descargas-modapk.js

@@ -0,0 +1,93 @@
+import axios from 'axios';
+import cheerio from 'cheerio';
+//import {search, download} from 'aptoide-scraper';
+const handler = async (m, {conn, usedPrefix, command, text}) => {
+const apkpureApi = 'https://apkpure.com/api/v2/search?q=';
+const apkpureDownloadApi = 'https://apkpure.com/api/v2/download?id=';
+if (!text) throw `⚠️ *𝙀𝙨𝙘𝙧𝙞𝙗𝙖 𝙚𝙡 𝙣𝙤𝙢𝙗𝙧𝙚 𝙙𝙚𝙡 𝘼𝙋𝙆*`
+m.react("⌛") 
+try {   
+const res = await fetch(`https://api.dorratz.com/v2/apk-dl?text=${text}`);
+const data = await res.json();
+const response = `≪DESCARGADO APKS🚀≫
+
+┏━━━━━━━━━━━━━━━━━━━━━━• 
+┃💫 𝙉𝙊𝙈𝘽𝙍𝙀: ${data.name}
+┃📦 𝙋𝘼𝘾𝙆𝘼𝙂𝙀: ${data.package}
+┃🕒 𝙐𝙇𝙏𝙄𝙈𝘼 𝘼𝘾𝙏𝙐𝙇𝙄𝙕𝘼𝘾𝙄𝙊𝙉: ${data.lastUpdate}
+┃💪 𝙋𝙀𝙎𝙊: ${data.size}
+┗━━━━━━━━━━━━━━━━━━━━━━━•
+
+> *⏳ ᴱˢᵖᵉʳᵉ ᵘⁿ ᵐᵒᵐᵉⁿᵗᵒ ˢᵘˢ ᵃᵖᵏ ˢᵉ ᵉˢᵗᵃ ᵉⁿᵛᶦᵃⁿᵈᵒ...*`;
+await conn.sendFile(m.chat, data.icon, 'error.jpg', response, m, null, fake);
+const apkSize = data.size.toLowerCase();
+if (apkSize.includes('gb') || (apkSize.includes('mb') && parseFloat(apkSize) > 999)) {
+return await m.reply('*𝙀𝙡 𝙖𝙥𝙠 𝙚𝙨 𝙢𝙪𝙮 𝙥𝙚𝙨𝙖𝙙𝙤.*');
+}
+await conn.sendMessage(m.chat, {document: { url: data.dllink }, mimetype: 'application/vnd.android.package-archive', fileName: `${data.name}.apk`, caption: null }, { quoted: m });
+await m.react("✅");
+} catch {
+try {
+const res = await fetch(`${apis}/download/apk?query=${text}`);
+const data = await res.json();
+const apkData = data.data;
+const response = `≪DESCARGADO APKS🚀≫
+
+┏━━━━━━━━━━━━━━━━━━━━━━• 
+┃💫 𝙉𝙊𝙈𝘽𝙍𝙀: ${apkData.name}
+┃👤 𝘿𝙀𝙎𝘼𝙍𝙍𝙊𝙇𝙇𝙊: ${apkData.developer}
+┃🕒 𝙐𝙇𝙏𝙄𝙈𝘼 𝘼𝘾𝙏𝙐𝙇𝙄𝙕𝘼𝘾𝙄𝙊𝙉: ${apkData.publish}
+┃💪 𝙋𝙀𝙎𝙊: ${apkData.size}
+┗━━━━━━━━━━━━━━━━━━━━━━━•
+
+> *⏳ ᴱˢᵖᵉʳᵉ ᵘⁿ ᵐᵒᵐᵉⁿᵗᵒ ˢᵘˢ ᵃᵖᵏ ˢᵉ ᵉˢᵗᵃ ᵉⁿᵛᶦᵃⁿᵈᵒ...*`
+await conn.sendFile(m.chat, apkData.image, 'error,jpg', response, m, null, fake);
+if (apkData.size.includes('GB') || parseFloat(apkData.size.replace(' MB', '')) > 999) {
+return await m.reply('*𝙀𝙡 𝙖𝙥𝙠 𝙚𝙨 𝙢𝙪𝙮 𝙥𝙚𝙨𝙖𝙙𝙤.*') 
+}
+
+await conn.sendMessage(m.chat, {document: { url: apkData.download }, mimetype: 'application/vnd.android.package-archive', fileName: `${apkData.name}.apk`, caption: null }, { quoted: m });
+await m.react("✅") 
+} catch {
+try {
+const searchA = await search(text);
+const data5 = await download(searchA[0].id);
+let response = `≪DESCARGADO APKS🚀≫
+
+┏━━━━━━━━━━━━━━━━━━━━━━• 
+┃💫 𝙉𝙊𝙈𝘽𝙍𝙀: ${data5.name}
+┃📦 𝙋𝘼𝘾𝙆𝘼𝙂𝙀: ${data5.package}
+┃🕒 𝙐𝙇𝙏𝙄𝙈𝘼 𝘼𝘾𝙏𝙐𝙇𝙄𝙕𝘼𝘾𝙄𝙊𝙉: ${data5.lastup}
+┃💪 𝙋𝙀𝙎𝙊: ${data5.size}
+┗━━━━━━━━━━━━━━━━━━━━━━━•
+
+> *⏳ ᴱˢᵖᵉʳᵉ ᵘⁿ ᵐᵒᵐᵉⁿᵗᵒ ˢᵘˢ ᵃᵖᵏ ˢᵉ ᵉˢᵗᵃ ᵉⁿᵛᶦᵃⁿᵈᵒ...*`
+await conn.sendFile(m.chat, data5.icon, 'akp.jpg', response, m, false, fake)   
+//conn.sendMessage(m.chat, {image: {url: data5.icon}, caption: response}, {quoted: m});
+if (data5.size.includes('GB') || data5.size.replace(' MB', '') > 999) {
+return await m.reply('*𝙀𝙡 𝙖𝙥𝙠 𝙚𝙨 𝙢𝙪𝙮 𝙥𝙚𝙨𝙖𝙙𝙤.*')}
+await conn.sendMessage(m.chat, {document: {url: data5.dllink}, mimetype: 'application/vnd.android.package-archive', fileName: data5.name + '.apk', caption: null}, {quoted: m}); 
+m.react("✅") 
+} catch (e) {
+m.react(`❌`) 
+console.log(e)
+handler.limit = false
+}}}}
+handler.help = ['apk', 'apkmod'];
+handler.tags = ['downloader'];
+handler.command = /^(apkmod|apk|modapk|dapk2|aptoide|aptoidedl)$/i;
+handler.register = true
+handler.limit = 2
+export default handler;
+
+async function searchApk(text) {
+  const response = await axios.get(`${apkpureApi}${encodeURIComponent(text)}`);
+  const data = response.data;
+  return data.results;
+}
+
+async function downloadApk(id) {
+  const response = await axios.get(`${apkpureDownloadApi}${id}`);
+  const data = response.data;
+  return data;
+}

+ 22 - 0
plugins/descargas-pinterest.js

@@ -0,0 +1,22 @@
+import {pinterest} from '@bochilteam/scraper';
+const handler = async (m, {conn, text, usedPrefix, command}) => {
+if (!text) throw `*⚠️ Ejemplo:* ${usedPrefix + command} Kantu`;
+try {
+const json = await pinterest(text);
+conn.sendFile(m.chat, json.getRandom(), 'error.jpg', `_🔎 𝙍𝙚𝙨𝙪𝙡𝙩𝙖𝙙𝙤𝙨 𝙙𝙚: ${text}_`, m, null, fake);
+} catch (error1) {
+try {
+const response=await fetch(`https://deliriussapi-oficial.vercel.app/search/pinterest?text=${text}`)
+const dataR = await response.json()
+const json = dataR.result
+conn.sendFile(m.chat, json.getRandom(), 'error.jpg', `_🔎 𝙍𝙚𝙨𝙪𝙡𝙩𝙖𝙙𝙤𝙨 𝙙𝙚: ${text}_`, m, null, fake);
+//conn.sendButton(m.chat, `💞 ${mid.buscador} ${text}`, `𝙋𝙞𝙣𝙩𝙚𝙧𝙚𝙨𝙩 | ${wm}`, json.getRandom(), [['🔄 𝙎𝙞𝙜𝙪𝙞𝙚𝙣𝙩𝙚 | 𝙉𝙚𝙭𝙩', `${usedPrefix}pinterest ${text}`]], null, null, m)
+} catch (e) {
+console.log(e) 
+}}}
+handler.help = ['pinterest <keyword>'];
+handler.tags = ['buscadores'];
+handler.command = /^(pinterest)$/i;
+handler.register = true 
+handler.limit = 1
+export default handler;

+ 242 - 0
plugins/descargas-play.js

@@ -0,0 +1,242 @@
+//import { youtubedl, youtubedlv2 } from '@bochilteam/scraper'
+import fetch from 'node-fetch';
+import yts from 'yt-search';
+import ytdl from 'ytdl-core';
+import axios from 'axios';
+import { savetube } from '../lib/yt-savetube.js'
+import { ogmp3 } from '../lib/youtubedl.js'; 
+import { createRequire } from 'module';
+const require = createRequire(import.meta.url);
+const { ytmp3, ytmp4 } = require("@hiudyy/ytdl");
+const LimitAud = 725 * 1024 * 1024; // 725MB
+const LimitVid = 425 * 1024 * 1024; // 425MB
+const youtubeRegexID = /(?:youtu\.be\/|youtube\.com\/(?:watch\?v=|embed\/))([a-zA-Z0-9_-]{11})/;
+
+const handler = async (m, { conn, command, args, text, usedPrefix }) => {
+if (!text) return m.reply(`**˚₊· ͟͟͞͞➳❥ Y T ¸.☆.¸ P L A Y*\n*Ingrese el nombre de la canción*\n\n*Ejemplo:*\n${usedPrefix + command} emilia 420`);
+const tipoDescarga = command === 'play' || command === 'musica' ? 'audio' : command === 'play2' ? 'video' : command === 'play3' ? 'audio (documento)' : command === 'play4' ? 'video (documento)' : '';
+let videoIdToFind = text.match(youtubeRegexID) || null;
+const yt_play = await search(args.join(' ')); 
+let ytplay2 = await yts(videoIdToFind === null ? text : 'https://youtu.be/' + videoIdToFind[1]);
+if (videoIdToFind) {
+const videoId = videoIdToFind[1];
+ytplay2 = ytplay2.all.find(item => item.videoId === videoId) || ytplay2.videos.find(item => item.videoId === videoId)}
+ytplay2 = ytplay2.all?.[0] || ytplay2.videos?.[0] || ytplay2;
+await conn.sendMessage(m.chat, { text: `${yt_play[0].title}
+> [ YOUTUBE - PLAY ] 
+
+*ੈ✰‧₊˚ /Duración ${secondString(yt_play[0].duration.seconds)}
+*ੈ✰‧₊˚ Aguarde un momento en lo que envío su ${tipoDescarga}*`,  
+contextInfo:{  
+forwardedNewsletterMessageInfo: { 
+newsletterJid: '120363371008200788@newsletter', 
+serverMessageId: '', 
+newsletterName: 'The Kantu Bot ⚡' },
+forwardingScore: 9999999,  
+isForwarded: true,   
+mentionedJid: null,  
+externalAdReply: {  
+showAdAttribution: true,  
+renderLargerThumbnail: true,  
+title: yt_play[0].title,   
+body: wm,
+containsAutoReply: true,  
+mediaType: 1,   
+thumbnailUrl: yt_play[0].thumbnail, 
+sourceUrl: [nna, nna2, nnaa].getRandom()
+}}}, { quoted: m })
+/*conn.sendFile(m.chat, yt_play[0].thumbnail, 'error.jpg', `${yt_play[0].title}
+*⇄ㅤ     ◁   ㅤ  ❚❚ㅤ     ▷ㅤ     ↻*
+
+*⏰ Duración:* ${secondString(yt_play[0].duration.seconds)}
+*👉🏻Aguarde un momento en lo que envío su audio*`, m, null, fake);*/
+
+const [input, qualityInput = command === 'play' || command === 'musica' || command === 'play3' ? '320' : '720'] = text.split(' ');
+const audioQualities = ['64', '96', '128', '192', '256', '320'];
+const videoQualities = ['240', '360', '480', '720', '1080'];
+const isAudioCommand = command === 'play' || command === 'musica' || command === 'play3';
+const selectedQuality = (isAudioCommand ? audioQualities : videoQualities).includes(qualityInput) ? qualityInput : (isAudioCommand ? '320' : '720');
+const isAudio = command.toLowerCase().includes('mp3') || command.toLowerCase().includes('audio')
+const format = isAudio ? 'mp3' : '720' 
+
+const audioApis = [
+{ url: () => savetube.download(yt_play[0].url, format), extract: (data) => ({ data: data.result.download, isDirect: false }) },
+{ url: () => ogmp3.download(yt_play[0].url, selectedQuality, 'audio'), extract: (data) => ({ data: data.result.download, isDirect: false }) },
+{ url: () => ytmp3(yt_play[0].url), extract: (data) => ({ data, isDirect: true }) },
+{ url: () => fetch(`https://api.dorratz.com/v3/ytdl?url=${yt_play[0].url}`).then(res => res.json()), extract: (data) => { 
+const mp3 = data.medias.find(media => media.quality === "160kbps" && media.extension === "mp3");
+return { data: mp3.url, isDirect: false }}},
+{ url: () => fetch(`${APIs.neoxr.url}/youtube?url=${yt_play[0].url}&type=audio&quality=128kbps&apikey=${APIs.neoxr.key}`).then(res => res.json()), extract: (data) => ({ data: data.data.url, isDirect: false }) },
+{ url: () => fetch(`https://api.fgmods.xyz/api/downloader/ytmp4?url=${yt_play[0].url}&apikey=${APIs.fgmods.url}`).then(res => res.json()), extract: (data) => ({ data: data.result.dl_url, isDirect: false }) },
+{ url: () => fetch(`https://api.siputzx.my.id/api/d/ytmp4?url=${yt_play[0].url}`).then(res => res.json()), extract: (data) => ({ data: data.dl, isDirect: false }) },
+{ url: () => fetch(`${apis}/download/ytmp3?url=${yt_play[0].url}`).then(res => res.json()), extract: (data) => ({ data: data.status ? data.data.download.url : null, isDirect: false }) },
+{ url: () => fetch(`https://api.zenkey.my.id/api/download/ytmp3?apikey=zenkey&url=${yt_play[0].url}`).then(res => res.json()), extract: (data) => ({ data: data.result.download.url, isDirect: false }) },
+{ url: () => fetch(`https://exonity.tech/api/dl/playmp3?query=${yt_play[0].title}`).then(res => res.json()), extract: (data) => ({ data: data.result.download, isDirect: false }) 
+}];
+
+const videoApis = [
+{ url: () => savetube.download(yt_play[0].url, '720'), extract: (data) => ({ data: data.result.download, isDirect: false }) },
+{ url: () => ogmp3.download(yt_play[0].url, selectedQuality, 'video'), extract: (data) => ({ data: data.result.download, isDirect: false }) },
+{ url: () => ytmp4(yt_play[0].url), extract: (data) => ({ data, isDirect: true }) },
+{ url: () => fetch(`https://api.siputzx.my.id/api/d/ytmp4?url=${yt_play[0].url}`).then(res => res.json()), extract: (data) => ({ data: data.dl, isDirect: false }) },
+{ url: () => fetch(`${APIs.neoxr.url}/youtube?url=${yt_play[0].url}&type=video&quality=720p&apikey=${APIs.neoxr.key}`).then(res => res.json()), extract: (data) => ({ data: data.data.url, isDirect: false }) },
+{ url: () => fetch(`https://api.fgmods.xyz/api/downloader/ytmp4?url=${yt_play[0].url}&apikey=${APIs.fgmods.key}`).then(res => res.json()), extract: (data) => ({ data: data.result.dl_url, isDirect: false }) },
+{ url: () => fetch(`${apis}/download/ytmp4?url=${encodeURIComponent(yt_play[0].url)}`).then(res => res.json()), extract: (data) => ({ data: data.status ? data.data.download.url : null, isDirect: false }) },
+{ url: () => fetch(`https://exonity.tech/api/dl/playmp4?query=${encodeURIComponent(yt_play[0].title)}`).then(res => res.json()), extract: (data) => ({ data: data.result.download, isDirect: false })
+}];
+
+const download = async (apis) => {
+let mediaData = null;
+let isDirect = false;
+for (const api of apis) {
+try {
+const data = await api.url();
+const { data: extractedData, isDirect: direct } = api.extract(data);
+if (extractedData) {
+const size = await getFileSize(extractedData);
+if (size >= 1024) {
+mediaData = extractedData;
+isDirect = direct;
+break;
+}}} catch (e) {
+console.log(`Error con API: ${e}`);
+continue;
+}}
+return { mediaData, isDirect };
+};
+
+if (command === 'play' || command === 'musica') {
+const { mediaData, isDirect } = await download(audioApis);
+if (mediaData) {
+const fileSize = await getFileSize(mediaData);
+if (fileSize > LimitAud) {
+await conn.sendMessage(m.chat, { document: isDirect ? mediaData : { url: mediaData }, mimetype: 'audio/mpeg', fileName: `${yt_play[0].title}.mp3` }, { quoted: m });
+} else {
+await conn.sendMessage(m.chat, { audio: isDirect ? mediaData : { url: mediaData }, mimetype: 'audio/mpeg' }, { quoted: m });
+}} else {
+await m.react('❌');
+}}
+
+if (command === 'play2' || command === 'video') {
+const { mediaData, isDirect } = await download(videoApis);
+if (mediaData) {
+const fileSize = await getFileSize(mediaData);
+const messageOptions = { fileName: `${yt_play[0].title}.mp4`, caption: `🔰 Aquí está tu video \n🔥 Título: ${yt_play[0].title}`, mimetype: 'video/mp4' };
+if (fileSize > LimitVid) {
+await conn.sendMessage(m.chat, { document: isDirect ? mediaData : { url: mediaData }, ...messageOptions }, { quoted: m });
+} else {
+await conn.sendMessage(m.chat, { video: isDirect ? mediaData : { url: mediaData }, thumbnail: yt_play[0].thumbnail, ...messageOptions }, { quoted: m });
+}} else {
+await m.react('❌');
+}}
+
+if (command === 'play3' || command === 'playdoc') {
+const { mediaData, isDirect } = await download(audioApis);
+if (mediaData) {
+await conn.sendMessage(m.chat, { document: isDirect ? mediaData : { url: mediaData }, mimetype: 'audio/mpeg', fileName: `${yt_play[0].title}.mp3`}, { quoted: m });
+} else {
+await m.react('❌');
+}}
+
+if (command === 'play4' || command === 'playdoc2') {
+const { mediaData, isDirect } = await download(videoApis);
+if (mediaData) {
+await conn.sendMessage(m.chat, { document: isDirect ? mediaData : { url: mediaData }, fileName: `${yt_play[0].title}.mp4`, caption: `🔰Título: ${yt_play[0].title}`, thumbnail: yt_play[0].thumbnail, mimetype: 'video/mp4'}, { quoted: m })
+} else {
+await m.react('❌');
+}}};
+handler.help = ['play', 'play2', 'play3', 'play4', 'playdoc'];
+handler.tags = ['downloader'];
+handler.command = ['play', 'play2', 'play3', 'play4', 'audio', 'video', 'playdoc', 'playdoc2', 'musica'];
+handler.register = true;
+export default handler;
+
+async function search(query, options = {}) {
+const search = await yts.search({query, hl: 'es', gl: 'ES', ...options});
+return search.videos;
+}
+
+function MilesNumber(number) {
+const exp = /(\d)(?=(\d{3})+(?!\d))/g;
+const rep = '$1.';
+const arr = number.toString().split('.');
+arr[0] = arr[0].replace(exp, rep);
+return arr[1] ? arr.join('.') : arr[0];
+}
+
+function secondString(seconds) {
+seconds = Number(seconds);
+const d = Math.floor(seconds / (3600 * 24));
+const h = Math.floor((seconds % (3600 * 24)) / 3600);
+const m = Math.floor((seconds % 3600) / 60);
+const s = Math.floor(seconds % 60);
+const dDisplay = d > 0 ? d + (d == 1 ? ' día, ' : ' días, ') : '';
+const hDisplay = h > 0 ? h + (h == 1 ? ' hora, ' : ' horas, ') : '';
+const mDisplay = m > 0 ? m + (m == 1 ? ' minuto, ' : ' minutos, ') : '';
+const sDisplay = s > 0 ? s + (s == 1 ? ' segundo' : ' segundos') : '';
+return dDisplay + hDisplay + mDisplay + sDisplay;
+  }
+  
+const getBuffer = async (url) => {
+  try {
+    const response = await fetch(url);
+    const buffer = await response.arrayBuffer();
+    return Buffer.from(buffer);
+  } catch (error) {
+    console.error("Error al obtener el buffer", error);
+    throw new Error("Error al obtener el buffer");
+  }
+}
+
+async function getFileSize(url) {
+  try {
+    const response = await fetch(url, { method: 'HEAD' });
+    return parseInt(response.headers.get('content-length') || 0);
+  } catch {
+    return 0; // Si falla, asumimos 0
+  }
+}
+
+async function fetchY2mate(url) {
+  const baseUrl = 'https://www.y2mate.com/mates/en60';
+  const videoInfo = await fetch(`${baseUrl}/analyze/ajax`, {
+    method: 'POST',
+    headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
+    body: new URLSearchParams({ url, q_auto: 0 })
+  }).then(res => res.json());
+
+  const id = videoInfo.result.id;
+  const downloadInfo = await fetch(`${baseUrl}/convert`, {
+    method: 'POST',
+    headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
+    body: new URLSearchParams({ type: 'youtube', _id: id, v_id: url, token: '', ftype: 'mp4', fquality: '360p' })
+  }).then(res => res.json());
+
+  return downloadInfo.result.url;
+}
+
+async function fetchInvidious(url) {
+  const apiUrl = `https://invidious.io/api/v1/get_video_info`;
+
+const response = await fetch(`${apiUrl}?url=${encodeURIComponent(url)}`);
+const data = await response.json();
+
+if (data && data.video) {
+const videoInfo = data.video;
+return videoInfo; 
+} else {
+throw new Error("No se pudo obtener información del video desde Invidious");
+  }
+}
+
+async function fetch9Convert(url) {
+const apiUrl = `https://9convert.com/en429/api`;
+const response = await fetch(`${apiUrl}?url=${encodeURIComponent(url)}`);
+const data = await response.json();
+
+if (data.status === 'ok') {
+    return data.result.mp3;
+  } else {
+    throw new Error("No se pudo obtener la descarga desde 9Convert");
+  }
+}

+ 198 - 0
plugins/descargas-play2.js

@@ -0,0 +1,198 @@
+//import { youtubedl, youtubedlv2 } from '@bochilteam/scraper'
+import fetch from 'node-fetch'
+import yts from 'yt-search'
+import ytdl from 'ytdl-core'
+import axios from 'axios'
+import { createRequire } from 'module';
+const require = createRequire(import.meta.url);
+const { ytmp3, ytmp4 } = require("@hiudyy/ytdl");
+let handler = async (m, { conn, args, usedPrefix, command }) => {
+if (!args[0]) throw '*𝙌𝙪𝙚 𝙚𝙨𝙩𝙖 𝙗𝙪𝙨𝙘𝙖𝙙𝙤🤔 𝙄𝙣𝙜𝙧𝙚𝙨𝙚 𝙚𝙡 𝙚𝙣𝙡𝙖𝙘𝙚 𝙙𝙚 𝙔𝙤𝙪𝙏𝙪𝙗𝙚 𝙥𝙖𝙧𝙖 𝙙𝙚𝙨𝙘𝙖𝙧𝙜𝙖𝙧 𝙚𝙡 𝙖𝙪𝙙𝙞𝙤*'
+
+if (command == 'ytmp3' || command == 'fgmp3') {
+let youtubeLink = '';
+if (args[0].includes('you')) {
+youtubeLink = args[0];
+} else {
+const index = parseInt(args[0]) - 1;
+if (index >= 0) {
+if (Array.isArray(global.videoList) && global.videoList.length > 0) {
+const matchingItem = global.videoList.find(item => item.from === m.sender);
+if (matchingItem) {
+if (index < matchingItem.urls.length) {
+youtubeLink = matchingItem.urls[index];
+} else {
+throw `⚠️ 𝙉𝙤 𝙨𝙚 𝙚𝙣𝙘𝙤𝙣𝙩𝙧𝙤 𝙪𝙣 𝙚𝙣𝙡𝙖𝙘𝙚𝙨 𝙥𝙖𝙧𝙖 𝙚𝙨𝙚 𝙣𝙪𝙢𝙚𝙧𝙤, 𝙥𝙤𝙧 𝙛𝙖𝙫𝙤𝙧 𝙞𝙣𝙜𝙧𝙚𝙨𝙚 𝙚𝙡 𝙣𝙪𝙢𝙚𝙧𝙤 𝙚𝙣𝙩𝙧𝙚 1 𝙮 𝙚𝙡 ${matchingItem.urls.length}*`
+}} else {
+return
+}} else {
+return
+}}}  
+  
+conn.reply(m.chat, [`*⌛ 𝙀𝙨𝙥𝙚𝙧𝙚 ✋ 𝙪𝙣 𝙢𝙤𝙢𝙚𝙣𝙩𝙤... 𝙔𝙖 𝙚𝙨𝙩𝙤𝙮 𝙙𝙚𝙨𝙘𝙖𝙧𝙜𝙖𝙙𝙤 𝙩𝙪 𝙖𝙪𝙙𝙞𝙤🍹*`, `⌛ 𝙋𝙍𝙊𝘾𝙀𝙎𝘼𝙉𝘿𝙊...\n*𝘌𝘴𝘵𝘰𝘺 𝘪𝘯𝘵𝘦𝘯𝘵𝘢𝘯𝘥𝘰 𝘥𝘦𝘴𝘤𝘢𝘳𝘨𝘢 𝘴𝘶𝘴 𝘈𝘶𝘥𝘪𝘰 𝘦𝘴𝘱𝘦𝘳𝘦 🏃‍♂️💨*`, `Calmao pa estoy bucando tu canción 😎\n\n*Recuerda colocar bien el nombre de la cancion o el link del video de youtube*\n\n> *Si el comando *play no funciona utiliza el comando *ytmp3*`].getRandom(), m, {contextInfo: {externalAdReply :{ mediaUrl: null, mediaType: 1, description: null, title: wm, body: ' 💫 𝐒𝐮𝐩𝐞𝐫 𝐁𝐨𝐭 𝐃𝐞 𝐖𝐡𝐚𝐭𝐬𝐚𝐩𝐩 🥳 ', previewType: 0, thumbnail: img.getRandom(), sourceUrl: redes.getRandom()}}})    
+try {
+const audiodlp = await ytmp3(args);
+conn.sendMessage(m.chat, { audio: audiodlp, mimetype: "audio/mpeg" }, { quoted: m });
+} catch {
+try {  
+const res = await fetch(`https://api.siputzx.my.id/api/d/ytmp3?url=${args}`);
+let { data } = await res.json();
+await conn.sendMessage(m.chat, { audio: { url: data.dl }, mimetype: 'audio/mpeg' }, { quoted: m ||null });
+} catch {
+try {  
+const res = await fetch(`https://api.zenkey.my.id/api/download/ytmp3?apikey=zenkey&url=${args}`)
+let { result } = await res.json()
+await conn.sendMessage(m.chat, { audio: { url: await result.download.url }, mimetype: 'audio/mpeg' }, { quoted: m })
+} catch {
+try {
+const apiUrl = `${apis}/download/ytmp3?url=${args}`;
+const apiResponse = await fetch(apiUrl);
+const delius = await apiResponse.json();
+
+if (!delius.status) {
+return m.react("❌")}
+const downloadUrl = delius.data.download.url;
+await conn.sendMessage(m.chat, { audio: { url: downloadUrl }, mimetype: 'audio/mpeg' }, { quoted: m });
+} catch {
+try {
+let q = '128kbps'
+let v = youtubeLink
+const yt = await youtubedl(v).catch(async _ => await youtubedlv2(v))
+const dl_url = await yt.audio[q].download()
+const ttl = await yt.title
+const size = await yt.audio[q].fileSizeH
+await conn.sendFile(m.chat, dl_url, ttl + '.mp3', null, m, false, { mimetype: 'audio/mp4' })
+} catch {
+try {
+let searchh = await yts(youtubeLink)
+let __res = searchh.all.map(v => v).filter(v => v.type == "video")
+let infoo = await ytdl.getInfo('https://youtu.be/' + __res[0].videoId)
+let ress = await ytdl.chooseFormat(infoo.formats, { filter: 'audioonly' })
+conn.sendMessage(m.chat, { audio: { url: ress.url }, fileName: __res[0].title + '.mp3', mimetype: 'audio/mp4' }, { quoted: m })  
+} catch {
+}}}}}}}
+
+if (command == 'ytmp4' || command == 'fgmp4') {
+let youtubeLink = '';
+if (args[0].includes('you')) {
+youtubeLink = args[0];
+} else {
+const index = parseInt(args[0]) - 1;
+if (index >= 0) {
+if (Array.isArray(global.videoList) && global.videoList.length > 0) {
+const matchingItem = global.videoList.find(item => item.from === m.sender);
+if (matchingItem) {
+if (index < matchingItem.urls.length) {
+youtubeLink = matchingItem.urls[index];
+} else {
+throw `⚠️ 𝙉𝙤 𝙨𝙚 𝙚𝙣𝙘𝙤𝙣𝙩𝙧𝙤 𝙪𝙣 𝙚𝙣𝙡𝙖𝙘𝙚𝙨 𝙥𝙖𝙧𝙖 𝙚𝙨𝙚 𝙣𝙪𝙢𝙚𝙧𝙤, 𝙥𝙤𝙧 𝙛𝙖𝙫𝙤𝙧 𝙞𝙣𝙜𝙧𝙚𝙨𝙚 𝙚𝙡 𝙣𝙪𝙢𝙚𝙧𝙤 𝙚𝙣𝙩𝙧𝙚 1 𝙮 𝙚𝙡 ${matchingItem.urls.length}*`
+}} else {
+return
+}} else {
+return
+}}}  
+conn.reply(m.chat, [`*⌛ 𝙔𝙖 𝙚𝙨𝙩𝙤𝙮 𝙙𝙚𝙨𝙘𝙖𝙧𝙜𝙖𝙙𝙤 𝙩𝙪 𝙑𝙞𝙙𝙚𝙤 🍹*`, `⌛ 𝙋𝙍𝙊𝘾𝙀𝙎𝘼𝙉𝘿𝙊...\n*𝘌𝘴𝘵𝘰𝘺 𝘪𝘯𝘵𝘦𝘯𝘵𝘢𝘯𝘥𝘰 𝘥𝘦𝘴𝘤𝘢𝘳𝘨𝘢r 𝘴𝘶𝘴 𝘝𝘪𝘥𝘦𝘰 𝘦𝘴𝘱𝘦𝘳𝘦...*`, `*Estoy descargando tu video 🔄*\n\n> *Aguarde un momento, por favor*`].getRandom(), m, {contextInfo: {externalAdReply :{ mediaUrl: null, mediaType: 1, description: null, title: wm, body: ' 💫 𝐒𝐮𝐩𝐞𝐫 Kantu Bot 🐣 ', previewType: 0, thumbnail: img.getRandom(), sourceUrl: redes.getRandom()}}})    
+try {
+const video = await ytmp4(args);
+await conn.sendMessage(m.chat, { video: { url: video }, fileName: `video.mp4`, mimetype: 'video/mp4', caption: `🔰 Aquí está tu video`}, { quoted: m })
+} catch {
+try {   
+const res = await fetch(`https://api.siputzx.my.id/api/d/ytmp4?url=${args}`);
+let { data } = await res.json();
+await conn.sendMessage(m.chat, { video: { url: data.dl }, fileName: `video.mp4`, mimetype: 'video/mp4', caption: `🔰 Aquí está tu video`}, { quoted: m || null })
+} catch {
+try {  
+const res = await fetch(`https://api.zenkey.my.id/api/download/ytmp3?apikey=zenkey&url=${args}`)
+let { result } = await res.json()
+await conn.sendMessage(m.chat, { video: { url: result.download.url }, fileName: `video.mp4`, caption: `${wm}` }, { quoted: m }) 
+} catch {
+try {
+const axeelApi = `https://axeel.my.id/api/download/video?url=${args}`;
+const axeelRes = await fetch(axeelApi);
+const axeelJson = await axeelRes.json();
+if (axeelJson && axeelJson.downloads?.url) {
+const videoUrl = axeelJson.downloads.url;
+await conn.sendMessage(m.chat, { video: { url: videoUrl }, fileName: `${yt_play[0].title}.mp4`, caption: `🔰 Aquí está tu video \n🔥 Título: ${yt_play[0].title}` }, { quoted: m }) 
+}} catch {
+try {              
+let qu = args[1] || '360'
+let q = qu + 'p'
+let v = youtubeLink
+const yt = await youtubedl(v).catch(async _ => await youtubedlv2(v))
+const dl_url = await yt.video[q].download()
+const ttl = await yt.title
+const size = await yt.video[q].fileSizeH
+await await conn.sendMessage(m.chat, { video: { url: dl_url }, fileName: `${ttl}.mp4`, mimetype: 'video/mp4', caption: `🔰 𝘼𝙦𝙪𝙞 𝙚𝙨𝙩𝙖 𝙩𝙪 𝙫𝙞𝙙𝙚𝙤 \n🔥 𝙏𝙞𝙩𝙪𝙡𝙤: ${ttl}`, thumbnail: await fetch(yt.thumbnail) }, { quoted: m })
+} catch {
+try {  
+let mediaa = await ytMp4(youtubeLink)
+await conn.sendMessage(m.chat, { video: { url: mediaa.result }, fileName: `error.mp4`, caption: `_${wm}_`, thumbnail: mediaa.thumb, mimetype: 'video/mp4' }, { quoted: m })     
+} catch (e) {
+console.log(e)   
+}}}}}}}}
+handler.help = ['ytmp4', 'ytmp3'];
+handler.tags = ['downloader'];
+handler.command = /^ytmp3|ytmp4|fgmp4|audio|fgmp3|dlmp3?$/i
+export default handler
+
+function bytesToSize(bytes) {
+return new Promise((resolve, reject) => {
+const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
+if (bytes === 0) return 'n/a';
+const i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024)), 10);
+if (i === 0) resolve(`${bytes} ${sizes[i]}`);
+resolve(`${(bytes / (1024 ** i)).toFixed(1)} ${sizes[i]}`)})};
+
+async function ytMp3(url) {
+return new Promise((resolve, reject) => {
+ytdl.getInfo(url).then(async(getUrl) => {
+let result = [];
+for(let i = 0; i < getUrl.formats.length; i++) {
+let item = getUrl.formats[i];
+if (item.mimeType == 'audio/webm; codecs=\"opus\"') {
+let { contentLength } = item;
+let bytes = await bytesToSize(contentLength);
+result[i] = { audio: item.url, size: bytes }}};
+let resultFix = result.filter(x => x.audio != undefined && x.size != undefined) 
+let tiny = await axios.get(`https://tinyurl.com/api-create.php?url=${resultFix[0].audio}`);
+let tinyUrl = tiny.data;
+let title = getUrl.videoDetails.title;
+let thumb = getUrl.player_response.microformat.playerMicroformatRenderer.thumbnail.thumbnails[0].url;
+resolve({ title, result: tinyUrl, result2: resultFix, thumb })}).catch(reject)})}
+
+async function ytMp4(url) {
+return new Promise(async(resolve, reject) => {
+ytdl.getInfo(url).then(async(getUrl) => {
+let result = [];
+for(let i = 0; i < getUrl.formats.length; i++) {
+let item = getUrl.formats[i];
+if (item.container == 'mp4' && item.hasVideo == true && item.hasAudio == true) {
+let { qualityLabel, contentLength } = item;
+let bytes = await bytesToSize(contentLength);
+result[i] = { video: item.url, quality: qualityLabel, size: bytes }}};
+let resultFix = result.filter(x => x.video != undefined && x.size != undefined && x.quality != undefined) 
+let tiny = await axios.get(`https://tinyurl.com/api-create.php?url=${resultFix[0].video}`);
+let tinyUrl = tiny.data;
+let title = getUrl.videoDetails.title;
+let thumb = getUrl.player_response.microformat.playerMicroformatRenderer.thumbnail.thumbnails[0].url;
+resolve({ title, result: tinyUrl, rersult2: resultFix[0].video, thumb })}).catch(reject)})};
+
+async function ytPlay(query) {
+return new Promise((resolve, reject) => {
+yts(query).then(async(getData) => {
+let result = getData.videos.slice( 0, 5 );
+let url = [];
+for (let i = 0; i < result.length; i++) { url.push(result[i].url) }
+let random = url[0];
+let getAudio = await ytMp3(random);
+resolve(getAudio)}).catch(reject)})};
+
+async function ytPlayVid(query) {
+return new Promise((resolve, reject) => {
+yts(query).then(async(getData) => {
+let result = getData.videos.slice( 0, 5 );
+let url = [];
+for (let i = 0; i < result.length; i++) { url.push(result[i].url) }
+let random = url[0];
+let getVideo = await ytMp4(random);
+resolve(getVideo)}).catch(reject)})};

+ 167 - 0
plugins/descargas-playdoc.js

@@ -0,0 +1,167 @@
+import { youtubedl, youtubedlv2 } from '@bochilteam/scraper'
+import fetch from 'node-fetch'
+import yts from 'yt-search'
+import ytdl from 'ytdl-core'
+import axios from 'axios'
+let handler = async (m, { conn, args, usedPrefix, command }) => {
+if (!args[0]) throw '*𝙌𝙪𝙚 𝙚𝙨𝙩𝙖 𝙗𝙪𝙨𝙘𝙖𝙙𝙤🤔 𝙄𝙣𝙜𝙧𝙚𝙨𝙚 𝙚𝙡 𝙚𝙣𝙡𝙖𝙘𝙚 𝙙𝙚 𝙔𝙤𝙪𝙏𝙪𝙗𝙚 𝙥𝙖𝙧𝙖 𝙙𝙚𝙨𝙘𝙖𝙧𝙜𝙖𝙧 𝙚𝙡 𝙖𝙪𝙙𝙞𝙤*'
+
+if (command == 'ytmp3doc') {
+let youtubeLink = '';
+if (args[0].includes('you')) {
+youtubeLink = args[0];
+} else {
+const index = parseInt(args[0]) - 1;
+if (index >= 0) {
+if (Array.isArray(global.videoList) && global.videoList.length > 0) {
+const matchingItem = global.videoList.find(item => item.from === m.sender);
+if (matchingItem) {
+if (index < matchingItem.urls.length) {
+youtubeLink = matchingItem.urls[index];
+} else {
+throw `⚠️ 𝙉𝙤 𝙨𝙚 𝙚𝙣𝙘𝙤𝙣𝙩𝙧𝙤 𝙪𝙣 𝙚𝙣𝙡𝙖𝙘𝙚𝙨 𝙥𝙖𝙧𝙖 𝙚𝙨𝙚 𝙣𝙪𝙢𝙚𝙧𝙤, 𝙥𝙤𝙧 𝙛𝙖𝙫𝙤𝙧 𝙞𝙣𝙜𝙧𝙚𝙨𝙚 𝙚𝙡 𝙣𝙪𝙢𝙚𝙧𝙤 𝙚𝙣𝙩𝙧𝙚 1 𝙮 𝙚𝙡 ${matchingItem.urls.length}*`
+}} else {
+throw `⚠️ 𝙋𝙖𝙧𝙖 𝙥𝙤𝙙𝙚𝙧 𝙪𝙨𝙖𝙧 𝙚𝙨𝙩𝙚 𝙘𝙤𝙢𝙖𝙣𝙙𝙤 𝙙𝙚 𝙚𝙨𝙩𝙖 𝙛𝙤𝙧𝙢𝙖 (${usedPrefix + command} <numero>), 𝙋𝙤𝙧 𝙛𝙖𝙫𝙤𝙧 𝙧𝙚𝙖𝙡𝙞𝙯𝙖𝙧 𝙡𝙖 𝙗𝙪𝙨𝙦𝙪𝙚𝙙𝙖 𝙙𝙚 𝙫𝙞𝙙𝙚𝙤𝙨 𝙘𝙤𝙣 𝙚𝙡 𝙘𝙤𝙢𝙖𝙣𝙙𝙤 ${usedPrefix}playlist <texto>*`
+}} else {
+throw `⚠️ 𝙋𝙖𝙧𝙖 𝙥𝙤𝙙𝙚𝙧 𝙪𝙨𝙖𝙧 𝙚𝙨𝙩𝙚 𝙘𝙤𝙢𝙖𝙣𝙙𝙤 𝙙𝙚 𝙚𝙨𝙩𝙖 𝙛𝙤𝙧𝙢𝙖 (${usedPrefix + command} <numero>), 𝙋𝙤𝙧 𝙛𝙖𝙫𝙤𝙧 𝙧𝙚𝙖𝙡𝙞𝙯𝙖𝙧 𝙡𝙖 𝙗𝙪𝙨𝙦𝙪𝙚𝙙𝙖 𝙙𝙚 𝙫𝙞𝙙𝙚𝙤𝙨 𝙘𝙤𝙣 𝙚𝙡 𝙘𝙤𝙢𝙖𝙣𝙙𝙤 ${usedPrefix}playlist <texto>*`
+}}}  
+  
+conn.reply(m.chat, [`*⌛ 𝙀𝙨𝙥𝙚𝙧𝙚 ✋ 𝙪𝙣 𝙢𝙤𝙢𝙚𝙣𝙩𝙤... 𝙔𝙖 𝙚𝙨𝙩𝙤𝙮 𝙙𝙚𝙨𝙘𝙖𝙧𝙜𝙖𝙙𝙤 𝙩𝙪 𝙖𝙪𝙙𝙞𝙤🍹*`, `⌛ 𝙋𝙍𝙊𝘾𝙀𝙎𝘼𝙉𝘿𝙊...\n*𝘌𝘴𝘵𝘰𝘺 𝘪𝘯𝘵𝘦𝘯𝘵𝘢𝘯𝘥𝘰 𝘥𝘦𝘴𝘤𝘢𝘳𝘨𝘢 𝘴𝘶𝘴 𝘈𝘶𝘥𝘪𝘰 𝘦𝘴𝘱𝘦𝘳𝘦 🏃‍♂️💨*`].getRandom(), m, {contextInfo: {externalAdReply :{ mediaUrl: null, mediaType: 1, description: null, title: wm, body: ' 💫 𝐒𝐮𝐩𝐞𝐫 𝐁𝐨𝐭 𝐃𝐞 𝐖𝐡𝐚𝐭𝐬𝐚𝐩𝐩 🥳 ', previewType: 0, thumbnail: img.getRandom(), sourceUrl: redes.getRandom()}}})    
+try {
+let q = '128kbps'
+let v = youtubeLink
+const yt = await youtubedl(v).catch(async _ => await youtubedlv2(v))
+const dl_url = await yt.audio[q].download()
+const ttl = await yt.title
+const size = await yt.audio[q].fileSizeH
+await conn.sendMessage(m.chat, { document: { url: dl_url }, fileName: `${ttl}.mp3`, mimetype: 'audio/mp4' }, { quoted: m })  
+//conn.sendFile(m.chat, dl_url, ttl + '.mp3', null, m, false, { mimetype: 'audio/mp4' })
+} catch {
+try {
+let lolhuman = await fetch(`https://api.lolhuman.xyz/api/ytaudio2?apikey=${lolkeysapi}&url=${youtubeLink}`)    
+let lolh = await lolhuman.json()
+let n = lolh.result.title || 'error'
+await conn.sendMessage(m.chat, { document: { url: lolh.result.link }, fileName: `${n}.mp3`, mimetype: 'audio/mp4' }, { quoted: m })  
+} catch {   
+try {
+let searchh = await yts(youtubeLink)
+let __res = searchh.all.map(v => v).filter(v => v.type == "video")
+let infoo = await ytdl.getInfo('https://youtu.be/' + __res[0].videoId)
+let ress = await ytdl.chooseFormat(infoo.formats, { filter: 'audioonly' })
+conn.sendMessage(m.chat, { document: { url: ress.url }, fileName: __res[0].title + '.mp3', mimetype: 'audio/mp4' }, { quoted: m })  
+} catch {
+}}}}
+
+if (command == 'ytmp4' || command == 'fgmp4') {
+let youtubeLink = '';
+if (args[0].includes('you')) {
+youtubeLink = args[0];
+} else {
+const index = parseInt(args[0]) - 1;
+if (index >= 0) {
+if (Array.isArray(global.videoList) && global.videoList.length > 0) {
+const matchingItem = global.videoList.find(item => item.from === m.sender);
+if (matchingItem) {
+if (index < matchingItem.urls.length) {
+youtubeLink = matchingItem.urls[index];
+} else {
+throw `⚠️ 𝙉𝙤 𝙨𝙚 𝙚𝙣𝙘𝙤𝙣𝙩𝙧𝙤 𝙪𝙣 𝙚𝙣𝙡𝙖𝙘𝙚𝙨 𝙥𝙖𝙧𝙖 𝙚𝙨𝙚 𝙣𝙪𝙢𝙚𝙧𝙤, 𝙥𝙤𝙧 𝙛𝙖𝙫𝙤𝙧 𝙞𝙣𝙜𝙧𝙚𝙨𝙚 𝙚𝙡 𝙣𝙪𝙢𝙚𝙧𝙤 𝙚𝙣𝙩𝙧𝙚 1 𝙮 𝙚𝙡 ${matchingItem.urls.length}*`
+}} else {
+throw `⚠️ 𝙋𝙖𝙧𝙖 𝙥𝙤𝙙𝙚𝙧 𝙪𝙨𝙖𝙧 𝙚𝙨𝙩𝙚 𝙘𝙤𝙢𝙖𝙣𝙙𝙤 𝙙𝙚 𝙚𝙨𝙩𝙖 𝙛𝙤𝙧𝙢𝙖 (${usedPrefix + command} <numero>), 𝙋𝙤𝙧 𝙛𝙖𝙫𝙤𝙧 𝙧𝙚𝙖𝙡𝙞𝙯𝙖𝙧 𝙡𝙖 𝙗𝙪𝙨𝙦𝙪𝙚𝙙𝙖 𝙙𝙚 𝙫𝙞𝙙𝙚𝙤𝙨 𝙘𝙤𝙣 𝙚𝙡 𝙘𝙤𝙢𝙖𝙣𝙙𝙤 ${usedPrefix}playlist <texto>*`
+}} else {
+throw `⚠️ 𝙋𝙖𝙧𝙖 𝙥𝙤𝙙𝙚𝙧 𝙪𝙨𝙖𝙧 𝙚𝙨𝙩𝙚 𝙘𝙤𝙢𝙖𝙣𝙙𝙤 𝙙𝙚 𝙚𝙨𝙩𝙖 𝙛𝙤𝙧𝙢𝙖 (${usedPrefix + command} <numero>), 𝙋𝙤𝙧 𝙛𝙖𝙫𝙤𝙧 𝙧𝙚𝙖𝙡𝙞𝙯𝙖𝙧 𝙡𝙖 𝙗𝙪𝙨𝙦𝙪𝙚𝙙𝙖 𝙙𝙚 𝙫𝙞𝙙𝙚𝙤𝙨 𝙘𝙤𝙣 𝙚𝙡 𝙘𝙤𝙢𝙖𝙣𝙙𝙤 ${usedPrefix}playlist <texto>*`
+}}}  
+conn.reply(m.chat, [`*⌛ 𝙔𝙖 𝙚𝙨𝙩𝙤𝙮 𝙙𝙚𝙨𝙘𝙖𝙧𝙜𝙖𝙙𝙤 𝙩𝙪 𝙑𝙞𝙙𝙚𝙤 🍹*`, `⌛ 𝙋𝙍𝙊𝘾𝙀𝙎𝘼𝙉𝘿𝙊...\n*𝘌𝘴𝘵𝘰𝘺 𝘪𝘯𝘵𝘦𝘯𝘵𝘢𝘯𝘥𝘰 𝘥𝘦𝘴𝘤𝘢𝘳𝘨𝘢 𝘴𝘶𝘴 𝘝𝘪𝘥𝘦o...*`].getRandom(), m, {contextInfo: {externalAdReply :{ mediaUrl: null, mediaType: 1, description: null, title: wm, body: ' ⚡ 𝐒𝐮𝐩𝐞𝐫 Kantu Bot 🐣 ', previewType: 0, thumbnail: img.getRandom(), sourceUrl: redes.getRandom()}}})    
+try {
+let qu = args[1] || '360'
+let q = qu + 'p'
+let v = youtubeLink
+const yt = await youtubedl(v).catch(async _ => await youtubedlv2(v))
+const dl_url = await yt.video[q].download()
+const ttl = await yt.title
+const size = await yt.video[q].fileSizeH
+await await conn.sendMessage(m.chat, { document: { url: dl_url }, fileName: `${ttl}.mp4`, mimetype: 'video/mp4', caption: `🔰 𝘼𝙦𝙪𝙞 𝙚𝙨𝙩𝙖 𝙩𝙪 𝙫𝙞𝙙𝙚𝙤 \n🔥 𝙏𝙞𝙩𝙪𝙡𝙤: ${ttl}`, thumbnail: await fetch(yt.thumbnail) }, { quoted: m })
+} catch (E1) {
+//console.log('Error 1 ' + E1)  
+try {  
+let mediaa = await ytMp4(youtubeLink)
+await conn.sendMessage(m.chat, { document: { url: mediaa.result }, fileName: `error.mp4`, caption: `_${wm}_`, thumbnail: mediaa.thumb, mimetype: 'video/mp4' }, { quoted: m })     
+} catch (E2) {  
+//console.log('Error 2 ' + E2)   
+try {
+let lolhuman = await fetch(`https://api.lolhuman.xyz/api/ytvideo2?apikey=${lolkeysapi}&url=${youtubeLink}`)    
+let lolh = await lolhuman.json()
+let n = lolh.result.title || 'error'
+let n2 = lolh.result.link
+let n3 = lolh.result.size
+let n4 = lolh.result.thumbnail
+await conn.sendMessage(m.chat, { document: { url: n2 }, fileName: `${n}.mp4`, mimetype: 'video/mp4', caption: `🔰 𝘼𝙦𝙪𝙞 𝙚𝙨𝙩𝙖 𝙩𝙪 𝙫𝙞𝙙𝙚𝙤 \n🔥 𝙏𝙞𝙩𝙪𝙡𝙤: ${n}`, thumbnail: await fetch(n4) }, { quoted: m })
+} catch (E3) {
+//console.log('Error 3 ' + E3)   
+}}}}}
+handler.help = ['ytmp4doc', 'ytmp3doc'];
+handler.tags = ['downloader'];
+handler.command = /^ytmp3doc|ytmp4doc?$/i
+export default handler
+
+function bytesToSize(bytes) {
+return new Promise((resolve, reject) => {
+const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
+if (bytes === 0) return 'n/a';
+const i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024)), 10);
+if (i === 0) resolve(`${bytes} ${sizes[i]}`);
+resolve(`${(bytes / (1024 ** i)).toFixed(1)} ${sizes[i]}`)})};
+
+async function ytMp3(url) {
+return new Promise((resolve, reject) => {
+ytdl.getInfo(url).then(async(getUrl) => {
+let result = [];
+for(let i = 0; i < getUrl.formats.length; i++) {
+let item = getUrl.formats[i];
+if (item.mimeType == 'audio/webm; codecs=\"opus\"') {
+let { contentLength } = item;
+let bytes = await bytesToSize(contentLength);
+result[i] = { audio: item.url, size: bytes }}};
+let resultFix = result.filter(x => x.audio != undefined && x.size != undefined) 
+let tiny = await axios.get(`https://tinyurl.com/api-create.php?url=${resultFix[0].audio}`);
+let tinyUrl = tiny.data;
+let title = getUrl.videoDetails.title;
+let thumb = getUrl.player_response.microformat.playerMicroformatRenderer.thumbnail.thumbnails[0].url;
+resolve({ title, result: tinyUrl, result2: resultFix, thumb })}).catch(reject)})}
+
+async function ytMp4(url) {
+return new Promise(async(resolve, reject) => {
+ytdl.getInfo(url).then(async(getUrl) => {
+let result = [];
+for(let i = 0; i < getUrl.formats.length; i++) {
+let item = getUrl.formats[i];
+if (item.container == 'mp4' && item.hasVideo == true && item.hasAudio == true) {
+let { qualityLabel, contentLength } = item;
+let bytes = await bytesToSize(contentLength);
+result[i] = { video: item.url, quality: qualityLabel, size: bytes }}};
+let resultFix = result.filter(x => x.video != undefined && x.size != undefined && x.quality != undefined) 
+let tiny = await axios.get(`https://tinyurl.com/api-create.php?url=${resultFix[0].video}`);
+let tinyUrl = tiny.data;
+let title = getUrl.videoDetails.title;
+let thumb = getUrl.player_response.microformat.playerMicroformatRenderer.thumbnail.thumbnails[0].url;
+resolve({ title, result: tinyUrl, rersult2: resultFix[0].video, thumb })}).catch(reject)})};
+
+async function ytPlay(query) {
+return new Promise((resolve, reject) => {
+yts(query).then(async(getData) => {
+let result = getData.videos.slice( 0, 5 );
+let url = [];
+for (let i = 0; i < result.length; i++) { url.push(result[i].url) }
+let random = url[0];
+let getAudio = await ytMp3(random);
+resolve(getAudio)}).catch(reject)})};
+
+async function ytPlayVid(query) {
+return new Promise((resolve, reject) => {
+yts(query).then(async(getData) => {
+let result = getData.videos.slice( 0, 5 );
+let url = [];
+for (let i = 0; i < result.length; i++) { url.push(result[i].url) }
+let random = url[0];
+let getVideo = await ytMp4(random);
+resolve(getVideo)}).catch(reject)})};

+ 65 - 0
plugins/descargas-playlist.js

@@ -0,0 +1,65 @@
+import yts from 'yt-search';
+
+let handler = async (m, { conn, usedPrefix, text, args, command }) => {
+if (!text) return m.reply(`*¿Qué está buscando?* Ingrese el nombre del tema\n*• Ejemplo*\n*${usedPrefix + command}* bad bunny`);
+m.react('📀');
+let result = await yts(text);
+let ytres = result.videos;
+if (!ytres.length) return m.reply('❌ No se encontraron resultados.');
+
+if (m.isWABusiness) {
+let textoo = `*• Resultados de:*  ${text}\n\n`;
+for (let i = 0; i < Math.min(15, ytres.length); i++) { 
+let v = ytres[i];
+textoo += `🎵 *Título:* ${v.title}\n📆 *Publicado hace:* ${v.ago}\n👀 *Vistas:* ${v.views}\n⌛ *Duración:* ${v.timestamp}\n🔗 *Enlace:* ${v.url}\n\n⊱ ────── {.⋅ ♫ ⋅.} ───── ⊰\n\n`;
+}
+await conn.sendFile(m.chat, ytres[0].image, 'thumbnail.jpg', textoo, m, null, fake);
+} else {
+let selectedResults = ytres.slice(0, 9);
+let messages = selectedResults.map(v => [
+``, 
+`🎵 *Título:* ${v.title}\n📆 Publicado hace: ${v.ago}\n👀 Vistas: ${v.views}\n⌛ Duración: ${v.timestamp}`, 
+v.image, 
+[],
+[["Copia para descargar", `.ytmp4 ${v.url}`]], 
+[], 
+[]]);
+
+await conn.sendCarousel(m.chat, `✅ Resultados para: ${text}`, "🎵 YouTube Search", messages, m);
+}
+};
+handler.help = ['playlist', 'yts'];
+handler.tags = ['downloader'];
+handler.command = ['playvid2', 'playlist', 'playlista', 'yts', 'ytsearch'];
+handler.register = true;
+export default handler;
+
+/*Codigo con la listas obsoleto
+import yts from 'yt-search';
+let handler = async (m, { conn, usedPrefix, text, args, command }) => {
+if (!text) return m.reply(`*Que esta buscado?* ingrese el nombre del tema\n*• Ejemplo*\n*${usedPrefix + command}* bad bunny `) 
+m.react('📀');
+    
+let result = await yts(text);
+let ytres = result.videos;
+let listSections = [];
+for (let index in ytres) {
+let v = ytres[index];
+listSections.push({title: `${index} | ${v.title}`,
+rows: [{header: '• • •「 🅐🅤🅓🅘🅞 」• • •', title: "", description: `▢ ⌚ Duración:* ${v.timestamp}\n▢ 👀 *Vistas:* ${v.views}\n▢ 📌 *Publicado* : ${v.title}\n▢ 📆 *Subidos:* ${v.ago}\n`, id: `${usedPrefix}fgmp3 ${v.url}`
+}, {
+header: "• • •「 🅥🅘🅓🅔🅞 」• • •", title: "" , description: `▢ ⌚ Duración:* ${v.timestamp}\n▢ 👀 *Vistas:* ${v.views}\n▢ 📌 *Publicado* : ${v.title}\n▢ 📆 *Subidos:* ${v.ago}\n`, id: `${usedPrefix}fgmp4 ${v.url}`
+}, {
+header: "• • •「 🅓🅞🅒🅤🅜🅔🅝🅣🅞🅢 🅜🅟❸ 」• • •", title: "" , description: `▢ ⌚ Duración:* ${v.timestamp}\n▢ 👀 *Vistas:* ${v.views}\n▢ 📌 *Publicado* : ${v.title}\n▢ 📆 *Subidos:* ${v.ago}\n`, id: `${usedPrefix}ytmp3doc ${v.url}` }, {
+header: "'• • •「 🅓🅞🅒🅤🅜🅔🅝🅣🅞🅢 🅜🅟❹ 」• • •", title: "" , description: `▢ ⌚ Duración:* ${v.timestamp}\n▢ 👀 *Vistas:* ${v.views}\n▢ 📌 *Publicado* : ${v.title}\n▢ 📆 *Subidos:* ${v.ago}\n`, id: `${usedPrefix}ytmp4doc ${v.url}`
+}]});}
+    
+await conn.sendList(m.chat, `*• Resultados:* ${text}*\n\n> *ᴇʟɪᴊᴀ ᴀ ᴜɴᴀ ᴏᴘᴄɪᴏɴ ʏ ᴘʀᴇsɪᴏɴᴇ ᴇɴᴠɪᴀʀ*`, wm, `🚀 𝙍𝙀𝙎𝙐𝙇𝙏𝘼𝘿𝙊𝙎 🚀`, ytres[0].image, listSections, m);
+};
+handler.help = ['playlist', 'yts']
+handler.tags = ['downloader']
+handler.command = ['playvid2', 'playlist', 'playlista', 'yts', 'ytsearch'] 
+handler.register = true 
+
+export default handler
+*/

+ 128 - 0
plugins/descargas-spotify.js

@@ -0,0 +1,128 @@
+import axios from 'axios'
+import fetch from 'node-fetch'
+import search from 'yt-search'
+
+let handler = async (m, { conn, text, usedPrefix, command }) => {
+if (!text) throw `*¿Que esta buscando? ingresa el nombre para descargar sus música de Spotify, Ejemplo:* ${usedPrefix + command} ozuna`
+m.react(`⌛`) 
+const spotify = await fetch(`${apis}/search/spotify?q=${text}`);
+const song = await spotify.json();
+if (!song.data || song.data.length === 0) throw '⚠️ No se encontraron resultados para esa búsqueda.';
+const track = song.data[0]; 
+let spotifyMessage = `*• Título:* ${track.title}\n*• Artista:* ${track.artist}\n*• Álbum:* ${track.album}\n*• Duración:* ${track.duration}\n*• Publicado:* ${track.publish}\n\n> 🚀 *ᴱⁿᵛᶦᵃⁿᵈᵒ ᶜᵃⁿᶜᶦᵒ́ⁿ ᵃᵍᵘᵃʳᵈᵉ ᵘⁿ ᵐᵒᵐᵉⁿᵗᵒ....*`;
+await conn.sendMessage(m.chat, {text: spotifyMessage,
+contextInfo: {
+forwardingScore: 1,
+isForwarded: true,
+externalAdReply: {
+showAdAttribution: true,
+containsAutoReply: true,
+renderLargerThumbnail: true,
+title: track.title,
+body: "ᴱⁿᵛᶦᵃⁿᵈᵒ ᶜᵃⁿᶜᶦᵒ́ⁿ ᵃᵍᵘᵃʳᵈᵉ ᵘⁿ ᵐᵒᵐᵉⁿᵗᵒ 🚀",
+mediaType: 1,
+thumbnailUrl: track.image,
+mediaUrl: track.url,
+sourceUrl: track.url
+}}}, { quoted: m });
+try {
+const res = await fetch(`https://api.siputzx.my.id/api/d/spotify?url=${track.url}`);
+const data = await res.json();
+conn.sendMessage(m.chat, {audio: { url: data.data.download }, fileName: `${track.title}.mp3`,mimetype: 'audio/mpeg'}, { quoted: m });
+m.react('✅️');
+} catch {
+try {
+const res = await fetch(`${apis}/download/spotifydl?url=${track.url}`);
+const data = await res.json();
+conn.sendMessage(m.chat, { audio: { url: data.data.url }, fileName: `${track.title}.mp3`, mimetype: 'audio/mpeg' }, { quoted: m });
+m.react('✅️');
+} catch (error) {
+m.reply(`\`\`\`⚠️ OCURRIO UN ERROR ⚠️\`\`\`\n\n> *Reporta el siguiente error a mi creador con el comando:* #report\n\n>>> ${error} <<<< `) 
+console.log(error) 
+m.react('❌')
+handler.limit = false 
+}}}
+handler.help = ['spotify']
+handler.tags = ['downloader']
+handler.command = /^(spotify|music)$/i
+handler.register = true
+handler.limit = 1
+//handler.level = 2
+export default handler
+
+async function spotifyxv(query) {
+    let token = await tokens();
+    try {
+        let response = await axios({
+            method: 'get',
+            url: 'https://api.spotify.com/v1/search?q=' + query + '&type=track',
+            headers: {
+                Authorization: 'Bearer ' + token,
+            },
+        });
+        const tracks = response.data.tracks.items;
+        const results = tracks.map((track) => ({
+            name: track.name,
+            artista: track.artists.map((artist) => artist.name),
+            album: track.album.name,
+            duracion: timestamp(track.duration_ms),
+            url: track.external_urls.spotify,
+            imagen: track.album.images.length ? track.album.images[0].url : '',
+        }));
+        return results;
+    } catch (error) {
+        console.error(`Error en spotifyxv: ${error}`);
+        return [];
+    }
+}
+
+async function tokens() {
+    try {
+        const response = await axios({
+            method: 'post',
+            url: 'https://accounts.spotify.com/api/token',
+            headers: {
+                'Content-Type': 'application/x-www-form-urlencoded',
+                Authorization: 'Basic ' + Buffer.from('acc6302297e040aeb6e4ac1fbdfd62c3:0e8439a1280a43aba9a5bc0a16f3f009').toString('base64'),
+            },
+            data: 'grant_type=client_credentials',
+        });
+        return response.data.access_token;
+    } catch (error) {
+        console.error(`Error en tokens: ${error}`);
+        throw new Error('No se pudo obtener el token de acceso');
+    }
+}
+
+function timestamp(time) {
+    const minutes = Math.floor(time / 60000);
+    const seconds = Math.floor((time % 60000) / 1000);
+    return minutes + ':' + (seconds < 10 ? '0' : '') + seconds;
+}
+
+async function getBuffer(url, options) {
+try {
+options = options || {};
+const res = await axios({
+method: 'get',
+url,
+headers: {
+DNT: 1,
+'Upgrade-Insecure-Request': 1,
+},
+...options,
+responseType: 'arraybuffer',
+});
+return res.data;
+} catch (err) {
+return err;
+}}
+async function getTinyURL(text) {
+try {
+let response = await axios.get(`https://tinyurl.com/api-create.php?url=${text}`);
+return response.data;
+} catch (error) {
+return text;
+}}
+
+

+ 47 - 0
plugins/descargas-tiktokimg.js

@@ -0,0 +1,47 @@
+import axios from 'axios';
+const userRequests = {};
+
+let handler = async (m, { conn, usedPrefix, command, text }) => {
+if (!text) throw `*⚠️ ${await tr("Ingresa el nombre del video que buscas")}.*\n${await tr("Ejemplo")}: ${usedPrefix + command} emilia_mernes`
+if (userRequests[m.sender]) return m.reply(`⏳ ${await tr("*Espera...* Ya hay una solicitud en proceso. Por favor, espera a que termine antes de hacer otra.")}`)
+userRequests[m.sender] = true;
+m.react("⏳")
+try {
+let resultTxt = await tr("Resultados para")
+let { data: response } = await axios.get(`${apis}/search/tiktoksearch?query=${text}`);
+if (!response || !response.meta || !Array.isArray(response.meta) || response.meta.length === 0) return m.reply(`❌ ${await tr("No se encontraron resultados para")} "${text}".`);
+let searchResults = response.meta;
+shuffleArray(searchResults);
+let selectedResults = searchResults.slice(0, 5);
+if (m.isWABusiness) {
+const medias = selectedResults.map(result => ({type: "video", data: { url: result.hd }}));
+await conn.sendAlbumMessage(m.chat, medias, `✅ ${resultTxt}: ${text}`, m);
+m.react("✅️");
+} else {
+let messages = selectedResults.map(result => [``,
+`${result.title}`, 
+result.hd
+]);
+await conn.sendCarousel(m.chat, `✅ ${resultTxt}: ${text}`, "🔍 TikTok Search", messages, m);
+m.react("✅️");
+}
+} catch (error) {
+m.react("❌️")
+console.error(error);    
+} finally {
+delete userRequests[m.sender];
+}};
+handler.help = ['tiktoksearch <texto>'];
+handler.tags = ['downloader'];
+handler.command = ['tiktoksearch', 'ttsearch'];
+handler.register = true;
+handler.limit = 4;
+
+export default handler;
+
+function shuffleArray(array) {
+    for (let i = array.length - 1; i > 0; i--) {
+      const j = Math.floor(Math.random() * (i + 1));
+      [array[i], array[j]] = [array[j], array[i]];
+    }
+  }

+ 48 - 0
plugins/descargas-tiktokstalk.js

@@ -0,0 +1,48 @@
+import fg from 'api-dylux'
+let handler = async (m, { conn, text, args }) => {
+if (!text) throw `✳️ Ingrese el Username de un usuario de TikTok`
+m.react("⌛");
+try {
+const apiUrl = `${apis}/tools/tiktokstalk?q=${encodeURIComponent(args[0])}`;
+const apiResponse = await fetch(apiUrl);
+const delius = await apiResponse.json();
+if (!delius || !delius.result || !delius.result.users) return m.react("❌");
+const profile = delius.result.users;
+const stats = delius.result.stats;
+const txt = `👤 *Perfil de TikTok*:
+*• Nombre de usuario*: ${profile.username}
+*• Nickname*: ${profile.nickname}
+*• Verificado*: ${profile.verified ? 'Sí' : 'No'}
+*• Seguidores*: ${stats.followerCount.toLocaleString()}
+*• Seguidos*: ${stats.followingCount.toLocaleString()}
+*• Likes Totales*: ${stats.heartCount.toLocaleString()}
+*• Videos*: ${stats.videoCount.toLocaleString()}
+*• Firma*: ${profile.signature}
+*• URL*: 
+${profile.url}`;
+
+await conn.sendFile(m.chat, profile.avatarLarger, 'tt.png', txt, m, null, fake);
+m.react("✅");
+} catch (e2) {
+try {
+  let res = await fg.ttStalk(args[0])
+  let txt = `👤 *Perfil de TikTok*:
+*• Nombre:* ${res.name}
+*• Username:* ${res.username}
+*• Seguidores:* ${res.followers}
+*• Siguiendo:* ${res.following}
+*• Desc:* ${res.desc}
+*• Link* : https://tiktok.com/${res.username}`
+await conn.sendFile(m.chat, res.profile, 'tt.png', txt, m, null, fake)
+m.react("✅");
+} catch (e) {
+await m.react(`❌`) 
+m.reply(`\`\`\`⚠️ OCURRIO UN ERROR ⚠️\`\`\`\n\n> *Reporta el siguiente error a mi creador con el comando:*#report\n\n>>> ${e} <<<< `)       
+console.log(e)
+}}}
+handler.help = ['tiktokstalk']
+handler.tags = ['downloader']
+handler.command = /^t(tstalk|iktokstalk|iktoksearch|tsearch)$/i
+handler.register = true
+handler.limit = 1
+export default handler

Some files were not shown because too many files changed in this diff