2023-09-16 23:38:07 +06:00
|
|
|
import HLS from 'hls-parser';
|
2024-04-29 21:36:35 +06:00
|
|
|
|
2024-05-16 20:57:48 +06:00
|
|
|
import { env } from "../../config.js";
|
2023-10-12 23:14:54 +06:00
|
|
|
import { cleanString } from '../../sub/utils.js';
|
2023-09-16 23:38:07 +06:00
|
|
|
|
2024-04-29 21:36:35 +06:00
|
|
|
async function requestJSON(url) {
|
|
|
|
try {
|
|
|
|
const r = await fetch(url);
|
|
|
|
return await r.json();
|
|
|
|
} catch {}
|
|
|
|
}
|
|
|
|
|
2023-09-16 23:38:07 +06:00
|
|
|
export default async function(obj) {
|
2024-04-29 21:36:35 +06:00
|
|
|
if (obj.yappyId) {
|
2024-05-29 13:02:05 +06:00
|
|
|
const yappy = await requestJSON(
|
2024-04-29 21:36:35 +06:00
|
|
|
`https://rutube.ru/pangolin/api/web/yappy/yappypage/?client=wdp&videoId=${obj.yappyId}&page=1&page_size=15`
|
|
|
|
)
|
2024-05-29 13:02:05 +06:00
|
|
|
const yappyURL = yappy?.results?.find(r => r.id === obj.yappyId)?.link;
|
2024-04-29 21:36:35 +06:00
|
|
|
if (!yappyURL) return { error: 'ErrorEmptyDownload' };
|
|
|
|
|
|
|
|
return {
|
|
|
|
urls: yappyURL,
|
|
|
|
filename: `rutube_yappy_${obj.yappyId}.mp4`,
|
|
|
|
audioFilename: `rutube_yappy_${obj.yappyId}_audio`
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-05-29 13:02:05 +06:00
|
|
|
const quality = obj.quality === "max" ? "9000" : obj.quality;
|
2024-04-29 21:36:35 +06:00
|
|
|
|
2024-05-29 13:02:05 +06:00
|
|
|
const requestURL = new URL(`https://rutube.ru/api/play/options/${obj.id}/?no_404=true&referer&pver=v2`);
|
|
|
|
if (obj.key) requestURL.searchParams.set('p', obj.key);
|
|
|
|
|
|
|
|
const play = await requestJSON(requestURL);
|
2023-09-16 23:38:07 +06:00
|
|
|
if (!play) return { error: 'ErrorCouldntFetch' };
|
|
|
|
|
2024-04-29 21:36:35 +06:00
|
|
|
if (play.detail || !play.video_balancer) return { error: 'ErrorEmptyDownload' };
|
|
|
|
if (play.live_streams?.hls) return { error: 'ErrorLiveVideo' };
|
|
|
|
|
2024-05-16 20:57:48 +06:00
|
|
|
if (play.duration > env.durationLimit * 1000)
|
|
|
|
return { error: ['ErrorLengthLimit', env.durationLimit / 60] };
|
2024-04-29 21:36:35 +06:00
|
|
|
|
|
|
|
let m3u8 = await fetch(play.video_balancer.m3u8)
|
|
|
|
.then(r => r.text())
|
|
|
|
.catch(() => {});
|
2023-09-16 23:38:07 +06:00
|
|
|
|
|
|
|
if (!m3u8) return { error: 'ErrorCouldntFetch' };
|
|
|
|
|
|
|
|
m3u8 = HLS.parse(m3u8).variants.sort((a, b) => Number(b.bandwidth) - Number(a.bandwidth));
|
|
|
|
|
|
|
|
let bestQuality = m3u8[0];
|
|
|
|
if (Number(quality) < bestQuality.resolution.height) {
|
2024-05-16 21:28:42 +06:00
|
|
|
bestQuality = m3u8.find((i) => (Number(quality) === i.resolution.height));
|
2023-09-16 23:38:07 +06:00
|
|
|
}
|
2024-04-29 21:36:35 +06:00
|
|
|
|
2024-05-29 13:02:05 +06:00
|
|
|
const fileMetadata = {
|
2023-10-15 15:11:39 +06:00
|
|
|
title: cleanString(play.title.trim()),
|
|
|
|
artist: cleanString(play.author.name.trim()),
|
2023-10-12 23:14:54 +06:00
|
|
|
}
|
2023-09-16 23:38:07 +06:00
|
|
|
|
|
|
|
return {
|
|
|
|
urls: bestQuality.uri,
|
|
|
|
isM3U8: true,
|
2023-10-12 23:14:54 +06:00
|
|
|
filenameAttributes: {
|
|
|
|
service: "rutube",
|
2024-04-29 21:36:35 +06:00
|
|
|
id: obj.id,
|
2023-10-12 23:14:54 +06:00
|
|
|
title: fileMetadata.title,
|
|
|
|
author: fileMetadata.artist,
|
|
|
|
resolution: `${bestQuality.resolution.width}x${bestQuality.resolution.height}`,
|
|
|
|
qualityLabel: `${bestQuality.resolution.height}p`,
|
|
|
|
extension: "mp4"
|
|
|
|
},
|
|
|
|
fileMetadata: fileMetadata
|
2023-09-16 23:38:07 +06:00
|
|
|
}
|
|
|
|
}
|