92 lines
2.3 KiB
JavaScript
92 lines
2.3 KiB
JavaScript
|
/**
|
||
|
* Get video ID.
|
||
|
*
|
||
|
* There are a few type of video URL formats.
|
||
|
* - https://www.youtube.com/watch?v=VIDEO_ID
|
||
|
* - https://m.youtube.com/watch?v=VIDEO_ID
|
||
|
* - https://youtu.be/VIDEO_ID
|
||
|
* - https://www.youtube.com/v/VIDEO_ID
|
||
|
* - https://www.youtube.com/embed/VIDEO_ID
|
||
|
* - https://music.youtube.com/watch?v=VIDEO_ID
|
||
|
* - https://gaming.youtube.com/watch?v=VIDEO_ID
|
||
|
*
|
||
|
* @param {string} link
|
||
|
* @return {string}
|
||
|
* @throws {Error} If unable to find a id
|
||
|
* @throws {TypeError} If videoid doesn't match specs
|
||
|
*/
|
||
|
const validQueryDomains = new Set([
|
||
|
'youtube.com',
|
||
|
'www.youtube.com',
|
||
|
'm.youtube.com',
|
||
|
'music.youtube.com',
|
||
|
'gaming.youtube.com',
|
||
|
]);
|
||
|
const validPathDomains = /^https?:\/\/(youtu\.be\/|(www\.)?youtube\.com\/(embed|v|shorts)\/)/;
|
||
|
exports.getURLVideoID = link => {
|
||
|
const parsed = new URL(link);
|
||
|
let id = parsed.searchParams.get('v');
|
||
|
if (validPathDomains.test(link) && !id) {
|
||
|
const paths = parsed.pathname.split('/');
|
||
|
id = parsed.host === 'youtu.be' ? paths[1] : paths[2];
|
||
|
} else if (parsed.hostname && !validQueryDomains.has(parsed.hostname)) {
|
||
|
throw Error('Not a YouTube domain');
|
||
|
}
|
||
|
if (!id) {
|
||
|
throw Error(`No video id found: ${link}`);
|
||
|
}
|
||
|
id = id.substring(0, 11);
|
||
|
if (!exports.validateID(id)) {
|
||
|
throw TypeError(`Video id (${id}) does not match expected ` +
|
||
|
`format (${idRegex.toString()})`);
|
||
|
}
|
||
|
return id;
|
||
|
};
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Gets video ID either from a url or by checking if the given string
|
||
|
* matches the video ID format.
|
||
|
*
|
||
|
* @param {string} str
|
||
|
* @returns {string}
|
||
|
* @throws {Error} If unable to find a id
|
||
|
* @throws {TypeError} If videoid doesn't match specs
|
||
|
*/
|
||
|
const urlRegex = /^https?:\/\//;
|
||
|
exports.getVideoID = str => {
|
||
|
if (exports.validateID(str)) {
|
||
|
return str;
|
||
|
} else if (urlRegex.test(str)) {
|
||
|
return exports.getURLVideoID(str);
|
||
|
} else {
|
||
|
throw Error(`No video id found: ${str}`);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Returns true if given id satifies YouTube's id format.
|
||
|
*
|
||
|
* @param {string} id
|
||
|
* @return {boolean}
|
||
|
*/
|
||
|
const idRegex = /^[a-zA-Z0-9-_]{11}$/;
|
||
|
exports.validateID = id => idRegex.test(id);
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Checks wether the input string includes a valid id.
|
||
|
*
|
||
|
* @param {string} string
|
||
|
* @returns {boolean}
|
||
|
*/
|
||
|
exports.validateURL = string => {
|
||
|
try {
|
||
|
exports.getURLVideoID(string);
|
||
|
return true;
|
||
|
} catch (e) {
|
||
|
return false;
|
||
|
}
|
||
|
};
|