diff --git a/src/Innertube.ts b/src/Innertube.ts index cf892ae00..94985c3d0 100644 --- a/src/Innertube.ts +++ b/src/Innertube.ts @@ -32,10 +32,11 @@ import { generateRandomString, throwIfMissing } from './utils/Utils'; export type InnertubeConfig = SessionOptions; export interface SearchFilters { - upload_date?: 'all' | 'hour' | 'today' | 'week' | 'month' | 'year', - type?: 'all' | 'video' | 'channel' | 'playlist' | 'movie', - duration?: 'all' | 'short' | 'medium' | 'long', - sort_by?: 'relevance' | 'rating' | 'upload_date' | 'view_count' + upload_date?: 'all' | 'hour' | 'today' | 'week' | 'month' | 'year'; + type?: 'all' | 'video' | 'channel' | 'playlist' | 'movie'; + duration?: 'all' | 'short' | 'medium' | 'long'; + sort_by?: 'relevance' | 'rating' | 'upload_date' | 'view_count'; + features?: ('hd' | 'subtitles' | 'creative_commons' | '3d' | 'live' | 'purchased' | '4k' | '360' | 'location' | 'hdr' | 'vr180')[]; } export type InnerTubeClient = 'WEB' | 'ANDROID' | 'YTMUSIC_ANDROID' | 'YTMUSIC' | 'YTSTUDIO_ANDROID' | 'TV_EMBEDDED'; diff --git a/src/proto/index.ts b/src/proto/index.ts index a6ed4b9b5..cec20d0e4 100644 --- a/src/proto/index.ts +++ b/src/proto/index.ts @@ -2,7 +2,7 @@ import { CLIENTS } from '../utils/Constants'; import { u8ToBase64 } from '../utils/Utils'; import { VideoMetadata } from '../core/Studio'; -import { ChannelAnalytics, CreateCommentParams, GetCommentsSectionParams, InnertubePayload, LiveMessageParams, MusicSearchFilter, NotificationPreferences, PeformCommentActionParams, SearchFilter } from './youtube'; +import { ChannelAnalytics, CreateCommentParams, GetCommentsSectionParams, InnertubePayload, LiveMessageParams, MusicSearchFilter, NotificationPreferences, PeformCommentActionParams, SearchFilter, SearchFilter_Filters } from './youtube'; class Proto { static encodeChannelAnalyticsParams(channel_id: string): string { @@ -18,7 +18,8 @@ class Proto { upload_date?: 'all' | 'hour' | 'today' | 'week' | 'month' | 'year', type?: 'all' | 'video' | 'channel' | 'playlist' | 'movie', duration?: 'all' | 'short' | 'medium' | 'long', - sort_by?: 'relevance' | 'rating' | 'upload_date' | 'view_count' + sort_by?: 'relevance' | 'rating' | 'upload_date' | 'view_count', + features?: ('hd' | 'subtitles' | 'creative_commons' | '3d' | 'live' | 'purchased' | '4k' | '360' | 'location' | 'hdr' | 'vr180')[] }): string { const upload_date = { all: undefined, @@ -51,6 +52,20 @@ class Proto { view_count: 3 }; + const features = { + hd: 'featuresHd', + subtitles: 'featuresSubtitles', + creative_commons: 'featuresCreativeCommons', + '3d': 'features3D', + live: 'featuresLive', + purchased: 'featuresPurchased', + '4k': 'features4K', + '360': 'features360', + location: 'featuresLocation', + hdr: 'featuresHdr', + vr180: 'featuresVr180' + }; + const data: SearchFilter = {}; if (filters) @@ -77,6 +92,12 @@ class Proto { if (filters.sort_by && filters.sort_by !== 'relevance') { data.sortBy = order[filters.sort_by]; } + + if (filters.features) { + for (const feature of filters.features) { + data.filters[features[feature] as keyof SearchFilter_Filters] = 1; + } + } } const buf = SearchFilter.toBinary(data); diff --git a/src/proto/youtube.proto b/src/proto/youtube.proto index 9d7e151d5..3ee3585c8 100644 --- a/src/proto/youtube.proto +++ b/src/proto/youtube.proto @@ -235,6 +235,18 @@ message SearchFilter { optional int32 upload_date = 1; optional int32 type = 2; optional int32 duration = 3; + + optional int32 features_hd = 4; + optional int32 features_subtitles = 5; + optional int32 features_creative_commons = 6; + optional int32 features_3d = 7; + optional int32 features_live = 8; + optional int32 features_purchased = 9; + optional int32 features_4k = 14; + optional int32 features_360 = 15; + optional int32 features_location = 23; + optional int32 features_hdr = 25; + optional int32 features_vr180 = 26; } optional Filters filters = 2; diff --git a/src/proto/youtube.ts b/src/proto/youtube.ts index ca8c5c72c..ef8c3f6cb 100644 --- a/src/proto/youtube.ts +++ b/src/proto/youtube.ts @@ -600,6 +600,50 @@ export interface SearchFilter_Filters { * @generated from protobuf field: optional int32 duration = 3; */ duration?: number; + /** + * @generated from protobuf field: optional int32 features_hd = 4; + */ + featuresHd?: number; + /** + * @generated from protobuf field: optional int32 features_subtitles = 5; + */ + featuresSubtitles?: number; + /** + * @generated from protobuf field: optional int32 features_creative_commons = 6; + */ + featuresCreativeCommons?: number; + /** + * @generated from protobuf field: optional int32 features_3d = 7 [json_name = "features3d"]; + */ + features3D?: number; + /** + * @generated from protobuf field: optional int32 features_live = 8; + */ + featuresLive?: number; + /** + * @generated from protobuf field: optional int32 features_purchased = 9; + */ + featuresPurchased?: number; + /** + * @generated from protobuf field: optional int32 features_4k = 14 [json_name = "features4k"]; + */ + features4K?: number; + /** + * @generated from protobuf field: optional int32 features_360 = 15; + */ + features360?: number; + /** + * @generated from protobuf field: optional int32 features_location = 23; + */ + featuresLocation?: number; + /** + * @generated from protobuf field: optional int32 features_hdr = 25; + */ + featuresHdr?: number; + /** + * @generated from protobuf field: optional int32 features_vr180 = 26; + */ + featuresVr180?: number; } // @generated message type with reflection information, may provide speed optimized methods class ChannelAnalytics$Type extends MessageType<ChannelAnalytics> { @@ -2844,7 +2888,18 @@ class SearchFilter_Filters$Type extends MessageType<SearchFilter_Filters> { super("youtube.SearchFilter.Filters", [ { no: 1, name: "upload_date", kind: "scalar", opt: true, T: 5 /*ScalarType.INT32*/ }, { no: 2, name: "type", kind: "scalar", opt: true, T: 5 /*ScalarType.INT32*/ }, - { no: 3, name: "duration", kind: "scalar", opt: true, T: 5 /*ScalarType.INT32*/ } + { no: 3, name: "duration", kind: "scalar", opt: true, T: 5 /*ScalarType.INT32*/ }, + { no: 4, name: "features_hd", kind: "scalar", opt: true, T: 5 /*ScalarType.INT32*/ }, + { no: 5, name: "features_subtitles", kind: "scalar", opt: true, T: 5 /*ScalarType.INT32*/ }, + { no: 6, name: "features_creative_commons", kind: "scalar", opt: true, T: 5 /*ScalarType.INT32*/ }, + { no: 7, name: "features_3d", kind: "scalar", jsonName: "features3d", opt: true, T: 5 /*ScalarType.INT32*/ }, + { no: 8, name: "features_live", kind: "scalar", opt: true, T: 5 /*ScalarType.INT32*/ }, + { no: 9, name: "features_purchased", kind: "scalar", opt: true, T: 5 /*ScalarType.INT32*/ }, + { no: 14, name: "features_4k", kind: "scalar", jsonName: "features4k", opt: true, T: 5 /*ScalarType.INT32*/ }, + { no: 15, name: "features_360", kind: "scalar", opt: true, T: 5 /*ScalarType.INT32*/ }, + { no: 23, name: "features_location", kind: "scalar", opt: true, T: 5 /*ScalarType.INT32*/ }, + { no: 25, name: "features_hdr", kind: "scalar", opt: true, T: 5 /*ScalarType.INT32*/ }, + { no: 26, name: "features_vr180", kind: "scalar", opt: true, T: 5 /*ScalarType.INT32*/ } ]); } create(value?: PartialMessage<SearchFilter_Filters>): SearchFilter_Filters { @@ -2868,6 +2923,39 @@ class SearchFilter_Filters$Type extends MessageType<SearchFilter_Filters> { case /* optional int32 duration */ 3: message.duration = reader.int32(); break; + case /* optional int32 features_hd */ 4: + message.featuresHd = reader.int32(); + break; + case /* optional int32 features_subtitles */ 5: + message.featuresSubtitles = reader.int32(); + break; + case /* optional int32 features_creative_commons */ 6: + message.featuresCreativeCommons = reader.int32(); + break; + case /* optional int32 features_3d = 7 [json_name = "features3d"];*/ 7: + message.features3D = reader.int32(); + break; + case /* optional int32 features_live */ 8: + message.featuresLive = reader.int32(); + break; + case /* optional int32 features_purchased */ 9: + message.featuresPurchased = reader.int32(); + break; + case /* optional int32 features_4k = 14 [json_name = "features4k"];*/ 14: + message.features4K = reader.int32(); + break; + case /* optional int32 features_360 */ 15: + message.features360 = reader.int32(); + break; + case /* optional int32 features_location */ 23: + message.featuresLocation = reader.int32(); + break; + case /* optional int32 features_hdr */ 25: + message.featuresHdr = reader.int32(); + break; + case /* optional int32 features_vr180 */ 26: + message.featuresVr180 = reader.int32(); + break; default: let u = options.readUnknownField; if (u === "throw") @@ -2889,6 +2977,39 @@ class SearchFilter_Filters$Type extends MessageType<SearchFilter_Filters> { /* optional int32 duration = 3; */ if (message.duration !== undefined) writer.tag(3, WireType.Varint).int32(message.duration); + /* optional int32 features_hd = 4; */ + if (message.featuresHd !== undefined) + writer.tag(4, WireType.Varint).int32(message.featuresHd); + /* optional int32 features_subtitles = 5; */ + if (message.featuresSubtitles !== undefined) + writer.tag(5, WireType.Varint).int32(message.featuresSubtitles); + /* optional int32 features_creative_commons = 6; */ + if (message.featuresCreativeCommons !== undefined) + writer.tag(6, WireType.Varint).int32(message.featuresCreativeCommons); + /* optional int32 features_3d = 7 [json_name = "features3d"]; */ + if (message.features3D !== undefined) + writer.tag(7, WireType.Varint).int32(message.features3D); + /* optional int32 features_live = 8; */ + if (message.featuresLive !== undefined) + writer.tag(8, WireType.Varint).int32(message.featuresLive); + /* optional int32 features_purchased = 9; */ + if (message.featuresPurchased !== undefined) + writer.tag(9, WireType.Varint).int32(message.featuresPurchased); + /* optional int32 features_4k = 14 [json_name = "features4k"]; */ + if (message.features4K !== undefined) + writer.tag(14, WireType.Varint).int32(message.features4K); + /* optional int32 features_360 = 15; */ + if (message.features360 !== undefined) + writer.tag(15, WireType.Varint).int32(message.features360); + /* optional int32 features_location = 23; */ + if (message.featuresLocation !== undefined) + writer.tag(23, WireType.Varint).int32(message.featuresLocation); + /* optional int32 features_hdr = 25; */ + if (message.featuresHdr !== undefined) + writer.tag(25, WireType.Varint).int32(message.featuresHdr); + /* optional int32 features_vr180 = 26; */ + if (message.featuresVr180 !== undefined) + writer.tag(26, WireType.Varint).int32(message.featuresVr180); let u = options.writeUnknownFields; if (u !== false) (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);