Skip to content

Advanced search filters. Custom language & location params#952

Open
speige wants to merge 1 commit into
Tyrrrz:primefrom
speige:prime
Open

Advanced search filters. Custom language & location params#952
speige wants to merge 1 commit into
Tyrrrz:primefrom
speige:prime

Conversation

@speige
Copy link
Copy Markdown

@speige speige commented May 21, 2026

No description provided.

Comment on lines +250 to +251
string hl = "en",
string gl = "US",
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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,
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SearchFilterType? Type -> SearchFilterKind? Kind, so as to not confuse with the CLR's concept of "type"

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 SearchFilter enum with a structured filter model that can encode advanced filter combinations into the params payload.
  • Adds hl/gl parameters to search request construction and exposes them on SearchClient APIs.
  • 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 now hl. Consider adding an overload GetVideosAsync(string searchQuery, CancellationToken cancellationToken = default) that forwards to the new method with default hl/gl values (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 now SearchFilter). Consider adding an overload GetResultsAsync(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 now hl). Consider adding an overload GetPlaylistsAsync(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 now hl). Consider adding an overload GetChannelsAsync(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.

Comment on lines +9 to +15
public readonly record struct SearchFilter(
SearchFilterType? Type = null,
SearchFilterDuration? Duration = null,
SearchFilterUploadDate? UploadDate = null,
SearchFilterFeatures Features = SearchFilterFeatures.None,
SearchFilterSortBy SortBy = SearchFilterSortBy.Relevance
)
Comment on lines +108 to +112
if (topBuffer.Count == 0)
return "";

return Convert.ToBase64String(topBuffer.ToArray());
}
Comment on lines +39 to +45
while (value >= 0x80)
{
buffer.Add((byte)(value | 0x80));
value >>= 7;
}
buffer.Add((byte)value);
}
Comment on lines +78 to +83
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);
Comment on lines 25 to 31
public async IAsyncEnumerable<Batch<ISearchResult>> GetResultBatchesAsync(
string searchQuery,
SearchFilter searchFilter,
SearchFilter searchFilter = default,
string hl = "en",
string gl = "US",
[EnumeratorCancellation] CancellationToken cancellationToken = default
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants