Advanced search filters. Custom language & location params#952
Conversation
| string hl = "en", | ||
| string gl = "US", |
There was a problem hiding this comment.
Does localization affect only how the results are presented, or does it filter by language?
If it filters too, then it should probably be included within SearchFilter.
If it's just for presetation, then it would make sense to configure it on the *Client object, since it can probably be relevant to all requests.
There was a problem hiding this comment.
It affects the search results, which is useful if you actually want a spanish video, so maybe SearchFilter would be better.
| /// </summary> | ||
| public enum SearchFilter | ||
| public readonly record struct SearchFilter( | ||
| SearchFilterType? Type = null, |
There was a problem hiding this comment.
SearchFilterType? Type -> SearchFilterKind? Kind, so as to not confuse with the CLR's concept of "type"
There was a problem hiding this comment.
Good point. I just threw this together quickly with AI to solve my need, it's working, but I didn't review the code. Feel free to refactor to your preferred style if you have time, or reject/delete the PR if it's too messy.
There was a problem hiding this comment.
Pull request overview
This PR extends the search subsystem to support richer YouTube search filtering (beyond the prior enum presets) and allows callers to pass localization parameters (language/region) through to the youtubei/v1/search request.
Changes:
- Replaces the simple
SearchFilterenum with a structured filter model that can encode advanced filter combinations into theparamspayload. - Adds
hl/glparameters to search request construction and exposes them onSearchClientAPIs. - Adds integration tests covering localization usage and advanced filter usage.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 5 comments.
| File | Description |
|---|---|
| YoutubeExplode/Search/SearchFilter.cs | Reworks filtering into a record-struct + supporting enums and serializes filters into the request params. |
| YoutubeExplode/Search/SearchController.cs | Passes hl/gl (and persist_hl) in the search request context and uses the new filter serialization. |
| YoutubeExplode/Search/SearchClient.cs | Updates public search APIs to accept filter/localization parameters and adjusts internal type checks. |
| YoutubeExplode.Tests/SearchSpecs.cs | Adds tests for localized search and advanced filters. |
Comments suppressed due to low confidence (4)
YoutubeExplode/Search/SearchClient.cs:263
- This signature change introduces positional-breaking changes for callers that previously used
GetVideosAsync(query, cancellationToken); the second argument is nowhl. Consider adding an overloadGetVideosAsync(string searchQuery, CancellationToken cancellationToken = default)that forwards to the new method with defaulthl/glvalues (and similarly for playlists/channels/results).
public IAsyncEnumerable<VideoSearchResult> GetVideosAsync(
string searchQuery,
string hl = "en",
string gl = "US",
CancellationToken cancellationToken = default
) =>
YoutubeExplode/Search/SearchClient.cs:253
- This signature change can break existing call sites that previously used
GetResultsAsync(query, cancellationToken)positionally (the second arg is nowSearchFilter). Consider adding an overloadGetResultsAsync(string searchQuery, CancellationToken cancellationToken = default)that forwards to the new overload with default filter/locale values.
public IAsyncEnumerable<ISearchResult> GetResultsAsync(
string searchQuery,
SearchFilter searchFilter = default,
string hl = "en",
string gl = "US",
CancellationToken cancellationToken = default
) => GetResultBatchesAsync(searchQuery, searchFilter, hl, gl, cancellationToken).FlattenAsync();
YoutubeExplode/Search/SearchClient.cs:276
- This signature change can break existing call sites that previously used
GetPlaylistsAsync(query, cancellationToken)positionally (the second arg is nowhl). Consider adding an overloadGetPlaylistsAsync(string searchQuery, CancellationToken cancellationToken = default)that forwards to the new overload with default locale values.
public IAsyncEnumerable<PlaylistSearchResult> GetPlaylistsAsync(
string searchQuery,
string hl = "en",
string gl = "US",
CancellationToken cancellationToken = default
) =>
YoutubeExplode/Search/SearchClient.cs:289
- This signature change can break existing call sites that previously used
GetChannelsAsync(query, cancellationToken)positionally (the second arg is nowhl). Consider adding an overloadGetChannelsAsync(string searchQuery, CancellationToken cancellationToken = default)that forwards to the new overload with default locale values.
public IAsyncEnumerable<ChannelSearchResult> GetChannelsAsync(
string searchQuery,
string hl = "en",
string gl = "US",
CancellationToken cancellationToken = default
) =>
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| public readonly record struct SearchFilter( | ||
| SearchFilterType? Type = null, | ||
| SearchFilterDuration? Duration = null, | ||
| SearchFilterUploadDate? UploadDate = null, | ||
| SearchFilterFeatures Features = SearchFilterFeatures.None, | ||
| SearchFilterSortBy SortBy = SearchFilterSortBy.Relevance | ||
| ) |
| if (topBuffer.Count == 0) | ||
| return ""; | ||
|
|
||
| return Convert.ToBase64String(topBuffer.ToArray()); | ||
| } |
| while (value >= 0x80) | ||
| { | ||
| buffer.Add((byte)(value | 0x80)); | ||
| value >>= 7; | ||
| } | ||
| buffer.Add((byte)value); | ||
| } |
| if (Features.HasFlag(SearchFilterFeatures.HD)) | ||
| WriteVarintField(filterBuffer, 4, 1); | ||
| if (Features.HasFlag(SearchFilterFeatures.Subtitles)) | ||
| WriteVarintField(filterBuffer, 5, 1); | ||
| if (Features.HasFlag(SearchFilterFeatures.CreativeCommons)) | ||
| WriteVarintField(filterBuffer, 6, 1); |
| public async IAsyncEnumerable<Batch<ISearchResult>> GetResultBatchesAsync( | ||
| string searchQuery, | ||
| SearchFilter searchFilter, | ||
| SearchFilter searchFilter = default, | ||
| string hl = "en", | ||
| string gl = "US", | ||
| [EnumeratorCancellation] CancellationToken cancellationToken = default | ||
| ) |
No description provided.