···161161162162#### Album name normalization
163163164164-The Apple Music API appends ` - EP` or ` - Single` to the album name for EPs and singles. Multi-Scrobbler strips this out so that the album name matches other sources.
164164+The Apple Music API appends ` - EP` or ` - Single` to the album name for EPs and singles. These suffixes are *not* part of the official names of the album and can cause issues when trying to scrobble or match metadata.
165165+166166+By default, Multi-Scrobbler strips these suffixes out so only the official name is used.
167167+168168+If you do not want this behavior it can be disabled with ENV `APPLEMUSIC_NORMALIZE_ALBUM=false` or File/AIO option `"normalizeAlbum": false`.
169169+170170+<DetailsAdmo type="tip" summary="Stripping Suffix with User Stage">
171171+172172+If you still want this stripping functionality but with more control over how it is applied you can use a [User Stage](/configuration/transforms/user).
173173+174174+Here is an example of creating a User Stage to only strip suffixes for a specific scrobble client:
175175+176176+<details>
177177+178178+<summary>Example</summary>
179179+180180+```json5 title="config.json"
181181+{
182182+ // ...
183183+ "transformers": [
184184+ {
185185+ "type": "user",
186186+ "name": "AppleAlbumStip",
187187+ "defaults": {
188188+ "album": [
189189+ "/ - (EP|Single)$/i"
190190+ ]
191191+ }
192192+ }
193193+ ]
194194+}
195195+```
196196+197197+```json5 title="applemusic.json"
198198+{
199199+ {
200200+ "id": "myAppleMusic",
201201+ "name": "My Apple Music",
202202+ "data": {
203203+ // ...
204204+ },
205205+ // highlight-start
206206+ "options": {
207207+ "normalizeAlbum": false
208208+ }
209209+ // highlight-end
210210+ }
211211+}
212212+```
213213+214214+```json5 title="lastfm.json"
215215+[
216216+ {
217217+ "name": "Foxx LFM Client",
218218+ "id": "myLastFmClient",
219219+ "enable": true,
220220+ "configureAs": "client",
221221+ "data": {
222222+ "apiKey": "a89cba1569901a0671d5a9875fed4be1",
223223+ "secret": "ec42e09d5ae0ee0f0816ca151008412a",
224224+ "redirectUri": "http://localhost:9078/lastfm/callback"
225225+ },
226226+ // highlight-start
227227+ "options": {
228228+ "playTransform": {
229229+ "preCompare": [
230230+ {
231231+ "type": "user",
232232+ "name": "AppleAlbumStip",
233233+ }
234234+ ]
235235+ }
236236+ }
237237+ // highlight-end
238238+ }
239239+]
240240+```
241241+242242+</details>
243243+244244+</DetailsAdmo>
165245166246## Configuration Reference
167247168248<Config config="AppleMusicSourceConfig" fileContent={AppleMusicConfig} name="applemusic">
169169- | Environment Variable | Required? | Default | Description |
170170- | ----------------------------- | --------- | ------- | ---------------------------------------------------- |
171171- | `APPLEMUSIC_ID` | Yes | | A unique ID for this source. |
172172- | `APPLEMUSIC_MEDIA_USER_TOKEN` | Yes | | The media-user-token extracted from the browser. |
173173- | `APPLEMUSIC_KEY_ID` | No | | Key ID from your MusicKit key. |
174174- | `APPLEMUSIC_TEAM_ID` | No | | Team ID from your Apple Developer account. |
175175- | `APPLEMUSIC_KEY_P8` | No | | The contents of your MusicKit `.p8` private key file.|
176176- | `APPLEMUSIC_TOKEN` | No | | The authentication JWT extracted from the browser. |
177177- | `APPLEMUSIC_INTERVAL` | No | `60` | Polling interval in seconds. |
178178- | `APPLEMUSIC_ORIGIN_HEADER` | No | | Origin header for API requests, e.g. `https://music.apple.com`. Required when using a browser token. |
179179- | `APPLEMUSIC_RECOVER_UNCHANGED_TOP_HISTORY` | No | `true` | Apple Music deduplicates its history by bumping re-played tracks to the top. If you listen to Song A → Song B → Song A, the history changes from `[A]` to `[A, B]` (bumping A). MS detects this "top-rebound" to recover the intermediate play (B) and the re-listen (A). Disable this only if you see incorrect duplicate scrobbles. |
180180- | `APPLEMUSIC_NAME` | No | | A vanity name different than the ID. |
249249+ | Environment Variable | Required? | Default | Description |
250250+ | ------------------------------------------ | --------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
251251+ | `APPLEMUSIC_ID` | Yes | | A unique ID for this source. |
252252+ | `APPLEMUSIC_MEDIA_USER_TOKEN` | Yes | | The media-user-token extracted from the browser. |
253253+ | `APPLEMUSIC_KEY_ID` | No | | Key ID from your MusicKit key. |
254254+ | `APPLEMUSIC_TEAM_ID` | No | | Team ID from your Apple Developer account. |
255255+ | `APPLEMUSIC_KEY_P8` | No | | The contents of your MusicKit `.p8` private key file. |
256256+ | `APPLEMUSIC_TOKEN` | No | | The authentication JWT extracted from the browser. |
257257+ | `APPLEMUSIC_INTERVAL` | No | `60` | Polling interval in seconds. |
258258+ | `APPLEMUSIC_ORIGIN_HEADER` | No | | Origin header for API requests, e.g. `https://music.apple.com`. Required when using a browser token. |
259259+ | `APPLEMUSIC_RECOVER_UNCHANGED_TOP_HISTORY` | No | `true` | Apple Music deduplicates its history by bumping re-played tracks to the top. If you listen to Song A → Song B → Song A, the history changes from `[A]` to `[A, B]` (bumping A). MS detects this "top-rebound" to recover the intermediate play (B) and the re-listen (A). Disable this only if you see incorrect duplicate scrobbles. |
260260+ | `APPLEMUSIC_NORMALIZE_ALBUM` | No | `true` | Strips extraneous `- EP` and `- Single` suffixes from album names |
261261+ | `APPLEMUSIC_NAME` | No | | A vanity name different than the ID. |
181262</Config>
···3737 * @examples [true, false]
3838 */
3939 recoverUnchangedTopHistory?: boolean
4040+ /**
4141+ * Removes extraneous suffixes from album data
4242+ *
4343+ * Apple Music add ' - EP' and ' - Single' to album names for EP's and singles, respectively.
4444+ * These suffixes are not part of the official names for the album and can cause issues in scrobble services
4545+ * or when matching metadata (musicbrainz).
4646+ *
4747+ * When this option is true (default), Multi-scrobbler automatically removes these suffixes.
4848+ *
4949+ * @default true
5050+ * @examples [true, false]
5151+ */
5252+ normalizeAlbum?: boolean
4053 }
4154}
4255
+8-6
src/backend/sources/AppleMusicSource.ts
···115115 return `Apple Music API is reachable (status ${status})`;
116116 }
117117118118- static formatPlayObj(track: Song, options: {newFromSource?: boolean} = {}): PlayObject {
119119- const {newFromSource = false} = options;
118118+ static formatPlayObj(track: Song, options: {newFromSource?: boolean, normalizeAlbum?: boolean} = {}): PlayObject {
119119+ const {newFromSource = false, normalizeAlbum = true} = options;
120120121121- // Apple Music appends " - EP" or " - Single" to the album name for EPs and singles
122122- // We strip this out so it matches other sources
123121 let albumName = track.albumName
124124- albumName = albumName.replace(/ - (EP|Single)$/i, '');
122122+ if(normalizeAlbum) {
123123+ // Apple Music appends " - EP" or " - Single" to the album name for EPs and singles
124124+ // We strip this out so it matches other sources
125125+ albumName = albumName.replace(/ - (EP|Single)$/i, '');
126126+ }
125127126128 const play: PlayObjectMinimal = {
127129 data: {
···164166 if (!result.data) {
165167 return [];
166168 }
167167- return (result.data as Song[]).map(track => AppleMusicSource.formatPlayObj(track));
169169+ return (result.data as Song[]).map(track => AppleMusicSource.formatPlayObj(track, {normalizeAlbum: this.config?.options?.normalizeAlbum}));
168170 }
169171170172 getIncomingHistoryConsistencyResult = (plays: PlayObject[]): HistoryConsistencyResult => {