mirror of
https://github.com/FoxxMD/multi-scrobbler.git
synced 2026-09-03 05:10:00 +03:00
feat(transformers): Implement applyng limited transform configs via ENV
This commit is contained in:
@@ -108,6 +108,66 @@ Each [Rule](/configuration/transforms#stage-rules) should be either a boolean, s
|
||||
}
|
||||
```
|
||||
|
||||
## ENV Configuration
|
||||
|
||||
The general configuration shown above can also be configured from a selection of *presets* using [ENV Config](/configuration?configType=env#configuration-types) for individual Sources/Clients.
|
||||
|
||||
You must **always** include the `MB_CONTACT` ENV to [identify your application](#api-setup):
|
||||
|
||||
```ini
|
||||
MB_CONTACT=contact@mydomain.com
|
||||
```
|
||||
|
||||
To configure [stage defaults](http://localhost:3000/docs/configuration/transforms/musicbrainz/#stage-configuration) use `MB_PRESETS` with a comma-delimited list of presets you wish to apply. More than one preset can be applied, in which case they combine. You must choose at least one of the presets below:
|
||||
|
||||
* `default` - Applies no defaults. This is the same as using no options from [Matching With Musicbrainz](#matching-with-musicbrainz)
|
||||
* `sensible` - Applies the [Sensible Default](#sensible-default) configuration for sorting releases
|
||||
* `native` - Applies `fallbackArtistSearch: native` for [Artist Extraction](#artist-extraction) if the first search fails to find matches
|
||||
* `aggressive` - Applies [Free Text Search](#free-text) `fallbackFreeTextSearch: true` if all other searches fail
|
||||
|
||||
Finally, use ENV `*_TRANSFORMS=musicbrainz` on each Source/Client you wish to apply this stage to. This applies the stage in the [`preTransform` Hook](#/configuration/transforms#lifecycle-hooks) with all [Rules](#rules) enabled.
|
||||
|
||||
The `*` stands for the prefix used for each Source/Client's ENV keys. Refer to the individual Source/Client Configuration sections to find this.
|
||||
|
||||
:::tip
|
||||
|
||||
Enhancing a scrobble with the `preTransform` hook for a Source means that all Clients that recieve the scrobble get the enhanced version. You only need to apply the transform once, for a Source, to use it everywhere for downstream Clients.
|
||||
|
||||
:::
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Example Full Docker Deploy with ENV Configuration</summary>
|
||||
|
||||
Using [Jellyfin + Maloja](/quickstart#create-docker-compose-file) example from Quickstart:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
multi-scrobbler:
|
||||
image: foxxmd/multi-scrobbler
|
||||
container_name: multi-scrobbler
|
||||
environment:
|
||||
- MB_CONTACT=contact@mydomain.com
|
||||
- MB_PRESETS=sensible,native # creates sensible defaults with native fallback searching
|
||||
|
||||
- JELLYFIN_URL=192.168.0.110:8096
|
||||
- JELLYFIN_APIKEY=c9fae8756fbf481ebd9c5bb56b
|
||||
- JELLYFIN_USER=MyUser
|
||||
- JELLYFIN_TRANSFORMS=musicbrainz # applies musicbrainz Stage to preTransform of Jellyfin source
|
||||
|
||||
- MALOJA_URL=http://192.168.0.100:42010 # maloja receives enhanced scrobble from Jellyfin
|
||||
- MALOJA_API_KEY=myApiKey
|
||||
|
||||
|
||||
volumes:
|
||||
- "./config:/config"
|
||||
ports:
|
||||
- "9078:9078"
|
||||
restart: unless-stopped
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
## Matching with Musicbrainz
|
||||
|
||||
:::note
|
||||
|
||||
@@ -73,6 +73,50 @@ Each [Rule](/configuration/transforms#stage-rules) should be either a boolean, s
|
||||
|
||||
If a rule is not present then multi-scrobbler defaults it to `true`.
|
||||
|
||||
## ENV Configuration
|
||||
|
||||
The default configuration shown above can also be applied using [ENV Config](/configuration?configType=env#configuration-types) for individual Sources/Clients.
|
||||
|
||||
Use ENV `*_TRANSFORMS=native` on each Source/Client you wish to apply this stage to. This applies the stage in the [`preTransform` Hook](#/configuration/transforms#lifecycle-hooks) with all [Rules](#rules) enabled.
|
||||
|
||||
The `*` stands for the prefix used for each Source/Client's ENV keys. Refer to the individual Source/Client Configuration sections to find this.
|
||||
|
||||
:::tip
|
||||
|
||||
Enhancing a scrobble with the `preTransform` hook for a Source means that all Clients that recieve the scrobble get the enhanced version. You only need to apply the transform once, for a Source, to use it everywhere for downstream Clients.
|
||||
|
||||
:::
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Example Full Docker Deploy with ENV Configuration</summary>
|
||||
|
||||
Using [Jellyfin + Maloja](/quickstart#create-docker-compose-file) example from Quickstart:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
multi-scrobbler:
|
||||
image: foxxmd/multi-scrobbler
|
||||
container_name: multi-scrobbler
|
||||
environment:
|
||||
- JELLYFIN_URL=192.168.0.110:8096
|
||||
- JELLYFIN_APIKEY=c9fae8756fbf481ebd9c5bb56b
|
||||
- JELLYFIN_USER=MyUser
|
||||
- JELLYFIN_TRANSFORMS=native # applies native Stage to preTransform of Jellyfin source
|
||||
|
||||
- MALOJA_URL=http://192.168.0.100:42010 # maloja receives enhanced scrobble from Jellyfin
|
||||
- MALOJA_API_KEY=myApiKey
|
||||
|
||||
|
||||
volumes:
|
||||
- "./config:/config"
|
||||
ports:
|
||||
- "9078:9078"
|
||||
restart: unless-stopped
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
## Examples
|
||||
|
||||
### Parse only artists string using a custom delimiter
|
||||
|
||||
@@ -642,4 +642,73 @@ export const rankReleasesByPriority = (list: IRecordingMatch[], stageConfig: Mus
|
||||
rec.releases.sort((a, b) => b.rankedScore - a.rankedScore);
|
||||
}
|
||||
return rankedList;
|
||||
};
|
||||
};
|
||||
|
||||
export const DEFAULTS_SENSIBLE = {
|
||||
// use official release over anything else
|
||||
"releaseStatusPriority": ["official"],
|
||||
// prefer album, then single, then ep
|
||||
"releaseGroupPrimaryTypePriority": ["album", "single", "ep"],
|
||||
// prefer worldwide release
|
||||
"releaseCountryPriority": ["XW"]
|
||||
}
|
||||
export const DEFAULTS_NATIVE: {fallbackArtistSearch: "native"} = {
|
||||
"fallbackArtistSearch": "native"
|
||||
}
|
||||
|
||||
export const DEFAULTS_AGGRESSIVE = {
|
||||
"fallbackFreeText": true
|
||||
}
|
||||
|
||||
export const configFromEnv = (logger: MaybeLogger = new MaybeLogger()) => {
|
||||
const mbEnv = process.env.MB_PRESETS;
|
||||
const mbContact = process.env.MB_CONTACT;
|
||||
let mbConfig: MusicbrainzTransformerConfig;
|
||||
if (mbEnv !== undefined && mbEnv.trim() !== '') {
|
||||
if (mbContact === undefined || mbContact.trim() === '') {
|
||||
throw new SimpleError('Must provide a contact url/email for musicbrainz ENV present!');
|
||||
}
|
||||
mbConfig = {
|
||||
type: 'musicbrainz',
|
||||
name: 'MSDefault',
|
||||
data: {
|
||||
apis: [
|
||||
{
|
||||
contact: mbEnv
|
||||
}
|
||||
]
|
||||
},
|
||||
defaults: {
|
||||
|
||||
}
|
||||
}
|
||||
const presets = mbEnv.split(',').map(x => x.trim().toLocaleLowerCase());
|
||||
for (const p of presets) {
|
||||
switch (p) {
|
||||
case 'default':
|
||||
break;
|
||||
case 'sensible':
|
||||
mbConfig.defaults = {
|
||||
...mbConfig.defaults,
|
||||
...DEFAULTS_SENSIBLE
|
||||
}
|
||||
break;
|
||||
case 'native':
|
||||
mbConfig.defaults = {
|
||||
...mbConfig.defaults,
|
||||
...DEFAULTS_NATIVE
|
||||
}
|
||||
break;
|
||||
case 'aggressive':
|
||||
mbConfig.defaults = {
|
||||
...mbConfig.defaults,
|
||||
...DEFAULTS_AGGRESSIVE
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
logger.debug(`Using presets: ${presets.join(',')}`);
|
||||
}
|
||||
|
||||
return mbConfig;
|
||||
}
|
||||
@@ -7,9 +7,11 @@ import { PlayObject } from "../../../core/Atomic.js";
|
||||
import { isStageTyped } from "../../utils/PlayTransformUtils.js";
|
||||
import { MSCache } from "../Cache.js";
|
||||
import NativeTransformer from "./NativeTransformer.js";
|
||||
import MusicbrainzTransformer, { MusicbrainzTransformerConfig } from "./MusicbrainzTransformer.js";
|
||||
import MusicbrainzTransformer, { configFromEnv, MusicbrainzTransformerConfig } from "./MusicbrainzTransformer.js";
|
||||
import { AsyncLocalStorage } from 'node:async_hooks';
|
||||
import { nanoid } from "nanoid";
|
||||
import { SimpleError } from "../errors/MSErrors.js";
|
||||
import { toHaveStyle } from "@testing-library/jest-dom/matchers.js";
|
||||
|
||||
export default class TransformerManager {
|
||||
|
||||
@@ -61,6 +63,27 @@ export default class TransformerManager {
|
||||
this.logger.verbose(`${config.type} transformer with name '${tName}' registered`);
|
||||
}
|
||||
|
||||
public async registeryDefaults() {
|
||||
if(!this.hasTransformerType('user')) {
|
||||
this.register({type: 'user', name: 'MSDefault'});
|
||||
}
|
||||
if(!this.hasTransformerType('native')) {
|
||||
this.register({type: 'native', name: 'MSDefault'});
|
||||
}
|
||||
}
|
||||
|
||||
public async registerFromEnv() {
|
||||
try {
|
||||
const mbConfig = configFromEnv(this.logger);
|
||||
this.register(mbConfig);
|
||||
} catch (e) {
|
||||
if(e instanceof SimpleError) {
|
||||
this.logger.error(`Unable to build Musicbrainz Transformer from ENV: ${e.message}`);
|
||||
}
|
||||
this.logger.error(new Error('Unable to build Musicbrainz Transformer from ENV', {cause: e}));
|
||||
}
|
||||
}
|
||||
|
||||
public async initTransformers() {
|
||||
this.logger.verbose('Initializing transformers...');
|
||||
for (const list of this.transformers.values()) {
|
||||
|
||||
@@ -119,6 +119,8 @@ const configDir = process.env.CONFIG_DIR || path.resolve(projectDir, `./config`)
|
||||
const notifiers = new Notifiers(root.get('notifierEmitter'), root.get('clientEmitter'), root.get('sourceEmitter'), root.get('logger')); //root.get('notifiers');
|
||||
await notifiers.buildWebhooks(webhooks);
|
||||
|
||||
await root.items.transformerManager.registerFromEnv();
|
||||
await root.items.transformerManager.registeryDefaults();
|
||||
await root.items.transformerManager.initTransformers();
|
||||
|
||||
/*
|
||||
|
||||
@@ -25,6 +25,8 @@ import TealScrobbler from './TealfmScrobbler.js';
|
||||
import { TealClientConfig } from '../common/infrastructure/config/client/tealfm.js';
|
||||
import RockskyScrobbler from './RockskyScrobbler.js';
|
||||
import { RockSkyClientConfig } from '../common/infrastructure/config/client/rocksky.js';
|
||||
import { CommonClientOptions } from '../common/infrastructure/config/client/index.js';
|
||||
import { ExternalMetadataTerm, PlayTransformHooks } from '../common/infrastructure/Transform.js';
|
||||
|
||||
type groupedNamedConfigs = {[key: string]: ParsedConfig[]};
|
||||
|
||||
@@ -192,7 +194,8 @@ export default class ScrobbleClients {
|
||||
data: {
|
||||
url,
|
||||
apiKey
|
||||
}
|
||||
},
|
||||
options: transformPresetEnv('MALOJA')
|
||||
})
|
||||
}
|
||||
break;
|
||||
@@ -210,7 +213,8 @@ export default class ScrobbleClients {
|
||||
source: 'ENV',
|
||||
mode: 'single',
|
||||
configureAs: 'client',
|
||||
data: {...lfm, redirectUri: lfm.redirectUri ?? joinedUrl(this.localUrl, 'lastfm/callback').toString()}
|
||||
data: {...lfm, redirectUri: lfm.redirectUri ?? joinedUrl(this.localUrl, 'lastfm/callback').toString()},
|
||||
options: transformPresetEnv('LASTFM')
|
||||
})
|
||||
}
|
||||
break;
|
||||
@@ -227,7 +231,8 @@ export default class ScrobbleClients {
|
||||
source: 'ENV',
|
||||
mode: 'single',
|
||||
configureAs: 'client',
|
||||
data: lz
|
||||
data: lz,
|
||||
options: transformPresetEnv('LZ')
|
||||
})
|
||||
}
|
||||
break;
|
||||
@@ -244,7 +249,8 @@ export default class ScrobbleClients {
|
||||
source: 'ENV',
|
||||
mode: 'single',
|
||||
configureAs: 'client',
|
||||
data: koit
|
||||
data: koit,
|
||||
options: transformPresetEnv('KOITO')
|
||||
})
|
||||
}
|
||||
break;
|
||||
@@ -261,7 +267,8 @@ export default class ScrobbleClients {
|
||||
source: 'ENV',
|
||||
mode: 'single',
|
||||
configureAs: 'client',
|
||||
data: teal
|
||||
data: teal,
|
||||
options: transformPresetEnv('TEALFM')
|
||||
})
|
||||
}
|
||||
break;
|
||||
@@ -277,7 +284,8 @@ export default class ScrobbleClients {
|
||||
source: 'ENV',
|
||||
mode: 'single',
|
||||
configureAs: 'client',
|
||||
data: rocksky
|
||||
data: rocksky,
|
||||
options: transformPresetEnv('ROCKSKY')
|
||||
})
|
||||
}
|
||||
break;
|
||||
@@ -468,3 +476,32 @@ ${sources.join('\n')}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const transformPresetEnv = <T extends CommonClientOptions = CommonClientOptions>(prefix: string, existing: T = undefined): undefined | T => {
|
||||
|
||||
const env = process.env[`${prefix}_TRANSFORMS`];
|
||||
if(env === undefined || env.trim() === '') {
|
||||
return existing;
|
||||
}
|
||||
|
||||
const popts: PlayTransformHooks<ExternalMetadataTerm> = {
|
||||
preCompare: [
|
||||
]
|
||||
}
|
||||
for(const p of env.split(',').map(x => x.trim().toLocaleLowerCase())) {
|
||||
switch(p) {
|
||||
case 'native':
|
||||
popts.preCompare.push({type: 'native'});
|
||||
break;
|
||||
case 'musicbrainz':
|
||||
popts.preCompare.push({type: 'musicbrainz'});
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
return {
|
||||
...(existing || {}),
|
||||
playTransform: popts
|
||||
};
|
||||
}
|
||||
@@ -20,7 +20,7 @@ import { LastfmSourceConfig } from "../common/infrastructure/config/source/lastf
|
||||
import { ListenBrainzSourceConfig } from "../common/infrastructure/config/source/listenbrainz.js";
|
||||
import { MopidySourceConfig } from "../common/infrastructure/config/source/mopidy.js";
|
||||
import { MusicCastData, MusicCastSourceConfig } from "../common/infrastructure/config/source/musiccast.js";
|
||||
import { IcecastData, IcecastSourceConfig } from "../common/infrastructure/config/source/icecast.js";
|
||||
import { IcecastData, IcecastSourceConfig, IcecastSourceOptions } from "../common/infrastructure/config/source/icecast.js";
|
||||
import { MPDSourceConfig } from "../common/infrastructure/config/source/mpd.js";
|
||||
import { MPRISData, MPRISSourceConfig } from "../common/infrastructure/config/source/mpris.js";
|
||||
import { MusikcubeData, MusikcubeSourceConfig } from "../common/infrastructure/config/source/musikcube.js";
|
||||
@@ -73,6 +73,8 @@ import TealfmSource from './TealfmSource.js';
|
||||
import { TealSourceConfig } from '../common/infrastructure/config/source/tealfm.js';
|
||||
import { RockskySourceConfig } from '../common/infrastructure/config/source/rocksky.js';
|
||||
import RockskySource from './RockskySource.js';
|
||||
import { CommonSourceOptions } from '../common/infrastructure/config/source/index.js';
|
||||
import { ExternalMetadataTerm, PlayTransformHooks, PlayTransformOptions } from '../common/infrastructure/Transform.js';
|
||||
|
||||
type groupedNamedConfigs = {[key: string]: ParsedConfig[]};
|
||||
|
||||
@@ -339,7 +341,8 @@ export default class ScrobbleSources {
|
||||
source: 'ENV',
|
||||
mode: 'single',
|
||||
configureAs: defaultConfigureAs,
|
||||
data: s as SpotifySourceData
|
||||
data: s as SpotifySourceData,
|
||||
options: transformPresetEnv('SPOTIFY')
|
||||
})
|
||||
}
|
||||
break;
|
||||
@@ -358,7 +361,7 @@ export default class ScrobbleSources {
|
||||
source: 'ENV',
|
||||
mode: 'single',
|
||||
configureAs: defaultConfigureAs,
|
||||
data: t
|
||||
data: t,
|
||||
})
|
||||
}
|
||||
break;
|
||||
@@ -381,7 +384,8 @@ export default class ScrobbleSources {
|
||||
source: 'ENV',
|
||||
mode: 'single',
|
||||
configureAs: defaultConfigureAs,
|
||||
data: p
|
||||
data: p,
|
||||
options: transformPresetEnv('PLEX')
|
||||
})
|
||||
}
|
||||
break;
|
||||
@@ -398,7 +402,8 @@ export default class ScrobbleSources {
|
||||
source: 'ENV',
|
||||
mode: 'single',
|
||||
configureAs: defaultConfigureAs,
|
||||
data: sub as SubsonicData
|
||||
data: sub as SubsonicData,
|
||||
options: transformPresetEnv('SUBSONIC')
|
||||
})
|
||||
}
|
||||
break;
|
||||
@@ -425,7 +430,8 @@ export default class ScrobbleSources {
|
||||
source: 'ENV',
|
||||
mode: 'single',
|
||||
configureAs: defaultConfigureAs,
|
||||
data: j
|
||||
data: j,
|
||||
options: transformPresetEnv('JELLYFIN')
|
||||
})
|
||||
}
|
||||
break;
|
||||
@@ -448,7 +454,8 @@ export default class ScrobbleSources {
|
||||
source: 'ENV',
|
||||
mode: 'single',
|
||||
configureAs: defaultConfigureAs,
|
||||
data: d as DeezerData
|
||||
data: d as DeezerData,
|
||||
options: transformPresetEnv('DEEZER')
|
||||
});
|
||||
}
|
||||
break;
|
||||
@@ -465,7 +472,8 @@ export default class ScrobbleSources {
|
||||
source: 'ENV',
|
||||
mode: 'single',
|
||||
configureAs: defaultConfigureAs,
|
||||
data: mp as MPRISData
|
||||
data: mp as MPRISData,
|
||||
options: transformPresetEnv('MPRIS')
|
||||
});
|
||||
}
|
||||
break;
|
||||
@@ -486,7 +494,8 @@ export default class ScrobbleSources {
|
||||
source: 'ENV',
|
||||
mode: 'single',
|
||||
configureAs: defaultConfigureAs,
|
||||
data: lze as ListenbrainzEndpointData
|
||||
data: lze as ListenbrainzEndpointData,
|
||||
options: transformPresetEnv('LZE')
|
||||
});
|
||||
}
|
||||
break;
|
||||
@@ -502,7 +511,8 @@ export default class ScrobbleSources {
|
||||
source: 'ENV',
|
||||
mode: 'single',
|
||||
configureAs: defaultConfigureAs,
|
||||
data: lfme as LastFMEndpointData
|
||||
data: lfme as LastFMEndpointData,
|
||||
options: transformPresetEnv('LFM')
|
||||
});
|
||||
}
|
||||
break;
|
||||
@@ -519,9 +529,9 @@ export default class ScrobbleSources {
|
||||
mode: 'single',
|
||||
configureAs: defaultConfigureAs,
|
||||
data: icecast as IcecastData,
|
||||
options: {
|
||||
options: transformPresetEnv<IcecastSourceOptions>('ICECAST', {
|
||||
systemScrobble: parseBool(icecast.scrobbleOnStart)
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
break;
|
||||
@@ -538,7 +548,8 @@ export default class ScrobbleSources {
|
||||
source: 'ENV',
|
||||
mode: 'single',
|
||||
configureAs: defaultConfigureAs,
|
||||
data: jr as JRiverData
|
||||
data: jr as JRiverData,
|
||||
options: transformPresetEnv('JRIVER')
|
||||
});
|
||||
}
|
||||
break;
|
||||
@@ -555,7 +566,8 @@ export default class ScrobbleSources {
|
||||
source: 'ENV',
|
||||
mode: 'single',
|
||||
configureAs: defaultConfigureAs,
|
||||
data: ko as KodiData
|
||||
data: ko as KodiData,
|
||||
options: transformPresetEnv('KODI')
|
||||
});
|
||||
}
|
||||
break;
|
||||
@@ -575,7 +587,8 @@ export default class ScrobbleSources {
|
||||
data: {
|
||||
blacklist: ws.blacklist !== undefined ? ws.blacklist.split(',') : [],
|
||||
whitelist: ws.whitelist !== undefined ? ws.whitelist.split(',') : [],
|
||||
}
|
||||
},
|
||||
options: transformPresetEnv('WS')
|
||||
});
|
||||
}
|
||||
break;
|
||||
@@ -599,7 +612,8 @@ export default class ScrobbleSources {
|
||||
whitelistDevices: cc.whitelistDevices !== undefined ? cc.whitelistDevices.split(',') : [],
|
||||
blacklistApps: cc.blacklistApps !== undefined ? cc.blacklistApps.split(',') : [],
|
||||
whitelistApps: cc.whitelistApps !== undefined ? cc.whitelistApps.split(',') : [],
|
||||
}
|
||||
},
|
||||
options: transformPresetEnv('CC')
|
||||
});
|
||||
}
|
||||
break;
|
||||
@@ -614,7 +628,8 @@ export default class ScrobbleSources {
|
||||
source: 'ENV',
|
||||
mode: 'single',
|
||||
configureAs: defaultConfigureAs,
|
||||
data: musecase as MusicCastData
|
||||
data: musecase as MusicCastData,
|
||||
options: transformPresetEnv('MCAST')
|
||||
});
|
||||
}
|
||||
break;
|
||||
@@ -630,7 +645,8 @@ export default class ScrobbleSources {
|
||||
source: 'ENV',
|
||||
mode: 'single',
|
||||
configureAs: defaultConfigureAs,
|
||||
data: mc as MusikcubeData
|
||||
data: mc as MusikcubeData,
|
||||
options: transformPresetEnv('MC')
|
||||
});
|
||||
}
|
||||
break;
|
||||
@@ -646,7 +662,8 @@ export default class ScrobbleSources {
|
||||
source: 'ENV',
|
||||
mode: 'single',
|
||||
configureAs: defaultConfigureAs,
|
||||
data: vlc as VLCData
|
||||
data: vlc as VLCData,
|
||||
options: transformPresetEnv('VLC')
|
||||
});
|
||||
}
|
||||
break;
|
||||
@@ -664,7 +681,8 @@ export default class ScrobbleSources {
|
||||
source: 'ENV',
|
||||
mode: 'single',
|
||||
configureAs: defaultConfigureAs,
|
||||
data: ytm as YTMusicData
|
||||
data: ytm as YTMusicData,
|
||||
options: transformPresetEnv('YTM')
|
||||
});
|
||||
}
|
||||
break;
|
||||
@@ -683,7 +701,8 @@ export default class ScrobbleSources {
|
||||
source: 'ENV',
|
||||
mode: 'single',
|
||||
configureAs: defaultConfigureAs,
|
||||
data: azura as unknown as AzuracastData
|
||||
data: azura as unknown as AzuracastData,
|
||||
options: transformPresetEnv('AZURA')
|
||||
});
|
||||
}
|
||||
break;
|
||||
@@ -911,3 +930,32 @@ export default class ScrobbleSources {
|
||||
newSource.logger.info(`Source Added from ${source}`);
|
||||
}
|
||||
}
|
||||
|
||||
const transformPresetEnv = <T extends CommonSourceOptions = CommonSourceOptions>(prefix: string, existing: T = undefined): undefined | T => {
|
||||
|
||||
const env = process.env[`${prefix}_TRANSFORMS`];
|
||||
if(env === undefined || env.trim() === '') {
|
||||
return existing;
|
||||
}
|
||||
|
||||
const popts: PlayTransformHooks<ExternalMetadataTerm> = {
|
||||
preCompare: [
|
||||
]
|
||||
}
|
||||
for(const p of env.split(',').map(x => x.trim().toLocaleLowerCase())) {
|
||||
switch(p) {
|
||||
case 'native':
|
||||
popts.preCompare.push({type: 'native'});
|
||||
break;
|
||||
case 'musicbrainz':
|
||||
popts.preCompare.push({type: 'musicbrainz'});
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
return {
|
||||
...(existing || {}),
|
||||
playTransform: popts
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user