summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorAdam Malczewski <[email protected]>2026-07-01 20:40:13 +0900
committerAdam Malczewski <[email protected]>2026-07-01 20:41:23 +0900
commit7d2ee45ab5ac2a9bfff61125b216a7baef05dca5 (patch)
tree387c64212729a7983d582480be0d382c654c1a08
parent8a0ed76b938d05336ae5c4a6232b5f00be00f273 (diff)
downloadyt-walkerman-7d2ee45ab5ac2a9bfff61125b216a7baef05dca5.tar.gz
yt-walkerman-7d2ee45ab5ac2a9bfff61125b216a7baef05dca5.zip
fix: segment editor metadata search sends title-only query (artist hint was YouTube channel name → 0 MB results)
-rw-r--r--.gitignore1
-rw-r--r--yt-music-dl-web/src/features/segment-editor/metadata.test.ts30
-rw-r--r--yt-music-dl-web/src/features/segment-editor/metadata.ts40
3 files changed, 39 insertions, 32 deletions
diff --git a/.gitignore b/.gitignore
index d1a0c84..ba410d8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -30,3 +30,4 @@ bin/yt-dlp.exe
# Worktrees (per-feature)
worktrees/
+.dispatch/
diff --git a/yt-music-dl-web/src/features/segment-editor/metadata.test.ts b/yt-music-dl-web/src/features/segment-editor/metadata.test.ts
index 2f76303..b917195 100644
--- a/yt-music-dl-web/src/features/segment-editor/metadata.test.ts
+++ b/yt-music-dl-web/src/features/segment-editor/metadata.test.ts
@@ -165,25 +165,23 @@ describe("metadata search state machine (pure)", () => {
// ─── request builders ────────────────────────────────────────────────────────
describe("buildRecordingSearch (pure)", () => {
- it("uses the query when non-blank, segment artist as the hint", () => {
+ it("uses the query when non-blank; sends a title-only request (no artist hint)", () => {
const s = seg("s1", "Chapter Title", "Seg Artist");
const req = buildRecordingSearch(s, "user query", "Global Artist");
- expect(req).toEqual({ query: "user query", artist: "Seg Artist", type: "recording" });
+ expect(req).toEqual({ query: "user query", type: "recording" });
});
- it("falls back to the segment title when the query is blank", () => {
+ it("falls back to the segment title when the query is blank (no artist hint)", () => {
const s = seg("s1", "Chapter Title", "Seg Artist");
const req = buildRecordingSearch(s, " ", "Global Artist");
- expect(req.query).toBe("Chapter Title");
- expect(req.artist).toBe("Seg Artist");
- expect(req.type).toBe("recording");
+ expect(req).toEqual({ query: "Chapter Title", type: "recording" });
});
- it("falls back to the global artist when the segment artist is blank", () => {
- const s = seg("s1", "Chapter Title", "");
+ it("omits artist even when a segment artist is set (channel name, not a real artist)", () => {
+ const s = seg("s1", "Chapter Title", "Seg Artist");
const req = buildRecordingSearch(s, "", "Global Artist");
expect(req.query).toBe("Chapter Title");
- expect(req.artist).toBe("Global Artist");
+ expect(req.artist).toBeUndefined();
});
it("omits artist when neither segment nor global artist is set", () => {
@@ -202,20 +200,18 @@ describe("buildRecordingSearch (pure)", () => {
});
describe("buildReleaseSearch (pure)", () => {
- it("uses album + artist inputs when provided", () => {
+ it("uses the album input; sends an album-only request (no artist hint)", () => {
const req = buildReleaseSearch("Dark Side", "Pink Floyd", "Global Album", "Global Artist");
- expect(req).toEqual({ query: "Dark Side", artist: "Pink Floyd", type: "release" });
+ expect(req).toEqual({ query: "Dark Side", type: "release" });
});
- it("falls back to global album / global artist when inputs are blank", () => {
+ it("falls back to the global album when the album input is blank (no artist hint)", () => {
const req = buildReleaseSearch(" ", "", "Global Album", "Global Artist");
- expect(req.query).toBe("Global Album");
- expect(req.artist).toBe("Global Artist");
- expect(req.type).toBe("release");
+ expect(req).toEqual({ query: "Global Album", type: "release" });
});
- it("omits artist when neither input nor global artist is set", () => {
- const req = buildReleaseSearch("Some Album", "", "", "");
+ it("omits artist even when an artist input / global artist is set (channel name, not a real artist)", () => {
+ const req = buildReleaseSearch("Some Album", "Pink Floyd", "Global Album", "Global Artist");
expect(req.query).toBe("Some Album");
expect(req.artist).toBeUndefined();
expect(req.type).toBe("release");
diff --git a/yt-music-dl-web/src/features/segment-editor/metadata.ts b/yt-music-dl-web/src/features/segment-editor/metadata.ts
index 914a28a..530893a 100644
--- a/yt-music-dl-web/src/features/segment-editor/metadata.ts
+++ b/yt-music-dl-web/src/features/segment-editor/metadata.ts
@@ -74,39 +74,49 @@ export function reduceSearch(state: SearchState, event: SearchEvent): SearchStat
/**
* Build the recording-search request for a segment's sidebar. `query` is the
- * search-box text (falling back to the segment title when blank); `artist` is
- * the segment's artist (falling back to the draft's global artist), omitted when
- * neither is set. Mirrors the backend's `MetadataSearchRequest`.
+ * search-box text (falling back to the segment title when blank). The search is
+ * title-only — no artist hint is sent. For YouTube downloads the segment/global
+ * artist is the channel name (e.g. 'Official YouTube Channel'), which MusicBrainz
+ * has no artist for, so a Lucene `artist:"…" AND recording:"…"` query returns
+ * zero results. Mirrors the backend's `MetadataSearchRequest`.
*
- * Pure: (segment, query, globalArtist) → request.
+ * `globalArtist` is retained in the signature for backward compatibility (the
+ * caller still passes it) but is now unused. Pure: (segment, query, globalArtist) → request.
*/
export function buildRecordingSearch(
segment: SegmentDraft,
query: string,
- globalArtist: string,
+ // Prefixed `_` to satisfy Biome's noUnusedFunctionParameters: retained in the
+ // signature for backward compatibility (the caller still passes it) but the
+ // artist hint is no longer sent — see the doc comment above.
+ _globalArtist: string,
): MetadataSearchRequest {
const q = query.trim() || segment.title.trim();
- const artist = segment.artist.trim() || globalArtist.trim();
- // exactOptionalPropertyTypes: omit `artist` rather than set undefined.
- return artist ? { query: q, artist, type: "recording" } : { query: q, type: "recording" };
+ return { query: q, type: "recording" };
}
/**
* Build the release-search request for the "Match Album" dialog. `album` is the
- * album-name search text (falling back to the global album); `artist` is the
- * artist search text (falling back to the global artist), omitted when blank.
+ * album-name search text (falling back to the global album). The search is
+ * album-only — no artist hint is sent. For YouTube downloads the draft's global
+ * artist is the channel name, and the dialog prefills its artist box with it, so
+ * sending it as a Lucene `artist:"…"` hint yields zero MB release results.
+ *
+ * `artist` and `globalArtist` are retained in the signature for backward
+ * compatibility (the caller still passes them) but are now unused.
* Pure: (album, artist, globalAlbum, globalArtist) → request.
*/
export function buildReleaseSearch(
album: string,
- artist: string,
+ // Prefixed `_` to satisfy Biome's noUnusedFunctionParameters: retained in the
+ // signature for backward compatibility (the caller still passes them) but the
+ // artist hint is no longer sent — see the doc comment above.
+ _artist: string,
globalAlbum: string,
- globalArtist: string,
+ _globalArtist: string,
): MetadataSearchRequest {
const q = album.trim() || globalAlbum.trim();
- const a = artist.trim() || globalArtist.trim();
- // exactOptionalPropertyTypes: omit `artist` rather than set undefined.
- return a ? { query: q, artist: a, type: "release" } : { query: q, type: "release" };
+ return { query: q, type: "release" };
}
// ─── Sidebar view-model (pure) ───────────────────────────────────────────────