JerryCoderr

autodl-yt+insta.js

May 14th, 2026
24
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. const { Module } = require("../main");
  2. const config = require("../config");
  3. const { setVar } = require("./manage");
  4. const { downloadGram } = require("./utils");
  5. const {
  6.   getVideoInfo,
  7.   downloadVideo,
  8.   downloadAudio,
  9.   convertM4aToMp3,
  10. } = require("./utils/yt");
  11.  
  12. const fs = require("fs");
  13.  
  14. const fromMe = false;
  15.  
  16. // temp yt quality store
  17. const YT_SELECTIONS = {};
  18.  
  19. const HANDLER_PREFIX =
  20.   config.HANDLERS === "false"
  21.     ? ""
  22.     : (config.HANDLERS || ".").charAt(0);
  23.  
  24. const URL_PATTERNS = {
  25.   instagram:
  26.     /^https?:\/\/(?:www\.)?instagram\.com\/(?:p\/[A-Za-z0-9_-]+\/?|reel\/[A-Za-z0-9_-]+\/?|tv\/[A-Za-z0-9_-]+\/?|stories\/[A-Za-z0-9_.-]+\/\d+\/?)(?:\?.*)?$/i,
  27.  
  28.   youtube:
  29.     /^https?:\/\/(?:www\.)?(?:youtube\.com\/(?:watch\?v=|shorts\/[A-Za-z0-9_-]+\/?)|youtu\.be\/)([A-Za-z0-9_-]{11})?(?:[\?&].*)?$/i,
  30. };
  31.  
  32. function getAllUrls(text) {
  33.   if (!text) return [];
  34.  
  35.   const urlMatches = text.match(/https?:\/\/\S+/gi);
  36.  
  37.   if (!urlMatches) return [];
  38.  
  39.   return urlMatches.map((url) =>
  40.     url.replace(/[)\]\.,!?>]*$/, "")
  41.   );
  42. }
  43.  
  44. function detectPlatform(url) {
  45.   for (const [platform, re] of Object.entries(URL_PATTERNS)) {
  46.     if (re.test(url)) return platform;
  47.   }
  48.  
  49.   return null;
  50. }
  51.  
  52. function isAlreadyCommand(text) {
  53.   text = text?.toLowerCase()?.trim();
  54.  
  55.   if (!text) return false;
  56.  
  57.   return /(insta\s|ytv\s|yta\s|play\s|instagram\s|youtube\s)/i.test(
  58.     text
  59.   );
  60. }
  61.  
  62. function formatBytes(bytes) {
  63.   if (bytes === 0) return "0 B";
  64.  
  65.   const k = 1024;
  66.   const sizes = ["B", "KB", "MB", "GB"];
  67.  
  68.   const i = Math.floor(Math.log(bytes) / Math.log(k));
  69.  
  70.   return (
  71.     Math.round((bytes / Math.pow(k, i)) * 100) / 100 +
  72.     " " +
  73.     sizes[i]
  74.   );
  75. }
  76.  
  77. // ========================================
  78. // NUMBER REPLY HANDLER
  79. // ========================================
  80.  
  81. Module({ on: "text", fromMe }, async (message) => {
  82.   try {
  83.     const text = message.text?.trim();
  84.  
  85.     if (!/^\d+$/.test(text)) return;
  86.  
  87.     if (!message.reply_message) return;
  88.  
  89.     const repliedText =
  90.       message.reply_message?.text ||
  91.       message.reply_message?.message ||
  92.       "";
  93.  
  94.     if (!repliedText.includes("Select Video Quality")) return;
  95.  
  96.     const selection = parseInt(text);
  97.  
  98.     const data = YT_SELECTIONS[message.jid];
  99.  
  100.     if (!data) {
  101.       return await message.sendReply(
  102.         "_Session expired. Send YouTube link again._"
  103.       );
  104.     }
  105.  
  106.     const { url, info, qualities } = data;
  107.  
  108.     // audio
  109.     if (selection === qualities.length + 1) {
  110.       let audioPath;
  111.  
  112.       const msg = await message.sendReply(
  113.         "_Downloading audio..._"
  114.       );
  115.  
  116.       try {
  117.         const result = await downloadAudio(url);
  118.  
  119.         audioPath = result.path;
  120.  
  121.         const mp3Path = await convertM4aToMp3(audioPath, {
  122.           title: result?.title,
  123.           artist: result?.info?.channel?.name,
  124.           thumbnail: result?.info?.thumbnail,
  125.         });
  126.  
  127.         audioPath = mp3Path;
  128.  
  129.         const stream = fs.createReadStream(audioPath);
  130.  
  131.         await message.sendMessage(
  132.           { stream },
  133.           "audio",
  134.           {
  135.             mimetype: "audio/mpeg",
  136.             fileName: `${result.title}.mp3`,
  137.           }
  138.         );
  139.  
  140.         stream.destroy();
  141.  
  142.         await message.edit(
  143.           "_Download complete!_",
  144.           message.jid,
  145.           msg.key
  146.         );
  147.  
  148.         if (fs.existsSync(audioPath)) {
  149.           fs.unlinkSync(audioPath);
  150.         }
  151.       } catch (err) {
  152.         console.log(err);
  153.  
  154.         await message.edit(
  155.           "_Download failed!_",
  156.           message.jid,
  157.           msg.key
  158.         );
  159.  
  160.         if (audioPath && fs.existsSync(audioPath)) {
  161.           fs.unlinkSync(audioPath);
  162.         }
  163.       }
  164.  
  165.       return;
  166.     }
  167.  
  168.     const quality = qualities[selection - 1];
  169.  
  170.     if (!quality) {
  171.       return await message.sendReply("_Invalid selection!_");
  172.     }
  173.  
  174.     const msg = await message.sendReply(
  175.       `_Downloading ${quality} video..._`
  176.     );
  177.  
  178.     try {
  179.       const result = await downloadVideo(url, quality);
  180.  
  181.       await message.sendMessage(
  182.         { url: result.path || result.url },
  183.         "video",
  184.         {
  185.           caption: `_*${info.title}*_`,
  186.         }
  187.       );
  188.  
  189.       await message.edit(
  190.         "_Download complete!_",
  191.         message.jid,
  192.         msg.key
  193.       );
  194.  
  195.       if (result.path && fs.existsSync(result.path)) {
  196.         fs.unlinkSync(result.path);
  197.       }
  198.     } catch (err) {
  199.       console.log(err);
  200.  
  201.       await message.edit(
  202.         "_Download failed!_",
  203.         message.jid,
  204.         msg.key
  205.       );
  206.     }
  207.   } catch (err) {
  208.     console.log(err);
  209.   }
  210. });
  211.  
  212. // ========================================
  213. // MAIN AUTODL
  214. // ========================================
  215.  
  216. Module({ on: "text", fromMe }, async (message) => {
  217.   try {
  218.     if (message.fromBot) return;
  219.  
  220.     const chatJid = message.jid;
  221.     const isGroup = chatJid.includes("@g.us");
  222.  
  223.     const autodlEnabledForChat = (() => {
  224.       try {
  225.         const enabledList = config.AUTODL || "";
  226.  
  227.         const enabled = enabledList
  228.           .split(",")
  229.           .map((s) => s.trim())
  230.           .filter(Boolean);
  231.  
  232.         if (enabled.includes(chatJid)) return true;
  233.  
  234.         if (isGroup && config.AUTODL_ALL_GROUPS === "true")
  235.           return true;
  236.  
  237.         if (!isGroup && config.AUTODL_ALL_DMS === "true")
  238.           return true;
  239.  
  240.         return false;
  241.       } catch (e) {
  242.         return false;
  243.       }
  244.     })();
  245.  
  246.     if (!autodlEnabledForChat) return;
  247.  
  248.     let text = message.text || "";
  249.  
  250.     if (isAlreadyCommand(text)) return;
  251.  
  252.     const urls = getAllUrls(text);
  253.  
  254.     if (!urls.length) return;
  255.  
  256.     const platformGroups = {};
  257.  
  258.     for (const url of urls) {
  259.       const platform = detectPlatform(url);
  260.  
  261.       if (!platform) continue;
  262.  
  263.       if (!platformGroups[platform]) {
  264.         platformGroups[platform] = [];
  265.       }
  266.  
  267.       platformGroups[platform].push(url);
  268.     }
  269.  
  270.     if (!Object.keys(platformGroups).length) return;
  271.  
  272.     await message.react("⬇️");
  273.  
  274.     // ========================================
  275.     // YOUTUBE
  276.     // ========================================
  277.  
  278.     if (platformGroups["youtube"]) {
  279.       let url = platformGroups["youtube"][0];
  280.  
  281.       try {
  282.         if (url.includes("youtube.com/shorts/")) {
  283.           const shortId = url.match(
  284.             /youtube\.com\/shorts\/([A-Za-z0-9_-]+)/
  285.           )?.[1];
  286.  
  287.           if (shortId) {
  288.             url = `https://www.youtube.com/watch?v=${shortId}`;
  289.           }
  290.         }
  291.  
  292.         const info = await getVideoInfo(url);
  293.  
  294.         const videoFormats = info.formats
  295.           .filter((f) => f.type === "video" && f.quality)
  296.           .sort((a, b) => {
  297.             const getRes = (q) => {
  298.               const match = q.match(/(\d+)/);
  299.               return match ? parseInt(match[1]) : 0;
  300.             };
  301.  
  302.             return getRes(b.quality) - getRes(a.quality);
  303.           });
  304.  
  305.         const uniqueQualities = [
  306.           ...new Set(videoFormats.map((f) => f.quality)),
  307.         ];
  308.  
  309.         if (!uniqueQualities.length) {
  310.           await message.react("❌");
  311.           return;
  312.         }
  313.  
  314.         // store selections
  315.         YT_SELECTIONS[message.jid] = {
  316.           url,
  317.           info,
  318.           qualities: uniqueQualities,
  319.         };
  320.  
  321.         let qualityText = `_*${info.title}*_\n\n`;
  322.         qualityText += "_Select Video Quality:_\n\n";
  323.  
  324.         uniqueQualities.forEach((quality, index) => {
  325.           const format = videoFormats.find(
  326.             (f) => f.quality === quality
  327.           );
  328.  
  329.           let sizeInfo = "";
  330.  
  331.           if (format?.size) {
  332.             const match = format.size.match(
  333.               /([\d.]+)\s*(KB|MB|GB)/i
  334.             );
  335.  
  336.             if (match) {
  337.               const value = parseFloat(match[1]);
  338.               const unit = match[2].toUpperCase();
  339.  
  340.               let bytes = value;
  341.  
  342.               if (unit === "KB") bytes *= 1024;
  343.               if (unit === "MB") bytes *= 1024 * 1024;
  344.               if (unit === "GB") bytes *= 1024 * 1024 * 1024;
  345.  
  346.               sizeInfo = ` ~ _${formatBytes(bytes)}_`;
  347.             }
  348.           }
  349.  
  350.           qualityText += `*${index + 1}.* _${quality}_${sizeInfo}\n`;
  351.         });
  352.  
  353.         qualityText += `*${
  354.           uniqueQualities.length + 1
  355.         }.* _Audio MP3_\n`;
  356.  
  357.         qualityText += "\n_Reply with number to download_";
  358.  
  359.         await message.sendReply(qualityText);
  360.       } catch (err) {
  361.         console.log(err);
  362.         await message.react("❌");
  363.       }
  364.  
  365.       return;
  366.     }
  367.  
  368.     // ========================================
  369.     // INSTAGRAM
  370.     // ========================================
  371.  
  372.     if (platformGroups["instagram"]) {
  373.       try {
  374.         const allMediaUrls = [];
  375.  
  376.         const quotedMessage = message.reply_message
  377.           ? message.quoted
  378.           : message.data;
  379.  
  380.         for (const url of platformGroups["instagram"]) {
  381.           try {
  382.             const result = await downloadGram(url);
  383.  
  384.             if (result && result.length) {
  385.               allMediaUrls.push(...result);
  386.             }
  387.           } catch (err) {
  388.             console.log(err);
  389.           }
  390.         }
  391.  
  392.         if (!allMediaUrls.length) {
  393.           await message.react("❌");
  394.           return;
  395.         }
  396.  
  397.         if (allMediaUrls.length === 1) {
  398.           const media = allMediaUrls[0];
  399.  
  400.           await message.sendMessage(
  401.             { url: media },
  402.             /\.(jpg|jpeg|png|webp|heic)(\?|$)/i.test(media)
  403.               ? "image"
  404.               : "video",
  405.             {
  406.               quoted: quotedMessage,
  407.             }
  408.           );
  409.  
  410.           return;
  411.         }
  412.  
  413.         const albumObject = allMediaUrls.map((mediaUrl) => {
  414.           return /\.(jpg|jpeg|png|webp|heic)(\?|$)/i.test(
  415.             mediaUrl
  416.           )
  417.             ? { image: mediaUrl }
  418.             : { video: mediaUrl };
  419.         });
  420.  
  421.         await message.client.albumMessage(
  422.           message.jid,
  423.           albumObject,
  424.           message.data
  425.         );
  426.       } catch (err) {
  427.         console.log(err);
  428.         await message.react("❌");
  429.       }
  430.  
  431.       return;
  432.     }
  433.   } catch (err) {
  434.     console.log(err);
  435.   }
  436. });
  437.  
  438. // ========================================
  439. // AUTODL SETTINGS
  440. // ========================================
  441.  
  442. Module(
  443.   {
  444.     pattern: "autold ?(.*)",
  445.     fromMe: false,
  446.     desc: "Auto-download manager",
  447.   },
  448.   async (message, match) => {
  449.     const input = match[1]?.trim();
  450.  
  451.     const chatJid = message.jid;
  452.  
  453.     const readList = () => {
  454.       try {
  455.         const list = config.AUTODL || "";
  456.  
  457.         return list
  458.           .split(",")
  459.           .map((s) => s.trim())
  460.           .filter(Boolean);
  461.       } catch (e) {
  462.         return [];
  463.       }
  464.     };
  465.  
  466.     if (!input) {
  467.       return await message.sendReply(
  468.         `*_⬇️ AutoDownload Manager_*\n\n` +
  469.           `- \`${HANDLER_PREFIX}autodl on\`\n` +
  470.           `- \`${HANDLER_PREFIX}autodl off\`\n` +
  471.           `- \`${HANDLER_PREFIX}autodl status\``
  472.       );
  473.     }
  474.  
  475.     const parts = input.split(" ");
  476.  
  477.     const cmd = parts[0]?.toLowerCase();
  478.     const target = parts[1]?.toLowerCase();
  479.  
  480.     if (cmd === "on") {
  481.       if (target === "groups") {
  482.         await setVar("AUTODL_ALL_GROUPS", "true");
  483.  
  484.         return await message.sendReply(
  485.           "_AutoDL enabled for all groups ✅_"
  486.         );
  487.       }
  488.  
  489.       if (target === "dms") {
  490.         await setVar("AUTODL_ALL_DMS", "true");
  491.  
  492.         return await message.sendReply(
  493.           "_AutoDL enabled for all DMs ✅_"
  494.         );
  495.       }
  496.  
  497.       const enabledList = readList();
  498.  
  499.       if (!enabledList.includes(chatJid)) {
  500.         enabledList.push(chatJid);
  501.       }
  502.  
  503.       await setVar("AUTODL", enabledList.join(","));
  504.  
  505.       return await message.sendReply(
  506.         "_AutoDL enabled in this chat ✅_"
  507.       );
  508.     }
  509.  
  510.     if (cmd === "off") {
  511.       if (target === "groups") {
  512.         await setVar("AUTODL_ALL_GROUPS", "false");
  513.  
  514.         return await message.sendReply(
  515.           "_AutoDL disabled for all groups ❌_"
  516.         );
  517.       }
  518.  
  519.       if (target === "dms") {
  520.         await setVar("AUTODL_ALL_DMS", "false");
  521.  
  522.         return await message.sendReply(
  523.           "_AutoDL disabled for all DMs ❌_"
  524.         );
  525.       }
  526.  
  527.       const enabledList = readList().filter(
  528.         (x) => x !== chatJid
  529.       );
  530.  
  531.       await setVar("AUTODL", enabledList.join(","));
  532.  
  533.       return await message.sendReply(
  534.         "_AutoDL disabled in this chat ❌_"
  535.       );
  536.     }
  537.  
  538.     if (cmd === "status") {
  539.       const enabledList = readList();
  540.  
  541.       return await message.sendReply(
  542.         `*_AutoDL Status_*\n\n` +
  543.           `• _Enabled chats:_ ${
  544.             enabledList.length
  545.               ? enabledList.join(", ")
  546.               : "None"
  547.           }`
  548.       );
  549.     }
  550.  
  551.     return await message.sendReply(
  552.       `Unknown option: ${cmd}`
  553.     );
  554.   }
  555. );
Add Comment
Please, Sign In to add comment