The problem
The topbar takes a pasted link. That means finding something to work on is: leave StemDeck, open a browser, search, copy the URL, come back, paste. Every time.
The box already knows how to accept a URL. It should accept a query too.
What it needs to do
- Type anything that is not a link, get results back
- Songs and playlists, from YouTube and SoundCloud
- Picking a result fills the box. It must not start an extraction: that is minutes of work and belongs behind a deliberate press, not a click in a list the user may still be reading.
Constraints that shape the design
Cost. This fires while the user types. Firing per keystroke would be twenty six requests for one phrase. Word-boundary triggering plus a debounce, cancellation of superseded requests, and a short server-side cache are what make it affordable rather than abusive.
The SSRF boundary (#173). A search reaches YouTube with user-supplied text, and its results are URLs that would then be handed to the pipeline. Each search needs the narrowest extractor allowlist that can serve it, generic must stay out, and every result has to go back through validate_youtube_url / validate_playlist_url before it can reach the pipeline. Anything that fails validation gets dropped, not shown.
The duration limit. Over the configured limit the pipeline refuses the job outright (download.py raises). So an over-limit result is not "this may be slow", it is "this cannot be imported", and the UI has to say so rather than letting the user queue something that can only fail. The limit is a live setting from 1 to 60 minutes, not a constant.
Known asymmetry
yt-dlp exposes exactly one SoundCloud search key (scsearch, tracks only). There is no SoundCloud playlist search, so that combination must not be offered rather than offered and always empty.
Known trap
SoundCloud search returns url as an api.soundcloud.com endpoint, which is not on the allowlisted host set and is rejected on sight. The real permalink is in webpage_url. Reading url first, as expand_playlist does, silently drops every SoundCloud result.
The problem
The topbar takes a pasted link. That means finding something to work on is: leave StemDeck, open a browser, search, copy the URL, come back, paste. Every time.
The box already knows how to accept a URL. It should accept a query too.
What it needs to do
Constraints that shape the design
Cost. This fires while the user types. Firing per keystroke would be twenty six requests for one phrase. Word-boundary triggering plus a debounce, cancellation of superseded requests, and a short server-side cache are what make it affordable rather than abusive.
The SSRF boundary (#173). A search reaches YouTube with user-supplied text, and its results are URLs that would then be handed to the pipeline. Each search needs the narrowest extractor allowlist that can serve it,
genericmust stay out, and every result has to go back throughvalidate_youtube_url/validate_playlist_urlbefore it can reach the pipeline. Anything that fails validation gets dropped, not shown.The duration limit. Over the configured limit the pipeline refuses the job outright (
download.pyraises). So an over-limit result is not "this may be slow", it is "this cannot be imported", and the UI has to say so rather than letting the user queue something that can only fail. The limit is a live setting from 1 to 60 minutes, not a constant.Known asymmetry
yt-dlp exposes exactly one SoundCloud search key (
scsearch, tracks only). There is no SoundCloud playlist search, so that combination must not be offered rather than offered and always empty.Known trap
SoundCloud search returns
urlas anapi.soundcloud.comendpoint, which is not on the allowlisted host set and is rejected on sight. The real permalink is inwebpage_url. Readingurlfirst, asexpand_playlistdoes, silently drops every SoundCloud result.