Something went wrong. Try again.
[READ-ONLY] Mirror of https://github.com/FoxxMD/multi-scrobbler. Scrobble plays from multiple sources to multiple clients docs.multi-scrobbler.app
deezer docker jellyfin koito lastfm listenbrainz maloja mopidy mpris music music-assistant plex scrobble self-hosted spotify subsonic tautulli youtube-music
Something went wrong. Try again.
7.2 kB · 318 lines
MDX
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318---title: User Stagedescription: Enhancing Scrobbles with Regex Parsingtoc_min_heading_level: 2toc_max_heading_level: 5---
The **User** [Stage](/configuration/transforms#stage) uses [**search-and-replace** expressions](#search-and-replace-expression), provided by you, to modify/replace parts of Play data.
This Stage is most useful for correcting individual instances of bad data, or patterns, in your known data. Example scenarios:
* Removing `(Album Version)` from all Titles* Removing `Various Artists` from Artist data* Correcting spelling mistakes for individual Artist names
The user [Stage `type`](/configuration/transforms#stage) is `user`.
## Configuration
All [Stage Configuration](/configuration/transforms#configuring-stages) is done using [**search-and-replace** expressions](#search-and-replace-expression) inside individual [rules](#rules). Default configuration for all Rules can still be done using Stage `defaults`.
<details>
<summary>Example</summary>
```json5 title="config.json"{ // ... "transformers": [ { "type": "user", "name": "Normalizer", "defaults": { "title": [ "(Album Version)" ], "artists": [ "Various Artists" ] } } ]}```
</details>
#### Default Stage
For your convenience, if you do not define any User [Stage Configurations](/configuration/transforms#configuring-stages) then multi-scrobbler automatically builds an empty one for you.
This can be used by omitting the `name` in your [modification Stage](/configuration/transforms#stage).
<details>
<summary>Example</summary>
In a [Subsonic](/configuration/sources/subsonic) [File Config](/configuration?configType=file#configuration-types):
```json5 title="subsonic.json"[ { "name": "MySubsonic", "data": { /* ... */}, "options": { "playTransform": { "preCompare": [ { "type": "user", "title": [ // removes badterm from track title "badterm" ] } ] } } }]```</details>
### Search-And-Replace Expression
A Search-And-Replace Expression can be a plain string that matches a literal, then removes it:
```Expression: "badTerm"
"this is badTerm cool string" => "this is a cool string"```
or a regular expression that matches and removes the match:
```Expression: "/bad\w+/i"
"this is badSomething cool string" => "this is a cool string"```
Or it may be an object that specifies what to match (using either plain string or regular expression) and what to replace it with:
```json5{ "search": "anotherBadTerm", // match all instances of 'anotherBadTerm' "replace": "goodTerm" // replace with the string 'goodTerm'}```
```"this is anotherBadTerm cool string" => "this is goodTerm cool string"```
```json5{ "search": "/^\(\w+.com)/i", // matches any string that starts with EX '(YourMusic.com)' "replace": "[MySite.com]" // replace with the string '[MySite.com]'}```
```"(Foo.com) this is a cool string" => "[MySite.com] this is a cool string"```
The `replace` property uses javascript's [`replace()` function and so can use any special string characters.](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace#specifying_a_string_as_the_replacement)
### Rules
Each [Rule](/configuration/transforms#stage-rules) must be an array of [search-and-replace expressions](#search-and-replace-expression):
```json5 title="lastfm.json"[ { "name": "myLastFm", "configureAs": "source", "data": { // ... }, "options": { "playTransform": { "preCompare": [ { "type": "user", "title": [ // removes "badTerm" from title "badTerm", { // removes "fooTerm" from title and replaces it with "barTerm" "search": "fooTerm", "replace": "barTerm" } ] } ], } } }]```
:::note
If the value of the field (title, an artist, album) is an empty string after transforming then the field is **removed.**
:::
## Examples
### Usage with `when` condition
Using `when` for [Conditional Modification](/configuration/transforms#conditional-modification)<details>
<summary>Example</summary>
```json5// On search-replace in title...// IF artist matches "Elephant Gym"// THEN Run regex search-replace ELSE skip this rule//// Run live|remastered regex remove on title{ "type": "user", "title": [ { "search": "/\\s\\-\\s滾石40\\s滾石撞樂隊\\s40團拚經典(.+)$/i", "replace": "", "when": [ { "artist": "/Elephant Gym/" } ] }, "/(\\s\\-\\s|\\s)(feat\\.(.+)|live|remastered(.+))$/i" ],}```
</details>
### Remove phrase from Title in all new Plays
Removes the phrase `(Album Version)` from the Title of a Play
<details>
<summary>Example</summary>
```json5{ "type": "user", "title": [ "(Album Version)" ]}
```</details>
### Remove all parenthesized content from the end of a title
<details>
<summary>Example</summary>```json5{"compare": { "candidate": { "type": "user", "title": [ "/(\(.+\))\s*$/" ] }, "existing": { "type": "user", "title": [ "/(\(.+\))\s*$/" ] }, },}```</details>
### Rename misspelled artist in all new Plays
<details>
<summary>Example</summary>```json5{ "type": "user", "artists": [ { "search": "Boz Skaggs", "replace": "Boz Scaggs" } ]}```</details>
### Remove "Various Artists" albums in all new Plays
<details>
<summary>Example</summary>```json5{ "type": "user", "album": [ { "search": "Various Artists", "replace": "" } ]}```</details>
### Extract primary Artist from delimited, multi-Artist string
<details>
When the Artist string is actually a multi-artist, delimited string, this search-and-replace will replace the string with just the first artist found.
Ex
``` My Artist One / My Artist Two / Another Guy My Artist One ```
Artists are delimited with a spaced forward slash (`/`) in the regex below. Replace the contents of the `delim` capture group with the delimiter for your use case. Some more common scenarios:
* `(?<delim>\\/)` No spaces between slash IE `My Artist One/My Artist Two/Another Guy` * `(?<delim>\\s*\\\\\s*)` Backslash instead of forward slash IE `My Artist One \ My Artist Two \ Another Guy` * `(?<delim>,)` Comma IE `My Artist One, My Artist Two, Another Guy`
<details>
<summary>Example</summary>```json{ "type": "user", "artists": [ { "search": "(.*?)(?<delim>\\s*\\/\\s*)(.*$)", "replace": "$1" } ]}``` </details>
</details>