diff --git a/client/composables/api/search.ts b/client/composables/api/search.ts index e56677838..76d17a80f 100644 --- a/client/composables/api/search.ts +++ b/client/composables/api/search.ts @@ -1,5 +1,5 @@ +import type { ApiDto } from '@viewtube/shared'; import { type LocationQuery } from 'vue-router'; -import type { VTSearchDto } from '../../../server/src/mapper/dto/search/vt-search.dto'; export type FilterType = { filterValue: any; filterType?: any; filterName: any }; @@ -21,7 +21,7 @@ export const useGetSearchResult = () => { `search`, async () => { const { apiUrl } = useApiUrl(); - const searchResponse = await vtFetch(`${apiUrl.value}search`, { + const searchResponse = await vtFetch>(`${apiUrl.value}search`, { query: { q: searchQuery.value, filters: searchFilters.value } }); @@ -33,7 +33,7 @@ export const useGetSearchResult = () => { ); }; -const getSearchFilters = (query: LocationQuery) => { +export const getSearchFilters = (query: LocationQuery) => { const searchParams = new URLSearchParams(query as Record); const filters: Record = {}; diff --git a/client/composables/proxyUrls.ts b/client/composables/proxyUrls.ts index abbe48a6c..511ccc6f0 100644 --- a/client/composables/proxyUrls.ts +++ b/client/composables/proxyUrls.ts @@ -3,11 +3,10 @@ export const useProxyUrls = () => { const origin = window?.location?.origin ?? ''; - const streamProxy = `${clientApiUrl.value}proxy/stream?url=`; + const streamProxy = `${clientApiUrl.value}proxy/stream?originUrl=${origin}&url=`; return { imgProxy: `${clientApiUrl.value}proxy/image?url=`, streamProxy, - m3u8Proxy: `${clientApiUrl.value}proxy/m3u8?proxyUrl=${origin}${streamProxy}&url=`, videoPlaybackProxy: `${clientApiUrl.value}videoplayback`, textProxy: `${clientApiUrl.value}proxy/text?url=` }; diff --git a/client/composables/videoplayer/videoSource.ts b/client/composables/videoplayer/videoSource.ts index 44a6aa269..fb36e2650 100644 --- a/client/composables/videoplayer/videoSource.ts +++ b/client/composables/videoplayer/videoSource.ts @@ -20,7 +20,6 @@ export const useVideoSource = (video: Ref>) => { sourceType = VideoSourceType.HLS; source = video.value.hlsManifestUrl; } else if (video.value.dashManifest) { - const googlevideoRegex = /https:\/\/.*?.googlevideo\.com/gi; const manifest = video.value.dashManifest.replace(googlevideoRegex, videoPlaybackProxy); sourceType = VideoSourceType.DASH; source = 'data:application/dash+xml;charset=utf-8;base64,' + btoa(manifest); diff --git a/client/pages/results.vue b/client/pages/results.vue index a86477cc8..61a7dfb75 100644 --- a/client/pages/results.vue +++ b/client/pages/results.vue @@ -2,8 +2,11 @@ import RelatedSearches from '@/components/search/RelatedSearches.vue'; import Spinner from '@/components/Spinner.vue'; import Filters from '@/components/search/Filters.vue'; +import SeparatorSmall from '@/components/list/SeparatorSmall.vue'; +import BadgeButton from '@/components/buttons/BadgeButton.vue'; import { useMessagesStore } from '@/store/messages'; import { useSettingsStore } from '@/store/settings'; +import type { ApiDto } from '@viewtube/shared'; const VideoEntry = resolveComponent('ListVideoEntry'); const PlaylistEntry = resolveComponent('ListPlaylistEntry'); @@ -14,6 +17,8 @@ const Shelf = resolveComponent('SearchShelf'); const route = useRoute(); const messagesStore = useMessagesStore(); const settingsStore = useSettingsStore(); +const { vtFetch } = useVtFetch(); +const { apiUrl } = useApiUrl(); const searchQuery = computed(() => { const searchParams = new URLSearchParams(route.query as Record); @@ -33,16 +38,16 @@ onMounted(() => { } }); -// const additionalResultItems = ref([]); -// const searchContinuationData = ref(searchData.value?.searchResults.continuation); +const additionalResultItems = ref([]); +const searchContinuationData = ref(searchData.value?.continuation); -// watch( -// () => searchData.value, -// newData => { -// // additionalResultItems.value = []; -// searchContinuationData.value = newData?.searchResults.continuation; -// } -// ); +watch( + () => searchData.value, + newData => { + additionalResultItems.value = []; + searchContinuationData.value = newData?.continuation; + } +); watch(error, newValue => { if (newValue) { @@ -76,42 +81,46 @@ const getListEntryType = (type: string) => { } }; -// const loadMoreVideos = async () => { -// moreVideosLoading.value = true; -// page.value += 1; +const moreVideosLoading = ref(false); +const page = ref(1); + +const loadMoreVideos = async () => { + moreVideosLoading.value = true; + page.value += 1; -// if (searchData.value?.searchResults && searchContinuationData.value) { -// try { -// const searchContinuation = await vtFetch( -// `${apiUrl.value}search/continuation`, -// { -// method: 'POST', -// body: { -// continuationData: searchContinuationData.value -// } -// } -// ); + if (searchData.value && searchContinuationData.value) { + try { + const searchContinuation = await vtFetch>(`${apiUrl.value}search`, { + query: { + q: searchQuery.value, + filters: getSearchFilters(route.query), + continuationString: searchContinuationData.value + } + }); -// if (searchContinuation) { -// additionalResultItems.value = [...additionalResultItems.value, ...searchContinuation.items]; -// searchContinuationData.value = searchContinuation.continuation; -// } -// } catch (error) { -// messagesStore.createMessage({ -// type: 'error', -// title: 'Unable to load more results', -// message: 'Try again or use a different search term for more results' -// }); -// } -// } else { -// messagesStore.createMessage({ -// type: 'error', -// title: 'Unable to load more results', -// message: 'Use a different search term for more results' -// }); -// } -// moreVideosLoading.value = false; -// }; + if (searchContinuation) { + additionalResultItems.value = [ + ...additionalResultItems.value, + ...searchContinuation.results + ]; + searchContinuationData.value = searchContinuation.continuation; + } + } catch (error) { + messagesStore.createMessage({ + type: 'error', + title: 'Unable to load more results', + message: 'Try again or use a different search term for more results' + }); + } + } else { + messagesStore.createMessage({ + type: 'error', + title: 'Unable to load more results', + message: 'Use a different search term for more results' + }); + } + moreVideosLoading.value = false; +}; @@ -273,7 +282,7 @@ const getListEntryType = (type: string) => { .show-more-btn-container { display: flex; width: 100%; - padding: 0 0 20px 0; + padding: 20px 0 20px 0; > a { margin: 0 auto; diff --git a/client/utils/googlevideoRegex.ts b/client/utils/googlevideoRegex.ts new file mode 100644 index 000000000..55b3e77c7 --- /dev/null +++ b/client/utils/googlevideoRegex.ts @@ -0,0 +1 @@ +export const googlevideoRegex = /https:\/\/.*?.googlevideo\.com/gi; diff --git a/client/utils/videoplayer/adapters/hlsAdapter.ts b/client/utils/videoplayer/adapters/hlsAdapter.ts index 60b987da9..41303fa33 100644 --- a/client/utils/videoplayer/adapters/hlsAdapter.ts +++ b/client/utils/videoplayer/adapters/hlsAdapter.ts @@ -111,7 +111,11 @@ export const hlsAdapter = async ({ }); playerInstance?.on(Hls.Events.ERROR, (event, data) => { - if (!['fragParsingError', 'bufferStalledError'].includes(data.details)) { + if ( + !['fragParsingError', 'bufferStalledError', 'levelLoadError', 'fragLoadError'].includes( + data.details + ) + ) { console.log('error', event, data); videoState.playerError = { message: data.details, diff --git a/client/utils/videoplayer/adapters/rxPlayerAdapter.ts b/client/utils/videoplayer/adapters/rxPlayerAdapter.ts index 3e7eadfd7..6faaf8952 100644 --- a/client/utils/videoplayer/adapters/rxPlayerAdapter.ts +++ b/client/utils/videoplayer/adapters/rxPlayerAdapter.ts @@ -41,13 +41,14 @@ export const rxPlayerAdapter = async ({ }: RxPlayerAdapterOptions) => { // RxPlayer.addFeatures([DASH_WASM]); - const RxPlayer = await import('rx-player').then(module => module.default); - const { DASH_WASM } = await import('rx-player/features'); + const RxPlayer = await import('rx-player/minimal').then(module => module.default); + const { DASH, DASH_WASM } = await import('rx-player/features'); const { EMBEDDED_DASH_WASM, EMBEDDED_WORKER } = await import( 'rx-player/experimental/features/embeds' ); try { + RxPlayer.addFeatures([DASH]); await DASH_WASM.initialize({ wasmUrl: EMBEDDED_DASH_WASM }).catch(() => {}); } catch { // Ignore @@ -257,7 +258,6 @@ export const rxPlayerAdapter = async ({ }; const mapAudioTracks = (audioTracks: IAvailableAudioTrack[]): AudioTrack[] => { - console.log(audioTracks); return audioTracks .filter(audioTrack => { if (videoState.languageList.length <= 1) return true; diff --git a/server/src/common/innertube/innertube.ts b/server/src/common/innertube/innertube.ts index 7a4f30d7d..129dc56a4 100644 --- a/server/src/common/innertube/innertube.ts +++ b/server/src/common/innertube/innertube.ts @@ -1,7 +1,9 @@ import path from 'path'; -import { Innertube, InnertubeConfig, UniversalCache } from 'youtubei.js'; +import { Innertube, InnertubeConfig, Log, UniversalCache } from 'youtubei.js'; import { innertubeFetch } from './innertubeFetch'; +Log.setLevel(Log.Level.ERROR); + let cacheDirectory = './cache'; if (process.env.VIEWTUBE_DATA_DIRECTORY) { cacheDirectory = path.join(process.env.VIEWTUBE_DATA_DIRECTORY, 'cache'); diff --git a/server/src/core/channels/channels.controller.ts b/server/src/core/channels/channels.controller.ts index 22a7fc1b7..215e3c89f 100644 --- a/server/src/core/channels/channels.controller.ts +++ b/server/src/core/channels/channels.controller.ts @@ -1,6 +1,6 @@ import { CacheInterceptor, CacheTTL } from '@nestjs/cache-manager'; import { Controller, Get, Header, Param, Query, Res, UseInterceptors } from '@nestjs/common'; -import { ApiResponse, ApiTags } from '@nestjs/swagger'; +import { ApiTags } from '@nestjs/swagger'; import { FastifyReply } from 'fastify'; import { ChannelsService } from './channels.service'; import { ChannelInfoErrorDto } from './dto/channel-info-error.dto'; @@ -38,8 +38,6 @@ export class ChannelsController { @Header('Cache-Control', 'public, max-age=3600') @Get(':id') - @ApiResponse({ status: 404 }) - @ApiResponse({ status: 500 }) @UseInterceptors(CacheInterceptor) @CacheTTL(3600000) getChannelInfo(@Param('id') channelId: string): Promise { @@ -48,8 +46,6 @@ export class ChannelsController { @Header('Cache-Control', 'public, max-age=3600') @Get(':id/home') - @ApiResponse({ status: 404 }) - @ApiResponse({ status: 500 }) @UseInterceptors(CacheInterceptor) @CacheTTL(3600000) getChannelHome(@Param('id') channelId: string): Promise { @@ -58,8 +54,6 @@ export class ChannelsController { @Header('Cache-Control', 'public, max-age=3600') @Get(':id/videos') - @ApiResponse({ status: 404 }) - @ApiResponse({ status: 500 }) @UseInterceptors(CacheInterceptor) @CacheTTL(3600000) getChannelVideos( @@ -71,8 +65,6 @@ export class ChannelsController { @Header('Cache-Control', 'public, max-age=3600') @Get('videos/continuation') - @ApiResponse({ status: 404 }) - @ApiResponse({ status: 500 }) @UseInterceptors(CacheInterceptor) @CacheTTL(3600000) getChannelVideosContinuation( @@ -85,8 +77,6 @@ export class ChannelsController { @Header('Cache-Control', 'public, max-age=3600') @Get(':id/shorts') - @ApiResponse({ status: 404 }) - @ApiResponse({ status: 500 }) @UseInterceptors(CacheInterceptor) @CacheTTL(3600000) getChannelShorts( @@ -98,8 +88,6 @@ export class ChannelsController { @Header('Cache-Control', 'public, max-age=3600') @Get(':id/livestreams') - @ApiResponse({ status: 404 }) - @ApiResponse({ status: 500 }) @UseInterceptors(CacheInterceptor) @CacheTTL(3600000) getChannelLivestreams( @@ -111,8 +99,6 @@ export class ChannelsController { @Header('Cache-Control', 'public, max-age=3600') @Get(':id/playlists') - @ApiResponse({ status: 404 }) - @ApiResponse({ status: 500 }) @UseInterceptors(CacheInterceptor) @CacheTTL(3600000) getChannelPlaylists(@Param('id') channelId: string): Promise { @@ -121,8 +107,6 @@ export class ChannelsController { @Header('Cache-Control', 'public, max-age=3600') @Get('playlists/continuation') - @ApiResponse({ status: 404 }) - @ApiResponse({ status: 500 }) @UseInterceptors(CacheInterceptor) @CacheTTL(3600000) getChannelPlaylistsContinuation( @@ -133,8 +117,6 @@ export class ChannelsController { @Header('Cache-Control', 'public, max-age=3600') @Get(':id/search') - @ApiResponse({ status: 404 }) - @ApiResponse({ status: 500 }) @UseInterceptors(CacheInterceptor) @CacheTTL(3600000) searchChannel( @@ -146,8 +128,6 @@ export class ChannelsController { @Header('Cache-Control', 'public, max-age=3600') @Get('search/continuation') - @ApiResponse({ status: 404 }) - @ApiResponse({ status: 500 }) @UseInterceptors(CacheInterceptor) @CacheTTL(3600000) searchChannelContinuation( @@ -158,8 +138,6 @@ export class ChannelsController { @Header('Cache-Control', 'public, max-age=3600') @Get('relatedchannels/continuation') - @ApiResponse({ status: 404 }) - @ApiResponse({ status: 500 }) @UseInterceptors(CacheInterceptor) @CacheTTL(3600000) getRelatedChannelsContinuation( @@ -170,8 +148,6 @@ export class ChannelsController { @Header('Cache-Control', 'public, max-age=3600') @Get(':id/communityposts') - @ApiResponse({ status: 404 }) - @ApiResponse({ status: 500 }) @UseInterceptors(CacheInterceptor) @CacheTTL(3600000) getChannelCommunityPosts(@Param('id') channelId: string): Promise { @@ -180,8 +156,6 @@ export class ChannelsController { @Header('Cache-Control', 'public, max-age=3600') @Get('communityposts/continuation') - @ApiResponse({ status: 404 }) - @ApiResponse({ status: 500 }) @UseInterceptors(CacheInterceptor) @CacheTTL(3600000) getChannelCommunityPostsContinuation( @@ -193,8 +167,6 @@ export class ChannelsController { @Header('Cache-Control', 'public, max-age=3600') @Get(':id/stats') - @ApiResponse({ status: 404 }) - @ApiResponse({ status: 500 }) @UseInterceptors(CacheInterceptor) @CacheTTL(3600000) getChannelStats(@Param('id') channelId: string): Promise { diff --git a/server/src/core/proxy/proxy.controller.ts b/server/src/core/proxy/proxy.controller.ts index cd6a08918..fb1a69e76 100644 --- a/server/src/core/proxy/proxy.controller.ts +++ b/server/src/core/proxy/proxy.controller.ts @@ -36,9 +36,4 @@ export class ProxyController { await this.proxyService.proxyStream(url, request, reply); } - @Get('m3u8') - @Header('Cache-Control', 'public, max-age=7200') - async proxyM3u8(@Query('url') url: string, @Query('proxyUrl') proxyUrl: string): Promise { - return this.proxyService.proxyM3u8(url, proxyUrl); - } } diff --git a/server/src/core/proxy/proxy.service.ts b/server/src/core/proxy/proxy.service.ts index f7c90d181..d3bd82fa9 100644 --- a/server/src/core/proxy/proxy.service.ts +++ b/server/src/core/proxy/proxy.service.ts @@ -39,36 +39,28 @@ export class ProxyService { } } - async proxyM3u8(url: string, proxyUrl: string): Promise { - try { - const headers = { - origin: 'https://www.youtube.com' - }; - const m3u8Response = await vtFetch(url, { headers, useProxy: true }); - const m3u8text = await m3u8Response.body.text(); - const urlReplacedText = m3u8text.replace( - /https:\/\/.*?.googlevideo\.com.*?\/seg\.ts/gi, - match => { - return `${proxyUrl}${encodeURI(match)}`; - } - ); - return urlReplacedText; - } catch (error) { - if (this.configService.get('NODE_ENV') !== 'production') { - this.logger.log(error); - } - } - } - async proxyStream(url: string, request: FastifyRequest, reply: FastifyReply): Promise { try { const rawHeaders = request.raw.headers; const headers = { range: rawHeaders.range, + 'accept-language': rawHeaders['accept-language'], + 'user-agent': rawHeaders['user-agent'], origin: 'https://www.youtube.com' }; const streamResponse = await vtFetch(url, { headers, useProxy: true }); - streamResponse.body.pipe(reply.raw); + + if (streamResponse.headers['location']) { + if (request.query['originUrl']) { + const originUrl = request.query['originUrl']; + reply.header( + 'location', + `${originUrl}/api/proxy/stream?originUrl=${originUrl}&url=${streamResponse.headers['location']}` + ); + } + } + + reply.status(streamResponse.statusCode).send(streamResponse.body); } catch (error) { if (this.configService.get('NODE_ENV') !== 'production') { this.logger.log(error); diff --git a/server/src/core/search/dto/search-query.dto.ts b/server/src/core/search/dto/search-query.dto.ts index 70459aadd..70546e7c1 100644 --- a/server/src/core/search/dto/search-query.dto.ts +++ b/server/src/core/search/dto/search-query.dto.ts @@ -3,4 +3,5 @@ import { SearchFiltersDto } from './search-filters.dto'; export class SearchQueryDto { q: string; filters?: SearchFiltersDto; + continuationString?: string; } diff --git a/server/src/core/search/search.controller.ts b/server/src/core/search/search.controller.ts index e2fb5a39a..29b4cd32a 100644 --- a/server/src/core/search/search.controller.ts +++ b/server/src/core/search/search.controller.ts @@ -14,6 +14,6 @@ export class SearchController { @Get() @Header('Cache-Control', 'public, max-age=1800') search(@Query() searchQuery: SearchQueryDto): Promise { - return this.searchService.doSearch(searchQuery); + return this.searchService.getSearch(searchQuery); } } diff --git a/server/src/core/search/search.service.ts b/server/src/core/search/search.service.ts index 3281cc9b2..4e7a0824c 100644 --- a/server/src/core/search/search.service.ts +++ b/server/src/core/search/search.service.ts @@ -2,6 +2,7 @@ import { BadRequestException, Injectable, Logger } from '@nestjs/common'; import { innertubeClient } from 'server/common/innertube/innertube'; import { toVTSearchResultDto } from 'server/mapper/converter/search/vt-search-result.converter'; import { VTSearchDto } from 'server/mapper/dto/search/vt-search.dto'; +import { Endpoints, Parser, Proto, YTNodes } from 'youtubei.js'; import { SearchFiltersDto } from './dto/search-filters.dto'; import { SearchQueryDto } from './dto/search-query.dto'; @@ -9,7 +10,7 @@ import { SearchQueryDto } from './dto/search-query.dto'; export class SearchService { constructor(private readonly logger: Logger) {} - async doSearch(searchQuery: SearchQueryDto): Promise { + async getSearch(searchQuery: SearchQueryDto): Promise { if (!searchQuery) { throw new BadRequestException(`Search query is required`); } @@ -24,8 +25,54 @@ export class SearchService { .split(',') as SearchFiltersDto['features']; } - const client = await innertubeClient(); - const searchResults = await client.search(searchQuery.q, searchQuery.filters); + const innertube = await innertubeClient(); + + const rawResults = await innertube.actions.execute( + Endpoints.SearchEndpoint.PATH, + Endpoints.SearchEndpoint.build({ + continuation: searchQuery.continuationString, + query: searchQuery.q, + params: searchQuery.filters ? Proto.encodeSearchFilters(searchQuery.filters) : undefined + }) + ); + + const parsedResults = Parser.parseResponse(rawResults.data); + + const contents = + parsedResults.contents_memo?.getType(YTNodes.SectionList).first().contents || + parsedResults.on_response_received_commands?.first().contents; + + const results = contents + .find( + content => + content.is(YTNodes.ItemSection) && content.contents && content.contents.length > 0 + ) + ?.as(YTNodes.ItemSection).contents; + + const continuationItems = [ + parsedResults.contents_memo?.getType(YTNodes.ContinuationItem), + parsedResults.continuation_contents_memo?.getType(YTNodes.ContinuationItem), + parsedResults.on_response_received_commands_memo?.getType(YTNodes.ContinuationItem), + parsedResults.on_response_received_endpoints_memo?.getType(YTNodes.ContinuationItem), + parsedResults.on_response_received_actions_memo?.getType(YTNodes.ContinuationItem), + parsedResults.sidebar_memo?.getType(YTNodes.ContinuationItem), + parsedResults.header_memo?.getType(YTNodes.ContinuationItem) + ] + .flat() + .filter(Boolean); + + const continuationToken = continuationItems?.find( + el => + el.type === 'ContinuationItem' && + el.endpoint?.payload?.request === 'CONTINUATION_REQUEST_TYPE_SEARCH' + )?.endpoint?.payload?.token; + + const searchResults = { + results, + estimated_results: parsedResults.estimated_results, + refinements: parsedResults.refinements, + continuation: continuationToken + }; return toVTSearchResultDto(searchResults); } diff --git a/server/src/core/videos/videos.service.ts b/server/src/core/videos/videos.service.ts index 3bfc3ac90..cc942efe8 100644 --- a/server/src/core/videos/videos.service.ts +++ b/server/src/core/videos/videos.service.ts @@ -168,6 +168,10 @@ export class VideosService { if (body) { const skipSectionsArray = await body.json(); + if (!Array.isArray(skipSectionsArray)) { + throw new InternalServerErrorException('Error fetching skip segments'); + } + const skipSections = skipSectionsArray?.find(el => el.videoID === id); if (!skipSections) { diff --git a/server/src/main.ts b/server/src/main.ts index 17ef1f9d6..cc88c2d4b 100644 --- a/server/src/main.ts +++ b/server/src/main.ts @@ -93,6 +93,7 @@ const bootstrap = async () => { directives: { defaultSrc: [`'self'`, `blob:`, `data:`], scriptSrc: [`'self'`, `blob:`, `https: 'unsafe-eval'`, `https: 'unsafe-inline'`], + connectSrc: [`'self'`, '*.viewtube.io'], scriptSrcAttr: null } } diff --git a/server/src/mapper/converter/search/vt-search-result.converter.ts b/server/src/mapper/converter/search/vt-search-result.converter.ts index 97bcf2c0e..dedc6f093 100644 --- a/server/src/mapper/converter/search/vt-search-result.converter.ts +++ b/server/src/mapper/converter/search/vt-search-result.converter.ts @@ -1,15 +1,19 @@ import { VTSearchDto } from 'server/mapper/dto/search/vt-search.dto'; -import { YT } from 'youtubei.js'; -import { - extractEstimatedResultCount, - extractRefinements, - extractSearchResults -} from './vt-search-result.extractors'; +import { SearchSourceApproximation } from './search-source-approximation'; +import { extractSearchResults } from './vt-search-result.extractors'; -export const toVTSearchResultDto = (searchResult: YT.Search): VTSearchDto => { +type SearchResults = { + results: SearchSourceApproximation[]; + estimated_results?: number; + refinements?: string[]; + continuation?: string; +}; + +export const toVTSearchResultDto = (searchResult: SearchResults): VTSearchDto => { return { results: extractSearchResults(searchResult.results), - estimatedResultCount: extractEstimatedResultCount(searchResult), - refinements: extractRefinements(searchResult) + estimatedResultCount: searchResult?.estimated_results, + refinements: searchResult?.refinements, + continuation: searchResult?.continuation }; }; diff --git a/server/src/mapper/dto/search/vt-search.dto.ts b/server/src/mapper/dto/search/vt-search.dto.ts index 3a5b1b140..41897c52a 100644 --- a/server/src/mapper/dto/search/vt-search.dto.ts +++ b/server/src/mapper/dto/search/vt-search.dto.ts @@ -16,4 +16,5 @@ export class VTSearchDto { >; estimatedResultCount: number; refinements: string[]; + continuation?: string; } diff --git a/server/src/metadata.ts b/server/src/metadata.ts index 9fa00714e..4cec99299 100644 --- a/server/src/metadata.ts +++ b/server/src/metadata.ts @@ -66,5 +66,5 @@ export default async () => { ["./core/videos/dto/dislike.dto"]: await import("./core/videos/dto/dislike.dto"), ["./core/videos/dto/sponsorblock/sponsorblock-segments.dto"]: await import("./core/videos/dto/sponsorblock/sponsorblock-segments.dto") }; - return { "@nestjs/swagger": { "models": [[import("./mapper/dto/vt-thumbnail.dto"), { "VTThumbnailDto": { quality: { required: false, type: () => String }, url: { required: true, type: () => String }, width: { required: true, type: () => Number }, height: { required: true, type: () => Number } } }], [import("./core/videos/dto/video-basic-info.dto"), { "VideoBasicInfoDto": { videoId: { required: true, type: () => String }, title: { required: true, type: () => String }, published: { required: false, type: () => Number }, publishedText: { required: true, type: () => String }, author: { required: true, type: () => String }, authorId: { required: true, type: () => String }, authorVerified: { required: false, type: () => Boolean }, authorThumbnails: { required: false, type: () => [t["./mapper/dto/vt-thumbnail.dto"].VTThumbnailDto] }, authorThumbnailUrl: { required: false, type: () => String }, videoThumbnails: { required: true, type: () => [t["./mapper/dto/vt-thumbnail.dto"].VTThumbnailDto] }, description: { required: false, type: () => String }, viewCount: { required: true, type: () => Number }, likeCount: { required: false, type: () => Number }, dislikeCount: { required: false, type: () => Number }, lengthSeconds: { required: false, type: () => Number }, lengthString: { required: false, type: () => String }, live: { required: false, type: () => Boolean } } }], [import("./user/settings/dto/settings.dto"), { "SettingsDto": { chapters: { required: true, type: () => Boolean }, theme: { required: true, type: () => String }, sponsorblockUrl: { required: true, type: () => String }, sponsorblockEnabled: { required: true, type: () => Boolean }, sponsorblockSegmentSponsor: { required: true, type: () => Object }, sponsorblockSegmentIntro: { required: true, type: () => Object }, sponsorblockSegmentOutro: { required: true, type: () => Object }, sponsorblockSegmentInteraction: { required: true, type: () => Object }, sponsorblockSegmentSelfpromo: { required: true, type: () => Object }, sponsorblockSegmentMusicOfftopic: { required: true, type: () => Object }, sponsorblockSegmentPreview: { required: true, type: () => Object }, sponsorblockSegmentFiller: { required: true, type: () => Object }, autoplay: { required: true, type: () => Boolean }, saveVideoHistory: { required: true, type: () => Boolean }, showHomeSubscriptions: { required: true, type: () => Boolean }, showHomeTrendingVideos: { required: true, type: () => Boolean }, showRecommendedVideos: { required: true, type: () => Boolean }, alwaysLoopVideo: { required: true, type: () => Boolean }, hideComments: { required: true, type: () => Boolean }, videoSpeedAsList: { required: true, type: () => Boolean }, autoplayNextVideo: { required: true, type: () => Boolean }, audioModeDefault: { required: true, type: () => Boolean }, defaultVideoSpeed: { required: true, type: () => Number }, maxVideoQuality: { required: true, type: () => String }, defaultAudioQuality: { required: true, type: () => String }, autoAdjustAudioQuality: { required: true, type: () => Boolean }, autoAdjustVideoQuality: { required: true, type: () => Boolean }, rewriteYouTubeURLs: { required: true, type: () => Boolean }, hideShortsFromSearch: { required: true, type: () => Boolean } } }], [import("./user/history/dto/video-visit.dto"), { "VideoVisitDto": { videoId: { required: true, type: () => String }, progressSeconds: { required: true, type: () => Number }, lengthSeconds: { required: true, type: () => Number }, lastVisit: { required: true, type: () => Date } } }], [import("./user/history/dto/video-visit-details.dto"), { "VideoVisitDetailsDto": { videoDetails: { required: true, type: () => t["./core/videos/dto/video-basic-info.dto"].VideoBasicInfoDto } } }], [import("./user/history/dto/history-response.dto"), { "HistoryResponseDto": { videos: { required: true, type: () => [t["./user/history/dto/video-visit-details.dto"].VideoVisitDetailsDto] }, videoCount: { required: true, type: () => Number } } }], [import("./user/history/dto/history.dto"), { "HistoryDto": { username: { required: true, type: () => String }, videoHistory: { required: true, type: () => [t["./user/history/dto/video-visit.dto"].VideoVisitDto] } } }], [import("./user/notifications/dto/notifications-subscription-keys.dto"), { "NotificationsSubscriptionKeys": { p256dh: { required: true, type: () => String }, auth: { required: true, type: () => String } } }], [import("./user/dto/push-notification.dto"), { "PushNotificationDto": { id: { required: true, type: () => String }, username: { required: true, type: () => String }, content: { required: true, type: () => Object }, sentAt: { required: true, type: () => Date } } }], [import("./core/channels/dto/channel-basic-info.dto"), { "ChannelBasicInfoDto": { authorId: { required: true, type: () => String }, author: { required: true, type: () => String }, authorUrl: { required: false, type: () => String }, authorThumbnails: { required: false, type: () => [t["./mapper/dto/vt-thumbnail.dto"].VTThumbnailDto] }, authorThumbnailUrl: { required: false, type: () => String }, authorVerified: { required: false, type: () => Boolean }, subCount: { required: false, type: () => Number }, videoCount: { required: false, type: () => Number }, description: { required: false, type: () => String } } }], [import("./user/subscriptions/dto/subscribed-channels-response.dto"), { "SubscribedChannelsResponseDto": { channels: { required: true, type: () => [t["./core/channels/dto/channel-basic-info.dto"].ChannelBasicInfoDto] }, channelCount: { required: true, type: () => Number } } }], [import("./user/subscriptions/dto/subscription-feed-response.dto"), { "SubscriptionFeedResponseDto": { videoCount: { required: true, type: () => Number }, videos: { required: true, type: () => [t["./core/videos/dto/video-basic-info.dto"].VideoBasicInfoDto] }, lastRefresh: { required: true, type: () => Date }, refreshInterval: { required: true, type: () => Number } } }], [import("./user/subscriptions/dto/subscription-status.dto"), { "SubscriptionStatusDto": { channelId: { required: true, type: () => String }, name: { required: false, type: () => String }, isSubscribed: { required: true, type: () => Boolean } } }], [import("./user/dto/userprofile.dto"), { "UserprofileDto": { username: { required: true, type: () => String }, profileImage: { required: true, type: () => String }, settings: { required: true, type: () => t["./user/settings/dto/settings.dto"].SettingsDto }, admin: { required: false, type: () => Boolean } } }], [import("./user/dto/session.dto"), { "SessionDto": { id: { required: true, type: () => String }, deviceName: { required: true, type: () => String }, deviceType: { required: true, type: () => String }, updatedAt: { required: true, type: () => Date }, expires: { required: true, type: () => Date }, current: { required: true, type: () => Boolean } } }], [import("./user/dto/userprofile-details.dto"), { "UserprofileDetailsDto": { username: { required: true, type: () => String }, profileImage: { required: true, type: () => String }, videoHistory: { required: true, type: () => [t["./user/history/dto/video-visit-details.dto"].VideoVisitDetailsDto] }, registeredAt: { required: true, type: () => Date }, totalVideosCount: { required: true, type: () => Number }, totalTimeString: { required: true, type: () => String }, subscribedChannelsCount: { required: true, type: () => Number }, admin: { required: true, type: () => Boolean } } }], [import("./user/user.dto"), { "UserDto": { username: { required: true, type: () => String }, password: { required: true, type: () => String } } }], [import("./admin/dto/info.dto"), { "InfoDto": { serverIpV4: { required: true, type: () => String }, serverIpV6: { required: true, type: () => String }, proxyIpV4: { required: true, type: () => String }, proxyIpV6: { required: true, type: () => String } } }], [import("./admin/dto/log-file.dto"), { "LogFileDto": { name: { required: true, type: () => String }, size: { required: true, type: () => Number }, created: { required: true, type: () => Number }, lastModified: { required: true, type: () => Number } } }], [import("./admin/dto/logs.dto"), { "LogsDto": { logFiles: { required: true, type: () => [t["./admin/dto/log-file.dto"].LogFileDto] }, location: { required: true, type: () => String } } }], [import("./admin/dto/server-settings.dto"), { "ServerSettingsDto": { registrationEnabled: { required: true, type: () => Boolean }, requireLoginEverywhere: { required: true, type: () => Boolean } } }], [import("./auth/captcha/dto/captcha.dto"), { "CaptchaDto": { token: { required: true, type: () => String }, captchaImage: { required: true, type: () => String } } }], [import("./auth/register/dto/registration.dto"), { "RegistrationDto": { username: { required: true, type: () => String }, password: { required: true, type: () => String }, captchaToken: { required: true, type: () => String }, captchaSolution: { required: true, type: () => String } } }], [import("./core/channels/dto/basic/channel-community-post.dto"), { "ChannelCommunityPostDto": { postText: { required: true, type: () => String }, postId: { required: true, type: () => String }, author: { required: true, type: () => String }, authorThumbnails: { required: true, type: () => String }, publishedText: { required: true, type: () => String }, voteCount: { required: true, type: () => String }, commentCount: { required: true, type: () => String }, postContent: { required: true, type: () => Object } } }], [import("./core/channels/dto/response/channel-community-posts-continuation.dto"), { "ChannelCommunityPostsContinuationDto": { innerTubeApi: { required: true, type: () => String }, items: { required: true, type: () => [t["./core/channels/dto/basic/channel-community-post.dto"].ChannelCommunityPostDto] }, continuation: { required: true, type: () => String } } }], [import("./core/channels/dto/response/channel-community-posts.dto"), { "ChannelCommunityPostsDto": { channelIdType: { required: true, type: () => Number }, innerTubeApi: { required: true, type: () => String }, items: { required: true, type: () => [t["./core/channels/dto/basic/channel-community-post.dto"].ChannelCommunityPostDto] }, continuation: { required: true, type: () => String } } }], [import("./core/channels/dto/basic/channel-image.dto"), { "ChannelImageDto": { url: { required: true, type: () => String }, width: { required: true, type: () => Number }, height: { required: true, type: () => Number } } }], [import("./core/channels/dto/basic/channel-video.dto"), { "ChannelVideoDto": { author: { required: true, type: () => String }, authorId: { required: true, type: () => String }, durationText: { required: false, type: () => String }, lengthSeconds: { required: false, type: () => Number }, liveNow: { required: true, type: () => Boolean }, premiere: { required: true, type: () => Boolean }, premium: { required: true, type: () => Boolean }, publishedText: { required: true, type: () => String }, title: { required: true, type: () => String }, type: { required: true, type: () => String }, videoId: { required: true, type: () => String }, videoThumbnails: { required: true, type: () => [t["./core/channels/dto/basic/channel-image.dto"].ChannelImageDto], nullable: true }, viewCount: { required: true, type: () => Number }, viewCountText: { required: true, type: () => String } } }], [import("./core/channels/dto/basic/channel-mix.dto"), { "ChannelMixDto": { playlistId: { required: true, type: () => String }, title: { required: true, type: () => String }, description: { required: true, type: () => String }, videoCount: { required: true, type: () => Number }, url: { required: true, type: () => String }, thumbnails: { required: true, type: () => [t["./core/channels/dto/basic/channel-image.dto"].ChannelImageDto] } } }], [import("./core/channels/dto/basic/channel-playlist.dto"), { "ChannelPlaylistDto": { author: { required: true, type: () => String }, authorId: { required: true, type: () => String }, authorUrl: { required: true, type: () => String }, playlistId: { required: true, type: () => String }, playlistThumbnail: { required: true, type: () => String }, playlistUrl: { required: true, type: () => String }, title: { required: true, type: () => String }, type: { required: true, type: () => String }, videoCount: { required: true, type: () => Number } } }], [import("./core/channels/dto/basic/related-channel.dto"), { "RelatedChannelDto": { channelName: { required: false, type: () => String }, channelId: { required: false, type: () => String }, channelUrl: { required: false, type: () => String }, author: { required: true, type: () => String }, authorId: { required: true, type: () => String }, authorUrl: { required: true, type: () => String }, authorThumbnails: { required: true, type: () => [Object] }, videoCount: { required: true, type: () => Number }, subscriberText: { required: true, type: () => String }, subscriberCount: { required: true, type: () => Number }, verified: { required: true, type: () => Boolean }, officialArtist: { required: true, type: () => Boolean }, officialArist: { required: true, type: () => Boolean } } }], [import("./core/channels/dto/response/channel-home-item.dto"), { "ChannelHomeItemDto": { shelfName: { required: true, type: () => String }, type: { required: true, type: () => Object }, items: { required: true, type: () => Object } } }], [import("./core/channels/dto/response/channel-home.dto"), { "ChannelHomeDto": { featuredVideo: { required: true, type: () => t["./core/channels/dto/basic/channel-video.dto"].ChannelVideoDto }, items: { required: true, type: () => [t["./core/channels/dto/response/channel-home-item.dto"].ChannelHomeItemDto] } } }], [import("./core/channels/dto/basic/channel-link.dto"), { "ChannelLinkDto": { url: { required: true, type: () => String }, icon: { required: true, type: () => String }, title: { required: true, type: () => String } } }], [import("./core/channels/dto/response/channel-info.dto"), { "ChannelInfoDto": { author: { required: true, type: () => String }, authorId: { required: true, type: () => String }, authorUrl: { required: true, type: () => String }, oResponse: { required: true, type: () => Object }, authorBanners: { required: true, type: () => [t["./core/channels/dto/basic/channel-image.dto"].ChannelImageDto] }, authorThumbnails: { required: true, type: () => [t["./core/channels/dto/basic/channel-image.dto"].ChannelImageDto] }, subscriberText: { required: true, type: () => String }, subscriberCount: { required: true, type: () => Number }, description: { required: true, type: () => String }, isFamilyFriendly: { required: true, type: () => Boolean }, relatedChannels: { required: true, type: () => ({ items: { required: true, type: () => [t["./core/channels/dto/basic/related-channel.dto"].RelatedChannelDto] }, continuation: { required: true, type: () => String, nullable: true } }) }, allowedRegions: { required: true, type: () => [String] }, isVerified: { required: true, type: () => Boolean }, isOfficialArtist: { required: true, type: () => Boolean }, tags: { required: true, type: () => [String] }, channelIdType: { required: true, type: () => Number }, channelTabs: { required: true, type: () => [String] }, alertMessage: { required: true, type: () => String }, channelLinks: { required: true, type: () => ({ primaryLinks: { required: true, type: () => [t["./core/channels/dto/basic/channel-link.dto"].ChannelLinkDto] }, secondaryLinks: { required: true, type: () => [t["./core/channels/dto/basic/channel-link.dto"].ChannelLinkDto] } }) } } }], [import("./core/channels/dto/response/channel-playlists-continuation.dto"), { "ChannelPlaylistsContinuationDto": { items: { required: false, type: () => [t["./core/channels/dto/basic/channel-playlist.dto"].ChannelPlaylistDto] }, continuation: { required: false, type: () => String } } }], [import("./core/channels/dto/response/channel-playlists.dto"), { "ChannelPlaylistsDto": { channelIdType: { required: false, type: () => Number }, alertMessage: { required: false, type: () => String }, items: { required: false, type: () => [t["./core/channels/dto/basic/channel-playlist.dto"].ChannelPlaylistDto] }, continuation: { required: false, type: () => String } } }], [import("./core/channels/dto/response/channel-search-continuation.dto"), { "ChannelSearchContinuationDto": { items: { required: false, type: () => [t["./core/channels/dto/basic/channel-video.dto"].ChannelVideoDto] }, continuation: { required: false, type: () => String } } }], [import("./core/channels/dto/response/channel-search.dto"), { "ChannelSearchDto": { items: { required: false, type: () => [t["./core/channels/dto/basic/channel-video.dto"].ChannelVideoDto] }, continuation: { required: false, type: () => String } } }], [import("./core/channels/dto/response/channel-stats.dto"), { "ChannelStatsDto": { joinedDate: { required: true, type: () => Number }, viewCount: { required: true, type: () => Number }, location: { required: true, type: () => String } } }], [import("./core/channels/dto/response/channel-videos-continuation.dto"), { "ChannelVideosContinuationDto": { items: { required: false, type: () => [t["./core/channels/dto/basic/channel-video.dto"].ChannelVideoDto] }, continuation: { required: false, type: () => String } } }], [import("./core/channels/dto/response/channel-videos.dto"), { "ChannelVideosDto": { channelIdType: { required: false, enum: t["./core/channels/yt-channel-info/app/types"].ChannelIdType }, alertMessage: { required: false, type: () => String }, items: { required: false, type: () => [t["./core/channels/dto/basic/channel-video.dto"].ChannelVideoDto] }, continuation: { required: false, type: () => String } } }], [import("./core/channels/dto/response/related-channels-continuation.dto"), { "RelatedChannelsContinuationDto": { items: { required: true, type: () => [Object] }, continuation: { required: true, type: () => String } } }], [import("./core/channels/dto/channel-info-error.dto"), { "ChannelInfoErrorDto": { alertMessage: { required: true, type: () => String } } }], [import("./mapper/dto/vt-author.dto"), { "VTAuthorDto": { id: { required: true, type: () => String }, name: { required: true, type: () => String }, thumbnails: { required: false, type: () => [t["./mapper/dto/vt-thumbnail.dto"].VTThumbnailDto] }, isVerified: { required: false, type: () => Boolean }, isArtist: { required: false, type: () => Boolean }, handle: { required: false, type: () => String }, subscriberCount: { required: false, type: () => Number } } }], [import("./mapper/dto/comments/vt-comment.dto"), { "VTCommentDto": { id: { required: true, type: () => String }, content: { required: true, type: () => String }, pinned: { required: false, type: () => Boolean }, creatorHeart: { required: false, type: () => Boolean }, likeCount: { required: true, type: () => Number }, replyCount: { required: true, type: () => Number }, hasReplies: { required: false, type: () => Boolean }, isEdited: { required: false, type: () => Boolean }, replyContinuation: { required: false, type: () => String }, creatorReplied: { required: false, type: () => Boolean }, creatorReplyThumbnail: { required: false, type: () => [t["./mapper/dto/vt-thumbnail.dto"].VTThumbnailDto] }, channelOwner: { required: false, type: () => Boolean }, channelMember: { required: false, type: () => Boolean }, published: { required: true, type: () => ({ date: { required: true, type: () => Date }, text: { required: true, type: () => String } }) }, author: { required: true, type: () => t["./mapper/dto/vt-author.dto"].VTAuthorDto } } }], [import("./mapper/converter/comments/vt-comments-reply.response.dto"), { "VTCommentsReplyResponseDto": { comments: { required: true, type: () => [t["./mapper/dto/comments/vt-comment.dto"].VTCommentDto] }, continuation: { required: false, type: () => String } } }], [import("./mapper/dto/comments/vt-comment-emoji.dto"), { "VTCommentEmojiDto": { name: { required: true, type: () => String }, shortcuts: { required: true, type: () => [String] }, thumbnails: { required: true, type: () => [t["./mapper/dto/vt-thumbnail.dto"].VTThumbnailDto] } } }], [import("./mapper/dto/comments/vt-comments-header.dto"), { "VTCommentsHeaderDto": { commentsCount: { required: true, type: () => Number }, customEmojis: { required: true, type: () => [t["./mapper/dto/comments/vt-comment-emoji.dto"].VTCommentEmojiDto] } } }], [import("./mapper/converter/comments/vt-comments-response.dto"), { "VTCommentsResponseDto": { comments: { required: true, type: () => [t["./mapper/dto/comments/vt-comment.dto"].VTCommentDto] }, header: { required: true, type: () => t["./mapper/dto/comments/vt-comments-header.dto"].VTCommentsHeaderDto }, continuation: { required: false, type: () => String } } }], [import("./mapper/dto/vt-video-core.dto"), { "VTVideoCoreDto": { id: { required: true, type: () => String }, title: { required: true, type: () => String }, duration: { required: false, type: () => ({ text: { required: true, type: () => String }, seconds: { required: true, type: () => Number } }) } } }], [import("./mapper/dto/vt-video.dto"), { "VTVideoDto": { author: { required: false, type: () => t["./mapper/dto/vt-author.dto"].VTAuthorDto }, description: { required: false, type: () => String }, thumbnails: { required: false, type: () => [t["./mapper/dto/vt-thumbnail.dto"].VTThumbnailDto] }, richThumbnails: { required: false, type: () => [t["./mapper/dto/vt-thumbnail.dto"].VTThumbnailDto] }, published: { required: false, type: () => ({ date: { required: false, type: () => Date }, text: { required: false, type: () => String } }) }, viewCount: { required: false, type: () => Number }, upcoming: { required: false, type: () => Date }, live: { required: false, type: () => Boolean } } }], [import("./core/homepage/dto/home-feed.dto"), { "HomeFeedDto": { videos: { required: true, type: () => [t["./mapper/dto/vt-video.dto"].VTVideoDto] } } }], [import("./core/playlists/dto/playlist-image.dto"), { "PlaylistImageDto": { url: { required: true, type: () => String, nullable: true }, width: { required: true, type: () => Number }, height: { required: true, type: () => Number } } }], [import("./core/playlists/dto/playlist-item.dto"), { "PlaylistItemDto": { title: { required: true, type: () => String }, index: { required: true, type: () => Number }, id: { required: true, type: () => String }, shortUrl: { required: true, type: () => String }, url: { required: true, type: () => String }, author: { required: true, type: () => ({ name: { required: true, type: () => String }, url: { required: true, type: () => String }, channelID: { required: true, type: () => String } }) }, thumbnails: { required: true, type: () => [t["./core/playlists/dto/playlist-image.dto"].PlaylistImageDto] }, bestThumbnail: { required: true, type: () => t["./core/playlists/dto/playlist-image.dto"].PlaylistImageDto }, isLive: { required: true, type: () => Boolean }, duration: { required: true, type: () => String, nullable: true }, durationSec: { required: true, type: () => Number, nullable: true } } }], [import("./core/playlists/dto/playlist-result.dto"), { "PlaylistResultDto": { id: { required: true, type: () => String }, url: { required: true, type: () => String }, title: { required: true, type: () => String }, estimatedItemCount: { required: true, type: () => Number }, views: { required: true, type: () => Number }, thumbnails: { required: true, type: () => [t["./core/playlists/dto/playlist-image.dto"].PlaylistImageDto] }, bestThumbnail: { required: true, type: () => t["./core/playlists/dto/playlist-image.dto"].PlaylistImageDto }, lastUpdated: { required: true, type: () => String }, description: { required: true, type: () => String, nullable: true }, visibility: { required: true, type: () => Object }, author: { required: true, type: () => ({ name: { required: true, type: () => String }, url: { required: true, type: () => String }, avatars: { required: true, type: () => [t["./core/playlists/dto/playlist-image.dto"].PlaylistImageDto] }, bestAvatar: { required: true, type: () => t["./core/playlists/dto/playlist-image.dto"].PlaylistImageDto }, channelID: { required: true, type: () => String } }) }, items: { required: true, type: () => [t["./core/playlists/dto/playlist-item.dto"].PlaylistItemDto] }, continuation: { required: true, type: () => Object, nullable: true } } }], [import("./mapper/dto/vt-channel.dto"), { "VTChannelDto": { id: { required: true, type: () => String }, name: { required: true, type: () => String }, handle: { required: false, type: () => String }, thumbnails: { required: false, type: () => [t["./mapper/dto/vt-thumbnail.dto"].VTThumbnailDto] }, isVerified: { required: false, type: () => Boolean }, isArtist: { required: false, type: () => Boolean }, subscribers: { required: false, type: () => Number }, description: { required: false, type: () => String }, videoCount: { required: false, type: () => Number } } }], [import("./mapper/dto/search/vt-search-channel-result.dto"), { "VTSearchChannelResultDto": { type: { required: true, type: () => String } } }], [import("./mapper/dto/search/vt-search-movie.dto"), { "VTSearchMovieDto": { type: { required: true, type: () => String } } }], [import("./mapper/dto/search/vt-search-playlist.dto"), { "VTSearchPlaylistDto": { type: { required: true, type: () => String }, id: { required: true, type: () => String }, title: { required: true, type: () => String }, thumbnails: { required: false, type: () => [t["./mapper/dto/vt-thumbnail.dto"].VTThumbnailDto] }, author: { required: false, type: () => t["./mapper/dto/vt-author.dto"].VTAuthorDto }, videoCount: { required: false, type: () => Number }, firstVideos: { required: false, type: () => [t["./mapper/dto/vt-video-core.dto"].VTVideoCoreDto] } } }], [import("./mapper/dto/search/vt-search-video-result.dto"), { "VTSearchVideoResultDto": { type: { required: true, type: () => String } } }], [import("./mapper/dto/search/vt-search-shelf.dto"), { "VTSearchShelfDto": { type: { required: true, type: () => String }, title: { required: true, type: () => String }, items: { required: true, type: () => [t["./mapper/dto/search/vt-search-video-result.dto"].VTSearchVideoResultDto] } } }], [import("./mapper/dto/vt-short.dto"), { "VTShortDto": { type: { required: true, type: () => String }, id: { required: true, type: () => String }, title: { required: true, type: () => String }, thumbnails: { required: false, type: () => [t["./mapper/dto/vt-thumbnail.dto"].VTThumbnailDto] }, viewCount: { required: false, type: () => Number }, duration: { required: false, type: () => ({ text: { required: true, type: () => String }, seconds: { required: true, type: () => Number } }) } } }], [import("./mapper/dto/search/vt-shorts-shelf.dto"), { "VTShortsShelfDto": { type: { required: true, type: () => String }, title: { required: true, type: () => String }, items: { required: true, type: () => [t["./mapper/dto/vt-short.dto"].VTShortDto] } } }], [import("./mapper/dto/search/vt-search.dto"), { "VTSearchDto": { results: { required: true, type: () => [Object] }, estimatedResultCount: { required: true, type: () => Number }, refinements: { required: true, type: () => [String] } } }], [import("./core/search/dto/search-filters.dto"), { "SearchFiltersDto": { upload_date: { required: false, type: () => Object }, type: { required: false, type: () => Object }, duration: { required: false, type: () => Object }, sort_by: { required: false, type: () => Object }, features: { required: false, type: () => [Object] } } }], [import("./core/search/dto/search-query.dto"), { "SearchQueryDto": { q: { required: true, type: () => String }, filters: { required: false, type: () => t["./core/search/dto/search-filters.dto"].SearchFiltersDto } } }], [import("./core/videos/dto/dislike.dto"), { "DislikeDto": { id: { required: true, type: () => String }, dateCreated: { required: true, type: () => String }, likes: { required: true, type: () => Number }, dislikes: { required: true, type: () => Number }, rating: { required: true, type: () => Number }, viewCount: { required: true, type: () => Number }, deleted: { required: true, type: () => Boolean } } }], [import("./mapper/dto/endscreen/vt-endscreen-element.dto"), { "VTEndscreenElementDto": { position: { required: true, type: () => ({ left: { required: true, type: () => Number }, top: { required: true, type: () => Number } }) }, dimensions: { required: true, type: () => ({ width: { required: true, type: () => Number }, aspectRatio: { required: true, type: () => Number } }) }, startMs: { required: true, type: () => Number }, endMs: { required: true, type: () => Number }, thumbnails: { required: true, type: () => [t["./mapper/dto/vt-thumbnail.dto"].VTThumbnailDto] } } }], [import("./mapper/dto/infocard/vt-playlist-card-content.dto"), { "VTPlaylistCardContentDto": { type: { required: true, type: () => String }, id: { required: true, type: () => String }, firstVideoId: { required: true, type: () => String }, videoCount: { required: true, type: () => Number }, title: { required: true, type: () => String }, author: { required: true, type: () => ({ name: { required: true, type: () => String } }) } } }], [import("./mapper/dto/infocard/vt-simple-card-content.dto"), { "VTSimpleCardContentDto": { type: { required: true, type: () => String }, title: { required: true, type: () => String }, thumbnails: { required: true, type: () => [t["./mapper/dto/vt-thumbnail.dto"].VTThumbnailDto] }, displayDomain: { required: true, type: () => String }, url: { required: true, type: () => String } } }], [import("./mapper/dto/infocard/vt-video-card-content.dto"), { "VTVideoCardContentDto": { type: { required: true, type: () => String }, id: { required: true, type: () => String }, title: { required: true, type: () => String }, author: { required: true, type: () => ({ name: { required: true, type: () => String } }) }, viewCount: { required: true, type: () => Number }, thumbnails: { required: true, type: () => [t["./mapper/dto/vt-thumbnail.dto"].VTThumbnailDto] }, duration: { required: true, type: () => ({ text: { required: true, type: () => String }, seconds: { required: true, type: () => Number } }) } } }], [import("./mapper/dto/infocard/vt-info-card.dto"), { "VTInfoCardDto": { shortName: { required: true, type: () => String }, startMs: { required: true, type: () => Number }, endMs: { required: true, type: () => Number }, content: { required: true, type: () => Object } } }], [import("./mapper/dto/vt-caption-track.dto"), { "VTCaptionTrackDto": { baseUrl: { required: true, type: () => String }, name: { required: true, type: () => String }, languageCode: { required: true, type: () => String } } }], [import("./mapper/dto/vt-chapter.dto"), { "VTChapterDto": { title: { required: true, type: () => String }, startMs: { required: true, type: () => Number }, thumbnails: { required: true, type: () => [t["./mapper/dto/vt-thumbnail.dto"].VTThumbnailDto] } } }], [import("./mapper/dto/vt-legacy-format.dto"), { "VTLegacyFormatDto": { mimeType: { required: true, type: () => String }, bitrate: { required: true, type: () => Number }, averageBitrate: { required: true, type: () => Number }, width: { required: true, type: () => Number }, height: { required: true, type: () => Number }, lastModified: { required: true, type: () => Date }, contentLength: { required: true, type: () => Number }, quality: { required: true, type: () => String }, qualityLabel: { required: true, type: () => String }, fps: { required: true, type: () => Number }, url: { required: true, type: () => String }, audioQuality: { required: true, type: () => String }, approxDurationMs: { required: true, type: () => Number }, audioSampleRate: { required: true, type: () => Number }, audioChannels: { required: true, type: () => Number }, hasAudio: { required: true, type: () => Boolean }, hasVideo: { required: true, type: () => Boolean } } }], [import("./mapper/dto/vt-preview-thumbnail.dto"), { "VTPreviewThumbnailDto": { urlTemplate: { required: true, type: () => String }, width: { required: true, type: () => Number }, height: { required: true, type: () => Number }, count: { required: true, type: () => Number }, interval: { required: true, type: () => Number }, columns: { required: true, type: () => Number }, rows: { required: true, type: () => Number }, previewThumbnailCount: { required: true, type: () => Number } } }], [import("./mapper/dto/vt-video-info.dto"), { "VTVideoInfoDto": { id: { required: true, type: () => String }, title: { required: true, type: () => String }, subtitle: { required: true, type: () => String }, author: { required: true, type: () => ({ id: { required: true, type: () => String }, name: { required: true, type: () => String }, thumbnails: { required: true, type: () => [t["./mapper/dto/vt-thumbnail.dto"].VTThumbnailDto] }, isVerified: { required: true, type: () => Boolean }, isArtist: { required: true, type: () => Boolean }, handle: { required: true, type: () => String }, subscriberCount: { required: true, type: () => String } }) }, description: { required: true, type: () => String }, thumbnails: { required: true, type: () => [t["./mapper/dto/vt-thumbnail.dto"].VTThumbnailDto] }, duration: { required: true, type: () => ({ text: { required: true, type: () => String }, seconds: { required: true, type: () => Number } }) }, published: { required: true, type: () => ({ date: { required: true, type: () => Date }, text: { required: true, type: () => String } }) }, viewCount: { required: true, type: () => Number }, upcoming: { required: false, type: () => Date }, live: { required: true, type: () => Boolean }, watching: { required: false, type: () => Number }, unlisted: { required: true, type: () => Boolean }, familyFriendly: { required: true, type: () => Boolean }, likeCount: { required: true, type: () => Number }, category: { required: true, type: () => String }, previewThumbnails: { required: true, type: () => [t["./mapper/dto/vt-preview-thumbnail.dto"].VTPreviewThumbnailDto] }, endscreen: { required: true, type: () => ({ elements: { required: true, type: () => [t["./mapper/dto/endscreen/vt-endscreen-element.dto"].VTEndscreenElementDto] }, startMs: { required: true, type: () => Number } }) }, keywords: { required: true, type: () => [String] }, captions: { required: true, type: () => [t["./mapper/dto/vt-caption-track.dto"].VTCaptionTrackDto] }, infoCards: { required: true, type: () => [t["./mapper/dto/infocard/vt-info-card.dto"].VTInfoCardDto] }, recommendedVideos: { required: true, type: () => [t["./mapper/dto/vt-video.dto"].VTVideoDto] }, chapters: { required: true, type: () => [t["./mapper/dto/vt-chapter.dto"].VTChapterDto] }, commentCount: { required: true, type: () => Number }, legacyFormats: { required: true, type: () => [t["./mapper/dto/vt-legacy-format.dto"].VTLegacyFormatDto] }, dashManifest: { required: false, type: () => String }, hlsManifestUrl: { required: false, type: () => String }, dashManifestUrl: { required: false, type: () => String } } }], [import("./core/videos/dto/sponsorblock/sponsorblock-segment.dto"), { "SponsorBlockSegmentDto": { UUID: { required: true, type: () => String }, category: { required: true, type: () => String }, segment: { required: true, type: () => [Number] }, videoDuration: { required: true, type: () => Number }, endPercentage: { required: false, type: () => Number } } }], [import("./core/videos/dto/sponsorblock/sponsorblock-segments.dto"), { "SponsorBlockSegmentsDto": { hash: { required: true, type: () => String }, segments: { required: true, type: () => [t["./core/videos/dto/sponsorblock/sponsorblock-segment.dto"].SponsorBlockSegmentDto] }, videoID: { required: true, type: () => String } } }], [import("./mapper/dto/endscreen/vt-endscreen-channel.dto"), { "VTEndscreenChannelDto": { type: { required: true, type: () => String }, title: { required: true, type: () => String }, id: { required: true, type: () => String }, description: { required: true, type: () => String } } }], [import("./mapper/dto/endscreen/vt-endscreen-video.dto"), { "VTEndscreenVideoDto": { type: { required: true, type: () => String }, title: { required: true, type: () => String }, id: { required: true, type: () => String }, viewCount: { required: true, type: () => Number }, duration: { required: true, type: () => ({ text: { required: true, type: () => String }, seconds: { required: true, type: () => Number } }) } } }], [import("./core/playlists/dto/preview-video.dto"), { "PreviewVideoDto": { title: { required: false, type: () => String }, videoId: { required: false, type: () => String }, videoThumbnails: { required: true, type: () => [t["./mapper/dto/vt-thumbnail.dto"].VTThumbnailDto] } } }], [import("./core/channels/dto/link-thumbnail.dto"), { "LinkThumbnailDto": { url: { required: true, type: () => String } } }], [import("./core/playlists/dto/playlist-basic-info.dto"), { "PlaylistBasicInfoDto": { title: { required: true, type: () => String }, playlistId: { required: true, type: () => String }, playlistVideoLink: { required: true, type: () => String }, playlistLink: { required: true, type: () => String }, author: { required: true, type: () => String }, authorId: { required: true, type: () => String }, authorUrl: { required: false, type: () => String }, videoCount: { required: true, type: () => Number }, firstVideoId: { required: false, type: () => String }, playlistThumbnails: { required: false, type: () => [t["./mapper/dto/vt-thumbnail.dto"].VTThumbnailDto] }, previewVideos: { required: false, type: () => [t["./core/playlists/dto/preview-video.dto"].PreviewVideoDto] } } }], [import("./core/videoplayback/dto/videoplayback-query.dto"), { "VideoplaybackQueryDto": { expire: { required: true, type: () => Number }, itag: { required: true, type: () => Number }, ei: { required: false, type: () => String }, ip: { required: false, type: () => String }, id: { required: false, type: () => String }, aitags: { required: false, type: () => String }, source: { required: false, type: () => String }, requiressl: { required: false, type: () => String }, mh: { required: false, type: () => String }, mm: { required: false, type: () => String }, mn: { required: false, type: () => String }, ms: { required: false, type: () => String }, mv: { required: false, type: () => String }, mvi: { required: false, type: () => String }, pl: { required: false, type: () => Number }, initcwndbps: { required: false, type: () => Number }, vprv: { required: false, type: () => Number }, mime: { required: false, type: () => String }, ns: { required: false, type: () => String }, gir: { required: false, type: () => String }, clen: { required: false, type: () => Number }, dur: { required: false, type: () => Number }, lmt: { required: false, type: () => Number }, mt: { required: false, type: () => Number }, fvip: { required: false, type: () => Number }, keepalive: { required: false, type: () => String }, fexp: { required: false, type: () => Number }, c: { required: false, type: () => String }, txp: { required: false, type: () => Number }, n: { required: false, type: () => String }, sparams: { required: false, type: () => String }, sig: { required: false, type: () => String }, lsparams: { required: false, type: () => String }, lsig: { required: false, type: () => String }, ratebypass: { required: false, type: () => String }, host: { required: true, type: () => String } } }]], "controllers": [[import("./user/settings/settings.controller"), { "SettingsController": { "setSettings": {}, "getSettings": { type: t["./user/settings/dto/settings.dto"].SettingsDto } } }], [import("./user/history/history.controller"), { "HistoryController": { "getHistory": { type: t["./user/history/dto/history-response.dto"].HistoryResponseDto }, "setVideoVisit": {}, "getVideoVisit": { type: t["./user/history/dto/video-visit.dto"].VideoVisitDto }, "deleteEntireHistory": {}, "deleteHistoryEntry": {}, "deleteHistoryRange": {} } }], [import("./user/notifications/notifications.controller"), { "NotificationsController": { "subscribeToNotifications": {} } }], [import("./user/subscriptions/subscriptions.controller"), { "SubscriptionsController": { "getSubscribedChannels": { type: t["./user/subscriptions/dto/subscribed-channels-response.dto"].SubscribedChannelsResponseDto }, "getSubscriptionVideos": { type: t["./user/subscriptions/dto/subscription-feed-response.dto"].SubscriptionFeedResponseDto }, "getSubscription": { type: t["./user/subscriptions/dto/subscription-status.dto"].SubscriptionStatusDto }, "createSubscription": { type: t["./user/subscriptions/dto/subscription-status.dto"].SubscriptionStatusDto }, "createMultipleSubscriptions": {}, "deleteSubscription": { type: t["./user/subscriptions/dto/subscription-status.dto"].SubscriptionStatusDto } } }], [import("./user/user.controller"), { "UserController": { "getProfile": { type: t["./user/dto/userprofile.dto"].UserprofileDto }, "getProfileDetails": { type: t["./user/dto/userprofile-details.dto"].UserprofileDetailsDto }, "getSessions": { type: [t["./user/dto/session.dto"].SessionDto] }, "getCurrentSession": { type: t["./user/dto/session.dto"].SessionDto }, "updateSession": {}, "deleteSession": {}, "getExport": {}, "getProfileImage": {}, "uploadProfileImage": {}, "deleteProfileImage": {}, "deleteUser": {}, "changePassword": {} } }], [import("./admin/admin.controller"), { "AdminController": { "getInfo": { type: t["./admin/dto/info.dto"].InfoDto }, "getServerSettings": { type: t["./admin/dto/server-settings.dto"].ServerSettingsDto }, "updateServerSettings": { type: t["./admin/dto/server-settings.dto"].ServerSettingsDto }, "getLogs": { type: t["./admin/dto/logs.dto"].LogsDto }, "downloadLogFile": {}, "findAll": { type: [String] }, "isVideoBlocked": { type: Boolean }, "create": { type: String }, "delete": {}, "createUser": { type: t["./user/dto/userprofile.dto"].UserprofileDto } } }], [import("./auth/auth.controller"), { "AuthController": { "login": {}, "logout": {} } }], [import("./auth/captcha/captcha.controller"), { "CaptchaController": { "getCaptcha": { type: t["./auth/captcha/dto/captcha.dto"].CaptchaDto } } }], [import("./auth/register/register.controller"), { "RegisterController": { "registerUser": { type: Object } } }], [import("./core/autocomplete/autocomplete.controller"), { "AutocompleteController": { "getQuery": { type: [String] } } }], [import("./core/channels/channels.controller"), { "ChannelsController": { "getTinyThumbnailJpg": {}, "getTinyThumbnailWebp": {}, "getChannelInfo": { type: t["./core/channels/dto/response/channel-info.dto"].ChannelInfoDto }, "getChannelHome": { type: t["./core/channels/dto/response/channel-home.dto"].ChannelHomeDto }, "getChannelVideos": { type: t["./core/channels/dto/response/channel-videos.dto"].ChannelVideosDto }, "getChannelVideosContinuation": { type: t["./core/channels/dto/response/channel-videos-continuation.dto"].ChannelVideosContinuationDto }, "getChannelShorts": { type: t["./core/channels/dto/response/channel-videos.dto"].ChannelVideosDto }, "getChannelLivestreams": { type: t["./core/channels/dto/response/channel-videos.dto"].ChannelVideosDto }, "getChannelPlaylists": { type: t["./core/channels/dto/response/channel-playlists.dto"].ChannelPlaylistsDto }, "getChannelPlaylistsContinuation": { type: t["./core/channels/dto/response/channel-playlists-continuation.dto"].ChannelPlaylistsContinuationDto }, "searchChannel": { type: Object }, "searchChannelContinuation": { type: t["./core/channels/dto/response/channel-search-continuation.dto"].ChannelSearchContinuationDto }, "getRelatedChannelsContinuation": { type: t["./core/channels/dto/response/related-channels-continuation.dto"].RelatedChannelsContinuationDto }, "getChannelCommunityPosts": { type: t["./core/channels/dto/response/channel-community-posts.dto"].ChannelCommunityPostsDto }, "getChannelCommunityPostsContinuation": { type: t["./core/channels/dto/response/channel-community-posts-continuation.dto"].ChannelCommunityPostsContinuationDto }, "getChannelStats": { type: t["./core/channels/dto/response/channel-stats.dto"].ChannelStatsDto } } }], [import("./core/comments/comments.controller"), { "CommentsController": { "getComments": { type: t["./mapper/converter/comments/vt-comments-response.dto"].VTCommentsResponseDto }, "getCommentReplies": { type: t["./mapper/converter/comments/vt-comments-reply.response.dto"].VTCommentsReplyResponseDto } } }], [import("./core/homepage/homepage.controller"), { "HomepageController": { "getHomeFeed": { type: t["./core/homepage/dto/home-feed.dto"].HomeFeedDto } } }], [import("./core/playlists/playlists.controller"), { "PlaylistsController": { "getPlaylist": { type: t["./core/playlists/dto/playlist-result.dto"].PlaylistResultDto }, "getPlaylistContinuation": { type: Object } } }], [import("./core/proxy/proxy.controller"), { "ProxyController": { "getQuery": {}, "proxyText": {}, "proxyStream": {}, "proxyM3u8": { type: String } } }], [import("./core/search/search.controller"), { "SearchController": { "search": { type: t["./mapper/dto/search/vt-search.dto"].VTSearchDto } } }], [import("./core/videoplayback/videoplayback.controller"), { "VideoplaybackController": { "getVideoplayback": {} } }], [import("./core/videos/videos.controller"), { "VideosController": { "getVideos": { type: t["./mapper/dto/vt-video-info.dto"].VTVideoInfoDto }, "getDash": { type: String }, "getDislikes": { type: t["./core/videos/dto/dislike.dto"].DislikeDto }, "getSkipSegments": { type: t["./core/videos/dto/sponsorblock/sponsorblock-segments.dto"].SponsorBlockSegmentsDto } } }], [import("./nuxt/nuxt.controller"), { "NuxtController": { "getPage": {} } }]] } }; + return { "@nestjs/swagger": { "models": [[import("./mapper/dto/vt-thumbnail.dto"), { "VTThumbnailDto": { quality: { required: false, type: () => String }, url: { required: true, type: () => String }, width: { required: true, type: () => Number }, height: { required: true, type: () => Number } } }], [import("./core/videos/dto/video-basic-info.dto"), { "VideoBasicInfoDto": { videoId: { required: true, type: () => String }, title: { required: true, type: () => String }, published: { required: false, type: () => Number }, publishedText: { required: true, type: () => String }, author: { required: true, type: () => String }, authorId: { required: true, type: () => String }, authorVerified: { required: false, type: () => Boolean }, authorThumbnails: { required: false, type: () => [t["./mapper/dto/vt-thumbnail.dto"].VTThumbnailDto] }, authorThumbnailUrl: { required: false, type: () => String }, videoThumbnails: { required: true, type: () => [t["./mapper/dto/vt-thumbnail.dto"].VTThumbnailDto] }, description: { required: false, type: () => String }, viewCount: { required: true, type: () => Number }, likeCount: { required: false, type: () => Number }, dislikeCount: { required: false, type: () => Number }, lengthSeconds: { required: false, type: () => Number }, lengthString: { required: false, type: () => String }, live: { required: false, type: () => Boolean } } }], [import("./user/settings/dto/settings.dto"), { "SettingsDto": { chapters: { required: true, type: () => Boolean }, theme: { required: true, type: () => String }, sponsorblockUrl: { required: true, type: () => String }, sponsorblockEnabled: { required: true, type: () => Boolean }, sponsorblockSegmentSponsor: { required: true, type: () => Object }, sponsorblockSegmentIntro: { required: true, type: () => Object }, sponsorblockSegmentOutro: { required: true, type: () => Object }, sponsorblockSegmentInteraction: { required: true, type: () => Object }, sponsorblockSegmentSelfpromo: { required: true, type: () => Object }, sponsorblockSegmentMusicOfftopic: { required: true, type: () => Object }, sponsorblockSegmentPreview: { required: true, type: () => Object }, sponsorblockSegmentFiller: { required: true, type: () => Object }, autoplay: { required: true, type: () => Boolean }, saveVideoHistory: { required: true, type: () => Boolean }, showHomeSubscriptions: { required: true, type: () => Boolean }, showHomeTrendingVideos: { required: true, type: () => Boolean }, showRecommendedVideos: { required: true, type: () => Boolean }, alwaysLoopVideo: { required: true, type: () => Boolean }, hideComments: { required: true, type: () => Boolean }, videoSpeedAsList: { required: true, type: () => Boolean }, autoplayNextVideo: { required: true, type: () => Boolean }, audioModeDefault: { required: true, type: () => Boolean }, defaultVideoSpeed: { required: true, type: () => Number }, maxVideoQuality: { required: true, type: () => String }, defaultAudioQuality: { required: true, type: () => String }, autoAdjustAudioQuality: { required: true, type: () => Boolean }, autoAdjustVideoQuality: { required: true, type: () => Boolean }, rewriteYouTubeURLs: { required: true, type: () => Boolean }, hideShortsFromSearch: { required: true, type: () => Boolean } } }], [import("./user/history/dto/video-visit.dto"), { "VideoVisitDto": { videoId: { required: true, type: () => String }, progressSeconds: { required: true, type: () => Number }, lengthSeconds: { required: true, type: () => Number }, lastVisit: { required: true, type: () => Date } } }], [import("./user/history/dto/video-visit-details.dto"), { "VideoVisitDetailsDto": { videoDetails: { required: true, type: () => t["./core/videos/dto/video-basic-info.dto"].VideoBasicInfoDto } } }], [import("./user/history/dto/history-response.dto"), { "HistoryResponseDto": { videos: { required: true, type: () => [t["./user/history/dto/video-visit-details.dto"].VideoVisitDetailsDto] }, videoCount: { required: true, type: () => Number } } }], [import("./user/history/dto/history.dto"), { "HistoryDto": { username: { required: true, type: () => String }, videoHistory: { required: true, type: () => [t["./user/history/dto/video-visit.dto"].VideoVisitDto] } } }], [import("./user/notifications/dto/notifications-subscription-keys.dto"), { "NotificationsSubscriptionKeys": { p256dh: { required: true, type: () => String }, auth: { required: true, type: () => String } } }], [import("./user/dto/push-notification.dto"), { "PushNotificationDto": { id: { required: true, type: () => String }, username: { required: true, type: () => String }, content: { required: true, type: () => Object }, sentAt: { required: true, type: () => Date } } }], [import("./core/channels/dto/channel-basic-info.dto"), { "ChannelBasicInfoDto": { authorId: { required: true, type: () => String }, author: { required: true, type: () => String }, authorUrl: { required: false, type: () => String }, authorThumbnails: { required: false, type: () => [t["./mapper/dto/vt-thumbnail.dto"].VTThumbnailDto] }, authorThumbnailUrl: { required: false, type: () => String }, authorVerified: { required: false, type: () => Boolean }, subCount: { required: false, type: () => Number }, videoCount: { required: false, type: () => Number }, description: { required: false, type: () => String } } }], [import("./user/subscriptions/dto/subscribed-channels-response.dto"), { "SubscribedChannelsResponseDto": { channels: { required: true, type: () => [t["./core/channels/dto/channel-basic-info.dto"].ChannelBasicInfoDto] }, channelCount: { required: true, type: () => Number } } }], [import("./user/subscriptions/dto/subscription-feed-response.dto"), { "SubscriptionFeedResponseDto": { videoCount: { required: true, type: () => Number }, videos: { required: true, type: () => [t["./core/videos/dto/video-basic-info.dto"].VideoBasicInfoDto] }, lastRefresh: { required: true, type: () => Date }, refreshInterval: { required: true, type: () => Number } } }], [import("./user/subscriptions/dto/subscription-status.dto"), { "SubscriptionStatusDto": { channelId: { required: true, type: () => String }, name: { required: false, type: () => String }, isSubscribed: { required: true, type: () => Boolean } } }], [import("./user/dto/userprofile.dto"), { "UserprofileDto": { username: { required: true, type: () => String }, profileImage: { required: true, type: () => String }, settings: { required: true, type: () => t["./user/settings/dto/settings.dto"].SettingsDto }, admin: { required: false, type: () => Boolean } } }], [import("./user/dto/session.dto"), { "SessionDto": { id: { required: true, type: () => String }, deviceName: { required: true, type: () => String }, deviceType: { required: true, type: () => String }, updatedAt: { required: true, type: () => Date }, expires: { required: true, type: () => Date }, current: { required: true, type: () => Boolean } } }], [import("./user/dto/userprofile-details.dto"), { "UserprofileDetailsDto": { username: { required: true, type: () => String }, profileImage: { required: true, type: () => String }, videoHistory: { required: true, type: () => [t["./user/history/dto/video-visit-details.dto"].VideoVisitDetailsDto] }, registeredAt: { required: true, type: () => Date }, totalVideosCount: { required: true, type: () => Number }, totalTimeString: { required: true, type: () => String }, subscribedChannelsCount: { required: true, type: () => Number }, admin: { required: true, type: () => Boolean } } }], [import("./user/user.dto"), { "UserDto": { username: { required: true, type: () => String }, password: { required: true, type: () => String } } }], [import("./admin/dto/info.dto"), { "InfoDto": { serverIpV4: { required: true, type: () => String }, serverIpV6: { required: true, type: () => String }, proxyIpV4: { required: true, type: () => String }, proxyIpV6: { required: true, type: () => String } } }], [import("./admin/dto/log-file.dto"), { "LogFileDto": { name: { required: true, type: () => String }, size: { required: true, type: () => Number }, created: { required: true, type: () => Number }, lastModified: { required: true, type: () => Number } } }], [import("./admin/dto/logs.dto"), { "LogsDto": { logFiles: { required: true, type: () => [t["./admin/dto/log-file.dto"].LogFileDto] }, location: { required: true, type: () => String } } }], [import("./admin/dto/server-settings.dto"), { "ServerSettingsDto": { registrationEnabled: { required: true, type: () => Boolean }, requireLoginEverywhere: { required: true, type: () => Boolean } } }], [import("./auth/captcha/dto/captcha.dto"), { "CaptchaDto": { token: { required: true, type: () => String }, captchaImage: { required: true, type: () => String } } }], [import("./auth/register/dto/registration.dto"), { "RegistrationDto": { username: { required: true, type: () => String }, password: { required: true, type: () => String }, captchaToken: { required: true, type: () => String }, captchaSolution: { required: true, type: () => String } } }], [import("./core/channels/dto/basic/channel-community-post.dto"), { "ChannelCommunityPostDto": { postText: { required: true, type: () => String }, postId: { required: true, type: () => String }, author: { required: true, type: () => String }, authorThumbnails: { required: true, type: () => String }, publishedText: { required: true, type: () => String }, voteCount: { required: true, type: () => String }, commentCount: { required: true, type: () => String }, postContent: { required: true, type: () => Object } } }], [import("./core/channels/dto/response/channel-community-posts-continuation.dto"), { "ChannelCommunityPostsContinuationDto": { innerTubeApi: { required: true, type: () => String }, items: { required: true, type: () => [t["./core/channels/dto/basic/channel-community-post.dto"].ChannelCommunityPostDto] }, continuation: { required: true, type: () => String } } }], [import("./core/channels/dto/response/channel-community-posts.dto"), { "ChannelCommunityPostsDto": { channelIdType: { required: true, type: () => Number }, innerTubeApi: { required: true, type: () => String }, items: { required: true, type: () => [t["./core/channels/dto/basic/channel-community-post.dto"].ChannelCommunityPostDto] }, continuation: { required: true, type: () => String } } }], [import("./core/channels/dto/basic/channel-image.dto"), { "ChannelImageDto": { url: { required: true, type: () => String }, width: { required: true, type: () => Number }, height: { required: true, type: () => Number } } }], [import("./core/channels/dto/basic/channel-video.dto"), { "ChannelVideoDto": { author: { required: true, type: () => String }, authorId: { required: true, type: () => String }, durationText: { required: false, type: () => String }, lengthSeconds: { required: false, type: () => Number }, liveNow: { required: true, type: () => Boolean }, premiere: { required: true, type: () => Boolean }, premium: { required: true, type: () => Boolean }, publishedText: { required: true, type: () => String }, title: { required: true, type: () => String }, type: { required: true, type: () => String }, videoId: { required: true, type: () => String }, videoThumbnails: { required: true, type: () => [t["./core/channels/dto/basic/channel-image.dto"].ChannelImageDto], nullable: true }, viewCount: { required: true, type: () => Number }, viewCountText: { required: true, type: () => String } } }], [import("./core/channels/dto/basic/channel-mix.dto"), { "ChannelMixDto": { playlistId: { required: true, type: () => String }, title: { required: true, type: () => String }, description: { required: true, type: () => String }, videoCount: { required: true, type: () => Number }, url: { required: true, type: () => String }, thumbnails: { required: true, type: () => [t["./core/channels/dto/basic/channel-image.dto"].ChannelImageDto] } } }], [import("./core/channels/dto/basic/channel-playlist.dto"), { "ChannelPlaylistDto": { author: { required: true, type: () => String }, authorId: { required: true, type: () => String }, authorUrl: { required: true, type: () => String }, playlistId: { required: true, type: () => String }, playlistThumbnail: { required: true, type: () => String }, playlistUrl: { required: true, type: () => String }, title: { required: true, type: () => String }, type: { required: true, type: () => String }, videoCount: { required: true, type: () => Number } } }], [import("./core/channels/dto/basic/related-channel.dto"), { "RelatedChannelDto": { channelName: { required: false, type: () => String }, channelId: { required: false, type: () => String }, channelUrl: { required: false, type: () => String }, author: { required: true, type: () => String }, authorId: { required: true, type: () => String }, authorUrl: { required: true, type: () => String }, authorThumbnails: { required: true, type: () => [Object] }, videoCount: { required: true, type: () => Number }, subscriberText: { required: true, type: () => String }, subscriberCount: { required: true, type: () => Number }, verified: { required: true, type: () => Boolean }, officialArtist: { required: true, type: () => Boolean }, officialArist: { required: true, type: () => Boolean } } }], [import("./core/channels/dto/response/channel-home-item.dto"), { "ChannelHomeItemDto": { shelfName: { required: true, type: () => String }, type: { required: true, type: () => Object }, items: { required: true, type: () => Object } } }], [import("./core/channels/dto/response/channel-home.dto"), { "ChannelHomeDto": { featuredVideo: { required: true, type: () => t["./core/channels/dto/basic/channel-video.dto"].ChannelVideoDto }, items: { required: true, type: () => [t["./core/channels/dto/response/channel-home-item.dto"].ChannelHomeItemDto] } } }], [import("./core/channels/dto/basic/channel-link.dto"), { "ChannelLinkDto": { url: { required: true, type: () => String }, icon: { required: true, type: () => String }, title: { required: true, type: () => String } } }], [import("./core/channels/dto/response/channel-info.dto"), { "ChannelInfoDto": { author: { required: true, type: () => String }, authorId: { required: true, type: () => String }, authorUrl: { required: true, type: () => String }, oResponse: { required: true, type: () => Object }, authorBanners: { required: true, type: () => [t["./core/channels/dto/basic/channel-image.dto"].ChannelImageDto] }, authorThumbnails: { required: true, type: () => [t["./core/channels/dto/basic/channel-image.dto"].ChannelImageDto] }, subscriberText: { required: true, type: () => String }, subscriberCount: { required: true, type: () => Number }, description: { required: true, type: () => String }, isFamilyFriendly: { required: true, type: () => Boolean }, relatedChannels: { required: true, type: () => ({ items: { required: true, type: () => [t["./core/channels/dto/basic/related-channel.dto"].RelatedChannelDto] }, continuation: { required: true, type: () => String, nullable: true } }) }, allowedRegions: { required: true, type: () => [String] }, isVerified: { required: true, type: () => Boolean }, isOfficialArtist: { required: true, type: () => Boolean }, tags: { required: true, type: () => [String] }, channelIdType: { required: true, type: () => Number }, channelTabs: { required: true, type: () => [String] }, alertMessage: { required: true, type: () => String }, channelLinks: { required: true, type: () => ({ primaryLinks: { required: true, type: () => [t["./core/channels/dto/basic/channel-link.dto"].ChannelLinkDto] }, secondaryLinks: { required: true, type: () => [t["./core/channels/dto/basic/channel-link.dto"].ChannelLinkDto] } }) } } }], [import("./core/channels/dto/response/channel-playlists-continuation.dto"), { "ChannelPlaylistsContinuationDto": { items: { required: false, type: () => [t["./core/channels/dto/basic/channel-playlist.dto"].ChannelPlaylistDto] }, continuation: { required: false, type: () => String } } }], [import("./core/channels/dto/response/channel-playlists.dto"), { "ChannelPlaylistsDto": { channelIdType: { required: false, type: () => Number }, alertMessage: { required: false, type: () => String }, items: { required: false, type: () => [t["./core/channels/dto/basic/channel-playlist.dto"].ChannelPlaylistDto] }, continuation: { required: false, type: () => String } } }], [import("./core/channels/dto/response/channel-search-continuation.dto"), { "ChannelSearchContinuationDto": { items: { required: false, type: () => [t["./core/channels/dto/basic/channel-video.dto"].ChannelVideoDto] }, continuation: { required: false, type: () => String } } }], [import("./core/channels/dto/response/channel-search.dto"), { "ChannelSearchDto": { items: { required: false, type: () => [t["./core/channels/dto/basic/channel-video.dto"].ChannelVideoDto] }, continuation: { required: false, type: () => String } } }], [import("./core/channels/dto/response/channel-stats.dto"), { "ChannelStatsDto": { joinedDate: { required: true, type: () => Number }, viewCount: { required: true, type: () => Number }, location: { required: true, type: () => String } } }], [import("./core/channels/dto/response/channel-videos-continuation.dto"), { "ChannelVideosContinuationDto": { items: { required: false, type: () => [t["./core/channels/dto/basic/channel-video.dto"].ChannelVideoDto] }, continuation: { required: false, type: () => String } } }], [import("./core/channels/dto/response/channel-videos.dto"), { "ChannelVideosDto": { channelIdType: { required: false, enum: t["./core/channels/yt-channel-info/app/types"].ChannelIdType }, alertMessage: { required: false, type: () => String }, items: { required: false, type: () => [t["./core/channels/dto/basic/channel-video.dto"].ChannelVideoDto] }, continuation: { required: false, type: () => String } } }], [import("./core/channels/dto/response/related-channels-continuation.dto"), { "RelatedChannelsContinuationDto": { items: { required: true, type: () => [Object] }, continuation: { required: true, type: () => String } } }], [import("./core/channels/dto/channel-info-error.dto"), { "ChannelInfoErrorDto": { alertMessage: { required: true, type: () => String } } }], [import("./mapper/dto/vt-author.dto"), { "VTAuthorDto": { id: { required: true, type: () => String }, name: { required: true, type: () => String }, thumbnails: { required: false, type: () => [t["./mapper/dto/vt-thumbnail.dto"].VTThumbnailDto] }, isVerified: { required: false, type: () => Boolean }, isArtist: { required: false, type: () => Boolean }, handle: { required: false, type: () => String }, subscriberCount: { required: false, type: () => Number } } }], [import("./mapper/dto/comments/vt-comment.dto"), { "VTCommentDto": { id: { required: true, type: () => String }, content: { required: true, type: () => String }, pinned: { required: false, type: () => Boolean }, creatorHeart: { required: false, type: () => Boolean }, likeCount: { required: true, type: () => Number }, replyCount: { required: true, type: () => Number }, hasReplies: { required: false, type: () => Boolean }, isEdited: { required: false, type: () => Boolean }, replyContinuation: { required: false, type: () => String }, creatorReplied: { required: false, type: () => Boolean }, creatorReplyThumbnail: { required: false, type: () => [t["./mapper/dto/vt-thumbnail.dto"].VTThumbnailDto] }, channelOwner: { required: false, type: () => Boolean }, channelMember: { required: false, type: () => Boolean }, published: { required: true, type: () => ({ date: { required: true, type: () => Date }, text: { required: true, type: () => String } }) }, author: { required: true, type: () => t["./mapper/dto/vt-author.dto"].VTAuthorDto } } }], [import("./mapper/converter/comments/vt-comments-reply.response.dto"), { "VTCommentsReplyResponseDto": { comments: { required: true, type: () => [t["./mapper/dto/comments/vt-comment.dto"].VTCommentDto] }, continuation: { required: false, type: () => String } } }], [import("./mapper/dto/comments/vt-comment-emoji.dto"), { "VTCommentEmojiDto": { name: { required: true, type: () => String }, shortcuts: { required: true, type: () => [String] }, thumbnails: { required: true, type: () => [t["./mapper/dto/vt-thumbnail.dto"].VTThumbnailDto] } } }], [import("./mapper/dto/comments/vt-comments-header.dto"), { "VTCommentsHeaderDto": { commentsCount: { required: true, type: () => Number }, customEmojis: { required: true, type: () => [t["./mapper/dto/comments/vt-comment-emoji.dto"].VTCommentEmojiDto] } } }], [import("./mapper/converter/comments/vt-comments-response.dto"), { "VTCommentsResponseDto": { comments: { required: true, type: () => [t["./mapper/dto/comments/vt-comment.dto"].VTCommentDto] }, header: { required: true, type: () => t["./mapper/dto/comments/vt-comments-header.dto"].VTCommentsHeaderDto }, continuation: { required: false, type: () => String } } }], [import("./mapper/dto/vt-video-core.dto"), { "VTVideoCoreDto": { id: { required: true, type: () => String }, title: { required: true, type: () => String }, duration: { required: false, type: () => ({ text: { required: true, type: () => String }, seconds: { required: true, type: () => Number } }) } } }], [import("./mapper/dto/vt-video.dto"), { "VTVideoDto": { author: { required: false, type: () => t["./mapper/dto/vt-author.dto"].VTAuthorDto }, description: { required: false, type: () => String }, thumbnails: { required: false, type: () => [t["./mapper/dto/vt-thumbnail.dto"].VTThumbnailDto] }, richThumbnails: { required: false, type: () => [t["./mapper/dto/vt-thumbnail.dto"].VTThumbnailDto] }, published: { required: false, type: () => ({ date: { required: false, type: () => Date }, text: { required: false, type: () => String } }) }, viewCount: { required: false, type: () => Number }, upcoming: { required: false, type: () => Date }, live: { required: false, type: () => Boolean } } }], [import("./core/homepage/dto/home-feed.dto"), { "HomeFeedDto": { videos: { required: true, type: () => [t["./mapper/dto/vt-video.dto"].VTVideoDto] } } }], [import("./core/playlists/dto/playlist-image.dto"), { "PlaylistImageDto": { url: { required: true, type: () => String, nullable: true }, width: { required: true, type: () => Number }, height: { required: true, type: () => Number } } }], [import("./core/playlists/dto/playlist-item.dto"), { "PlaylistItemDto": { title: { required: true, type: () => String }, index: { required: true, type: () => Number }, id: { required: true, type: () => String }, shortUrl: { required: true, type: () => String }, url: { required: true, type: () => String }, author: { required: true, type: () => ({ name: { required: true, type: () => String }, url: { required: true, type: () => String }, channelID: { required: true, type: () => String } }) }, thumbnails: { required: true, type: () => [t["./core/playlists/dto/playlist-image.dto"].PlaylistImageDto] }, bestThumbnail: { required: true, type: () => t["./core/playlists/dto/playlist-image.dto"].PlaylistImageDto }, isLive: { required: true, type: () => Boolean }, duration: { required: true, type: () => String, nullable: true }, durationSec: { required: true, type: () => Number, nullable: true } } }], [import("./core/playlists/dto/playlist-result.dto"), { "PlaylistResultDto": { id: { required: true, type: () => String }, url: { required: true, type: () => String }, title: { required: true, type: () => String }, estimatedItemCount: { required: true, type: () => Number }, views: { required: true, type: () => Number }, thumbnails: { required: true, type: () => [t["./core/playlists/dto/playlist-image.dto"].PlaylistImageDto] }, bestThumbnail: { required: true, type: () => t["./core/playlists/dto/playlist-image.dto"].PlaylistImageDto }, lastUpdated: { required: true, type: () => String }, description: { required: true, type: () => String, nullable: true }, visibility: { required: true, type: () => Object }, author: { required: true, type: () => ({ name: { required: true, type: () => String }, url: { required: true, type: () => String }, avatars: { required: true, type: () => [t["./core/playlists/dto/playlist-image.dto"].PlaylistImageDto] }, bestAvatar: { required: true, type: () => t["./core/playlists/dto/playlist-image.dto"].PlaylistImageDto }, channelID: { required: true, type: () => String } }) }, items: { required: true, type: () => [t["./core/playlists/dto/playlist-item.dto"].PlaylistItemDto] }, continuation: { required: true, type: () => Object, nullable: true } } }], [import("./mapper/dto/vt-channel.dto"), { "VTChannelDto": { id: { required: true, type: () => String }, name: { required: true, type: () => String }, handle: { required: false, type: () => String }, thumbnails: { required: false, type: () => [t["./mapper/dto/vt-thumbnail.dto"].VTThumbnailDto] }, isVerified: { required: false, type: () => Boolean }, isArtist: { required: false, type: () => Boolean }, subscribers: { required: false, type: () => Number }, description: { required: false, type: () => String }, videoCount: { required: false, type: () => Number } } }], [import("./mapper/dto/search/vt-search-channel-result.dto"), { "VTSearchChannelResultDto": { type: { required: true, type: () => String } } }], [import("./mapper/dto/search/vt-search-movie.dto"), { "VTSearchMovieDto": { type: { required: true, type: () => String } } }], [import("./mapper/dto/search/vt-search-playlist.dto"), { "VTSearchPlaylistDto": { type: { required: true, type: () => String }, id: { required: true, type: () => String }, title: { required: true, type: () => String }, thumbnails: { required: false, type: () => [t["./mapper/dto/vt-thumbnail.dto"].VTThumbnailDto] }, author: { required: false, type: () => t["./mapper/dto/vt-author.dto"].VTAuthorDto }, videoCount: { required: false, type: () => Number }, firstVideos: { required: false, type: () => [t["./mapper/dto/vt-video-core.dto"].VTVideoCoreDto] } } }], [import("./mapper/dto/search/vt-search-video-result.dto"), { "VTSearchVideoResultDto": { type: { required: true, type: () => String } } }], [import("./mapper/dto/search/vt-search-shelf.dto"), { "VTSearchShelfDto": { type: { required: true, type: () => String }, title: { required: true, type: () => String }, items: { required: true, type: () => [t["./mapper/dto/search/vt-search-video-result.dto"].VTSearchVideoResultDto] } } }], [import("./mapper/dto/vt-short.dto"), { "VTShortDto": { type: { required: true, type: () => String }, id: { required: true, type: () => String }, title: { required: true, type: () => String }, thumbnails: { required: false, type: () => [t["./mapper/dto/vt-thumbnail.dto"].VTThumbnailDto] }, viewCount: { required: false, type: () => Number }, duration: { required: false, type: () => ({ text: { required: true, type: () => String }, seconds: { required: true, type: () => Number } }) } } }], [import("./mapper/dto/search/vt-shorts-shelf.dto"), { "VTShortsShelfDto": { type: { required: true, type: () => String }, title: { required: true, type: () => String }, items: { required: true, type: () => [t["./mapper/dto/vt-short.dto"].VTShortDto] } } }], [import("./mapper/dto/search/vt-search.dto"), { "VTSearchDto": { results: { required: true, type: () => [Object] }, estimatedResultCount: { required: true, type: () => Number }, refinements: { required: true, type: () => [String] }, continuation: { required: false, type: () => String } } }], [import("./core/search/dto/search-filters.dto"), { "SearchFiltersDto": { upload_date: { required: false, type: () => Object }, type: { required: false, type: () => Object }, duration: { required: false, type: () => Object }, sort_by: { required: false, type: () => Object }, features: { required: false, type: () => [Object] } } }], [import("./core/search/dto/search-query.dto"), { "SearchQueryDto": { q: { required: true, type: () => String }, filters: { required: false, type: () => t["./core/search/dto/search-filters.dto"].SearchFiltersDto }, continuationString: { required: false, type: () => String } } }], [import("./core/videos/dto/dislike.dto"), { "DislikeDto": { id: { required: true, type: () => String }, dateCreated: { required: true, type: () => String }, likes: { required: true, type: () => Number }, dislikes: { required: true, type: () => Number }, rating: { required: true, type: () => Number }, viewCount: { required: true, type: () => Number }, deleted: { required: true, type: () => Boolean } } }], [import("./mapper/dto/endscreen/vt-endscreen-element.dto"), { "VTEndscreenElementDto": { position: { required: true, type: () => ({ left: { required: true, type: () => Number }, top: { required: true, type: () => Number } }) }, dimensions: { required: true, type: () => ({ width: { required: true, type: () => Number }, aspectRatio: { required: true, type: () => Number } }) }, startMs: { required: true, type: () => Number }, endMs: { required: true, type: () => Number }, thumbnails: { required: true, type: () => [t["./mapper/dto/vt-thumbnail.dto"].VTThumbnailDto] } } }], [import("./mapper/dto/infocard/vt-playlist-card-content.dto"), { "VTPlaylistCardContentDto": { type: { required: true, type: () => String }, id: { required: true, type: () => String }, firstVideoId: { required: true, type: () => String }, videoCount: { required: true, type: () => Number }, title: { required: true, type: () => String }, author: { required: true, type: () => ({ name: { required: true, type: () => String } }) } } }], [import("./mapper/dto/infocard/vt-simple-card-content.dto"), { "VTSimpleCardContentDto": { type: { required: true, type: () => String }, title: { required: true, type: () => String }, thumbnails: { required: true, type: () => [t["./mapper/dto/vt-thumbnail.dto"].VTThumbnailDto] }, displayDomain: { required: true, type: () => String }, url: { required: true, type: () => String } } }], [import("./mapper/dto/infocard/vt-video-card-content.dto"), { "VTVideoCardContentDto": { type: { required: true, type: () => String }, id: { required: true, type: () => String }, title: { required: true, type: () => String }, author: { required: true, type: () => ({ name: { required: true, type: () => String } }) }, viewCount: { required: true, type: () => Number }, thumbnails: { required: true, type: () => [t["./mapper/dto/vt-thumbnail.dto"].VTThumbnailDto] }, duration: { required: true, type: () => ({ text: { required: true, type: () => String }, seconds: { required: true, type: () => Number } }) } } }], [import("./mapper/dto/infocard/vt-info-card.dto"), { "VTInfoCardDto": { shortName: { required: true, type: () => String }, startMs: { required: true, type: () => Number }, endMs: { required: true, type: () => Number }, content: { required: true, type: () => Object } } }], [import("./mapper/dto/vt-caption-track.dto"), { "VTCaptionTrackDto": { baseUrl: { required: true, type: () => String }, name: { required: true, type: () => String }, languageCode: { required: true, type: () => String } } }], [import("./mapper/dto/vt-chapter.dto"), { "VTChapterDto": { title: { required: true, type: () => String }, startMs: { required: true, type: () => Number }, thumbnails: { required: true, type: () => [t["./mapper/dto/vt-thumbnail.dto"].VTThumbnailDto] } } }], [import("./mapper/dto/vt-legacy-format.dto"), { "VTLegacyFormatDto": { mimeType: { required: true, type: () => String }, bitrate: { required: true, type: () => Number }, averageBitrate: { required: true, type: () => Number }, width: { required: true, type: () => Number }, height: { required: true, type: () => Number }, lastModified: { required: true, type: () => Date }, contentLength: { required: true, type: () => Number }, quality: { required: true, type: () => String }, qualityLabel: { required: true, type: () => String }, fps: { required: true, type: () => Number }, url: { required: true, type: () => String }, audioQuality: { required: true, type: () => String }, approxDurationMs: { required: true, type: () => Number }, audioSampleRate: { required: true, type: () => Number }, audioChannels: { required: true, type: () => Number }, hasAudio: { required: true, type: () => Boolean }, hasVideo: { required: true, type: () => Boolean } } }], [import("./mapper/dto/vt-preview-thumbnail.dto"), { "VTPreviewThumbnailDto": { urlTemplate: { required: true, type: () => String }, width: { required: true, type: () => Number }, height: { required: true, type: () => Number }, count: { required: true, type: () => Number }, interval: { required: true, type: () => Number }, columns: { required: true, type: () => Number }, rows: { required: true, type: () => Number }, previewThumbnailCount: { required: true, type: () => Number } } }], [import("./mapper/dto/vt-video-info.dto"), { "VTVideoInfoDto": { id: { required: true, type: () => String }, title: { required: true, type: () => String }, subtitle: { required: true, type: () => String }, author: { required: true, type: () => ({ id: { required: true, type: () => String }, name: { required: true, type: () => String }, thumbnails: { required: true, type: () => [t["./mapper/dto/vt-thumbnail.dto"].VTThumbnailDto] }, isVerified: { required: true, type: () => Boolean }, isArtist: { required: true, type: () => Boolean }, handle: { required: true, type: () => String }, subscriberCount: { required: true, type: () => String } }) }, description: { required: true, type: () => String }, thumbnails: { required: true, type: () => [t["./mapper/dto/vt-thumbnail.dto"].VTThumbnailDto] }, duration: { required: true, type: () => ({ text: { required: true, type: () => String }, seconds: { required: true, type: () => Number } }) }, published: { required: true, type: () => ({ date: { required: true, type: () => Date }, text: { required: true, type: () => String } }) }, viewCount: { required: true, type: () => Number }, upcoming: { required: false, type: () => Date }, live: { required: true, type: () => Boolean }, watching: { required: false, type: () => Number }, unlisted: { required: true, type: () => Boolean }, familyFriendly: { required: true, type: () => Boolean }, likeCount: { required: true, type: () => Number }, category: { required: true, type: () => String }, previewThumbnails: { required: true, type: () => [t["./mapper/dto/vt-preview-thumbnail.dto"].VTPreviewThumbnailDto] }, endscreen: { required: true, type: () => ({ elements: { required: true, type: () => [t["./mapper/dto/endscreen/vt-endscreen-element.dto"].VTEndscreenElementDto] }, startMs: { required: true, type: () => Number } }) }, keywords: { required: true, type: () => [String] }, captions: { required: true, type: () => [t["./mapper/dto/vt-caption-track.dto"].VTCaptionTrackDto] }, infoCards: { required: true, type: () => [t["./mapper/dto/infocard/vt-info-card.dto"].VTInfoCardDto] }, recommendedVideos: { required: true, type: () => [t["./mapper/dto/vt-video.dto"].VTVideoDto] }, chapters: { required: true, type: () => [t["./mapper/dto/vt-chapter.dto"].VTChapterDto] }, commentCount: { required: true, type: () => Number }, legacyFormats: { required: true, type: () => [t["./mapper/dto/vt-legacy-format.dto"].VTLegacyFormatDto] }, dashManifest: { required: false, type: () => String }, hlsManifestUrl: { required: false, type: () => String }, dashManifestUrl: { required: false, type: () => String } } }], [import("./core/videos/dto/sponsorblock/sponsorblock-segment.dto"), { "SponsorBlockSegmentDto": { UUID: { required: true, type: () => String }, category: { required: true, type: () => String }, segment: { required: true, type: () => [Number] }, videoDuration: { required: true, type: () => Number }, endPercentage: { required: false, type: () => Number } } }], [import("./core/videos/dto/sponsorblock/sponsorblock-segments.dto"), { "SponsorBlockSegmentsDto": { hash: { required: true, type: () => String }, segments: { required: true, type: () => [t["./core/videos/dto/sponsorblock/sponsorblock-segment.dto"].SponsorBlockSegmentDto] }, videoID: { required: true, type: () => String } } }], [import("./mapper/dto/endscreen/vt-endscreen-channel.dto"), { "VTEndscreenChannelDto": { type: { required: true, type: () => String }, title: { required: true, type: () => String }, id: { required: true, type: () => String }, description: { required: true, type: () => String } } }], [import("./mapper/dto/endscreen/vt-endscreen-video.dto"), { "VTEndscreenVideoDto": { type: { required: true, type: () => String }, title: { required: true, type: () => String }, id: { required: true, type: () => String }, viewCount: { required: true, type: () => Number }, duration: { required: true, type: () => ({ text: { required: true, type: () => String }, seconds: { required: true, type: () => Number } }) } } }], [import("./core/playlists/dto/preview-video.dto"), { "PreviewVideoDto": { title: { required: false, type: () => String }, videoId: { required: false, type: () => String }, videoThumbnails: { required: true, type: () => [t["./mapper/dto/vt-thumbnail.dto"].VTThumbnailDto] } } }], [import("./core/channels/dto/link-thumbnail.dto"), { "LinkThumbnailDto": { url: { required: true, type: () => String } } }], [import("./core/playlists/dto/playlist-basic-info.dto"), { "PlaylistBasicInfoDto": { title: { required: true, type: () => String }, playlistId: { required: true, type: () => String }, playlistVideoLink: { required: true, type: () => String }, playlistLink: { required: true, type: () => String }, author: { required: true, type: () => String }, authorId: { required: true, type: () => String }, authorUrl: { required: false, type: () => String }, videoCount: { required: true, type: () => Number }, firstVideoId: { required: false, type: () => String }, playlistThumbnails: { required: false, type: () => [t["./mapper/dto/vt-thumbnail.dto"].VTThumbnailDto] }, previewVideos: { required: false, type: () => [t["./core/playlists/dto/preview-video.dto"].PreviewVideoDto] } } }], [import("./core/videoplayback/dto/videoplayback-query.dto"), { "VideoplaybackQueryDto": { expire: { required: true, type: () => Number }, itag: { required: true, type: () => Number }, ei: { required: false, type: () => String }, ip: { required: false, type: () => String }, id: { required: false, type: () => String }, aitags: { required: false, type: () => String }, source: { required: false, type: () => String }, requiressl: { required: false, type: () => String }, mh: { required: false, type: () => String }, mm: { required: false, type: () => String }, mn: { required: false, type: () => String }, ms: { required: false, type: () => String }, mv: { required: false, type: () => String }, mvi: { required: false, type: () => String }, pl: { required: false, type: () => Number }, initcwndbps: { required: false, type: () => Number }, vprv: { required: false, type: () => Number }, mime: { required: false, type: () => String }, ns: { required: false, type: () => String }, gir: { required: false, type: () => String }, clen: { required: false, type: () => Number }, dur: { required: false, type: () => Number }, lmt: { required: false, type: () => Number }, mt: { required: false, type: () => Number }, fvip: { required: false, type: () => Number }, keepalive: { required: false, type: () => String }, fexp: { required: false, type: () => Number }, c: { required: false, type: () => String }, txp: { required: false, type: () => Number }, n: { required: false, type: () => String }, sparams: { required: false, type: () => String }, sig: { required: false, type: () => String }, lsparams: { required: false, type: () => String }, lsig: { required: false, type: () => String }, ratebypass: { required: false, type: () => String }, host: { required: true, type: () => String } } }]], "controllers": [[import("./user/settings/settings.controller"), { "SettingsController": { "setSettings": {}, "getSettings": { type: t["./user/settings/dto/settings.dto"].SettingsDto } } }], [import("./user/history/history.controller"), { "HistoryController": { "getHistory": { type: t["./user/history/dto/history-response.dto"].HistoryResponseDto }, "setVideoVisit": {}, "getVideoVisit": { type: t["./user/history/dto/video-visit.dto"].VideoVisitDto }, "deleteEntireHistory": {}, "deleteHistoryEntry": {}, "deleteHistoryRange": {} } }], [import("./user/notifications/notifications.controller"), { "NotificationsController": { "subscribeToNotifications": {} } }], [import("./user/subscriptions/subscriptions.controller"), { "SubscriptionsController": { "getSubscribedChannels": { type: t["./user/subscriptions/dto/subscribed-channels-response.dto"].SubscribedChannelsResponseDto }, "getSubscriptionVideos": { type: t["./user/subscriptions/dto/subscription-feed-response.dto"].SubscriptionFeedResponseDto }, "getSubscription": { type: t["./user/subscriptions/dto/subscription-status.dto"].SubscriptionStatusDto }, "createSubscription": { type: t["./user/subscriptions/dto/subscription-status.dto"].SubscriptionStatusDto }, "createMultipleSubscriptions": {}, "deleteSubscription": { type: t["./user/subscriptions/dto/subscription-status.dto"].SubscriptionStatusDto } } }], [import("./user/user.controller"), { "UserController": { "getProfile": { type: t["./user/dto/userprofile.dto"].UserprofileDto }, "getProfileDetails": { type: t["./user/dto/userprofile-details.dto"].UserprofileDetailsDto }, "getSessions": { type: [t["./user/dto/session.dto"].SessionDto] }, "getCurrentSession": { type: t["./user/dto/session.dto"].SessionDto }, "updateSession": {}, "deleteSession": {}, "getExport": {}, "getProfileImage": {}, "uploadProfileImage": {}, "deleteProfileImage": {}, "deleteUser": {}, "changePassword": {} } }], [import("./admin/admin.controller"), { "AdminController": { "getInfo": { type: t["./admin/dto/info.dto"].InfoDto }, "getServerSettings": { type: t["./admin/dto/server-settings.dto"].ServerSettingsDto }, "updateServerSettings": { type: t["./admin/dto/server-settings.dto"].ServerSettingsDto }, "getLogs": { type: t["./admin/dto/logs.dto"].LogsDto }, "downloadLogFile": {}, "findAll": { type: [String] }, "isVideoBlocked": { type: Boolean }, "create": { type: String }, "delete": {}, "createUser": { type: t["./user/dto/userprofile.dto"].UserprofileDto } } }], [import("./auth/auth.controller"), { "AuthController": { "login": {}, "logout": {} } }], [import("./auth/captcha/captcha.controller"), { "CaptchaController": { "getCaptcha": { type: t["./auth/captcha/dto/captcha.dto"].CaptchaDto } } }], [import("./auth/register/register.controller"), { "RegisterController": { "registerUser": { type: Object } } }], [import("./core/autocomplete/autocomplete.controller"), { "AutocompleteController": { "getQuery": { type: [String] } } }], [import("./core/channels/channels.controller"), { "ChannelsController": { "getTinyThumbnailJpg": {}, "getTinyThumbnailWebp": {}, "getChannelInfo": { type: t["./core/channels/dto/response/channel-info.dto"].ChannelInfoDto }, "getChannelHome": { type: t["./core/channels/dto/response/channel-home.dto"].ChannelHomeDto }, "getChannelVideos": { type: t["./core/channels/dto/response/channel-videos.dto"].ChannelVideosDto }, "getChannelVideosContinuation": { type: t["./core/channels/dto/response/channel-videos-continuation.dto"].ChannelVideosContinuationDto }, "getChannelShorts": { type: t["./core/channels/dto/response/channel-videos.dto"].ChannelVideosDto }, "getChannelLivestreams": { type: t["./core/channels/dto/response/channel-videos.dto"].ChannelVideosDto }, "getChannelPlaylists": { type: t["./core/channels/dto/response/channel-playlists.dto"].ChannelPlaylistsDto }, "getChannelPlaylistsContinuation": { type: t["./core/channels/dto/response/channel-playlists-continuation.dto"].ChannelPlaylistsContinuationDto }, "searchChannel": { type: Object }, "searchChannelContinuation": { type: t["./core/channels/dto/response/channel-search-continuation.dto"].ChannelSearchContinuationDto }, "getRelatedChannelsContinuation": { type: t["./core/channels/dto/response/related-channels-continuation.dto"].RelatedChannelsContinuationDto }, "getChannelCommunityPosts": { type: t["./core/channels/dto/response/channel-community-posts.dto"].ChannelCommunityPostsDto }, "getChannelCommunityPostsContinuation": { type: t["./core/channels/dto/response/channel-community-posts-continuation.dto"].ChannelCommunityPostsContinuationDto }, "getChannelStats": { type: t["./core/channels/dto/response/channel-stats.dto"].ChannelStatsDto } } }], [import("./core/comments/comments.controller"), { "CommentsController": { "getComments": { type: t["./mapper/converter/comments/vt-comments-response.dto"].VTCommentsResponseDto }, "getCommentReplies": { type: t["./mapper/converter/comments/vt-comments-reply.response.dto"].VTCommentsReplyResponseDto } } }], [import("./core/homepage/homepage.controller"), { "HomepageController": { "getHomeFeed": { type: t["./core/homepage/dto/home-feed.dto"].HomeFeedDto } } }], [import("./core/playlists/playlists.controller"), { "PlaylistsController": { "getPlaylist": { type: t["./core/playlists/dto/playlist-result.dto"].PlaylistResultDto }, "getPlaylistContinuation": { type: Object } } }], [import("./core/proxy/proxy.controller"), { "ProxyController": { "getQuery": {}, "proxyText": {}, "proxyStream": {} } }], [import("./core/search/search.controller"), { "SearchController": { "search": { type: t["./mapper/dto/search/vt-search.dto"].VTSearchDto } } }], [import("./core/videoplayback/videoplayback.controller"), { "VideoplaybackController": { "getVideoplayback": {} } }], [import("./core/videos/videos.controller"), { "VideosController": { "getVideos": { type: t["./mapper/dto/vt-video-info.dto"].VTVideoInfoDto }, "getDash": { type: String }, "getDislikes": { type: t["./core/videos/dto/dislike.dto"].DislikeDto }, "getSkipSegments": { type: t["./core/videos/dto/sponsorblock/sponsorblock-segments.dto"].SponsorBlockSegmentsDto } } }], [import("./nuxt/nuxt.controller"), { "NuxtController": { "getPage": {} } }]] } }; }; \ No newline at end of file diff --git a/shared/src/api.schema.ts b/shared/src/api.schema.ts index 760283556..4cfcb046f 100644 --- a/shared/src/api.schema.ts +++ b/shared/src/api.schema.ts @@ -171,9 +171,6 @@ export interface paths { "/api/proxy/stream": { get: operations["ProxyController_proxyStream"]; }; - "/api/proxy/m3u8": { - get: operations["ProxyController_proxyM3u8"]; - }; "/api/comments/{videoId}": { get: operations["CommentsController_getComments"]; }; @@ -472,6 +469,7 @@ export interface components { /** Format: date-time */ upcoming?: string; live: boolean; + watching?: number; unlisted: boolean; familyFriendly: boolean; likeCount: number; @@ -517,6 +515,7 @@ export interface components { results: Record[]; estimatedResultCount: number; refinements: string[]; + continuation?: string; }; ChannelImageDto: { url: string; @@ -1158,6 +1157,9 @@ export interface operations { }; VideosController_getSkipSegments: { parameters: { + query: { + url: string; + }; path: { id: string; }; @@ -1200,6 +1202,7 @@ export interface operations { duration?: Record; sort_by?: Record; features?: Record[]; + continuationString?: string; }; }; responses: { @@ -1246,12 +1249,6 @@ export interface operations { "application/json": components["schemas"]["ChannelInfoDto"]; }; }; - 404: { - content: never; - }; - 500: { - content: never; - }; }; }; ChannelsController_getChannelHome: { @@ -1266,12 +1263,6 @@ export interface operations { "application/json": components["schemas"]["ChannelHomeDto"]; }; }; - 404: { - content: never; - }; - 500: { - content: never; - }; }; }; ChannelsController_getChannelVideos: { @@ -1289,12 +1280,6 @@ export interface operations { "application/json": components["schemas"]["ChannelVideosDto"]; }; }; - 404: { - content: never; - }; - 500: { - content: never; - }; }; }; ChannelsController_getChannelVideosContinuation: { @@ -1309,12 +1294,6 @@ export interface operations { "application/json": components["schemas"]["ChannelVideosContinuationDto"]; }; }; - 404: { - content: never; - }; - 500: { - content: never; - }; }; }; ChannelsController_getChannelShorts: { @@ -1332,12 +1311,6 @@ export interface operations { "application/json": components["schemas"]["ChannelVideosDto"]; }; }; - 404: { - content: never; - }; - 500: { - content: never; - }; }; }; ChannelsController_getChannelLivestreams: { @@ -1355,12 +1328,6 @@ export interface operations { "application/json": components["schemas"]["ChannelVideosDto"]; }; }; - 404: { - content: never; - }; - 500: { - content: never; - }; }; }; ChannelsController_getChannelPlaylists: { @@ -1375,12 +1342,6 @@ export interface operations { "application/json": components["schemas"]["ChannelPlaylistsDto"]; }; }; - 404: { - content: never; - }; - 500: { - content: never; - }; }; }; ChannelsController_getChannelPlaylistsContinuation: { @@ -1395,12 +1356,6 @@ export interface operations { "application/json": components["schemas"]["ChannelPlaylistsContinuationDto"]; }; }; - 404: { - content: never; - }; - 500: { - content: never; - }; }; }; ChannelsController_searchChannel: { @@ -1418,12 +1373,6 @@ export interface operations { "application/json": Record; }; }; - 404: { - content: never; - }; - 500: { - content: never; - }; }; }; ChannelsController_searchChannelContinuation: { @@ -1438,12 +1387,6 @@ export interface operations { "application/json": components["schemas"]["ChannelSearchContinuationDto"]; }; }; - 404: { - content: never; - }; - 500: { - content: never; - }; }; }; ChannelsController_getRelatedChannelsContinuation: { @@ -1458,12 +1401,6 @@ export interface operations { "application/json": components["schemas"]["RelatedChannelsContinuationDto"]; }; }; - 404: { - content: never; - }; - 500: { - content: never; - }; }; }; ChannelsController_getChannelCommunityPosts: { @@ -1478,12 +1415,6 @@ export interface operations { "application/json": components["schemas"]["ChannelCommunityPostsDto"]; }; }; - 404: { - content: never; - }; - 500: { - content: never; - }; }; }; ChannelsController_getChannelCommunityPostsContinuation: { @@ -1499,12 +1430,6 @@ export interface operations { "application/json": components["schemas"]["ChannelCommunityPostsContinuationDto"]; }; }; - 404: { - content: never; - }; - 500: { - content: never; - }; }; }; ChannelsController_getChannelStats: { @@ -1519,12 +1444,6 @@ export interface operations { "application/json": components["schemas"]["ChannelStatsDto"]; }; }; - 404: { - content: never; - }; - 500: { - content: never; - }; }; }; HomepageController_getHomeFeed: { @@ -1573,21 +1492,6 @@ export interface operations { }; }; }; - ProxyController_proxyM3u8: { - parameters: { - query: { - url: string; - proxyUrl: string; - }; - }; - responses: { - 200: { - content: { - "application/json": string; - }; - }; - }; - }; CommentsController_getComments: { parameters: { query?: {