wolfyflutter

43. ytmp3.lat [downloader] [audio] [video] [ytmp3.lat]

Aug 3rd, 2025 (edited)
371
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
JavaScript 5.97 KB | Source Code | 0 0
  1. /*
  2.   base    : https://ytmp3.lat/
  3.   note    : bisa download audio/video maks 60 menit
  4.             gw ada skrep yg bs pick resolusi video
  5.             dan bitrate audio.. tapi rasis IP.. kadang 403
  6.             coba aja di sini : https://pastebin.com/XCkhteBn
  7.             kalau worek syukur, kalau gk worek jangan komplen ya owkowkw
  8.   update  : 4 agustus 2025
  9.   node    : v24.4.0
  10.   by      : wolep
  11. */
  12.  
  13. const yt = {
  14.     _tools: {
  15.         genRandomHex: (length = 32) => {
  16.             const charSet = '0123456789abcdef'
  17.             return Array.from({ length }, _ => charSet.charAt(Math.floor(Math.random() * charSet.length))).join('')
  18.         },
  19.         enc1: (url) => url.split("").map(v => v.charCodeAt()).reverse().join(),
  20.         enc2: (url) => url.split("").map(v => String.fromCharCode(v.charCodeAt() ^ 1)).join(''),
  21.         validateString: (description, variable) => { if (typeof (variable) !== "string" || variable?.trim()?.length === 0) throw Error(`${description} harus string dan gak boleh kosong!`) },
  22.         mintaJson: async function (description, url, fetchOptions) {
  23.             try {
  24.                 const response = await fetch(url, fetchOptions)
  25.                 if (!response.ok) throw Error(`${response.status} ${response.statusText} ${(await response.text() || `(respond body kosong)`).substring(0, 150)}...`)
  26.                 const json = await response.json()
  27.                 return json
  28.             } catch (error) {
  29.                 throw Error(`gagal minta json: ${description}\nerror: ${error.message}`)
  30.             }
  31.         },
  32.     },
  33.     get baseHeaders() {
  34.         return {
  35.             'content-type': 'application/json',
  36.             'Referer': 'https://ytmp3.lat/',
  37.             'accept-encoding': 'gzip, deflate, br, zstd',
  38.             'user-agent' : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0'
  39.         }
  40.     },
  41.  
  42.     init: async function (ytUrl, format = 'mp3') {
  43.         // validate string
  44.         this._tools.validateString(`url youtube`, ytUrl)
  45.  
  46.         // validate format
  47.         const formatList = {
  48.             'mp3' : 0,
  49.             'mp4' : 1
  50.         }
  51.         const selectedFormat = formatList?.[format]
  52.         if (selectedFormat === undefined) throw Error (`invalid format, format tersedia: ${Object.keys(formatList).join(', ')}`)
  53.  
  54.         const encUrl = this._tools.enc1(ytUrl)
  55.         const encPayload = this._tools.enc2(ytUrl)
  56.         const hash1 = this._tools.genRandomHex()
  57.         const hash2 = this._tools.genRandomHex()
  58.  
  59.         const url = `https://ytmp3.lat/${hash1}/init/${encUrl}/${hash2}/`
  60.         const headers = {
  61.             ... this.baseHeaders
  62.         }
  63.         const body = JSON.stringify({
  64.             "data": encPayload,
  65.             "format": selectedFormat + "", //0=audio, 1=video
  66.         })
  67.         const json = await this._tools.mintaJson(`init`, url, { headers, body, method: 'post' })
  68.         json.format = format
  69.         console.log(`init`)
  70.         return json
  71.     },
  72.  
  73.     cekStatus: async function (initObject) {
  74.         // redirect
  75.         let wolep = initObject
  76.         let fetchCount = 1
  77.         const MAX_FETCH_ATTEMPT = 60
  78.  
  79.         if (wolep?.s == 'C') {
  80.             console.log('got directed')
  81.             const url = this.createDownloadUrl(wolep)
  82.             const title = initObject?.t || `(no name)`
  83.             const format = initObject?.format
  84.             const result = {url, title, format}
  85.             return result
  86.         } else {
  87.             const hash1 = this._tools.genRandomHex()
  88.             const hash2 = this._tools.genRandomHex()
  89.             const { i } = wolep
  90.             const headers = { ... this.baseHeaders }
  91.             const url = `https://ytmp3.lat/${hash1}/status/${i}/${hash2}/`
  92.             const body = JSON.stringify({
  93.                 data: i
  94.             })
  95.  
  96.             do {
  97.                 wolep = await this._tools.mintaJson(`status`, url, { headers, body, 'method': 'post' })
  98.                 const print = `checking ke ${fetchCount} | ${wolep?.t || `(no name)`}`
  99.                 console.log(print)
  100.  
  101.                 if (wolep.le) throw Error(`The video is longer than 30 minutes. Please select another video.`)
  102.                 if (wolep.e) throw Error(`There was an error in converting video. Please try again.`)
  103.                 if (wolep.i == 'invalid') throw Error(`Please enter a correct YouTube video URL.`)
  104.                 if (wolep.s == 'C') {
  105.                     const url = this.createDownloadUrl(wolep)
  106.                     const title = wolep.t || `(no name)`
  107.                     const format = initObject.format
  108.                     const result = {url, title, format}
  109.                     return result
  110.                 }
  111.                 await new Promise(re => setTimeout(re, 3000))
  112.                 fetchCount++
  113.  
  114.             } while (wolep?.s == 'P' && fetchCount < MAX_FETCH_ATTEMPT)
  115.             throw Error(`mencapai maksimal batas checking ${MAX_FETCH_ATTEMPT}`)
  116.         }
  117.  
  118.     },
  119.  
  120.     createDownloadUrl: function (cekStatusObject) {
  121.         const hash1 = this._tools.genRandomHex()
  122.         const hash2 = this._tools.genRandomHex()
  123.         const encTaskId = this._tools.enc2(cekStatusObject.i)
  124.         const url = `https://ytmp3.lat/${hash1}/download/${encTaskId}/${hash2}/`
  125.         return url
  126.  
  127.     },
  128.  
  129.     download: async function (youtubeUrl, format = 'mp3') {
  130.         const initObject = await this.init(youtubeUrl, format)
  131.         const result = await this.cekStatus(initObject)
  132.         return result
  133.     }
  134. }
  135.  
  136. // cara pakai
  137. const url = 'https://www.youtube.com/watch?v=HyHNuVaZJ-k&list=RDHyHNuVaZJ-k&start_radio=1'
  138. yt.download(url, "mp3")
  139.     .then(console.log)
  140.     .catch(console.log)
  141.  
  142. /* atau
  143. yt.download(url) -> audio
  144. yt.download(url, 'mp3') -> audio
  145. yt.download(url, 'mp4') -> video
  146.  
  147. /* output
  148. {
  149.   url: 'https://ytmp3.lat/8f34385a9cc89c4fb9321788......d41709b89fa038561bdf8/',
  150.   title: 'Gorillaz - Feel Good Inc. (Official Video)',
  151.   format: 'mp3'
  152. }
  153. */
  154.  
Advertisement
Add Comment
Please, Sign In to add comment