notmebotz-tools
Version:
Sebuah Tools yang berfungsi untuk mendownload Video atau Foto dari media sosial, serta sebagai tools yang berguna untuk aplikasi kamu seperti untuk BOT
410 lines (356 loc) • 14.2 kB
JavaScript
const crypto = require("crypto");
function getYouTubeVideoId(url) {
const regex = /(?:https?:\/\/)?(?:www\.)?(?:youtube\.com\/(?:[^\/\n\s]+\/\S+\/|v\/|embed\/|user\/[^\/\n\s]+\/)?(?:watch\?v=|v%3D|embed%2F|video%2F)?|youtu\.be\/|youtube\.com\/watch\?v=|youtube\.com\/embed\/|youtube\.com\/v\/|youtube\.com\/shorts\/|youtube\.com\/playlist\?list=)([a-zA-Z0-9_-]{11})/;
const match = url.match(regex);
return match ? match[1] : null;
}
const savetube = {
api: {
base: "https://media.savetube.me/api",
cdn: "/random-cdn",
info: "/v2/info",
download: "/download"
},
headers: {
'accept': '*/*',
'content-type': 'application/json',
'origin': 'https://yt.savetube.me',
'referer': 'https://yt.savetube.me/',
'user-agent': 'Postify/1.0.0'
},
formats: ['144', '240', '360', '480', '720', '1080', 'mp3'],
crypto: {
hexToBuffer: (hexString) => {
const matches = hexString.match(/.{1,2}/g);
return new Uint8Array(matches.map(byte => parseInt(byte, 16)));
},
decrypt: async (enc) => {
try {
const secretKey = 'C5D58EF67A7584E4A29F6C35BBC4EB12';
const data = new Uint8Array(atob(enc).split('').map(c => c.charCodeAt(0)));
const iv = data.slice(0, 16);
const content = data.slice(16);
const key = savetube.crypto.hexToBuffer(secretKey);
const cryptoKey = await crypto.subtle.importKey(
'raw',
key,
{ name: 'AES-CBC' },
false,
['decrypt']
);
const decrypted = await crypto.subtle.decrypt(
{ name: 'AES-CBC', iv: iv },
cryptoKey,
content
);
const decryptedText = new TextDecoder().decode(decrypted);
return JSON.parse(decryptedText);
} catch (error) {
throw new Error(`Decryption failed: ${error.message}`);
}
}
},
isUrl: (str) => {
try {
new URL(str);
return true;
} catch (_) {
return false;
}
},
youtube: (url) => {
if (!url) return null;
const patterns = [
/youtube\.com\/watch\?v=([a-zA-Z0-9_-]{11})/,
/youtube\.com\/embed\/([a-zA-Z0-9_-]{11})/,
/youtube\.com\/v\/([a-zA-Z0-9_-]{11})/,
/youtube\.com\/shorts\/([a-zA-Z0-9_-]{11})/,
/youtu\.be\/([a-zA-Z0-9_-]{11})/
];
for (let pattern of patterns) {
if (pattern.test(url)) return url.match(pattern)[1];
}
return null;
},
request: async (endpoint, data = {}, method = 'POST') => {
try {
const url = endpoint.startsWith('http') ? endpoint : `${savetube.api.base}${endpoint}`;
const options = {
method,
headers: savetube.headers
};
if (method === 'POST') {
options.body = JSON.stringify(data);
}
const response = await fetch(url, options);
const responseData = await response.json();
return {
status: response.ok,
code: response.status,
data: responseData
};
} catch (error) {
return {
status: false,
code: 500,
error: error.message
};
}
},
getCDN: async () => {
const response = await savetube.request(savetube.api.cdn, {}, 'GET');
if (!response.status) return response;
return {
status: true,
code: 200,
data: response.data.cdn
};
},
download: async (link, format) => {
if (!link) {
return {
status: false,
code: 400,
error: "URL is required"
};
}
if (!savetube.isUrl(link)) {
return {
status: false,
code: 400,
error: "Invalid YouTube URL"
};
}
if (!format || !savetube.formats.includes(format)) {
return {
status: false,
code: 400,
error: "Format is unavailable",
available_fmt: savetube.formats
};
}
const id = savetube.youtube(link);
if (!id) {
return {
status: false,
code: 400,
error: "Cannot extract YouTube video ID"
};
}
try {
const cdnx = await savetube.getCDN();
if (!cdnx.status) return cdnx;
const cdn = cdnx.data;
const result = await savetube.request(`https://${cdn}${savetube.api.info}`, {
url: `https://www.youtube.com/watch?v=${id}`
});
if (!result.status) return result;
const decrypted = await savetube.crypto.decrypt(result.data.data);
const dl = await savetube.request(`https://${cdn}${savetube.api.download}`, {
id: id,
downloadType: format === 'mp3' ? 'audio' : 'video',
quality: format === 'mp3' ? '128' : format,
key: decrypted.key
});
return {
status: true,
code: 200,
result: {
title: decrypted.title || "Unknown",
type: format === 'mp3' ? 'audio' : 'video',
format: format,
thumbnail: decrypted.thumbnail || `https://i.ytimg.com/vi/${id}/maxresdefault.jpg`,
download: dl.data.data.downloadUrl,
id: id,
key: decrypted.key,
duration: decrypted.duration,
quality: format === 'mp3' ? '128' : format,
downloaded: dl.data.data.downloaded || false
}
};
} catch (error) {
return {
status: false,
code: 500,
error: error.message
};
}
}
};
async function search(query) {
try {
const searchUrl = `https://www.youtube.com/results?search_query=${encodeURIComponent(query)}`;
const response = await fetch(searchUrl);
const html = await response.text();
const videoDataRegex = /var ytInitialData = ({.+?});/;
const match = html.match(videoDataRegex);
if (!match) {
throw new Error('Could not parse search results');
}
const data = JSON.parse(match[1]);
const contents = data?.contents?.twoColumnSearchResultsRenderer?.primaryContents?.sectionListRenderer?.contents?.[0]?.itemSectionRenderer?.contents || [];
const videos = contents
.filter(item => item.videoRenderer)
.map(item => {
const video = item.videoRenderer;
const videoId = video.videoId;
const title = video.title?.runs?.[0]?.text || video.title?.simpleText || 'Unknown Title';
const author = video.ownerText?.runs?.[0]?.text || 'Unknown Channel';
const duration = video.lengthText?.simpleText || '0:00';
const views = video.viewCountText?.simpleText || '0 views';
const thumbnail = video.thumbnail?.thumbnails?.[0]?.url || `https://i.ytimg.com/vi/${videoId}/maxresdefault.jpg`;
const url = `https://www.youtube.com/watch?v=${videoId}`;
return {
type: 'video',
videoId,
url,
title,
description: video.descriptionSnippet?.runs?.map(r => r.text).join('') || '',
thumbnail,
duration: { text: duration },
ago: video.publishedTimeText?.simpleText || '',
views: parseInt(views.replace(/[^\d]/g, '')) || 0,
author: {
name: author,
url: video.ownerText?.runs?.[0]?.navigationEndpoint?.commandMetadata?.webCommandMetadata?.url || ''
}
};
})
.slice(0, 20);
return { author: "Herza", status: 200, data: videos };
} catch (error) {
return { author: "Herza", status: 500, data: error.message };
}
}
async function transcript(link) {
try {
const videoId = getYouTubeVideoId(link);
if (!videoId) {
return { author: "Herza", status: 400, data: "Invalid YouTube URL" };
}
const response = await fetch("https://ytb2mp4.com/api/fetch-transcript", {
method: 'GET',
headers: {
"User-Agent": "Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Mobile Safari/537.36",
"Referer": "https://ytb2mp4.com/youtube-transcript"
}
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
return { author: "Herza", status: 200, data: data.transcript };
} catch (error) {
return { author: "Herza", status: 500, data: error.message };
}
}
async function ytMp3(link) {
const videoId = getYouTubeVideoId(link);
if (!videoId) return { author: "Herza", status: 400, data: "Invalid YouTube URL" };
try {
const saveTubeResult = await savetube.download(link, "mp3");
if (!saveTubeResult.status) {
return { author: "Herza", status: 400, data: saveTubeResult.error || "Failed to get audio" };
}
let audioUrl = saveTubeResult.result.download;
return {
author: "Herza",
status: 200,
data: {
metadata: {
title: saveTubeResult.result.title,
duration: saveTubeResult.result.duration,
thumbnail: saveTubeResult.result.thumbnail
},
download: {
url: audioUrl,
filename: `${saveTubeResult.result.title}.mp3`
}
}
};
} catch (error) {
return { author: "Herza", status: 500, data: error.message };
}
}
async function ytMp4(link, resolution = "480") {
const videoId = getYouTubeVideoId(link);
if (!videoId) return { author: "Herza", status: 400, data: "Invalid YouTube URL" };
if (!savetube.formats.includes(resolution) || resolution === "mp3") {
return {
author: "Herza",
status: 400,
data: `Invalid resolution. Choose from: ${savetube.formats.filter(f => f !== "mp3").join(", ")}`
};
}
try {
const saveTubeResult = await savetube.download(link, resolution);
if (!saveTubeResult.status) {
return { author: "Herza", status: 400, data: saveTubeResult.error || "Failed to get video" };
}
return {
author: "Herza",
status: 200,
data: {
metadata: {
title: saveTubeResult.result.title,
duration: saveTubeResult.result.duration,
thumbnail: saveTubeResult.result.thumbnail
},
download: {
url: saveTubeResult.result.download,
filename: `${saveTubeResult.result.title}.mp4`,
resolution: resolution
}
}
};
} catch (error) {
return { author: "Herza", status: 500, data: error.message };
}
}
async function getAvailableResolutions(link) {
const videoId = getYouTubeVideoId(link);
if (!videoId) return { author: "Herza", status: 400, data: "Invalid YouTube URL" };
return {
author: "Herza",
status: 200,
data: {
message: "Available resolutions",
resolutions: savetube.formats.filter(f => f !== "mp3")
}
};
}
async function ytdl(type, ...args) {
switch (type.toLowerCase()) {
case "ytmp4":
if (args.length < 1) return { author: "Herza", status: 400, data: "Missing arguments. Usage: ytdl('ytmp4', 'url', 'resolution')" };
return await ytMp4(args[0], args[1] || "480");
case "ytmp3":
if (args.length < 1) return { author: "Herza", status: 400, data: "Missing arguments. Usage: ytdl('ytmp3', 'url')" };
return await ytMp3(args[0]);
case "search":
if (args.length < 1) return { author: "Herza", status: 400, data: "Missing arguments. Usage: ytdl('search', 'query')" };
return await search(args[0]);
case "transcript":
if (args.length < 1) return { author: "Herza", status: 400, data: "Missing arguments. Usage: ytdl('transcript', 'url')" };
return await transcript(args[0]);
case "resolutions":
if (args.length < 1) return { author: "Herza", status: 400, data: "Missing arguments. Usage: ytdl('resolutions', 'url')" };
return await getAvailableResolutions(args[0]);
default:
return {
author: "Herza",
status: 400,
data: {
message: "Invalid type. Available types: ytmp4, ytmp3, search, transcript, resolutions",
usage: {
ytmp4: "ytdl('ytmp4', 'url', 'resolution')",
ytmp3: "ytdl('ytmp3', 'url')",
search: "ytdl('search', 'query')",
transcript: "ytdl('transcript', 'url')",
resolutions: "ytdl('resolutions', 'url')"
}
}
};
}
}
module.exports = { ytdl };