-
Notifications
You must be signed in to change notification settings - Fork 14
/
index.ts
172 lines (146 loc) · 4.79 KB
/
index.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
import express, { Express, Request, Response } from 'express';
import cors from 'cors';
import ytdl from 'ytdl-core';
import { google } from 'googleapis';
import contentDisposition from 'content-disposition';
import db from './db';
import statisticRoutes from './routes';
import dotenv from 'dotenv';
import { sendMail } from './sendMail';
dotenv.config();
const app: Express = express();
const port: string | number = process.env.PORT || 4000;
const youtube = google.youtube({
version: 'v3',
auth: process.env.YOUTUBE_KEY,
});
interface SearchParams {
q?: string;
pageToken?: string;
maxResults?: number;
}
async function searchYouTube(params: SearchParams = {}) {
const res = await youtube.search.list({
// @ts-ignore
part: 'snippet',
type: 'video',
...params,
});
return (res as any).data;
}
app.listen(port, () => console.log(`Server is running on port ${port}`));
app.use(cors());
app.use(express.json());
app.use('/api', statisticRoutes);
app.post('/contact', async (req, res) => {
const { email, issueType, description } = req.body;
if (!email || !issueType || !description) {
return res.status(400).json({ message: 'All fields are required.' });
}
const mailOptions = {
from: `"YouTubdle.com" ${process.env.MAIL_USER}`,
to: process.env.MAIL_TO as string,
subject: "YouTubdle.com Form",
replyTo: email,
text: `Nachricht von: ${email}\n\n${description}`,
};
const result = await sendMail(mailOptions);
if (result.success) {
res.json({ success: true, message: 'Deine Nachricht wurde erfolgreich gesendet.' });
} else {
res.status(500).json({ success: false, message: 'Fehler beim Senden deiner Nachricht.' });
}
});
app.get('/formats', async (req: Request, res: Response) => {
try {
const videoURL: string = req.query.url as string;
const formats = await ytdl.getInfo(videoURL);
res.status(200).json(formats.formats);
} catch (error) {
console.error('Error while getting the formats:', error);
res.status(500).send('Some error occurred while getting the formats.');
}
});
/**
* Get suggestions depending on the search query/value.
*/
app.get('/suggestions', async (req: Request, res: Response) => {
const { search, next = null } = req.query as { search?: string; next?: string | null };
try {
await db.collection('searchstatistics').insertOne({ searchInput: search });
const data = await searchYouTube({
q: search,
// nextPageToken: next,
pageToken: next as any,
maxResults: 14,
});
// @ts-ignore
const { items, nextPageToken, pageInfo, regionCode, prevPageToken } = data;
return res.status(200).json({
success: true,
data: items,
pagingInfo: { ...pageInfo, nextPageToken, regionCode, prevPageToken },
});
} catch (error: any) {
console.error(error);
if (error.status === 403) {
return res.status(403).json({ success: false, error, limitExceeded: true });
}
return res.status(400).json({ success: false, error, limitExceeded: true });
}
});
/**
* Get information about a video.
*/
app.get('/metainfo', async (req: Request, res: Response) => {
const url = req.query.url as string;
if (!ytdl.validateID(url) && !ytdl.validateURL(url)) {
return res.status(400).json({ success: false, error: 'No valid YouTube Id!' });
}
try {
const result = await ytdl.getInfo(url);
return res.status(200).json({ success: true, data: result });
} catch (error: any) {
console.error(error);
return res.status(400).json({ success: false, error });
}
});
/**
* Download a video with the selected format.
*/
app.get('/watch', async (req: Request, res: Response) => {
const { v: url, format: f = '.mp4' } = req.query as {
v?: string;
format?: string;
};
if (url === undefined || (!ytdl.validateID(url) && !ytdl.validateURL(url))) {
return res.status(400).json({ success: false, error: 'No valid YouTube Id!' });
}
const formats = ['.mp4', '.mp3', '.mov', '.flv'];
let format: string = formats.includes(f) ? f : '.mp4';
try {
const result = await ytdl.getBasicInfo(url);
const {
videoDetails: { title, videoId, uploadDate, likes, category, author },
} = result;
const videoInfo = {
title,
videoId,
uploadDate,
likes,
category,
authorId: author.id,
downloadedFormat: format,
};
await db.collection('downloadstatistics').insertOne(videoInfo);
res.setHeader('Content-Disposition', contentDisposition(`${title}${format}`));
let filterQuality: 'audioandvideo' | 'audioonly' = format === '.mp3' ? 'audioonly' : 'audioandvideo';
ytdl(url, { filter: filterQuality })
.on('progress', () => {
})
.pipe(res);
} catch (err: any) {
console.error('error', err);
res.redirect(`http://${req.headers.host}?error=downloadError`);
}
});