Add option to unblur thumbnails in YouTube search results
This commit is contained in:
parent
5d4485a54e
commit
9670e6ccfb
@ -2,11 +2,23 @@ import { YouTubeVideo } from '../classes/Video';
|
|||||||
import { YouTubePlayList } from '../classes/Playlist';
|
import { YouTubePlayList } from '../classes/Playlist';
|
||||||
import { YouTubeChannel } from '../classes/Channel';
|
import { YouTubeChannel } from '../classes/Channel';
|
||||||
import { YouTube } from '..';
|
import { YouTube } from '..';
|
||||||
|
import { YouTubeThumbnail } from '../classes/Thumbnail';
|
||||||
|
import { writeFileSync } from 'fs';
|
||||||
|
|
||||||
|
const BLURRED_THUMBNAILS = [
|
||||||
|
'-oaymwEpCOADEI4CSFryq4qpAxsIARUAAAAAGAElAADIQj0AgKJDeAHtAZmZGUI=',
|
||||||
|
'-oaymwEiCOADEI4CSFXyq4qpAxQIARUAAIhCGAFwAcABBu0BmZkZQg==',
|
||||||
|
'-oaymwEiCOgCEMoBSFXyq4qpAxQIARUAAIhCGAFwAcABBu0BZmbmQQ==',
|
||||||
|
'-oaymwEiCNAFEJQDSFXyq4qpAxQIARUAAIhCGAFwAcABBu0BZmZmQg==',
|
||||||
|
'-oaymwEdCNAFEJQDSFryq4qpAw8IARUAAIhCGAHtAWZmZkI=',
|
||||||
|
'-oaymwEdCNACELwBSFryq4qpAw8IARUAAIhCGAHtAT0K10E='
|
||||||
|
];
|
||||||
|
|
||||||
export interface ParseSearchInterface {
|
export interface ParseSearchInterface {
|
||||||
type?: 'video' | 'playlist' | 'channel';
|
type?: 'video' | 'playlist' | 'channel';
|
||||||
limit?: number;
|
limit?: number;
|
||||||
language?: string;
|
language?: string;
|
||||||
|
unblurNSFWThumbnails?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface thumbnail {
|
export interface thumbnail {
|
||||||
@ -25,6 +37,7 @@ export function ParseSearchResult(html: string, options?: ParseSearchInterface):
|
|||||||
if (!options) options = { type: 'video', limit: 0 };
|
if (!options) options = { type: 'video', limit: 0 };
|
||||||
else if (!options.type) options.type = 'video';
|
else if (!options.type) options.type = 'video';
|
||||||
const hasLimit = typeof options.limit === 'number' && options.limit > 0;
|
const hasLimit = typeof options.limit === 'number' && options.limit > 0;
|
||||||
|
options.unblurNSFWThumbnails ??= false;
|
||||||
|
|
||||||
const data = html
|
const data = html
|
||||||
.split('var ytInitialData = ')?.[1]
|
.split('var ytInitialData = ')?.[1]
|
||||||
@ -35,13 +48,17 @@ export function ParseSearchResult(html: string, options?: ParseSearchInterface):
|
|||||||
const details =
|
const details =
|
||||||
json_data.contents.twoColumnSearchResultsRenderer.primaryContents.sectionListRenderer.contents[0]
|
json_data.contents.twoColumnSearchResultsRenderer.primaryContents.sectionListRenderer.contents[0]
|
||||||
.itemSectionRenderer.contents;
|
.itemSectionRenderer.contents;
|
||||||
|
writeFileSync('results.json', JSON.stringify(details));
|
||||||
for (const detail of details) {
|
for (const detail of details) {
|
||||||
if (hasLimit && results.length === options.limit) break;
|
if (hasLimit && results.length === options.limit) break;
|
||||||
if (!detail.videoRenderer && !detail.channelRenderer && !detail.playlistRenderer) continue;
|
if (!detail.videoRenderer && !detail.channelRenderer && !detail.playlistRenderer) continue;
|
||||||
switch (options.type) {
|
switch (options.type) {
|
||||||
case 'video': {
|
case 'video': {
|
||||||
const parsed = parseVideo(detail);
|
const parsed = parseVideo(detail);
|
||||||
if (parsed) results.push(parsed);
|
if (parsed) {
|
||||||
|
if (options.unblurNSFWThumbnails) parsed.thumbnails.forEach(unblurThumbnail);
|
||||||
|
results.push(parsed);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'channel': {
|
case 'channel': {
|
||||||
@ -51,7 +68,10 @@ export function ParseSearchResult(html: string, options?: ParseSearchInterface):
|
|||||||
}
|
}
|
||||||
case 'playlist': {
|
case 'playlist': {
|
||||||
const parsed = parsePlaylist(detail);
|
const parsed = parsePlaylist(detail);
|
||||||
if (parsed) results.push(parsed);
|
if (parsed) {
|
||||||
|
if (options.unblurNSFWThumbnails && parsed.thumbnail) unblurThumbnail(parsed.thumbnail);
|
||||||
|
results.push(parsed);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@ -189,3 +209,36 @@ export function parsePlaylist(data?: any): YouTubePlayList {
|
|||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function unblurThumbnail(thumbnail: YouTubeThumbnail) {
|
||||||
|
if (BLURRED_THUMBNAILS.find((sqp) => thumbnail.url.includes(sqp))) {
|
||||||
|
thumbnail.url = thumbnail.url.split('?')[0];
|
||||||
|
|
||||||
|
// we need to update the size parameters as the sqp parameter also included a cropped size
|
||||||
|
switch (thumbnail.url.split('/').at(-1)!.split('.')[0]) {
|
||||||
|
case 'hq2':
|
||||||
|
case 'hqdefault':
|
||||||
|
thumbnail.width = 480;
|
||||||
|
thumbnail.height = 360;
|
||||||
|
break;
|
||||||
|
case 'hq720':
|
||||||
|
thumbnail.width = 1280;
|
||||||
|
thumbnail.height = 720;
|
||||||
|
break;
|
||||||
|
case 'sddefault':
|
||||||
|
thumbnail.width = 640;
|
||||||
|
thumbnail.height = 480;
|
||||||
|
break;
|
||||||
|
case 'mqdefault':
|
||||||
|
thumbnail.width = 320;
|
||||||
|
thumbnail.height = 180;
|
||||||
|
break;
|
||||||
|
case 'default':
|
||||||
|
thumbnail.width = 120;
|
||||||
|
thumbnail.height = 90;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
thumbnail.width = thumbnail.height = NaN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -67,6 +67,11 @@ interface SearchOptions {
|
|||||||
};
|
};
|
||||||
fuzzy?: boolean;
|
fuzzy?: boolean;
|
||||||
language?: string;
|
language?: string;
|
||||||
|
/**
|
||||||
|
* !!! Before enabling this for public servers, please consider using Discord features like NSFW channels as not everyone in your server wants to see NSFW images. !!!
|
||||||
|
* Unblurred images will likely have different dimensions than specified in the {@link YouTubeThumbnail} objects.
|
||||||
|
*/
|
||||||
|
unblurNSFWThumbnails?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
import { createInterface } from 'node:readline';
|
import { createInterface } from 'node:readline';
|
||||||
@ -184,6 +189,9 @@ async function search(query: string, options?: SearchOptions): Promise<YouTubeVi
|
|||||||
*
|
*
|
||||||
* - `number` limit : No of searches you want to have.
|
* - `number` limit : No of searches you want to have.
|
||||||
* - `string` language : Sets language of searched content [ YouTube search only. ], e.g. "en-US"
|
* - `string` language : Sets language of searched content [ YouTube search only. ], e.g. "en-US"
|
||||||
|
* - `boolean` unblurNSFWThumbnails : Unblurs NSFW thumbnails. Defaults to `false` [ YouTube search only. ]
|
||||||
|
* !!! Before enabling this for public servers, please consider using Discord features like NSFW channels as not everyone in your server wants to see NSFW images. !!!
|
||||||
|
* Unblurred images will likely have different dimensions than specified in the {@link YouTubeThumbnail} objects.
|
||||||
* - `boolean` fuzzy : Whether the search should be fuzzy or only return exact matches. Defaults to `true`. [ for `Deezer` Only ]
|
* - `boolean` fuzzy : Whether the search should be fuzzy or only return exact matches. Defaults to `true`. [ for `Deezer` Only ]
|
||||||
* - `Object` source : Contains type of source and type of result you want to have
|
* - `Object` source : Contains type of source and type of result you want to have
|
||||||
* ```ts
|
* ```ts
|
||||||
@ -204,7 +212,8 @@ async function search(
|
|||||||
return await yt_search(query, {
|
return await yt_search(query, {
|
||||||
limit: options.limit,
|
limit: options.limit,
|
||||||
type: options.source.youtube,
|
type: options.source.youtube,
|
||||||
language: options.language
|
language: options.language,
|
||||||
|
unblurNSFWThumbnails: options.unblurNSFWThumbnails
|
||||||
});
|
});
|
||||||
else if (options.source.spotify) return await sp_search(query, options.source.spotify, options.limit);
|
else if (options.source.spotify) return await sp_search(query, options.source.spotify, options.limit);
|
||||||
else if (options.source.soundcloud) return await so_search(query, options.source.soundcloud, options.limit);
|
else if (options.source.soundcloud) return await so_search(query, options.source.soundcloud, options.limit);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user