Skip to content
This repository has been archived by the owner on Oct 1, 2023. It is now read-only.

Commit

Permalink
Merge pull request #4 from MarconiGRF/ytsr_hotfix
Browse files Browse the repository at this point in the history
Fixes for node_ytsr lib and new youtube search layout.
  • Loading branch information
MarconiGRF authored Jan 6, 2021
2 parents a0b9f35 + b5d9636 commit 31180f1
Show file tree
Hide file tree
Showing 4 changed files with 749 additions and 848 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
node_modules/*
.vscode/*
status.log
242 changes: 65 additions & 177 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@

const { connect } = require('http2');
/**
* This file represents Youtube Game Bar Overlay's Search Server. It anonymously makes searches on YouTube
* This file represents Youtube Game Bar Overlay's Search Server. It anonymously makes searches on YouTube
* by the given term using TimeForANinja's node-ytsr lib, parsing its results to the minimal useful JSON
* which will be returned to YTGBO.
*
Expand All @@ -17,20 +18,20 @@ 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.File({ filename: 'status.log' }),
new winston.transports.Console()
]
});;
level: 'http',
format: winston.format.prettyPrint(),
transports: [
new winston.transports.File({ filename: 'status.log' }),
new winston.transports.Console()
]
});


/**
* Listens for connections on port 54522.
*/
http.listen(54522, () => {
logger.log({ timestamp: new Date().toUTCString(), level: 'info', message: 'Ready.' });
logger.log({ timestamp: new Date().toUTCString(), level: 'info', message: 'Ready.' });
});


Expand All @@ -44,45 +45,19 @@ http.listen(54522, () => {
* 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.' });
}
});


/**
* Handles legacy GET requests on /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 body wasn't in the expected format. The status code is returned.
* 500 INTERNAL SERVER ERROR - Something went wrong with search. The status code is returned.
*/
YTGBss.get('/search/:term', (request, response, next) => {
logger.log({ timestamp: new Date().toUTCString(), level: 'http', message: 'Got LEGACY GET search request...' });

if (request.params.term !== undefined) {
handleLegacySearch(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 or malfunct body.' });
}
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.' });
}
});


Expand All @@ -93,160 +68,73 @@ 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!' })
}
}

logger.log({ timestamp: new Date().toUTCString(), level: 'error', message: error.details })

/**
* Searchs for YouTube's videos and playlists results using node-ytsr lib.
*
* @param {string} term The term to search results for.
*/
function handleSearch(term) {
return new Promise((resolve, reject) => {
let finalResults = [];
let pageRef = "https://www.youtube.com/results?search_query=" + term;

var searchOptions = {
limit: 10,
nextpageRef: pageRef
};

doSearch(searchOptions).then(function (videoResults) {
for (let videoResult of videoResults) {
finalResults.push(videoResult);
}

resolve(finalResults);
}).catch(function (errorData) {
reject(errorData);
});
});
if (error.message.startsWith('500')) {
response.status(500).send({ error: 'Internal Server Error!' })
}
else {
response.status(400).send({ error: 'Bad request!' })
}
}


/**
* Searchs for YouTube's videos results using node-ytsr lib.
* Parses and returns the search results with necessary information used by YTGBO new version.
*
* @param {string} term The term to search results for.
* @param {Array} results
*/
function handleLegacySearch(term) {
return new Promise((resolve, reject) => {
let finalResults = [];
let videoRef = "https://www.youtube.com/results?search_query=" + term + "&sp=EgIQAQ%253D%253D";

var searchOptions = {
limit: 5,
nextpageRef: videoRef
};

doLegacySearch(searchOptions).then(function (videoResults) {
for (let videoResult of videoResults) {
finalResults.push(videoResult);
}

resolve(finalResults);
}).catch(function (errorData) {
reject(errorData);
function parseResults(results) {
var parsedResults = [];

results.forEach(result => {
let parsed = {
mediaType: result.type,
mediaTitle: result.title,
mediaUrl: result.link,
channelTitle: result.author.name
};
parsedResults.push(parsed);
});
});
return parsedResults;
}

/**
* Does the search using node-ytsr lib based on the given options.
* When finished parses and returns the results on the new YTGBO format.
*
* @param {*} searchOptions The given search options for ytsr.
* Handles the search process by the given term.
* @param {*} term
*/
function doSearch(searchOptions) {
return new Promise(function (resolve, reject) {
ytsr(null, searchOptions, function (err, searchResults) {
if (err) {
reject(err);
};

let parsedResults = parseResults(searchResults.items);
resolve(parsedResults);
});
})
}
const handleSearch = async function(term) {
term = term.replace(" ", "");
const videoResults = handleVideoSearch(term).catch((errorData) => { throw new Error(errorData) });
const playlistResults = handlePlaylistSearch(term).catch((errorData) => { throw new Error(errorData) });

/**
* Does the search using node-ytsr lib based on the given options.
* When finished parses and returns the results on the legacy YTGBO format.
*
* @param {*} searchOptions The given search options for ytsr.
*/
function doLegacySearch(searchOptions) {
return new Promise(function (resolve, reject) {
ytsr(null, searchOptions, function (err, searchResults) {
if (err) {
reject(err);
};

let parsedResults = parseLegacyResults(searchResults.items);
resolve(parsedResults);
return Promise.all([videoResults, playlistResults]).then((results) => {
return results[0].concat(results[1]);
});
})
}

const handleVideoSearch = async function (term) {
const filters = await ytsr.getFilters(term);
const videoFilter = filters.get('Type').find(obj => obj.name === 'Video');
const options = { limit: 5 };

/**
* Parses and returns the search results with necessary information used by YTGBO new versoin.
*
* @param {Array} results
*/
function parseResults(results) {
var parsedResults = [];

for (let result of results) {
var parsed = {};

if (result.type == "video" || result.type == "playlist") {
parsed.mediaType = result.type;
parsed.mediaTitle = result.title;
parsed.channelTitle = result.author.name;
parsed.mediaUrl = result.link;
const searchResults = await ytsr(videoFilter.ref, options);

parsedResults.push(parsed);
}
}

return parsedResults;
return parseResults(searchResults.items);
}

const handlePlaylistSearch = async function (term) {
const filters = await ytsr.getFilters(term);
const playlistFilter = filters.get('Type').find(obj => obj.name === 'Playlist');
const options = { limit: 3 };

/**
* Parses and returns the search results with necessary information used by YTGBO Legacy Version.
*
* @param {Array} results
*/
function parseLegacyResults(results) {
var parsedResults = [];

for (let result of results) {
var parsed = {};

parsed.videoTitle = result.title;
parsed.channelTitle = result.author.name;
parsed.mediaUrl = result.link;

parsedResults.push(parsed);
}
const searchResults = await ytsr(playlistFilter.ref, options);

return parsedResults;
return parseResults(searchResults.items);
}
Loading

0 comments on commit 31180f1

Please sign in to comment.