Skip to content

Commit

Permalink
Fix Bandcamp track search caused by imprecise query
Browse files Browse the repository at this point in the history
When the name of a track was very simple, the actual search match could
be on a page higher than the configured maximum. This caused the search
to fail and the track wouldn't be played. The amount of search results
can be greatly reduced by simply adding the artist name to the query.
  • Loading branch information
sferra committed Feb 10, 2024
1 parent c7a43c5 commit a67adfb
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 6 deletions.
54 changes: 53 additions & 1 deletion packages/core/src/plugins/stream/BandcampPlugin.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {BandcampPlugin} from '.';
import fn = jest.fn;
import {Bandcamp} from '../../rest';
import spyOn = jest.spyOn;
import {BandcampSearchResult} from '../../rest/Bandcamp';
Expand All @@ -15,9 +16,17 @@ describe('Bandcamp plugin tests', () => {
artist: 'Artist Name',
track: 'Track Name'
};
const trackQuery = 'Track Name';
const trackQuery = 'Artist Name Track Name';
const bandcampSearch = spyOn(Bandcamp, 'search');

beforeEach(() => {
spyOn(plugin, 'createTrackQuery')
.mockImplementation(fn(() => trackQuery));
// 'accept all' matcher
spyOn(plugin, 'createTrackMatcher')
.mockImplementation(fn(query => () => true));
});

afterEach(() => {
bandcampSearch.mockReset();
});
Expand Down Expand Up @@ -57,4 +66,47 @@ describe('Bandcamp plugin tests', () => {
expect(bandcampSearch).toHaveBeenCalledTimes(5);
});
});

test('creates track query', () => {
const streamQuery = {
artist: 'Artist Name',
track: 'Track Name'
};
const trackQuery = plugin.createTrackQuery(streamQuery);
expect(trackQuery).toBe('Artist Name Track Name');
});

test('creates track matcher', () => {
const streamQuery = {
artist: 'Artist Name',
track: 'Track Name'
};
const matcher = plugin.createTrackMatcher(streamQuery);
const matchingResult = {
type: 'track',
artist: 'Artist Name',
name: 'Track Name'
};
const searchResults = [
matchingResult, // first match
{
type: 'album' // type shouldn't match
},
{
type: 'artist' // type shouldn't match
},
{
type: 'track',
artist: 'Wrong Artist' // artist shouldn't match
},
{
type: 'track',
artist: 'Artist Name',
name: 'Wrong Title' // track name shouldn't match
},
matchingResult // second match
];
const tracks = searchResults.filter(matcher);
expect(tracks).toEqual([matchingResult, matchingResult]);
});
});
22 changes: 17 additions & 5 deletions packages/core/src/plugins/stream/BandcampPlugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,19 +18,31 @@ class BandcampPlugin extends StreamProviderPlugin {
const limit = 5;
let tracks: BandcampSearchResult[];

const trackQuery: string = this.createTrackQuery(query);
const isMatchingTrack = this.createTrackMatcher(query);
for (let page = 0; page < limit; page++) {
const searchResults = await Bandcamp.search(query.track, page);
tracks = searchResults.filter(item =>
item.type === 'track' &&
item.artist.toLowerCase() === query.artist.toLowerCase()
);
const searchResults = await Bandcamp.search(trackQuery, page);
tracks = searchResults.filter(isMatchingTrack);
if (tracks.length > 0) {
break;
}
}
return tracks;
}

createTrackQuery(query: StreamQuery): string {
return `${query.artist} ${query.track}`;
}

createTrackMatcher(query: StreamQuery): (BandcampSearchResult) => boolean {
const lowerCaseTrack: string = query.track.toLowerCase();
const lowerCaseArtist: string = query.artist.toLowerCase();
return (searchResult) =>
searchResult.type === 'track' &&
searchResult.artist.toLowerCase() === lowerCaseArtist &&
searchResult.name.toLowerCase() === lowerCaseTrack;
}

resultToStream(result: BandcampSearchResult, stream: string, duration: number): StreamData {
return {
source: this.sourceName,
Expand Down

0 comments on commit a67adfb

Please sign in to comment.