@aidarkezio/main-func
Version:
📦 It has my funcs
380 lines (364 loc) • 11.4 kB
text/typescript
import cheerio from 'cheerio'
import got from 'got'
import { ScraperError } from '../utils.js'
import {
YoutubeDownloader,
YoutubeVideoOrAudio,
YoutubeDownloaderV3,
YoutubeVideoOrAudioV3,
YoutubeDownloaderArgsSchema,
YoutubeDonwloaderSchema,
YoutubeDownloaderV2ArgsSchema,
YoutubeDownloaderV3ArgsSchema,
YoutubeDonwloaderV3Schema,
Spmp3Converter
} from './types.js'
import { sizeFormatter } from 'human-readable'
const toFormat = sizeFormatter({
std: 'JEDEC', // 'SI' (default) | 'IEC' | 'JEDEC'
decimalPlaces: 2,
keepTrailingZeroes: false,
render: (literal, symbol) => `${literal} ${symbol}B`
})
interface IresFetch {
status: string;
result: string;
}
// TODO: Fix "Refresh to try again. (code 02)", example link have that error: https://youtu.be/JFC3tYYW_UI
// https://github.com/BochilGaming/games-wabot/blob/main/lib/y2mate.js
const servers = ['en163', 'id90', 'en172']
export async function youtubedl (
url: string,
server: string = 'en163'
): Promise<YoutubeDownloader> {
YoutubeDownloaderArgsSchema.parse(arguments)
if (!servers.includes(server)) server = servers[0]
const params: { url: string; q_auto: number; ajax: number } = {
url: url,
q_auto: 0,
ajax: 1
}
const json: IresFetch = await got
.post(`https://www.y2mate.com/mates/${server}/analyze/ajax`, {
headers: {
'content-type': 'application/x-www-form-urlencoded; charset=UTF-8',
cookie:
'_ga=GA1.2.1405332118.1641699259; _gid=GA1.2.70284915.1642387108; _gat_gtag_UA_84863187_23=1',
origin: 'https://www.y2mate.com'
},
form: params
})
.json()
const $ = cheerio.load(json.result)
const id = (/var k__id = "(.*?)"/.exec($.html()) || ['', ''])[1]
const v_id = (/var k_data_vid = "(.*?)"/.exec($.html()) || ['', ''])[1]
const thumbnail = $('.video-thumbnail > img').attr('src') as string
const title = $('div.caption > b').text().trim()
const video: YoutubeVideoOrAudio = {}
const audio: YoutubeVideoOrAudio = {}
$('#mp4 > table > tbody > tr').each(function () {
const el = $(this).find('td')
const _quality = el.eq(0).find('a').text()
const quality = _quality.split('(')?.[0]?.trim()?.toLowerCase()
const fileSizeH = el.eq(1).text()
const fileSize = parseFloat(fileSizeH) * (/MB$/.test(fileSizeH) ? 1000 : 1)
if (!/\.3gp/i.test(_quality)) {
video[quality] = {
quality,
fileSizeH,
fileSize: isNaN(fileSize) ? 0 : fileSize,
download: convert.bind(
null,
id,
v_id,
'mp4',
quality.replace(/p/i, '')
)
}
}
})
$('#mp3 > table > tbody > tr').each(function () {
const el = $(this).find('td')
const _quality = el.eq(0).find('a').text()
const quality = _quality
.split('(')?.[1]
?.replace(')', '')
?.trim()
?.toLowerCase()
const fileSizeH = el.eq(1).text()
const fileSize = parseFloat(fileSizeH) * (/MB$/.test(fileSizeH) ? 1000 : 1)
audio[quality] = {
quality,
fileSizeH,
fileSize: isNaN(fileSize) ? 0 : fileSize,
download: convert.bind(
null,
id,
v_id,
'mp3',
quality.replace(/kbps/i, '')
)
}
})
const res = {
id,
v_id,
thumbnail,
title,
video,
audio
}
return YoutubeDonwloaderSchema.parse(res)
}
interface IresLinks {
f: string;
k: string;
key: string;
q: string;
selected?: string;
size: string;
}
export async function youtubedlv2 (url: string): Promise<YoutubeDownloader> {
YoutubeDownloaderV2ArgsSchema.parse(arguments)
const html = await got('https://yt5s.com/en32').text()
const urlAjax = (/k_url_search="(.*?)"/.exec(html) || ['', ''])[1]
const urlConvert = (/k_url_convert="(.*?)"/.exec(html) || ['', ''])[1]
const params: { [Key: string]: string } = {
q: url,
vt: 'home'
}
const json: {
vid: string;
title: string;
a: string;
token: string;
timeExpires: string;
fn: string;
links: {
[Key: string]: {
[Key: string]: IresLinks;
};
};
} = await got(urlAjax, {
method: 'POST',
headers: {
'content-type': 'application/x-www-form-urlencoded; charset=UTF-8',
cookie:
'__cflb=04dToSoFRg9oqH9pYF2En9gKJK4fe8D9TcYtUD6tYu; _ga=GA1.2.1350132744.1641709803; _gid=GA1.2.1492233267.1641709803; _gat_gtag_UA_122831834_4=1',
origin: 'https://yt5s.com',
'user-agent':
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36'
},
searchParams: new URLSearchParams(Object.entries(params) as [string, string][])
}).json()
const video: YoutubeVideoOrAudio = {}
Object.values(json.links.mp4).forEach(({ k, size }: IresLinks) => {
video[k] = {
quality: k,
fileSizeH: size,
fileSize: parseFloat(size) * (/MB$/.test(size) ? 1000 : 1),
// @ts-ignore
download: convertv2.bind(
null,
urlConvert,
json.vid,
'mp4',
k,
json.token,
parseInt(json.timeExpires),
json.fn
)
}
})
const audio: YoutubeVideoOrAudio = {}
Object.values(json.links.mp3).forEach(({ key, size }: IresLinks) => {
audio[key] = {
quality: key,
fileSizeH: size,
fileSize: parseFloat(size) * (/MB$/.test(size) ? 1000 : 1),
// @ts-ignore
download: convertv2.bind(
null,
urlConvert,
json.vid,
'mp3',
key.replace(/kbps/i, ''),
json.token,
parseInt(json.timeExpires),
json.fn
)
}
})
const res = {
id: json.vid,
title: json.title,
thumbnail: `https://i.ytimg.com/vi/${json.vid}/0.jpg`,
video,
audio
}
return YoutubeDonwloaderSchema.parse(res)
}
export async function youtubedlv3 (Url: string): Promise<YoutubeDownloaderV3> {
YoutubeDownloaderV3ArgsSchema.parse(arguments)
const payload = {
url: Url
}
const { id, meta, thumb, url }: Spmp3Converter = await got
.post('https://api.onlinevideoconverter.pro/api/convert', {
headers: {
accept: 'application/json, text/plain, */*',
'accept-encoding': 'gzip, deflate, br',
'accept-language': 'en-US,en;q=0.9',
'content-type': 'application/json',
origin: 'https://onlinevideoconverter.pro',
referer: 'https://onlinevideoconverter.pro/',
'user-agent':
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36'
},
body: JSON.stringify(payload)
}).json()
const video: YoutubeVideoOrAudioV3 = {}; const audioArray: YoutubeVideoOrAudioV3 = {}
url.forEach(({ url, info_url, attr, quality, audio, no_audio, filesize, ext }) => {
if (!no_audio && ext === 'mp4') {
video[quality] = {
quality,
fileSizeH: (filesize && toFormat(filesize)) || undefined,
fileSize: filesize,
download: async () => (url || info_url)
}
}
if (audio && !no_audio) {
audioArray[quality] = {
quality,
fileSizeH: (filesize && toFormat(filesize)) || undefined,
fileSize: filesize,
download: async () => (url || info_url)
}
}
})
const res = {
id,
title: meta.title,
thumbnail: thumb,
video,
audio: audioArray
}
return YoutubeDonwloaderV3Schema.parse(res)
}
async function convert (
_id: string,
v_id: string,
ftype: string,
fquality: string
): Promise<string> {
const params: { [Key: string]: string | number; fquality: string } = {
type: 'youtube',
_id,
v_id,
ajax: '1',
token: '',
ftype,
fquality
}
const json: IresFetch = await got('https://www.y2mate.com/mates/convert', {
method: 'POST',
headers: {
'content-type': 'application/x-www-form-urlencoded; charset=UTF-8',
cookie:
'_ga=GA1.2.1405332118.1641699259; _gid=GA1.2.1117783105.1641699259; MarketGidStorage=%7B%220%22%3A%7B%7D%2C%22C702514%22%3A%7B%22page%22%3A2%2C%22time%22%3A1641701743540%7D%7D; _PN_SBSCRBR_FALLBACK_DENIED=1641701744162',
'user-agent':
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36'
},
form: params
}).json()
const $ = cheerio.load(json.result)
const link = $('a[href]').attr('href')
if (link === 'https://app.y2mate.com/download') throw new ScraperError(JSON.stringify({ link, json: json }, null, 2))
return link as string
}
function convertv2 (
url: string,
v_id: string,
ftype: string,
fquality: string,
token: string,
timeExpire: number,
fname: string
): Promise<string> {
return new Promise<string>(async (resolve, reject) => {
const params: { [Key: string]: string | number } = {
v_id,
ftype,
fquality,
token,
timeExpire,
client: 'yt5s.com'
}
const resServer: { c_server?: string; d_url?: string; c_status: string } =
await got(url, {
method: 'POST',
headers: {
'content-type': 'application/x-www-form-urlencoded; charset=UTF-8',
origin: 'https://yt5s.com',
referer: 'https://yt5s.com/',
'user-agent':
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36',
'X-Requested-Key': 'de0cfuirtgf67a'
},
form: params
}).json()
const server = resServer.c_server
if (!server && ftype === 'mp3') return resolve(server || resServer.d_url || '')
const payload: { [Key: string]: string | number } = {
v_id,
ftype,
fquality,
fname,
token,
timeExpire
}
const results: {
status: string;
jobId?: string;
statusCode: number;
result: string;
} = await got(`${server}/api/json/convert`, {
method: 'POST',
form: payload
}).json()
if (results.statusCode === 200) return resolve(results.result)
else if (results.statusCode === 300) {
try {
// @ts-ignore
const WebSocket = (await import('ws')).default
const Url = new URL(server as string)
const WSUrl = `${/https/i.test(Url.protocol) ? 'wss:' : 'ws:'}//${Url.host
}/sub/${results.jobId}?fname=yt5s.com`
const ws = new WebSocket(WSUrl, undefined, {
headers: {
'Accept-Encoding': 'gzip, deflate, br',
Host: Url.host,
Origin: 'https://yt5s.com',
'Sec-WebSocket-Extensions':
'permessage-deflate; client_max_window_bits',
'User-Agent':
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36'
}
})
ws.on('message', function incoming (message: Buffer) {
const msg: { action: string; url: string } = JSON.parse(
message.toString()
)
if (msg.action === 'success') {
try { ws.close() } catch (e) { console.error(e) }
ws.removeAllListeners('message')
return resolve(msg.url)
} else if (msg.action === 'error') return reject(msg)
})
} catch (e) {
console.error(e)
return reject(e)
}
} else return reject(results)
})
}