This repository has been archived by the owner on Oct 1, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
/
ytgbss.js
139 lines (119 loc) · 4.4 KB
/
ytgbss.js
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
/**
* This file represents YTGameBar Overlay's Search Server. It anonymously makes searches on the web
* by the given term using TimeForANinja's node-ytsr lib, parsing its results to the minimal useful JSON
* which will be returned to YTGBO.
*
* @author: Marconi Gomes ([email protected])
*/
const ytScraper = require('youtube-scrape/scraper')
const winston = require('winston');
const port = process.env.PORT || 3000;
var YTGBss = require('express')();
var http = require('http').createServer(YTGBss);
/**
* Creates a Winston Logger instance.
*/
const logger = winston.createLogger({
level: 'http',
format: winston.format.prettyPrint(),
transports: [
new winston.transports.Console()
]
});
/**
* Listens for connections on port 54522.
*/
http.listen(port, () => {
logger.log({ timestamp: new Date().toUTCString(), level: 'info', message: 'Ready.' });
});
/**
* Handles GET requests on /current/search route.
* It makes the search by the term available on the request parameters.
*
* We can expect the following results:
* 200 OK - The search was sucessful. The result will be returned to requester.
* 400 BAD REQUEST - The request term wasn't found in the url. The status code is returned.
* 500 INTERNAL SERVER ERROR - Something went wrong with search. The status code is returned.
*/
YTGBss.get('/current/search/:term', (request, response, next) => {
logger.log({ timestamp: new Date().toUTCString(), level: 'http', message: 'Got GET search request...' });
if (request.params.term !== undefined) {
handleSearch(request.params.term).then(function (parsedResults) {
logger.log({ level: 'info', message: 'Sucess.' })
response.send(parsedResults);
}).catch(function (errorData) {
next({ message: '500 INTERNAL SERVER ERROR', details: errorData });
});
}
else {
next({ message: '400 BAD REQUEST', details: 'Missing request parameter.' });
}
});
/**
* Uses the specified error handler.
*/
YTGBss.use(errorHandler);
/**
* Handles the errors provided by the server, answering them accordingly to the client.
*
* @param {*} error The error received from above layers.
* @param {*} request The source request.
* @param {*} response The response to be made.
* @param {*} next The next function to be used.
*/
function errorHandler(error, request, response, next) {
logger.log({ timestamp: new Date().toUTCString(), level: 'error', message: error.details })
if (error.message.startsWith('500')) {
response.status(500).send({ error: 'Internal Server Error!' })
}
else {
response.status(400).send({ error: 'Bad request!' })
}
}
/**
* Parses and returns the search results with necessary information used by YTGBO new version.
*
* @param {Array} results
*/
function parseResults(results) {
const parsedResults = [];
results.forEach(result => {
let parsed = {
mediaType: result.content.type,
mediaTitle: result.content.title,
mediaUrl: result.content.url,
thumbnail: result.content.thumbnail_src,
channelTitle: result.uploader.username
}
parsedResults.push(parsed);
})
return parsedResults;
}
/**
* Handles the search process by the given term.
* It searchs asynchronously 5 video results and 3 playlist results, parsing and returning them
* @param {*} term
*/
const handleSearch = async function(term) {
const videoResults = handleVideoSearch(term).catch(errorData => { throw new Error(errorData) });
const playlistResults = handlePlaylistSearch(term).catch(errorData => { throw new Error(errorData) });
return Promise.all([videoResults, playlistResults]).then((results) => {
return results[0].concat(results[1]);
});
}
/**
* Handles the video search for the given term, parses and returns the results.
* @param {String} term - The term to be searched for video results.
*/
const handleVideoSearch = async function (term) {
const searchResults = await ytScraper.youtube(term, 5, "video");
return parseResults(searchResults.results);
}
/**
* Handles the playlist search for the given term, parses and returns the results.
* @param {String} term - The term to be searched for playlist results.
*/
const handlePlaylistSearch = async function (term) {
const searchResults = await ytScraper.youtube(term, 3, "playlist");
return parseResults(searchResults.results);
}