Skip to content

fix: fix SoundCloud capitalization #766

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 26, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -29,7 +29,7 @@ The following table describes the types of links supported by MB: Upload to CAA
| Qobuz | ✔️ | ✔️ | Goodies are grabbed whenever possible. Back covers might not be supported at this time, if you have a release with a back cover, please let me know. Maximised to original source image. |
| RateYourMusic | ✔️ | ✔️ | Requires being logged in to RYM. |
| Rockipedia | ✔️ | ❌ |
| Soundcloud | ✔️ | ✔️ | Grabs custom track images. |
| SoundCloud | ✔️ | ✔️ | Grabs custom track images. |
| Spotify | ✔️ | ✔️ |
| Tidal | ✔️ | ✔️ | listen.tidal.com/store.tidal.com are converted to tidal.com prior to fetching |
| Traxsource | ✔️ | ✔️ | Limited to 600x600. |
2 changes: 1 addition & 1 deletion src/mb_enhanced_cover_art_uploads/providers/base.ts
Original file line number Diff line number Diff line change
@@ -163,7 +163,7 @@ export abstract class ProviderWithTrackImages extends CoverArtProvider {
// Providers that provide track images which need to be deduplicated. The
// base class supports deduping by URL and thumbnail content.
//
// Some providers, like Soundcloud and sometimes Bandcamp, use unique URLs
// Some providers, like SoundCloud and sometimes Bandcamp, use unique URLs
// for each track image, so deduplicating based on URL won't work. They may
// also not return any headers that uniquely identify the image (like a
// Digest or an ETag), so we need to load the image and compare its data
4 changes: 2 additions & 2 deletions src/mb_enhanced_cover_art_uploads/providers/index.ts
Original file line number Diff line number Diff line change
@@ -25,7 +25,7 @@ import { NetEaseProvider } from './netease';
import { QobuzProvider } from './qobuz';
import { RateYourMusicProvider } from './rateyourmusic';
import { RockipediaProvider } from './rockipedia';
import { SoundcloudProvider } from './soundcloud';
import { SoundCloudProvider } from './soundcloud';
import { SpotifyProvider } from './spotify';
import { TidalProvider } from './tidal';
import { TraxsourceProvider } from './traxsource';
@@ -68,7 +68,7 @@ addProvider(new QobuzProvider());
addProvider(new RateYourMusicProvider());
addProvider(new RockipediaProvider());
addProvider(new SevenDigitalProvider());
addProvider(new SoundcloudProvider());
addProvider(new SoundCloudProvider());
addProvider(new SpotifyProvider());
addProvider(new TidalProvider());
addProvider(new TraxsourceProvider());
32 changes: 16 additions & 16 deletions src/mb_enhanced_cover_art_uploads/providers/soundcloud.ts
Original file line number Diff line number Diff line change
@@ -51,11 +51,11 @@
const SC_CLIENT_ID_CACHE_KEY = 'ROpdebee_ECAU_SC_ID';
const SC_HOMEPAGE = 'https://soundcloud.com/';

export class SoundcloudProvider extends ProviderWithTrackImages {
export class SoundCloudProvider extends ProviderWithTrackImages {
public readonly supportedDomains = ['soundcloud.com'];
public readonly favicon = 'https://a-v2.sndcdn.com/assets/images/sc-icons/favicon-2cadd14bdb.ico';
public readonly name = 'Soundcloud';
// Soundcloud's URL scheme is a bit complicated, so instead of creating overly
public readonly name = 'SoundCloud';
// SoundCloud's URL scheme is a bit complicated, so instead of creating overly
// complex regular expressions, we'll match URLs programmatically. However,
// we still need to define this field, even though it'll never be used.
protected readonly urlRegex = [];
@@ -88,7 +88,7 @@
}
}

throw new Error('Could not extract Soundcloud Client ID');
throw new Error('Could not extract SoundCloud Client ID');

Check warning on line 91 in src/mb_enhanced_cover_art_uploads/providers/soundcloud.ts

Codecov / codecov/patch

src/mb_enhanced_cover_art_uploads/providers/soundcloud.ts#L91

Added line #L91 was not covered by tests
}

private static async getClientID(): Promise<string> {
@@ -106,7 +106,7 @@
const oldId = await this.getClientID();
const newId = await this.loadClientID();

assert(oldId !== newId, 'Attempted to refresh Soundcloud Client ID but retrieved the same one.');
assert(oldId !== newId, 'Attempted to refresh SoundCloud Client ID but retrieved the same one.');
localStorage.setItem(SC_CLIENT_ID_CACHE_KEY, newId);
}

@@ -120,10 +120,10 @@
.split('/');

return (pathParts.length > 0
&& !SoundcloudProvider.badArtistIDs.has(artistId)
&& !SoundCloudProvider.badArtistIDs.has(artistId)
// artist/likes, artist/track/recommended, artist/sets, ...
// but not artist/sets/setname!
&& !SoundcloudProvider.badSubpaths.has(urlBasename(url)));
&& !SoundCloudProvider.badSubpaths.has(urlBasename(url)));
}

public override extractId(url: URL): string | undefined {
@@ -141,7 +141,7 @@
const metadata = this.extractMetadataFromJS(pageContent)
?.find((data) => ['sound', 'playlist'].includes(data.hydratable));
if (!metadata) {
throw new Error('Could not extract metadata from Soundcloud page. The release may have been removed.');
throw new Error('Could not extract metadata from SoundCloud page. The release may have been removed.');
}

if (metadata.hydratable === 'sound') {
@@ -175,7 +175,7 @@
covers.push(...backdrops.map((backdropUrl) => ({
url: new URL(backdropUrl),
types: [ArtworkTypeIDs.Other],
comment: 'Soundcloud backdrop',
comment: 'SoundCloud backdrop',
})));
}

@@ -195,7 +195,7 @@
// Don't bother extracting track covers if they won't be used anyway
if (onlyFront) return covers;

// Soundcloud page only contains data for the first 5 tracks at first,
// SoundCloud page only contains data for the first 5 tracks at first,
// we need to load the rest of the tracks.
const tracks = await this.lazyLoadTracks(metadata.data.tracks);

@@ -215,7 +215,7 @@
trackImages.push(...visuals.map((visualUrl) => ({
url: visualUrl,
trackNumber: (trackNumber + 1).toString(),
customCommentPrefix: ['Soundcloud backdrop for track', 'Soundcloud backdrop for tracks'] as [string, string],
customCommentPrefix: ['SoundCloud backdrop for track', 'SoundCloud backdrop for tracks'] as [string, string],
})));

return trackImages;
@@ -235,7 +235,7 @@
try {
trackData = await this.getTrackData(lazyTrackIDs);
} catch (error) {
LOGGER.error('Failed to load Soundcloud track data, some track images may be missed', error);
LOGGER.error('Failed to load SoundCloud track data, some track images may be missed', error);
// We'll still return the tracks that we couldn't load, otherwise
// the track indices will be wrong.
return tracks;
@@ -260,8 +260,8 @@
}

private async getTrackData(lazyTrackIDs: number[], firstTry = true): Promise<SCHydrationTrack[]> {
LOGGER.info('Loading Soundcloud track data');
const clientId = await SoundcloudProvider.getClientID();
LOGGER.info('Loading SoundCloud track data');
const clientId = await SoundCloudProvider.getClientID();

// TODO: Does this work still work if we pass a large list of IDs?
const parameters = new URLSearchParams({
@@ -278,11 +278,11 @@
}

LOGGER.debug('Attempting to refresh client ID');
await SoundcloudProvider.refreshClientID();
await SoundCloudProvider.refreshClientID();
return this.getTrackData(lazyTrackIDs, firstTry = false);
}

return safeParseJSON<LoadedAPITrack[]>(trackDataResponse.text, 'Failed to parse Soundcloud API response');
return safeParseJSON<LoadedAPITrack[]>(trackDataResponse.text, 'Failed to parse SoundCloud API response');
}

private extractVisuals(track: SCHydrationTrack): string[] {
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { LOGGER } from '@lib/logging/logger';
import { ArtworkTypeIDs } from '@lib/MB/cover-art';
import { SoundcloudProvider } from '@src/mb_enhanced_cover_art_uploads/providers/soundcloud';
import { SoundCloudProvider } from '@src/mb_enhanced_cover_art_uploads/providers/soundcloud';
import { setupPolly } from '@test-utils/pollyjs';
import { itBehavesLike } from '@test-utils/shared-behaviour';

@@ -16,7 +16,7 @@ afterEach(() => {
});

describe('soundcloud provider', () => {
const provider = new SoundcloudProvider();
const provider = new SoundCloudProvider();
const pollyContext = setupPolly();

describe('url matching', () => {
@@ -113,7 +113,7 @@ describe('soundcloud provider', () => {
index: 3,
urlPart: '9b0d4395-cc72-4aa9-84e1-17b807264e2f',
types: [ArtworkTypeIDs.Track],
comment: 'Soundcloud backdrop for tracks 2, 4, 6, 8, 10, 18, 20',
comment: 'SoundCloud backdrop for tracks 2, 4, 6, 8, 10, 18, 20',
}],
}];

@@ -168,7 +168,7 @@ describe('soundcloud provider', () => {
const covers = await provider.findImages(new URL('https://soundcloud.com/soundcloud/sets/i-am-other-vol-2'));

expect(covers).toBeArrayOfSize(6);
expect(mockLoggerError).toHaveBeenCalledWith('Failed to load Soundcloud track data, some track images may be missed', expect.any(Error));
expect(mockLoggerError).toHaveBeenCalledWith('Failed to load SoundCloud track data, some track images may be missed', expect.any(Error));
});

it('attempts to refresh client ID', async () => {