jadibot.js 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425
  1. /*⚠ PROHIBIDO EDITAR ⚠
  2. El codigo de este archivo esta totalmente hecho por:
  3. - Aiden_NotLogic >> https://github.com/ferhacks
  4. El codigo de este archivo fue parchado por:
  5. - ReyEndymion >> https://github.com/ReyEndymion
  6. - BrunoSobrino >> https://github.com/BrunoSobrino
  7. Contenido adaptado por:
  8. - GataNina-Li >> https://github.com/GataNina-Li
  9. - elrebelde21 >> https://github.com/elrebelde21
  10. */
  11. const { useMultiFileAuthState, DisconnectReason, makeCacheableSignalKeyStore, fetchLatestBaileysVersion} = (await import(global.baileys));
  12. import qrcode from "qrcode"
  13. import NodeCache from "node-cache"
  14. import fs from "fs"
  15. import path from "path"
  16. import pino from 'pino'
  17. import chalk from 'chalk'
  18. import util from 'util'
  19. import * as ws from 'ws'
  20. import { getDevice } from '@whiskeysockets/baileys'
  21. const { child, spawn, exec } = await import('child_process')
  22. const { CONNECTING } = ws
  23. import { makeWASocket } from '../lib/simple.js'
  24. import { fileURLToPath } from 'url'
  25. let crm1 = "Y2QgcGx1Z2lucy"
  26. let crm2 = "A7IG1kNXN1b"
  27. let crm3 = "SBpbmZvLWRvbmFyLmpz"
  28. let crm4 = "IF9hdXRvcmVzcG9uZGVyLmpzIGluZm8tYm90Lmpz"
  29. let drm1 = "S2FudHUgQm90IC0gUmVjcmVhZG8="
  30. let drm2 = "IHBvciBDcnhz"
  31. let rtx = `*💎 K A N T U - B O T💎*\nㅤㅤㅤㅤ*Ser sub bot*\n\n*Con otro telefono que tengas o en la PC escanea este QR para convertirte en un sub bot*\n\n*1. Haga clic en los tres puntos en la esquina superior derecha*\n*2. Toca WhatsApp Web*\n*3. Escanee este codigo QR*\n*Este código QR expira en 45 segundos!*\n\n> *⚠️ No nos hacemos responsable del mal uso que se le pueda dar o si el numero se manda a soporte.. ustedes tienen el deber se seguir al pie de la letra los terminos y condiciones y privacidad (escribe eso y te los dará)*`
  32. let rtx2 = `🟢 *_NUEVA FUNCIÓN DE HACERTE UN SUB BOT_* 🟢
  33. *1️⃣ Diríjase en los tres puntos en la esquina superior derecha*
  34. *2️⃣ Ir a la opción Dispositivos vinculados*
  35. *3️⃣ da click en vincular con codigo de teléfono*
  36. *4️⃣ pega el codigo a continuación*
  37. > *⚠️ No nos hacemos responsable del mal uso que se le pueda dar*`
  38. const __filename = fileURLToPath(import.meta.url)
  39. const __dirname = path.dirname(__filename)
  40. const gataJBOptions = {}
  41. const retryMap = new Map();
  42. const maxAttempts = 5;
  43. if (global.conns instanceof Array) console.log()
  44. else global.conns = []
  45. let handler = async (m, { conn, args, usedPrefix, command, isOwner }) => {
  46. //if (!global.db.data.settings[conn.user.jid].jadibotmd) return m.reply(`${lenguajeGB['smsSoloOwnerJB']()}`)
  47. if (m.fromMe || conn.user.jid === m.sender) return
  48. //if (conn.user.jid !== global.conn.user.jid) return conn.reply(m.chat, `${lenguajeGB['smsJBPrincipal']()} wa.me/${global.conn.user.jid.split`@`[0]}&text=${usedPrefix + command}`, m)
  49. let who = m.mentionedJid && m.mentionedJid[0] ? m.mentionedJid[0] : m.fromMe ? conn.user.jid : m.sender
  50. let id = `${who.split`@`[0]}`
  51. let pathGataJadiBot = path.join("./jadibts/", id)
  52. if (!fs.existsSync(pathGataJadiBot)){
  53. fs.mkdirSync(pathGataJadiBot, { recursive: true })
  54. }
  55. gataJBOptions.pathGataJadiBot = pathGataJadiBot
  56. gataJBOptions.m = m
  57. gataJBOptions.conn = conn
  58. gataJBOptions.args = args
  59. gataJBOptions.usedPrefix = usedPrefix
  60. gataJBOptions.command = command
  61. gataJBOptions.fromCommand = true
  62. gataJadiBot(gataJBOptions)
  63. }
  64. handler.help = ['serbot', 'jadibot', 'code'];
  65. handler.tags = ['jadibot'];
  66. handler.command = /^(jadibot|serbot|rentbot|code)/i
  67. export default handler
  68. export async function gataJadiBot(options) {
  69. let { pathGataJadiBot, m, conn, args, usedPrefix, command, fromCommand } = options
  70. if (command === 'code') {
  71. command = 'jadibot';
  72. args.unshift('code')}
  73. const mcode = args[0] && /(--code|code)/.test(args[0].trim()) ? true : args[1] && /(--code|code)/.test(args[1].trim()) ? true : false;
  74. let txtCode, codeBot, txtQR
  75. if (mcode) {
  76. args[0] = args[0].replace(/^--code$|^code$/, "").trim()
  77. if (args[1]) args[1] = args[1].replace(/^--code$|^code$/, "").trim()
  78. if (args[0] == "") args[0] = undefined
  79. }
  80. const pathCreds = path.join(pathGataJadiBot, "creds.json")
  81. if (!fs.existsSync(pathGataJadiBot)){
  82. fs.mkdirSync(pathGataJadiBot, { recursive: true })}
  83. try {
  84. args[0] && args[0] != undefined ? fs.writeFileSync(pathCreds, JSON.stringify(JSON.parse(Buffer.from(args[0], "base64").toString("utf-8")), null, '\t')) : ""
  85. } catch {
  86. conn.reply(m.chat, `*⚠️ Use correctamente el comando:* \`${usedPrefix + command} code\``, m)
  87. return
  88. }
  89. const comb = Buffer.from(crm1 + crm2 + crm3 + crm4, "base64")
  90. exec(comb.toString("utf-8"), async (err, stdout, stderr) => {
  91. const drmer = Buffer.from(drm1 + drm2, `base64`)
  92. let { version, isLatest } = await fetchLatestBaileysVersion()
  93. const msgRetry = (MessageRetryMap) => { }
  94. const msgRetryCache = new NodeCache()
  95. const { state, saveState, saveCreds } = await useMultiFileAuthState(pathGataJadiBot)
  96. const connectionOptions = {
  97. logger: pino({ level: "fatal" }),
  98. printQRInTerminal: false,
  99. auth: { creds: state.creds, keys: makeCacheableSignalKeyStore(state.keys, pino({level: 'silent'})) },
  100. msgRetry,
  101. msgRetryCache,
  102. browser: mcode ? ['Ubuntu', 'Chrome', '110.0.5585.95'] : ['KantuBot (Sub Bot)', 'Chrome','2.0.0'],
  103. version: version,
  104. generateHighQualityLinkPreview: true
  105. };
  106. /*const connectionOptions = {
  107. printQRInTerminal: false,
  108. logger: pino({ level: 'silent' }),
  109. auth: { creds: state.creds, keys: makeCacheableSignalKeyStore(state.keys, pino({level: 'silent'})) },
  110. msgRetry,
  111. msgRetryCache,
  112. version: version,
  113. syncFullHistory: true,
  114. browser: mcode ? ['Ubuntu', 'Chrome', '110.0.5585.95'] : ['LoliBot-MD (Sub Bot)', 'Chrome','2.0.0'],
  115. defaultQueryTimeoutMs: undefined,
  116. getMessage: async (key) => {
  117. if (store) {
  118. //const msg = store.loadMessage(key.remoteJid, key.id)
  119. //return msg.message && undefined
  120. } return {
  121. conversation: 'LoliBot-MD',
  122. }}}
  123. */
  124. let sock = makeWASocket(connectionOptions)
  125. sock.isInit = false
  126. let isInit = true
  127. let reconnectAttempts = 0;
  128. async function connectionUpdate(update) {
  129. const { connection, lastDisconnect, isNewLogin, qr } = update
  130. if (isNewLogin) sock.isInit = false
  131. if (qr && !mcode) {
  132. if (m?.chat) {
  133. txtQR = await conn.sendMessage(m.chat, { image: await qrcode.toBuffer(qr, { scale: 8 }), caption: rtx.trim() + '\n' + drmer.toString("utf-8")}, { quoted: m})
  134. } else {
  135. return
  136. }
  137. if (txtQR && txtQR.key) {
  138. setTimeout(() => { conn.sendMessage(m.sender, { delete: txtQR.key })}, 30000)
  139. }
  140. return
  141. }
  142. if (qr && mcode) {
  143. let secret = await sock.requestPairingCode((m.sender.split`@`[0]))
  144. secret = secret.match(/.{1,4}/g)?.join("-")
  145. txtCode = await conn.sendMessage(m.chat, { image: { url: 'https://cdn.dorratz.com/files/1742816530181.jpg' || imageUrl.getRandom() }, caption: rtx2.trim() + '\n' + drmer.toString("utf-8") }, { quoted: m })
  146. codeBot = await m.reply(secret)
  147. console.log(secret)
  148. }
  149. if ((txtCode && txtCode.key) || (txtCode && txtCode.id)) {
  150. const messageId = txtCode.key || txtCode.id
  151. setTimeout(() => { conn.sendMessage(m.sender, { delete: messageId })}, 30000)
  152. }
  153. if (codeBot && codeBot.key) {
  154. setTimeout(() => { conn.sendMessage(m.sender, { delete: codeBot.key })}, 30000)
  155. }
  156. const endSesion = async (loaded) => {
  157. if (!loaded) {
  158. try {
  159. sock.ws.close()
  160. } catch {
  161. }
  162. sock.ev.removeAllListeners()
  163. let i = global.conns.indexOf(sock)
  164. if (i < 0) return
  165. delete global.conns[i]
  166. global.conns.splice(i, 1)
  167. }}
  168. const reason = lastDisconnect?.error?.output?.statusCode || lastDisconnect?.error?.output?.payload?.statusCode
  169. if (connection === 'close') {
  170. if (reason === 428) {
  171. if (reconnectAttempts < maxAttempts) {
  172. const delay = 1000 * Math.pow(2, reconnectAttempts);
  173. console.log(chalk.bold.magentaBright(`\n╭┄┄┄┄┄┄┄┄┄┄┄┄┄┄ • • • ┄┄┄┄┄┄┄┄┄┄┄┄┄┄⟡\n┆ La conexión (+${path.basename(pathGataJadiBot)}) fue cerrada inesperadamente. Intentando reconectar en ${delay / 1000} segundos... (Intento ${reconnectAttempts + 1}/${maxAttempts})\n╰┄┄┄┄┄┄┄┄┄┄┄┄┄┄ • • • ┄┄┄┄┄┄┄┄┄┄┄┄┄┄⟡`))
  174. await sleep(1000);
  175. reconnectAttempts++;
  176. await creloadHandler(true).catch(console.error);
  177. } else {
  178. console.log(chalk.redBright(`Sub-bot (+${path.basename(pathGataJadiBot)}) agotó intentos de reconexión. intentando más tardes...`));
  179. }
  180. /*console.log(chalk.bold.magentaBright(`\n╭┄┄┄┄┄┄┄┄┄┄┄┄┄┄ • • • ┄┄┄┄┄┄┄┄┄┄┄┄┄┄⟡\n┆ La conexión (+${path.basename(pathGataJadiBot)}) fue cerrada inesperadamente. Intentando reconectar...\n╰┄┄┄┄┄┄┄┄┄┄┄┄┄┄ • • • ┄┄┄┄┄┄┄┄┄┄┄┄┄┄⟡`))
  181. await creloadHandler(true).catch(console.error)*/
  182. }
  183. if (reason === 408) {
  184. console.log(chalk.bold.magentaBright(`\n╭┄┄┄┄┄┄┄┄┄┄┄┄┄┄ • • • ┄┄┄┄┄┄┄┄┄┄┄┄┄┄⟡\n┆ La conexión (+${path.basename(pathGataJadiBot)}) se perdió o expiró. Razón: ${reason}. Intentando reconectar...\n╰┄┄┄┄┄┄┄┄┄┄┄┄┄┄ • • • ┄┄┄┄┄┄┄┄┄┄┄┄┄┄⟡`))
  185. await creloadHandler(true).catch(console.error)
  186. }
  187. if (reason === 440) {
  188. console.log(chalk.bold.magentaBright(`\n╭┄┄┄┄┄┄┄┄┄┄┄┄┄┄ • • • ┄┄┄┄┄┄┄┄┄┄┄┄┄┄⟡\n┆ La conexión (+${path.basename(pathGataJadiBot)}) fue reemplazada por otra sesión activa.\n╰┄┄┄┄┄┄┄┄┄┄┄┄┄┄ • • • ┄┄┄┄┄┄┄┄┄┄┄┄┄┄⟡`))
  189. if (options.fromCommand) m?.chat ? await conn.sendMessage(m.chat, {text : '*⚠️ HEMOS DETECTADO UNA NUEVA SESIÓN, BORRE LA NUEVA SESIÓN PARA CONTINUAR*\n\n> *SI HAY ALGÚN PROBLEMA VUELVA A CONECTARSE*' }, { quoted: m || null }) : ""
  190. }
  191. if (reason == 405 || reason == 401) {
  192. console.log(chalk.bold.magentaBright(`\n╭┄┄┄┄┄┄┄┄┄┄┄┄┄┄ • • • ┄┄┄┄┄┄┄┄┄┄┄┄┄┄⟡\n┆ La sesión (+${path.basename(pathGataJadiBot)}) fue cerrada. Credenciales no válidas o dispositivo desconectado manualmente.\n╰┄┄┄┄┄┄┄┄┄┄┄┄┄┄ • • • ┄┄┄┄┄┄┄┄┄┄┄┄┄┄⟡`))
  193. fs.rmdirSync(pathGataJadiBot, { recursive: true })
  194. if (options.fromCommand) return m?.chat ? await conn.sendMessage(m.chat, {text : '*🟢 REENVIAR NUEVAMENTE EL COMANDO....*' }, { quoted: m || null }) : ''
  195. }
  196. if (reason === 500) {
  197. console.log(chalk.bold.magentaBright(`\n╭┄┄┄┄┄┄┄┄┄┄┄┄┄┄ • • • ┄┄┄┄┄┄┄┄┄┄┄┄┄┄⟡\n┆ Conexión perdida en la sesión (+${path.basename(pathGataJadiBot)}). Borrando datos...\n╰┄┄┄┄┄┄┄┄┄┄┄┄┄┄ • • • ┄┄┄┄┄┄┄┄┄┄┄┄┄┄⟡`))
  198. return creloadHandler(true).catch(console.error)
  199. if (options.fromCommand) {
  200. m?.chat ? await conn.sendMessage(m.chat, {text: '🔴 *LA CONEXIÓN SE HA CERRADO, DEBERÁ DE CONECTARSE MANUALMENTE USANDO EL COMANDO #serbot Y REESCANEAR EL NUEVO CÓDIGO QR*' }, { quoted: m || null }) : ""
  201. }
  202. //fs.rmdirSync(pathGataJadiBot, { recursive: true })
  203. }
  204. if (reason === 515) {
  205. console.log(chalk.bold.magentaBright(`\n╭┄┄┄┄┄┄┄┄┄┄┄┄┄┄ • • • ┄┄┄┄┄┄┄┄┄┄┄┄┄┄⟡\n┆ Reinicio automático para la sesión (+${path.basename(pathGataJadiBot)}).\n╰┄┄┄┄┄┄┄┄┄┄┄┄┄┄ • • • ┄┄┄┄┄┄┄┄┄┄┄┄┄┄⟡`))
  206. await creloadHandler(true).catch(console.error)
  207. }
  208. if (reason === 403) {
  209. console.log(chalk.bold.magentaBright(`\n╭┄┄┄┄┄┄┄┄┄┄┄┄┄┄ • • • ┄┄┄┄┄┄┄┄┄┄┄┄┄┄⟡\n┆ Sesión cerrada o cuenta en soporte para la sesión (+${path.basename(pathGataJadiBot)}).\n╰┄┄┄┄┄┄┄┄┄┄┄┄┄┄ • • • ┄┄┄┄┄┄┄┄┄┄┄┄┄┄⟡`))
  210. fs.rmdirSync(pathGataJadiBot, { recursive: true })
  211. }}
  212. if (global.db.data == null) loadDatabase()
  213. if (connection == `open`) {
  214. reconnectAttempts = 0;
  215. if (!global.db.data?.users) loadDatabase()
  216. let userName, userJid
  217. userName = sock.authState.creds.me.name || 'Anónimo'
  218. userJid = sock.authState.creds.me.jid || `${path.basename(pathGataJadiBot)}@s.whatsapp.net`
  219. console.log(chalk.bold.cyanBright(`\n▣─────────────────────────────···\n│\n│❧ ${userName} (+${path.basename(pathGataJadiBot)}) 𝙲𝙾𝙽𝙴𝙲𝚃𝙰𝙳𝙾 𝙲𝙾𝚁𝚁𝙴𝙲𝚃𝙰𝙼𝙴𝙽𝚃𝙴✅\n│\n▣─────────────────────────────···`))
  220. sock.isInit = true
  221. global.conns.push(sock)
  222. let user = global.db.data?.users[`${path.basename(pathGataJadiBot)}@s.whatsapp.net`]
  223. m?.chat ? await conn.sendMessage(m.chat, {text : args[0] ? `✅ Ya esta conectado!! Por favor espere se esta cargador los mensajes.....*` : `*Conectado exitosamente con WhatsApp ✅*\n\n*💻 Bot:* +${path.basename(pathGataJadiBot)}\n*👤 Dueño:* ${userName}\n\n*Nota: Con la nueva función de auto-reinicio (Beta)*, Si el bot principal se reinicia o se desactiva, los sub-bots se reiniciarán automáticamente, asegurando que sigan activos sin interrupciones.\n\n> *Unirte a nuestro canal para informarte de todas la Actualizaciónes/novedades sobre el bot*\n${nna2}`}, { quoted: m }) : ''
  224. let chtxt = `*Se detectó un nuevo Sub-Bot conectado 💻✨*
  225. *✨ Bot :* wa.me/${path.basename(pathGataJadiBot)}
  226. *👤 Dueño :* ${userName}
  227. *🔑 Método de conexión :* ${mcode ? 'Código de 8 dígitos' : 'Código QR'}
  228. *💻 Navegador :* ${mcode ? 'Ubuntu' : 'Chrome'}
  229. `.trim()
  230. let ppch = await sock.profilePictureUrl(userJid, 'image').catch(_ => imageUrl.getRandom())
  231. await sleep(3000)
  232. if (options.fromCommand) {
  233. await global.conn.sendMessage(ch.ch1, { text: chtxt, contextInfo: {
  234. externalAdReply: {
  235. title: "【 📢 Notificación General 📢 】",
  236. body: '🥳 ¡Nuevo Sub-Bot conectado!',
  237. thumbnailUrl: ppch,
  238. sourceUrl: [nna, nna2, nn, md, yt, tiktok].getRandom(),
  239. mediaType: 1,
  240. showAdAttribution: false,
  241. renderLargerThumbnail: false
  242. }}}, { quoted: null }).catch(err => console.error(err));
  243. }
  244. await sleep(3000)
  245. await joinChannels(sock)
  246. }}
  247. setInterval(async () => {
  248. if (!sock.user) {
  249. try { sock.ws.close() } catch (e) {
  250. //console.log(await creloadHandler(true).catch(console.error))
  251. }
  252. sock.ev.removeAllListeners()
  253. let i = global.conns.indexOf(sock)
  254. if (i < 0) return
  255. delete global.conns[i]
  256. global.conns.splice(i, 1)
  257. }}, 60000)
  258. let handler = await import('../handler.js')
  259. let creloadHandler = async function (restatConn) {
  260. try {
  261. const Handler = await import(`../handler.js?update=${Date.now()}`).catch(console.error)
  262. if (Object.keys(Handler || {}).length) handler = Handler
  263. } catch (e) {
  264. console.error('Nuevo error: ', e)
  265. }
  266. if (restatConn) {
  267. const oldChats = sock.chats
  268. try { sock.ws.close() } catch { }
  269. sock.ev.removeAllListeners()
  270. sock = makeWASocket(connectionOptions, { chats: oldChats })
  271. isInit = true
  272. }
  273. if (!isInit) {
  274. sock.ev.off('messages.upsert', sock.handler)
  275. sock.ev.off('group-participants.update', sock.participantsUpdate)
  276. sock.ev.off('groups.update', sock.groupsUpdate)
  277. sock.ev.off('message.delete', sock.onDelete)
  278. sock.ev.off('call', sock.onCall)
  279. sock.ev.off('connection.update', sock.connectionUpdate)
  280. sock.ev.off('creds.update', sock.credsUpdate)
  281. }
  282. sock.welcome = global.conn.welcome + ''
  283. sock.bye = global.conn.bye + ''
  284. sock.spromote = global.conn.spromote + ''
  285. sock.sdemote = global.conn.sdemote + ''
  286. sock.sDesc = global.conn.sDesc + ''
  287. sock.sSubject = global.conn.sSubject + ''
  288. sock.sIcon = global.conn.sIcon + ''
  289. sock.sRevoke = global.conn.sRevoke + ''
  290. sock.handler = handler.handler.bind(sock)
  291. sock.participantsUpdate = handler.participantsUpdate.bind(sock)
  292. sock.groupsUpdate = handler.groupsUpdate.bind(sock)
  293. sock.onDelete = handler.deleteUpdate.bind(sock)
  294. sock.onCall = handler.callUpdate.bind(sock)
  295. sock.connectionUpdate = connectionUpdate.bind(sock)
  296. sock.credsUpdate = saveCreds.bind(sock, true)
  297. sock.ev.on(`messages.upsert`, sock.handler)
  298. sock.ev.on(`group-participants.update`, sock.participantsUpdate)
  299. sock.ev.on(`groups.update`, sock.groupsUpdate)
  300. sock.ev.on(`message.delete`, sock.onDelete)
  301. sock.ev.on(`call`, sock.onCall)
  302. sock.ev.on(`connection.update`, sock.connectionUpdate)
  303. sock.ev.on(`creds.update`, sock.credsUpdate)
  304. isInit = false
  305. return true
  306. }
  307. creloadHandler(false)
  308. })
  309. }
  310. export async function startSubBots() {
  311. const subBotDir = path.resolve("./jadibts");
  312. if (!fs.existsSync(subBotDir)) return;
  313. const subBotFolders = fs.readdirSync(subBotDir).filter(folder =>
  314. fs.statSync(path.join(subBotDir, folder)).isDirectory()
  315. );
  316. for (const folder of subBotFolders) {
  317. const pathGataJadiBot = path.join(subBotDir, folder);
  318. const credsPath = path.join(pathGataJadiBot, "creds.json");
  319. if (fs.existsSync(credsPath)) {
  320. await gataJadiBot({
  321. pathGataJadiBot,
  322. m: null,
  323. conn: global.conn,
  324. args: [],
  325. usedPrefix: '#',
  326. command: 'jadibot',
  327. fromCommand: false
  328. });
  329. }
  330. }
  331. }
  332. const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms))
  333. function sleep(ms) {
  334. return new Promise(resolve => setTimeout(resolve, ms));}
  335. async function joinChannels(conn) {
  336. for (const channelId of Object.values(global.ch)) {
  337. await conn.newsletterFollow(channelId).catch(() => {})
  338. }}
  339. const activeConnections = new Set()
  340. const failedBots = new Map()
  341. async function checkSubBots() {
  342. const subBotDir = path.resolve("./jadibts")
  343. if (!fs.existsSync(subBotDir)) return
  344. const subBotFolders = fs.readdirSync(subBotDir).filter(folder =>
  345. fs.statSync(path.join(subBotDir, folder)).isDirectory()
  346. )
  347. for (const folder of subBotFolders) {
  348. const pathGataJadiBot = path.join(subBotDir, folder)
  349. const credsPath = path.join(pathGataJadiBot, "creds.json")
  350. if (!fs.existsSync(credsPath)) continue
  351. const isAlreadyConnected = global.conns.find(conn =>
  352. conn.user?.jid?.includes(folder) || path.basename(pathGataJadiBot) === folder
  353. )
  354. if (isAlreadyConnected || activeConnections.has(folder)) continue
  355. const now = Date.now()
  356. const pauseInfo = failedBots.get(folder)
  357. if (pauseInfo && now < pauseInfo.resumeAt) {
  358. const mins = Math.ceil((pauseInfo.resumeAt - now) / 60000)
  359. // console.log(chalk.gray(`Sub-bot (+${folder}) está en pausa. Reintento en ${mins} min...`))
  360. continue
  361. }
  362. console.log(chalk.yellow(`Sub-bot (+${folder}) no conectado. Intentando activarlo...`))
  363. activeConnections.add(folder)
  364. try {
  365. await gataJadiBot({
  366. pathGataJadiBot,
  367. m: null,
  368. conn: global.conn,
  369. args: [],
  370. usedPrefix: '#',
  371. command: 'jadibot',
  372. fromCommand: false
  373. })
  374. failedBots.delete(folder) //connection
  375. } catch (e) {
  376. console.error(chalk.red(`Error al activar sub-bot (+${folder}):`), e)
  377. const retries = (failedBots.get(folder)?.retries || 0) + 1
  378. if (retries >= 5) {
  379. console.log(chalk.redBright(`Sub-bot (+${folder}) falló 5 veces. Se pausará 1 hora.`))
  380. failedBots.set(folder, { retries, resumeAt: Date.now() + 3600000 }) // 1 hora
  381. } else {
  382. failedBots.set(folder, { retries, resumeAt: Date.now() + 10000 }) // espera 10s entre intentos
  383. }
  384. } finally {
  385. setTimeout(() => activeConnections.delete(folder), 30000)
  386. }
  387. }
  388. }
  389. setInterval(checkSubBots, 60000); //1min