R-Kentaren commited on
Commit
0bafb27
·
verified ·
1 Parent(s): c5487e3

Create savetube.js

Browse files
Files changed (1) hide show
  1. savetube.js +82 -0
savetube.js ADDED
@@ -0,0 +1,82 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const crypto = require("crypto")
2
+ const axios = require("axios")
3
+
4
+ class savetube {
5
+ constructor() {
6
+ this.ky = 'C5D58EF67A7584E4A29F6C35BBC4EB12';
7
+ this.fmt = ['144', '240', '360', '480', '720', '1080', 'mp3'];
8
+ this.m = /^((?:https?:)?\/\/)?((?:www|m|music)\.)?(?:youtube\.com|youtu\.be)\/(?:watch\?v=)?(?:embed\/)?(?:v\/)?(?:shorts\/)?([a-zA-Z0-9_-]{11})/;
9
+ this.is = axios.create({
10
+ headers: {
11
+ 'content-type': 'application/json',
12
+ 'origin': 'https://yt.savetube.me',
13
+ 'user-agent': 'Mozilla/5.0 (Android 15; Mobile; SM-F958; rv:130.0) Gecko/130.0 Firefox/130.0'
14
+ }
15
+ })
16
+ }
17
+
18
+ async decrypt(enc) {
19
+ try {
20
+ const [sr, ky] = [Buffer.from(enc,'base64'), Buffer.from(this.ky,'hex')]
21
+ const [iv, dt] = [sr.slice(0,16), sr.slice(16)]
22
+ const dc = crypto.createDecipheriv('aes-128-cbc', ky, iv);
23
+ return JSON.parse(Buffer.concat([dc.update(dt), dc.final()]).toString());
24
+ } catch (e) {
25
+ throw new Error(`Error while decrypting data: ${e.message}`);
26
+ }
27
+ }
28
+
29
+ async getCdn() {
30
+ const response = await this.is.get("https://media.savetube.vip/api/random-cdn");
31
+ if (!response.status) return response;
32
+ return {
33
+ status: true,
34
+ data: response.data.cdn
35
+ };
36
+ }
37
+
38
+ async download(url, format = 'mp3') {
39
+ const id = url.match(this.m)?.[3];
40
+ if (!id) {
41
+ return {
42
+ status: false,
43
+ msg: "ID cannot be extracted from url"
44
+ };
45
+ }
46
+ if (!format || !this.fmt.includes(format)) {
47
+ return {
48
+ status: false,
49
+ msg: "Formats not found",
50
+ list: this.fmt
51
+ };
52
+ }
53
+ try {
54
+ const u = await this.getCdn();
55
+ if (!u.status) return u;
56
+ const res = await this.is.post(`https://${u.data}/v2/info`, {
57
+ url: `https://www.youtube.com/watch?v=${id}`
58
+ });
59
+ const dec = await this.decrypt(res.data.data);
60
+ const dl = await this.is.post(`https://${u.data}/download`, {
61
+ id: id,
62
+ downloadType: format === 'mp3' ? 'audio' : 'video',
63
+ quality: format === 'mp3' ? '128' : format,
64
+ key: dec.key
65
+ })
66
+
67
+ return {
68
+ status: true,
69
+ title: dec.title,
70
+ format: format,
71
+ thumb: dec.thumbnail || `https://i.ytimg.com/vi/${id}/hqdefault.jpg`,
72
+ duration: dec.duration,
73
+ cached: dec.fromCache,
74
+ dl: dl.data.data.downloadUrl
75
+ };
76
+ } catch (error) {
77
+ return {
78
+ status: false,
79
+ error: error.message
80
+ };
81
+ }
82
+ }