Repository: ROpdebee/mb-userscripts (ts)

Issue:
RYM Provider: Support singles
[Release “Undertale” by Hot Dad - MusicBrainz](https://beta.musicbrainz.org/release/93e1a441-9ac6-4c24-9119-44c992f48abc/) →
https://rateyourmusic.com/release/single/hot_dad/undertale/ or https://rateyourmusic.com/release/single/hot-dad/undertale.p/
Failed to grab images: Expected to receive an image, but received text. Perhaps this provider is not supported yet? 

https://community.metabrainz.org/t/ropdebees-userscripts-support-thread/551947/44

Pull request description:
feat(ecau): support RateYourMusic single URLs
Fixes #329.

~This ran 715 test cases on my machine, so CI should do the same. Does it though?~ It does, ignore me, I got confused as I only added two URL test cases but of course each URL tests translates into 3 smaller test cases (matching, ID extraction, and checking the dispatch map) 🤦‍♂️ 

Patch:
diff --git a/src/mb_enhanced_cover_art_uploads/providers/rateyourmusic.ts b/src/mb_enhanced_cover_art_uploads/providers/rateyourmusic.ts
index d858c3fe..d3c8e3ba 100644
--- a/src/mb_enhanced_cover_art_uploads/providers/rateyourmusic.ts
+++ b/src/mb_enhanced_cover_art_uploads/providers/rateyourmusic.ts
@@ -10,7 +10,10 @@ export class RateYourMusicProvider extends CoverArtProvider {
     supportedDomains = ['rateyourmusic.com'];
     favicon = 'https://e.snmc.io/2.5/img/sonemic.png';
     name = 'RateYourMusic';
-    urlRegex = /\/release\/album\/([^/]+\/[^/]+)(?:\/|$)/;
+    // Include release type in the ID to make sure it doesn't redirect a single
+    // to an album and vice versa, and also to simplify the URL transformation
+    // below.
+    urlRegex = /\/release\/((?:album|single)\/[^/]+\/[^/]+)(?:\/|$)/;
 
     async findImages(url: URL): Promise<CoverArt[]> {
         const releaseId = this.extractId(url);
@@ -19,7 +22,7 @@ export class RateYourMusicProvider extends CoverArtProvider {
         // must be logged in to get the full-res image. We can't use the
         // thumbnails in case the user is not logged in, since they're served
         // as WebP, which isn't supported by CAA (yet).
-        const buyUrl = `https://rateyourmusic.com/release/album/${releaseId}/buy`;
+        const buyUrl = `https://rateyourmusic.com/release/${releaseId}/buy`;
         const buyDoc = parseDOM(await this.fetchPage(new URL(buyUrl)), buyUrl);
 
         if (qsMaybe('.header_profile_logged_in', buyDoc) === null) {


Test patch:
diff --git a/tests/unit/mb_enhanced_cover_art_uploads/providers/rateyourmusic.test.ts b/tests/unit/mb_enhanced_cover_art_uploads/providers/rateyourmusic.test.ts
index 125d91e3..1f07a0b6 100644
--- a/tests/unit/mb_enhanced_cover_art_uploads/providers/rateyourmusic.test.ts
+++ b/tests/unit/mb_enhanced_cover_art_uploads/providers/rateyourmusic.test.ts
@@ -16,11 +16,19 @@ describe('rateyourmusic provider', () => {
         const supportedUrls = [{
             desc: 'album URLs',
             url: 'https://rateyourmusic.com/release/album/fishmans/long-season.p/',
-            id: 'fishmans/long-season.p',
+            id: 'album/fishmans/long-season.p',
         }, {
             desc: 'album buy URLs',
             url: 'https://rateyourmusic.com/release/album/fishmans/long-season.p/buy/',
-            id: 'fishmans/long-season.p',
+            id: 'album/fishmans/long-season.p',
+        }, {
+            desc: 'single URLs',
+            url: 'https://rateyourmusic.com/release/single/hot_dad/undertale/',
+            id: 'single/hot_dad/undertale',
+        }, {
+            desc: 'single buy URLs',
+            url: 'https://rateyourmusic.com/release/single/hot_dad/undertale/buy',
+            id: 'single/hot_dad/undertale',
         }];
 
         const unsupportedUrls = [{