تخطَّ إلى المحتوى
ARAB CODEمجتمع المطورين العرب

ytmp3

javascriptv1MITنُشر ٢ أغسطس ٢٠٢٦· ♥ 0 · ⬇ 2 · 💬 0

تحميل صوت من يوتيوب بصغه ريكورد علشان عادي استعماله في القنوات

/**
 * 🎵 YouTube Audio Downloader (PTT/Record Mode) — نيزوكو ريكورد
 * ⏤͟͞ू⃪𝑵𝜩𝒁𝑼𝑲̤͝𝜣͓ۧٛ͢ ͝ 𝑩𝜣𝑻🎀
 * يقوم بتحميل الصوت من يوتيوب وتحويله ديناميكياً إلى صيغة opus ليعمل كـ ريكورد أزرق
 */

import crypto from "crypto"
import axios from "axios"
import fs from "fs"
import path from "path"
import ffmpeg from "fluent-ffmpeg"

// --- إعدادات وثوابت البث والقناة (Newsletter) للوهم البرمجي ---
const newsletterJid  = '120363407598531220@newsletter';
const newsletterName = '.𓏲⋆˙𝑵𝜩𝒁𝑼𝑲̤͝𝜣͓ۧٛ͢ ͝ 𝑩𝜣𝑻🎀';

class SaveTube {
  constructor() {
    this.ky = 'C5D58EF67A7584E4A29F6C35BBC4EB12'
    this.m = /^((?:https?:)?\/\/)?((?:www|m|music)\.)?(?:youtube\.com|youtu\.be)\/(?:watch\?v=)?(?:embed\/)?(?:v\/)?(?:shorts\/)?([a-zA-Z0-9_-]{11})/
    this.is = axios.create({
      headers: {
        'content-type': 'application/json',
        'origin': 'https://yt.savetube.me',
        'user-agent': 'Mozilla/5.0 (Android 15; Mobile)'
      }
    })
  }

  async decrypt(enc) {
    const buf = Buffer.from(enc, 'base64')
    const key = Buffer.from(this.ky, 'hex')
    const iv = buf.slice(0, 16)
    const data = buf.slice(16)

    const decipher = crypto.createDecipheriv('aes-128-cbc', key, iv)
    const decrypted = Buffer.concat([
      decipher.update(data),
      decipher.final()
    ])

    return JSON.parse(decrypted.toString())
  }

  async getCdn() {
    const res = await this.is.get("https://media.savetube.vip/api/random-cdn")
    return { status: true, data: res.data.cdn }
  }

  async download(url) {
    const id = url.match(this.m)?.[3]
    if (!id) throw "رابط يوتيوب غير صالح"

    const cdn = await this.getCdn()
    const info = await this.is.post(`https://${cdn.data}/v2/info`, {
      url: `https://www.youtube.com/watch?v=${id}`
    })

    const dec = await this.decrypt(info.data.data)

    const dl = await this.is.post(`https://${cdn.data}/download`, {
      id,
      downloadType: 'audio',
      quality: '128',
      key: dec.key
    })

    return {
      title: dec.title,
      duration: dec.duration,
      thumb: dec.thumbnail,
      download: dl.data.data.downloadUrl
    }
  }
}

/* ================= المعالج ================= */

let handler = async (m, { conn, args, usedPrefix, command }) => {
  if (!args[0]) {
    return m.reply(
      `❌ الاستخدام:\n${usedPrefix + command} <رابط_يوتيوب>\n\nمثال:\n${usedPrefix + command} https://youtu.be/U2vyax9Uufc`
    )
  }

  const url = args[0]
  const st = new SaveTube()

  // 1️⃣ كائن الـ contextInfo للرسائل النصية التوضيحية
  const infoContextInfo = {
    mentionedJid: [m.sender],
    isForwarded: true,
    forwardingScore: 999,
    forwardedNewsletterMessageInfo: {
      newsletterJid: newsletterJid,
      newsletterName: newsletterName,
      serverMessageId: -1
    },
    externalAdReply: {
      title: '.𓏲⋆˙𝑵𝜩𝒁𝑼𝑲̤͝𝜣͓ۧٛ͢ ͝ 𝑩𝜣𝑻🎀',
      body: 'تحميل يوتيوب وتحويله لـ ريكورد 🎧',
      thumbnail: global.icons || '', 
      sourceUrl: 'https://whatsapp.com/channel/0029Vb7AkG84inotOc8BXE1K',
      mediaType: 1,
      renderLargerThumbnail: false
    }
  };

  // 2️⃣ كائن الـ contextInfo المخصص للريكورد الصوتي (بدون إعلانات ومربعات روابط)
  const audioContextInfo = {
    mentionedJid: [m.sender],
    isForwarded: true,
    forwardingScore: 999,
    forwardedNewsletterMessageInfo: {
      newsletterJid: newsletterJid,
      newsletterName: newsletterName,
      serverMessageId: -1
    }
  };

  // مسارات مؤقتة لمعالجة الملف بداخل السيرفر وتفادي استهلاك الرام
  const tmpInput = path.join(`./tmp_${Date.now()}.mp3`);
  const tmpOutput = path.join(`./tmp_${Date.now()}.opus`);

  try {
    await conn.reply(
      m.chat,
      `*⏳ جَــأࢪي م࣬ـــ؏ٚـأݪـجَۿ أݪــࢪأبٚطَ وتنزيل المقطع الصوتي...*`,
      m,
      { contextInfo: infoContextInfo, quoted: m }
    )

    const res = await st.download(url)

    // تحميل ملف الـ MP3 الأصلي وحفظه مؤقتاً في السيرفر
    const audioResponse = await axios.get(res.download, { responseType: 'arraybuffer' })
    fs.writeFileSync(tmpInput, Buffer.from(audioResponse.data, 'binary'))

    // تحديث الحالة إلى تسجيل صوتي لإعطاء المظهر الحقيقي الحركي
    await conn.sendPresenceUpdate('recording', m.chat);

    // ⚙️ عملية التحويل البرمجية إلى ترميز opus المتوافق بالملي مع الـ PTT
    await new Promise((resolve, reject) => {
      ffmpeg(tmpInput)
        .toFormat('opus')
        .audioChannels(1) // تحويله لأحادية لتطابق تسجيل الواتساب القياسي
        .audioFrequency(48000)
        .on('end', () => resolve())
        .on('error', (err) => reject(err))
        .save(tmpOutput);
    });

    // قراءة ملف الـ opus الناتج
    const opusBuffer = fs.readFileSync(tmpOutput);

    // إرسال المقطع على هيئة ريكورد رسمي أزرق
    await conn.sendMessage(
      m.chat,
      {
        audio: opusBuffer,
        mimetype: 'audio/ogg; codecs=opus', // تفعيل الترميز المعتمد
        ptt: true, // تفعيل ميزة الريكورد الحقيقي الحركي
        fileName: `${res.title}.opus`,
        contextInfo: audioContextInfo // خالي من الـ externalAdReply لحذف المربع الأسود وعلامة الرابط
      },
      { quoted: m }
    )

    // رسالة إتمام العملية بنجاح بالثيم الخاص بك
    let successText = `✔ *تـم الـتـحـمـيـل ✨ بـنـجـاح!* \n\n` +
                      `📌 *العنوان:* ${res.title}\n` +
                      `⏱ *المدة:* ${res.duration}\n` +
                      `🎀 *بواسطة:* ${newsletterName}`;

    await conn.reply(m.chat, successText, m, { contextInfo: infoContextInfo, quoted: m });

  } catch (e) {
    console.error(e)
    await conn.reply(
      m.chat,
      `❌ *حدث خطأ أثناء معالجة وتحويل الصوت:*\n${e.message || e}`,
      m,
      { contextInfo: infoContextInfo, quoted: m }
    )
  } finally {
    // تنظيف السيرفر وحذف الملفات المؤقتة تلقائياً لعدم ملء مساحة التخزين (Storage)
    if (fs.existsSync(tmpInput)) fs.unlinkSync(tmpInput);
    if (fs.existsSync(tmpOutput)) fs.unlinkSync(tmpOutput);
  }
}

handler.help = ['صوت']
handler.command = ['صوت', 'ytmp3', 'mp3']
handler.tags = ['download']

export default handler

التعليقات (0)

سجّل الدخول للتعليق.