mirror of
https://github.com/FoxxMD/multi-scrobbler.git
synced 2026-09-03 05:10:00 +03:00
Compare commits
361
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e1324921e9 | ||
|
|
9f71fbef97 | ||
|
|
dd22418c41 | ||
|
|
d296b825d6 | ||
|
|
792ccc3c09 | ||
|
|
6772e9934d | ||
|
|
4ce7219214 | ||
|
|
b2ce42fecf | ||
|
|
46a061a602 | ||
|
|
ff7360fced | ||
|
|
425a0b2807 | ||
|
|
ad632f38d8 | ||
|
|
1d1b3b6f56 | ||
|
|
7575e8bff7 | ||
|
|
31546ed4c1 | ||
|
|
bf9cdc141c | ||
|
|
02ab1571b6 | ||
|
|
699bd02782 | ||
|
|
0d45d06966 | ||
|
|
a93d02e1b7 | ||
|
|
513e2dde15 | ||
|
|
2fc90dcfda | ||
|
|
fd2a178808 | ||
|
|
9f54d45576 | ||
|
|
78aff32334 | ||
|
|
0115ccb862 | ||
|
|
8a71663c9f | ||
|
|
40eff0b901 | ||
|
|
13acc56424 | ||
|
|
09fc0ce15c | ||
|
|
4fbdd71588 | ||
|
|
7cf105935e | ||
|
|
1bd10326eb | ||
|
|
74605caf15 | ||
|
|
90a8426748 | ||
|
|
8469d161e9 | ||
|
|
941f50bff2 | ||
|
|
f8d882cfcf | ||
|
|
0704cebe72 | ||
|
|
e43a18bcbb | ||
|
|
0baa399e9f | ||
|
|
05b2e1c116 | ||
|
|
a0cdaeb01f | ||
|
|
73c35751ed | ||
|
|
516a8d2178 | ||
|
|
d595bf9961 | ||
|
|
8345779030 | ||
|
|
b58d39c90e | ||
|
|
7074ece0a5 | ||
|
|
bfb0d6b392 | ||
|
|
5c3f49fb2f | ||
|
|
f70e680d55 | ||
|
|
c2fda1e7d9 | ||
|
|
70e4239e52 | ||
|
|
d96073282c | ||
|
|
2887600aa0 | ||
|
|
6f7aa6f567 | ||
|
|
857f44fa14 | ||
|
|
d764b0204e | ||
|
|
ee2f988357 | ||
|
|
de69977d7e | ||
|
|
6eab629168 | ||
|
|
f21572bed0 | ||
|
|
98084665ba | ||
|
|
e8a91bb6de | ||
|
|
206d1571ac | ||
|
|
ebf6ec6957 | ||
|
|
03fc3e3a09 | ||
|
|
aa50842444 | ||
|
|
03dbbdc2cf | ||
|
|
bf0b27924e | ||
|
|
e02a0cc6ae | ||
|
|
ff4dd25a97 | ||
|
|
28e0d03e6f | ||
|
|
d7f2d6fa8e | ||
|
|
8f33dc9f28 | ||
|
|
fe068a9216 | ||
|
|
06b6e200f5 | ||
|
|
afea13e681 | ||
|
|
f8401faf61 | ||
|
|
7c3590adf9 | ||
|
|
742025fecc | ||
|
|
b983de1a58 | ||
|
|
ea77ea435a | ||
|
|
ecf3273eb9 | ||
|
|
a79b697496 | ||
|
|
79874c6c20 | ||
|
|
aa91d2cb92 | ||
|
|
c727445f76 | ||
|
|
c25ca5297c | ||
|
|
956054f387 | ||
|
|
86ebd3d673 | ||
|
|
0679937b54 | ||
|
|
61a2ff5180 | ||
|
|
26db80d8c7 | ||
|
|
fc85790df5 | ||
|
|
212ac27dd3 | ||
|
|
a30d1ae6a5 | ||
|
|
5c586fb635 | ||
|
|
de0d336325 | ||
|
|
65d0c7c16b | ||
|
|
fc6cc68d59 | ||
|
|
8c83969e95 | ||
|
|
084dca73c1 | ||
|
|
7ac57ca757 | ||
|
|
1dc8c21716 | ||
|
|
6f8e7d3862 | ||
|
|
a6d33fc2ef | ||
|
|
26121ace10 | ||
|
|
27e5656a04 | ||
|
|
f3d7d59af6 | ||
|
|
2a4afefe64 | ||
|
|
1dba73ccb2 | ||
|
|
3e82e035ac | ||
|
|
b12153fba9 | ||
|
|
8c82412de4 | ||
|
|
e804ce33ef | ||
|
|
3907fa5474 | ||
|
|
a7b3593314 | ||
|
|
76ef994067 | ||
|
|
c3cb3cf3a1 | ||
|
|
8096219526 | ||
|
|
67c1823195 | ||
|
|
2014e78ade | ||
|
|
b3c332deeb | ||
|
|
93a1042e03 | ||
|
|
ba010240c0 | ||
|
|
7f491d6974 | ||
|
|
74e67e0e41 | ||
|
|
1853f9abba | ||
|
|
c13e7ebeec | ||
|
|
207354e799 | ||
|
|
d7f6b17308 | ||
|
|
c069020aac | ||
|
|
f84a0f190d | ||
|
|
d0f43fbd2d | ||
|
|
b38168975e | ||
|
|
a845ac10ce | ||
|
|
56fdb12683 | ||
|
|
1f40e1e414 | ||
|
|
c1a260dc56 | ||
|
|
5d34ea68af | ||
|
|
41ea9e0aa7 | ||
|
|
a9d91c2c8a | ||
|
|
a696436a75 | ||
|
|
4ae388676e | ||
|
|
89b698d48d | ||
|
|
b71a4cbbd6 | ||
|
|
a870cdc6f4 | ||
|
|
c404dd5396 | ||
|
|
cae845028d | ||
|
|
1698c5d71e | ||
|
|
765d86e02b | ||
|
|
f347b82d33 | ||
|
|
87aa9c461e | ||
|
|
417ce85bc7 | ||
|
|
c8d917cfe6 | ||
|
|
8c789123f9 | ||
|
|
06ed3f4388 | ||
|
|
fab2e4938d | ||
|
|
fbcd1e1b9a | ||
|
|
d48f2bd4ac | ||
|
|
e2dad463f6 | ||
|
|
642af13f3c | ||
|
|
4146b159bd | ||
|
|
3a3a97132d | ||
|
|
04a5b91694 | ||
|
|
945f494a2e | ||
|
|
4b09909b33 | ||
|
|
a5a1365b72 | ||
|
|
6bc618c481 | ||
|
|
85d1a0e648 | ||
|
|
1ae45c6060 | ||
|
|
7daa43a883 | ||
|
|
f8501b2a2e | ||
|
|
14c35edadf | ||
|
|
cbb9774a18 | ||
|
|
7b1eb7c2c1 | ||
|
|
8c8d1e1673 | ||
|
|
fbdd504453 | ||
|
|
612a90d7e7 | ||
|
|
de8ad60db8 | ||
|
|
43fd8ea807 | ||
|
|
ec3a7e2d20 | ||
|
|
981a211e56 | ||
|
|
c42b5cacaa | ||
|
|
919907f1cb | ||
|
|
9eac9fdfa1 | ||
|
|
86cea49ed4 | ||
|
|
8fc892a738 | ||
|
|
fd591be3d6 | ||
|
|
63b23689a4 | ||
|
|
3035d4c5e8 | ||
|
|
7891133002 | ||
|
|
66db4d017e | ||
|
|
15e55dc6c5 | ||
|
|
239fb5919e | ||
|
|
7e53553a8e | ||
|
|
4bd0345d1b | ||
|
|
b207109697 | ||
|
|
77de2a7526 | ||
|
|
69b19da6aa | ||
|
|
f2e2d67668 | ||
|
|
9c44ccb663 | ||
|
|
f431f4d5af | ||
|
|
be872d5ce1 | ||
|
|
0246f7dfa6 | ||
|
|
b57f325684 | ||
|
|
153f37e927 | ||
|
|
de4cb8a5c2 | ||
|
|
eb133e4f7e | ||
|
|
a3e056e7c5 | ||
|
|
7d8b00ab22 | ||
|
|
8b633dd901 | ||
|
|
f055cf683f | ||
|
|
baaa954f31 | ||
|
|
c727de9c40 | ||
|
|
e6f4a1dbd2 | ||
|
|
3d6e86f258 | ||
|
|
e6130eb5eb | ||
|
|
97b6042768 | ||
|
|
b3c1ce6d8a | ||
|
|
5daba47ac7 | ||
|
|
8d7760df6d | ||
|
|
75c95fdaa8 | ||
|
|
e874ccc2d3 | ||
|
|
17e97b3a6a | ||
|
|
c6389590fe | ||
|
|
7151d96b59 | ||
|
|
b2b2018764 | ||
|
|
655b97ce1c | ||
|
|
5c6edefc56 | ||
|
|
bf7fb4f558 | ||
|
|
32b64ff384 | ||
|
|
f6e0f4be4a | ||
|
|
fb66f0ca84 | ||
|
|
c4b1d72f3f | ||
|
|
fb452eb40b | ||
|
|
d3fd03a78c | ||
|
|
7b04e76c3b | ||
|
|
9f34c45192 | ||
|
|
7ab0f710ff | ||
|
|
ea1fb54de1 | ||
|
|
35fd84a1d0 | ||
|
|
e498db8ad3 | ||
|
|
145960ca04 | ||
|
|
91ba24e165 | ||
|
|
66fc7a2b09 | ||
|
|
97a7c7044c | ||
|
|
53d7de7e8d | ||
|
|
32da14c08e | ||
|
|
c7f370f121 | ||
|
|
9d105173da | ||
|
|
3e7bbab5b0 | ||
|
|
e04965eb35 | ||
|
|
f2c5e82665 | ||
|
|
4c41f0976d | ||
|
|
db333184cc | ||
|
|
a5963a2333 | ||
|
|
0fe81d6164 | ||
|
|
3ad9f5dcac | ||
|
|
d39abe40c6 | ||
|
|
6f8ca72ccf | ||
|
|
2ae32ee19f | ||
|
|
2ac89c5db3 | ||
|
|
b0db1dd8bc | ||
|
|
a603be6e22 | ||
|
|
7ad23a76de | ||
|
|
4481646153 | ||
|
|
5d2c9b557f | ||
|
|
eb69ae48f1 | ||
|
|
c7479b2f00 | ||
|
|
8ae7a8d338 | ||
|
|
7573c762c0 | ||
|
|
6d503a1a15 | ||
|
|
94d3ea5da8 | ||
|
|
e998006e6c | ||
|
|
234fc67ab2 | ||
|
|
37bb507359 | ||
|
|
1237056d59 | ||
|
|
7174702f7b | ||
|
|
3b721673c8 | ||
|
|
b64f0d2dd5 | ||
|
|
7738dc004a | ||
|
|
5c5563a917 | ||
|
|
7d08939a18 | ||
|
|
fabc50aa62 | ||
|
|
4c0615d427 | ||
|
|
b4dd729150 | ||
|
|
f336089755 | ||
|
|
4fc6285081 | ||
|
|
0cf3e33fe6 | ||
|
|
ab424aee0d | ||
|
|
9fb55d479d | ||
|
|
c8fb01bbab | ||
|
|
f008c4074d | ||
|
|
d66922c99a | ||
|
|
c7689199cc | ||
|
|
9a8b6bfa09 | ||
|
|
45c8141137 | ||
|
|
4e7b3e9ceb | ||
|
|
dfcc9c32a8 | ||
|
|
a3d891aa2f | ||
|
|
088ae4a26a | ||
|
|
f425b5a906 | ||
|
|
a4ddaeff61 | ||
|
|
8932224b57 | ||
|
|
ffe2203ba5 | ||
|
|
987819cc7c | ||
|
|
974a017e5a | ||
|
|
594a59347e | ||
|
|
b0970c6653 | ||
|
|
d8017dda62 | ||
|
|
a8c3e88ec9 | ||
|
|
7bf31a7fc7 | ||
|
|
deb3310e3f | ||
|
|
5450b48eb3 | ||
|
|
70a94cff9b | ||
|
|
ff31259092 | ||
|
|
8b4f1849f6 | ||
|
|
110ffad7d7 | ||
|
|
62a0670b4d | ||
|
|
7a1142fdd5 | ||
|
|
5def3cde99 | ||
|
|
075fa877ed | ||
|
|
6ffb46a65a | ||
|
|
ac5f34ea5f | ||
|
|
9975f377d0 | ||
|
|
76b4606d17 | ||
|
|
1244e0ee3e | ||
|
|
c56b16e2e6 | ||
|
|
831fd420ff | ||
|
|
2125f92bd8 | ||
|
|
42c9383dda | ||
|
|
f5eab006f5 | ||
|
|
5a2c664fe1 | ||
|
|
d7cbb7c9bd | ||
|
|
8afe30bfd4 | ||
|
|
24b67fc430 | ||
|
|
d01a00ad13 | ||
|
|
ac250eba39 | ||
|
|
778a2d6565 | ||
|
|
0b9a7b78df | ||
|
|
6b93e839fa | ||
|
|
7e6040ce7b | ||
|
|
d4b2057c41 | ||
|
|
bc04603fb4 | ||
|
|
ba2a23e039 | ||
|
|
6bfe203a34 | ||
|
|
8c6f34ebc7 | ||
|
|
18e20123c2 | ||
|
|
dc44f6c921 | ||
|
|
a19fd42a5b | ||
|
|
206fd62f70 | ||
|
|
6123503ee8 | ||
|
|
b751c6f5f9 | ||
|
|
d1ef09ba0d | ||
|
|
d073642203 | ||
|
|
9bb48fbf13 | ||
|
|
bf8f1175ce | ||
|
|
4bfcc40571 |
@@ -60,7 +60,7 @@ jobs:
|
||||
run: |
|
||||
set +e
|
||||
export NODE_ENV=production
|
||||
timeout --preserve-status 10s node node_modules/.bin/tsx src/backend/index.ts
|
||||
timeout --preserve-status 10s node src/backend/index.ts
|
||||
exitcode="$?"
|
||||
if [[ "$exitcode" -eq 143 ]] || [[ "$exitcode" -eq 137 ]]; then
|
||||
echo "App stayed up long enough and exited with expected status"
|
||||
|
||||
+5
-1
@@ -155,4 +155,8 @@ storybook-static
|
||||
*.db
|
||||
*.db*
|
||||
|
||||
**/lexicons/**/*.json
|
||||
**/lexicons/**/*.json
|
||||
|
||||
bun.lock
|
||||
.DS_Store
|
||||
**/.DS_Store
|
||||
@@ -1,7 +1,6 @@
|
||||
{
|
||||
"reporter": "dot",
|
||||
"extension": "ts",
|
||||
"import": "tsx/esm",
|
||||
"spec": "./src/backend/tests/**/*.test.ts",
|
||||
"file": [
|
||||
"./src/backend/tests/setup.ts"
|
||||
|
||||
@@ -12,6 +12,7 @@ export default defineMain({
|
||||
// "@storybook/addon-vitest",
|
||||
"@storybook/addon-a11y",
|
||||
"@storybook/addon-docs",
|
||||
'storybook-addon-remix-react-router'
|
||||
// "@storybook/addon-onboarding"
|
||||
],
|
||||
features: {
|
||||
|
||||
@@ -2,5 +2,5 @@ import { addons } from 'storybook/manager-api';
|
||||
import { themes } from 'storybook/theming';
|
||||
|
||||
addons.setConfig({
|
||||
theme: themes.dark,
|
||||
theme: themes.normal,
|
||||
});
|
||||
@@ -3,9 +3,14 @@ import addonA11y from "@storybook/addon-a11y";
|
||||
import { definePreview } from "@storybook/react-vite";
|
||||
|
||||
import { themes } from 'storybook/theming';
|
||||
import { initialize, mswLoader } from 'msw-storybook-addon';
|
||||
import { initialize, mswLoader, getWorker } from 'msw-storybook-addon';
|
||||
|
||||
initialize();
|
||||
// https://github.com/mswjs/msw-storybook-addon/issues/82#issuecomment-3894302575
|
||||
try {
|
||||
getWorker();
|
||||
} catch (_) {
|
||||
initialize();
|
||||
}
|
||||
|
||||
export default definePreview({
|
||||
loaders: [mswLoader],
|
||||
@@ -24,7 +29,7 @@ export default definePreview({
|
||||
test: 'todo'
|
||||
},
|
||||
docs: {
|
||||
theme: themes.dark,
|
||||
theme: themes.normal,
|
||||
},
|
||||
},
|
||||
|
||||
|
||||
Vendored
+24
-21
@@ -1,6 +1,24 @@
|
||||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Debug Zod Conversion",
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
// Debug app in VSCode
|
||||
"program": "${workspaceFolder}/ts-zod.ts",
|
||||
"args": [
|
||||
"${file}"
|
||||
],
|
||||
"runtimeExecutable": "node",
|
||||
"console": "integratedTerminal",
|
||||
"internalConsoleOptions": "neverOpen",
|
||||
"skipFiles": [
|
||||
"<node_internals>/**",
|
||||
// Ignore all dependencies (optional)
|
||||
"${workspaceFolder}/node_modules/**",
|
||||
],
|
||||
},
|
||||
{
|
||||
"name": "Run Canonical Replace",
|
||||
"program": "${workspaceFolder}/docsite/canonical-replace.ts",
|
||||
@@ -20,7 +38,7 @@
|
||||
"request": "launch",
|
||||
// Debug app in VSCode
|
||||
"program": "${workspaceFolder}/src/backend/index.ts",
|
||||
"runtimeExecutable": "${workspaceFolder}/node_modules/.bin/tsx",
|
||||
"runtimeExecutable": "node",
|
||||
"console": "integratedTerminal",
|
||||
"internalConsoleOptions": "neverOpen",
|
||||
"skipFiles": [
|
||||
@@ -35,7 +53,7 @@
|
||||
"request": "launch",
|
||||
// Debug app in VSCode
|
||||
"program": "${workspaceFolder}/src/backend/index.ts",
|
||||
"runtimeExecutable": "${workspaceFolder}/node_modules/.bin/tsx",
|
||||
"runtimeExecutable": "node",
|
||||
"console": "integratedTerminal",
|
||||
"envFile": "${workspaceFolder}/.env",
|
||||
"env": {
|
||||
@@ -48,28 +66,13 @@
|
||||
"${workspaceFolder}/node_modules/**",
|
||||
],
|
||||
},
|
||||
{
|
||||
"name": "tsx",
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
// Debug current file in VSCode
|
||||
"program": "${file}",
|
||||
"runtimeExecutable": "${workspaceFolder}/node_modules/.bin/tsx",
|
||||
"console": "integratedTerminal",
|
||||
"internalConsoleOptions": "neverOpen",
|
||||
"skipFiles": [
|
||||
"<node_internals>/**",
|
||||
// Ignore all dependencies (optional)
|
||||
"${workspaceFolder}/node_modules/**",
|
||||
],
|
||||
},
|
||||
{
|
||||
"name": "schema",
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
// Debug app in VSCode
|
||||
"program": "${workspaceFolder}/src/backend/utils/SchemaStaticUtil.ts",
|
||||
"runtimeExecutable": "${workspaceFolder}/node_modules/.bin/tsx",
|
||||
"program": "${workspaceFolder}/src/backend/utils/SchemaDocsStaticUtils.ts",
|
||||
"runtimeExecutable": "node",
|
||||
"console": "integratedTerminal",
|
||||
"internalConsoleOptions": "neverOpen",
|
||||
"skipFiles": [
|
||||
@@ -96,7 +99,7 @@
|
||||
"--recursive",
|
||||
"${workspaceFolder}/src/backend/tests/**/*.test.ts"
|
||||
],
|
||||
"runtimeExecutable": "${workspaceFolder}/node_modules/.bin/tsx",
|
||||
"runtimeExecutable": "node",
|
||||
"internalConsoleOptions": "openOnSessionStart",
|
||||
"name": "Mocha Tests",
|
||||
"program": "${workspaceFolder}/node_modules/mocha/bin/_mocha",
|
||||
@@ -120,7 +123,7 @@
|
||||
"--config", "${workspaceRoot}/.mocharc.json",
|
||||
"${file}"
|
||||
],
|
||||
"runtimeExecutable": "${workspaceFolder}/node_modules/.bin/tsx",
|
||||
"runtimeExecutable": "node",
|
||||
"internalConsoleOptions": "openOnSessionStart",
|
||||
"name": "Mocha Test on File",
|
||||
"program": "${workspaceFolder}/node_modules/mocha/bin/_mocha",
|
||||
|
||||
Vendored
+4
-3
@@ -1,5 +1,4 @@
|
||||
{
|
||||
"mochaExplorer.require": "tsx/esm",
|
||||
"mochaExplorer.timeout": 1200000,
|
||||
"mochaExplorer.exit": true,
|
||||
"search.exclude": {
|
||||
@@ -11,7 +10,9 @@
|
||||
"docsite/**"
|
||||
],
|
||||
"files.associations": {
|
||||
"*.css": "tailwindcss"
|
||||
"*.css": "tailwindcss",
|
||||
"**/config/*.json": "jsonc"
|
||||
},
|
||||
"tailwindCSS.experimental.configFile": "src/client/index.css"
|
||||
"tailwindCSS.experimental.configFile": "src/client/index.css",
|
||||
|
||||
}
|
||||
+3
-2
@@ -56,6 +56,7 @@ RUN npm install -g concurrently
|
||||
ARG data_dir=/config
|
||||
VOLUME $data_dir
|
||||
ENV CONFIG_DIR=$data_dir
|
||||
ENV DATA_DIR=$data_dir
|
||||
|
||||
COPY docker/root /
|
||||
|
||||
@@ -114,10 +115,10 @@ ARG APP_BUILD_VERSION
|
||||
ENV APP_VERSION=$APP_BUILD_VERSION
|
||||
|
||||
RUN npm ci --omit=dev --no-audit \
|
||||
# we used compiled schema json for production so this isn't needed
|
||||
&& npm uninstall ts-json-schema-generator \
|
||||
&& npm cache clean --force \
|
||||
&& chown -R abc:abc node_modules \
|
||||
## peerDependency of validbot and can(?) be removed for production
|
||||
&& rm -r node_modules/typescript \
|
||||
&& npx @usex/prune-mod -w \
|
||||
&& rm -rf /root/.cache
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ alt="multi-scrobbler logo" width="180" height="180">
|
||||
A dockerized app that monitors your music listening activity from *everywhere* and scrobbles it *anywhere*.
|
||||
|
||||
* Supports scrobbling from many [**Sources**](https://docs.multi-scrobbler.app/configuration/sources)
|
||||
* [Apple Music](https://docs.multi-scrobbler.app/configuration/sources/applemusic/?configType=file)
|
||||
* [Azuracast](https://docs.multi-scrobbler.app/configuration/sources/azuracast)
|
||||
* [Deezer](https://docs.multi-scrobbler.app/configuration/sources/deezer)
|
||||
* [Google Cast (Chromecast)](https://docs.multi-scrobbler.app/configuration/sources/google-cast)
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
[
|
||||
{
|
||||
"id": "myAppleMusic",
|
||||
"name": "My Apple Music",
|
||||
"enable": true,
|
||||
"clients": [],
|
||||
"data": {
|
||||
// either key or token needs to be provided
|
||||
"key": {
|
||||
"id": "2HPSNJZ88N",
|
||||
"teamId": "SN6YASW8G4",
|
||||
"p8": "-----BEGIN PRIVATE KEY-----\nMIGTAgEAMBMGByqGSM49AgEG...-----END PRIVATE KEY-----"
|
||||
},
|
||||
"token": "your-jwt-token-here",
|
||||
"mediaUserToken": "your-media-user-token-here",
|
||||
|
||||
// optional: Origin header for API requests (required when using a browser token)
|
||||
"origin": "https://music.apple.com",
|
||||
|
||||
// optional: polling interval in seconds (default 60)
|
||||
"interval": 60
|
||||
},
|
||||
"options": {
|
||||
"logDiff": true,
|
||||
"recoverUnchangedTopHistory": true,
|
||||
"normalizeAlbum": true
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -7,7 +7,8 @@
|
||||
"url": "http://localhost:4040/airsonic",
|
||||
"user": "yourUser",
|
||||
"password": "yourPassword",
|
||||
"usersAllow": ["yourUser"]
|
||||
"usersAllow": ["yourUser"],
|
||||
"detectStaleNowPlayingFromMinutesAgo": true
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
@@ -1,33 +1,19 @@
|
||||
#!/usr/bin/with-contenv bash
|
||||
|
||||
# used https://github.com/linuxserver/docker-plex as a template
|
||||
|
||||
POPULATE_EXAMPLES=false
|
||||
|
||||
echo "-------------------------------------"
|
||||
echo -e "Setting up multi-scrobbler config directory based on CONFIG_DIR env: ${CONFIG_DIR}\n"
|
||||
echo -e "Verifying multi-scrobbler directory permissions based on CONFIG_DIR env: ${CONFIG_DIR} and DATA_DIR env: ${DATA_DIR}\n"
|
||||
|
||||
# make config folder if it does not exist
|
||||
if [ ! -d "${CONFIG_DIR}" ]; then
|
||||
echo "Directory does not exist! Creating..."
|
||||
POPULATE_EXAMPLES=true
|
||||
mkdir -p "${CONFIG_DIR}"
|
||||
else
|
||||
if [ "$(ls -A ${CONFIG_DIR})" ]; then
|
||||
echo "Directory is not empty, not creating examples."
|
||||
else
|
||||
POPULATE_EXAMPLES=true
|
||||
fi
|
||||
if [ -d "${CONFIG_DIR}" ]; then
|
||||
echo "chown'ing config directory to ensure correct permissions."
|
||||
chown -R abc:abc "${CONFIG_DIR}"
|
||||
echo "Done!"
|
||||
fi
|
||||
|
||||
# add example configs
|
||||
if [ "$POPULATE_EXAMPLES" = true ]; then
|
||||
echo "Directory is empty, adding examples..."
|
||||
cp -r /app/config/. "${CONFIG_DIR}"/
|
||||
if [ -d "${DATA_DIR}" ]; then
|
||||
echo "chown'ing data directory to ensure correct permissions."
|
||||
chown -R abc:abc "${DATA_DIR}"
|
||||
echo "Done!"
|
||||
fi
|
||||
|
||||
# permissions
|
||||
echo "chown'ing directory to ensure correct permissions."
|
||||
chown -R abc:abc "${CONFIG_DIR}"
|
||||
echo "Done!"
|
||||
echo -e "-------------------------------------\n"
|
||||
|
||||
@@ -7,4 +7,4 @@ echo -e "\nmulti-scrobbler is starting!"
|
||||
export NODE_ENV=production
|
||||
cd /app || exit
|
||||
exec \
|
||||
s6-setuidgid abc /usr/bin/node $NODE_ARGS /app/node_modules/.bin/tsx /app/src/backend/index.ts
|
||||
s6-setuidgid abc /usr/bin/node $NODE_ARGS /app/src/backend/index.ts
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 1.9 MiB |
Binary file not shown.
|
After Width: | Height: | Size: 1.4 MiB |
Binary file not shown.
|
After Width: | Height: | Size: 501 KiB |
@@ -0,0 +1,12 @@
|
||||
| Environmental Variable | Type | Default | Description |
|
||||
| ---------------------------------- | -------------------------- | --------------------- | --------------------------------------- |
|
||||
| _**`DISCORD_ID`**_ | string | | A globally unique ID EX `myComponentId` |
|
||||
| `DISCORD_NAME` | string | Value of `DISCORD_ID` | A vanity name EX `My Cool Component` |
|
||||
| `DISCORD_ENABLE` | boolean | true | Should this component be used? |
|
||||
| `DISCORD_TOKEN` | string | | |
|
||||
| `DISCORD_ARTWORK` | boolean OR string OR array | | |
|
||||
| `DISCORD_APPLICATION_ID` | string | | |
|
||||
| `DISCORD_IPC_LOCATIONS` | string OR array | | |
|
||||
| `DISCORD_ARTWORK_DEFAULT_URL` | string | | |
|
||||
| `DISCORD_STATUS_OVERRIDE_ALLOW` | string OR array | | |
|
||||
| `DISCORD_LISTENING_ACTIVITY_ALLOW` | string OR array | | |
|
||||
@@ -0,0 +1,8 @@
|
||||
| Environmental Variable | Type | Default | Description |
|
||||
| ---------------------- | ------- | ------------------- | --------------------------------------- |
|
||||
| _**`KOITO_ID`**_ | string | | A globally unique ID EX `myComponentId` |
|
||||
| `KOITO_NAME` | string | Value of `KOITO_ID` | A vanity name EX `My Cool Component` |
|
||||
| `KOITO_ENABLE` | boolean | true | Should this component be used? |
|
||||
| _**`KOITO_URL`**_ | string | | URL for the Koito server |
|
||||
| _**`KOITO_TOKEN`**_ | string | | User token for the user to scrobble for |
|
||||
| _**`KOITO_USER`**_ | string | | Username of the user to scrobble for |
|
||||
@@ -0,0 +1,9 @@
|
||||
| Environmental Variable | Type | Default | Description |
|
||||
| ---------------------- | ------- | ------------------------------------- | ------------------------------------------------------- |
|
||||
| _**`LASTFM_ID`**_ | string | | A globally unique ID EX `myComponentId` |
|
||||
| `LASTFM_NAME` | string | Value of `LASTFM_ID` | A vanity name EX `My Cool Component` |
|
||||
| `LASTFM_ENABLE` | boolean | true | Should this component be used? |
|
||||
| _**`LASTFM_API_KEY`**_ | string | | API Key generated from Last.fm/Libre.fm account |
|
||||
| _**`LASTFM_SECRET`**_ | string | | Secret generated from Last.fm/Libre.fm account |
|
||||
| `LASTFM_REDIRECT_URI` | string | http://localhost:9078/lastfm/callback | Optional URI to use for callback. |
|
||||
| `LASTFM_SESSION` | string | | Optional session id returned from a completed auth flow |
|
||||
@@ -0,0 +1,10 @@
|
||||
| Environmental Variable | Type | Default | Description |
|
||||
| ---------------------- | ------- | -------------------------------------- | -------------------------------------------------------------- |
|
||||
| _**`LIBREFM_ID`**_ | string | | A globally unique ID EX `myComponentId` |
|
||||
| `LIBREFM_NAME` | string | Value of `LIBREFM_ID` | A vanity name EX `My Cool Component` |
|
||||
| `LIBREFM_ENABLE` | boolean | true | Should this component be used? |
|
||||
| `LIBREFM_API_KEY` | string | | Optional Secret for Libre.fm account |
|
||||
| `LIBREFM_SECRET` | string | | Optional Secret for Libre.fm account |
|
||||
| `LIBREFM_REDIRECT_URI` | string | http://localhost:9078/librefm/callback | Optional URI to use for callback. |
|
||||
| `LIBREFM_SESSION` | string | | Optional session id returned from a completed auth flow |
|
||||
| `LIBREFM_URLBASE` | string | https://libre.fm/2.0/ | (Optional) The host and path prefix for your Libre.fm instance |
|
||||
@@ -0,0 +1,8 @@
|
||||
| Environmental Variable | Type | Default | Description |
|
||||
| ---------------------- | ------- | ----------------------------- | --------------------------------------------------------- |
|
||||
| _**`LZ_ID`**_ | string | | A globally unique ID EX `myComponentId` |
|
||||
| `LZ_NAME` | string | Value of `LZ_ID` | A vanity name EX `My Cool Component` |
|
||||
| `LZ_ENABLE` | boolean | true | Should this component be used? |
|
||||
| `LZ_URL` | string | https://api.listenbrainz.org/ | URL for the ListenBrainz server, if not using the default |
|
||||
| _**`LZ_TOKEN`**_ | string | | User token for the user to scrobble for |
|
||||
| _**`LZ_USER`**_ | string | | Username of the user to scrobble for |
|
||||
@@ -0,0 +1,7 @@
|
||||
| Environmental Variable | Type | Default | Description |
|
||||
| ---------------------- | ------- | -------------------- | --------------------------------------- |
|
||||
| _**`MALOJA_ID`**_ | string | | A globally unique ID EX `myComponentId` |
|
||||
| `MALOJA_NAME` | string | Value of `MALOJA_ID` | A vanity name EX `My Cool Component` |
|
||||
| `MALOJA_ENABLE` | boolean | true | Should this component be used? |
|
||||
| _**`MALOJA_URL`**_ | string | | URL for maloja server |
|
||||
| _**`MALOJA_API_KEY`**_ | string | | API Key for Maloja server |
|
||||
@@ -0,0 +1,8 @@
|
||||
| Environmental Variable | Type | Default | Description |
|
||||
| ---------------------- | ------- | --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| _**`ROCKSKY_ID`**_ | string | | A globally unique ID EX `myComponentId` |
|
||||
| `ROCKSKY_NAME` | string | Value of `ROCKSKY_ID` | A vanity name EX `My Cool Component` |
|
||||
| `ROCKSKY_ENABLE` | boolean | true | Should this component be used? |
|
||||
| `ROCKSKY_KEY` | string | | API Key generated from [API Applications](https://docs.rocksky.app/migrating-from-listenbrainz-to-rocksky-1040189m0) in Rocksky for your account |
|
||||
| `ROCKSKY_TOKEN` | string | | Access Token generated from https://rocksky.app/access-tokens in Rocksky for your account |
|
||||
| _**`ROCKSKY_HANDLE`**_ | string | | The **fully-qualified** handle for your ATPRoto/Bluesky account, like: |
|
||||
@@ -0,0 +1,7 @@
|
||||
| Environmental Variable | Type | Default | Description |
|
||||
| ------------------------- | ------- | -------------------- | --------------------------------------- |
|
||||
| _**`TEALFM_ID`**_ | string | | A globally unique ID EX `myComponentId` |
|
||||
| `TEALFM_NAME` | string | Value of `TEALFM_ID` | A vanity name EX `My Cool Component` |
|
||||
| `TEALFM_ENABLE` | boolean | true | Should this component be used? |
|
||||
| _**`TEALFM_IDENTIFIER`**_ | string | | Identify the account to login as |
|
||||
| `TEALFM_APP_PW` | string | | |
|
||||
@@ -8,6 +8,7 @@ import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
import CodeBlock from '@theme/CodeBlock';
|
||||
import JsonConfig from '!!raw-loader!@site/../config/koito.json.example';
|
||||
import ENVConfig from "@site/docs/configuration/clients/_env_configs/_koito.md"
|
||||
|
||||
:::tip[Other Uses]
|
||||
|
||||
@@ -52,11 +53,5 @@ For Koito versions `<=0.1.7`, you must have the environment variable `KOITO_ALLO
|
||||
## Configuration
|
||||
|
||||
<Config config="KoitoClientConfig" fileContent={JsonConfig} client name="koito">
|
||||
| Environmental Variable | Required? | Default | Description |
|
||||
| :--------------------- | --------- | ------- | --------------------------------- |
|
||||
| `KOITO_ID` | Yes | | A unique id |
|
||||
| `KOITO_TOKEN` | Yes | | API Key from your Koito Account |
|
||||
| `KOITO_USER` | Yes | | Your Koito username |
|
||||
| `KOITO_URL` | No | | The base URL for the Koito server |
|
||||
| `KOITO_NAME` | No | | A vanity name, different than ID |
|
||||
<ENVConfig/>
|
||||
</Config>
|
||||
|
||||
@@ -8,6 +8,7 @@ import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
import CodeBlock from '@theme/CodeBlock';
|
||||
import JsonConfig from '!!raw-loader!@site/../config/lastfm.json.example';
|
||||
import ENVConfig from "@site/docs/configuration/clients/_env_configs/_lastfm.md"
|
||||
|
||||
:::tip[Other Users]
|
||||
|
||||
@@ -63,12 +64,5 @@ The Redirect URL can be explicitly specified in the configuration below, or by u
|
||||
## Configuration
|
||||
|
||||
<Config config="LastfmClientConfig" fileContent={JsonConfig} client name="lastfm">
|
||||
| Environmental Variable | Required? | Default | Description |
|
||||
| ---------------------- | --------- | --------------------------------------- | ----------------------------------------------------------------------------- |
|
||||
| `LASTFM_ID` | Yes | | A unique id |
|
||||
| `LASTFM_API_KEY` | Yes | | Api Key from your API Account |
|
||||
| `LASTFM_SECRET` | Yes | | Shared secret from your API Account |
|
||||
| `LASTFM_REDIRECT_URI` | No | `http://localhost:9078/lastfm/callback` | Url to use for authentication. Must include `lastfm/callback` somewhere in it |
|
||||
| `LASTFM_SESSION` | No | | Session id. Will be generated by authentication flow if not provided. |
|
||||
| `LASTFM_NAME` | No | | A vanity name, different than ID |
|
||||
<ENVConfig/>
|
||||
</Config>
|
||||
@@ -8,6 +8,7 @@ import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
import CodeBlock from '@theme/CodeBlock';
|
||||
import JsonConfig from '!!raw-loader!@site/../config/librefm.json.example';
|
||||
import ENVConfig from "@site/docs/configuration/clients/_env_configs/_librefm.md"
|
||||
|
||||
:::tip[Other Users]
|
||||
|
||||
@@ -15,9 +16,9 @@ import JsonConfig from '!!raw-loader!@site/../config/librefm.json.example';
|
||||
|
||||
:::
|
||||
|
||||
To use the official [Libre.fm](https://libre.fm/) instance you will need an account. Or, you can run your own Libre.fm instance [using the legacy source code](https://github.com/foocorp/gnu-fm).
|
||||
To use the official [Libre.fm](https://libre.fm/) website you will need an account. Or, you can run your own GNU FM instance [using the source code](https://github.com/foocorp/gnu-fm).
|
||||
|
||||
No API account, [API Key, or Secret](https://github.com/libre-fm/developer/wiki/Libre.fm-fundamentals#api-keys) is needed to use the Libre.fm API. Instead, use **any values** for API Key/Secret in the configuration. Authentication is done by allowing access from your account on redirect.
|
||||
No API account, [API Key, or Secret](https://github.com/libre-fm/developer/wiki/Libre.fm-fundamentals#api-keys) is currently needed to use the Libre.fm API. Instead, use **any values** for API Key/Secret in the configuration. Authentication is done by allowing access from your account on redirect.
|
||||
|
||||
### Callback/Redirect URL
|
||||
|
||||
@@ -54,14 +55,5 @@ https://my.cool.libre.com/2.0/
|
||||
## Configuration
|
||||
|
||||
<Config config="LibrefmClientConfig" fileContent={JsonConfig} client name="librefm">
|
||||
| Environmental Variable | Required? | Default | Description |
|
||||
| ---------------------- | --------- | ---------------------------------------- | ------------------------------------------------------------------------------------------------ |
|
||||
| `LIBREFM_ID` | Yes | | A unique ID |
|
||||
| `LIBREFM_ENABLE` | No | | Set to `true` to enable Libre.fm, if not using any of the below variables |
|
||||
| `LIBREFM_API_KEY` | No | `anything` | Optional API Key |
|
||||
| `LIBREFM_SECRET` | No | `anything` | Optional shared secret |
|
||||
| `LIBREFM_REDIRECT_URI` | No | `http://localhost:9078/librefm/callback` | Url to use for authentication. Must include `librefm/callback` somewhere in it |
|
||||
| `LIBREFM_SESSION` | No | | Session id. Will be generated by authentication flow if not provided. |
|
||||
| `LIBREFM_URLBASE` | No | | Use for custom Libre.fm instance only. The host + path prefix EX `https://my.libre.example/2.0/` |
|
||||
| `LIBREFM_NAME` | No | | A vanity name different than ID |
|
||||
</Config>
|
||||
<ENVConfig/>
|
||||
</Config>
|
||||
|
||||
@@ -8,6 +8,7 @@ import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
import CodeBlock from '@theme/CodeBlock';
|
||||
import JsonConfig from '!!raw-loader!@site/../config/listenbrainz.json.example';
|
||||
import ENVConfig from "@site/docs/configuration/clients/_env_configs/_listenbrainz.md"
|
||||
|
||||
:::tip[Other Users]
|
||||
|
||||
@@ -23,11 +24,5 @@ On your [profile page](https://listenbrainz.org/profile/) find your **User Token
|
||||
## Configuration
|
||||
|
||||
<Config config="ListenBrainzClientConfig" fileContent={JsonConfig} client name="listenbrainz">
|
||||
| Environmental Variable | Required? | Default | Description |
|
||||
| ---------------------- | --------- | ----------------------------- | ------------------------------- |
|
||||
| `LZE_ID` | Yes | | A unique ID |
|
||||
| `LZ_TOKEN` | Yes | | User token from your LZ profile |
|
||||
| `LZ_USER` | Yes | | Your LZ username |
|
||||
| `LZ_URL` | No | https://api.listenbrainz.org/ | The base URL for the LZ server |
|
||||
| `LZ_NAME` | No | | A vanity name different than ID |
|
||||
<ENVConfig/>
|
||||
</Config>
|
||||
@@ -8,6 +8,7 @@ import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
import CodeBlock from '@theme/CodeBlock';
|
||||
import JsonConfig from '!!raw-loader!@site/../config/maloja.json.example';
|
||||
import ENVConfig from "@site/docs/configuration/clients/_env_configs/_maloja.md"
|
||||
|
||||
Setup a [Maloja server](https://github.com/krateng/maloja?tab=readme-ov-file#how-to-install) if you have not already done this.
|
||||
|
||||
@@ -38,10 +39,5 @@ Finally, add the Maloja server URL and API Key to the configuration type you cho
|
||||
## Configuration
|
||||
|
||||
<Config config="MalojaClientConfig" fileContent={JsonConfig} client name="maloja">
|
||||
| Environmental Variable | Required? | Default | Description |
|
||||
| ---------------------- | --------- | ------- | ------------------------------- |
|
||||
| `MALOJA_ID` | Yes | | A unique ID |
|
||||
| `MALOJA_URL` | Yes | | Base URL of your installation |
|
||||
| `MALOJA_API_KEY` | Yes | | Api Key |
|
||||
| `MALOJA_NAME` | No | | A vanity name different than ID |
|
||||
<ENVConfig/>
|
||||
</Config>
|
||||
@@ -6,6 +6,7 @@ toc_max_heading_level: 5
|
||||
|
||||
import Bluesky from "@site/src/components/snippets/_bluesky.mdx";
|
||||
import JsonConfig from '!!raw-loader!@site/../config/rocksky.json.example';
|
||||
import ENVConfig from "@site/docs/configuration/clients/_env_configs/_rocksky.md"
|
||||
|
||||
:::tip[Other Uses]
|
||||
|
||||
@@ -13,7 +14,7 @@ To monitor and re-scrobble activity **from** Rocksky create a [Rocksky (Source)]
|
||||
|
||||
:::
|
||||
|
||||
[**Rocksky**](https://rocksky.app/) is music tracking and discovery platform built on the AT Protocol (Bluesky).
|
||||
[**Rocksky**](https://rocksky.app/) is music tracking and discovery platform built on the AT Protocol and your your [**Atmosphere Account**](https://atmosphereaccount.com/).
|
||||
|
||||
<details>
|
||||
|
||||
@@ -41,16 +42,16 @@ If you need your scrobbles to be 100% captured then you should scrobble to an *a
|
||||
|
||||
## Setup
|
||||
|
||||
You will need a [Bluesky](https://bsky.app/), or other [ATmosphere](https://atproto.brussels/about-the-atmosphere), account to use Rocksky.
|
||||
You will need an [**Atmosphere Account**](https://atmosphereaccount.com/) to use Rocksky.
|
||||
|
||||
* Navigate to [rocksky.app](https://rocksky.app/) and sign up/logn using your ATmosphere account
|
||||
* Navigate to [rocksky.app](https://rocksky.app/) and sign up/logn using your Atmosphere Account
|
||||
* Then, navigate to the [Access Tokens](https://rocksky.app/access-tokens) in the Rocksky settings dropdown, and create a new token
|
||||
|
||||
## Configuration
|
||||
|
||||
### Handle
|
||||
|
||||
The handle used with multi-scrobbler should be your **full** ATProto handle, including TLD.
|
||||
The handle used with multi-scrobbler should be your **full** [**Atmosphere Account**](https://atmosphereaccount.com/) handle, including TLD.
|
||||
|
||||
* For regular Bluesky account this will be like: `alice.bsky.social`
|
||||
* For Bluesky accounts that [use their website as their account](https://bsky.social/about/blog/4-28-2023-domain-handle-tutorial) this is your domain: `mydomain.com`
|
||||
@@ -69,17 +70,12 @@ If your configuration is using either
|
||||
* (File/AIO) `'key': ...`
|
||||
* (ENV) `ROCKSKY_KEY`
|
||||
|
||||
you should redo the [Setup](#setup) modify your configuration to use an Access Token instead.
|
||||
you should redo the [Setup](#setup) section and modify your configuration to use an Access Token instead.
|
||||
|
||||
Keys are now **deprecated** and functionality for them will be removed in a future version of Multi-Scrobbler.
|
||||
|
||||
</DetailsAdmo>
|
||||
|
||||
<Config config="RockSkyClientConfig" fileContent={JsonConfig} client name="rocksky">
|
||||
| Environmental Variable | Required? | Default | Description |
|
||||
| :--------------------- | --------- | ------- | ----------------------------------------------------------------------------------- |
|
||||
| `ROCKSKY_ID` | Yes | | A unique ID used in MS |
|
||||
| `ROCKSKY_HANDLE` | Yes | | Your **full** ATProto handle. For Bluesky account this is like `myUser.bsky.social` |
|
||||
| `ROCKSKY_TOKEN` | Yes | | Access Token obtained from Rocksky |
|
||||
| `ROCKSKY_NAME` | No | | A vanity name different than ID |
|
||||
<ENVConfig/>
|
||||
</Config>
|
||||
@@ -9,6 +9,7 @@ import TabItem from '@theme/TabItem';
|
||||
import CodeBlock from '@theme/CodeBlock';
|
||||
import JsonConfig from '!!raw-loader!@site/../config/tealfm.json.example';
|
||||
import Bluesky from "@site/src/components/snippets/_bluesky.mdx";
|
||||
import ENVConfig from "@site/docs/configuration/clients/_env_configs/_tealfm.md"
|
||||
|
||||
:::tip[Other Uses]
|
||||
|
||||
@@ -16,7 +17,7 @@ To monitor and re-scrobble activity from a ATProto Profile create a [teal.fm (So
|
||||
|
||||
:::
|
||||
|
||||
[**teal.fm**](https://teal.fm/) is a social discovery and web viewing service for scrobbles stored/available on the ATProto network/your repository in a [PDS (Personal Data Server)](https://github.com/Bluesky-social/pds).
|
||||
[**teal.fm**](https://teal.fm/) is a social discovery and browsing app for scrobbles stored in your [**Atmosphere Account**](https://atmosphereaccount.com/).
|
||||
|
||||
<details>
|
||||
|
||||
@@ -46,6 +47,13 @@ To view your teal.fm scrobble data you can:
|
||||
|
||||
## Setup
|
||||
|
||||
|
||||
:::note
|
||||
|
||||
Multi-scrobbler will work with *any* Atmosphere Account, not just Bluesky. See [Configuration](#configuration) below for provider-agnostic config.
|
||||
|
||||
:::
|
||||
|
||||
#### Bluesky
|
||||
|
||||
* Create a [Bluesky](https://bsky.app) account, if you don't already have one
|
||||
@@ -57,10 +65,10 @@ To view your teal.fm scrobble data you can:
|
||||
|
||||
### Identifier
|
||||
|
||||
The ATPRoto identifier used with multi-scrobbler should be either:
|
||||
The ATProto identifier used with multi-scrobbler should be either:
|
||||
|
||||
* A valid [DID](https://atproto.com/specs/did#at-protocol-did-identifier-syntax), starting with `did:plc:...` or `did:web:...`
|
||||
* Your **full** ATProto handle, including TLD
|
||||
* Your **full** [Atmosphere Account](https://atmosphereaccount.com/) ATProto handle, including TLD
|
||||
|
||||
If using a handle:
|
||||
|
||||
@@ -71,10 +79,5 @@ If using a handle:
|
||||
If your identifier does not look like a DID and does not include a TLD then multi-scrobbler will automatically append `.bsky.social` to your handle value.
|
||||
|
||||
<Config config="TealClientConfig" fileContent={JsonConfig} client name="tealfm">
|
||||
| Environmental Variable | Required? | Default | Description |
|
||||
| :--------------------- | --------- | ------- | ------------------------------------------------------------------------------------------ |
|
||||
| `TEAMFM_ID` | Yes | | A unique ID |
|
||||
| `TEALFM_IDENTIFIER` | Yes | | Your **full** ATProto handle or DID. For Bluesky account this is like `myUser.bsky.social` |
|
||||
| `TEALFM_APP_PW` | Yes | | Bluesky/ATProto network App Password |
|
||||
| `TEALFM_NAME` | No | | A vanity name different than ID |
|
||||
<ENVConfig/>
|
||||
</Config>
|
||||
@@ -146,7 +146,7 @@ Check the [**FAQ**](../FAQ.md) if you have any issues after configuration!
|
||||
* There is also a [**kitchensink example**](/configuration/kitchensink) that provides examples of using all sources/clients in a complex configuration.
|
||||
:::
|
||||
|
||||
[**Explore the schema for this configuration, along with an example generator and validator, here**](https://json-schema.app/view/%23?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fmulti-scrobbler%2Fmaster%2Fsrc%2Fbackend%2Fcommon%2Fschema%2Faio.json)
|
||||
[**Explore the schema for this configuration, along with an example generator and validator, here**](/playground)
|
||||
|
||||
<details>
|
||||
|
||||
@@ -810,7 +810,7 @@ Webhooks are configured in the AIO [config.json](#configuration-types) file unde
|
||||
|
||||
#### [Gotify](https://gotify.net/)
|
||||
|
||||
Refer to the [config schema for GotifyConfig](https://json-schema.app/view/%23/%23%2Fdefinitions%2FGotifyConfig?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fmulti-scrobbler%2Fmaster%2Fsrc%2Fbackend%2Fcommon%2Fschema%2Faio.json)
|
||||
Refer to the [config schema for GotifyConfig](/playground)
|
||||
|
||||
multi-scrobbler optionally supports setting message notification priority via `info` `warn` and `error` mappings.
|
||||
|
||||
@@ -836,7 +836,7 @@ multi-scrobbler optionally supports setting message notification priority via `i
|
||||
|
||||
#### [Ntfy](https://ntfy.sh/)
|
||||
|
||||
Refer to the [config schema for NtfyConfig](https://json-schema.app/view/%23/%23%2Fdefinitions%2FNtfyConfig?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fmulti-scrobbler%2Fmaster%2Fsrc%2Fbackend%2Fcommon%2Fschema%2Faio.json)
|
||||
Refer to the [config schema for NtfyConfig](/playground)
|
||||
|
||||
multi-scrobbler optionally supports setting message notification priority via `info` `warn` and `error` mappings.
|
||||
|
||||
@@ -864,7 +864,7 @@ multi-scrobbler optionally supports setting message notification priority via `i
|
||||
|
||||
#### [Apprise](https://github.com/caronc/apprise-api)
|
||||
|
||||
Refer to the [config schema for AppriseConfig](https://json-schema.app/view/%23/%23%2Fdefinitions%2FAppriseConfig?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fmulti-scrobbler%2Fmaster%2Fsrc%2Fbackend%2Fcommon%2Fschema%2Faio.json)
|
||||
Refer to the [config schema for AppriseConfig](/playground)
|
||||
|
||||
multi-scrobbler supports [stateless](https://github.com/caronc/apprise-api?tab=readme-ov-file#stateless-solution) and [persistent storage](https://github.com/caronc/apprise-api?tab=readme-ov-file#persistent-storage-solution) endpoints as well as [tags](https://github.com/caronc/apprise-api?tab=readme-ov-file#tagging)/
|
||||
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
| Environmental Variable | Type | Default | Description |
|
||||
| ------------------------------------------ | ------- | ------------------------ | -------------------------------------------------------------------- |
|
||||
| _**`APPLEMUSIC_ID`**_ | string | | A globally unique ID EX `myComponentId` |
|
||||
| `APPLEMUSIC_NAME` | string | Value of `APPLEMUSIC_ID` | A vanity name EX `My Cool Component` |
|
||||
| `APPLEMUSIC_ENABLE` | boolean | true | Should this component be used? |
|
||||
| `APPLEMUSIC_KEY_ID` | string | | |
|
||||
| `APPLEMUSIC_TEAM_ID` | string | | |
|
||||
| `APPLEMUSIC_KEY_P8` | string | | |
|
||||
| _**`APPLEMUSIC_MEDIA_USER_TOKEN`**_ | string | | |
|
||||
| `APPLEMUSIC_TOKEN` | string | | |
|
||||
| `APPLEMUSIC_ORIGIN_HEADER` | string | | Origin header to include in every Apple Music API request. |
|
||||
| `APPLEMUSIC_RECOVER_UNCHANGED_TOP_HISTORY` | boolean | true | Fixes a quirk where Apple Music's history API hides duplicate plays. |
|
||||
| `APPLEMUSIC_NORMALIZE_ALBUM` | boolean | true | Removes extraneous suffixes from album data |
|
||||
@@ -0,0 +1,10 @@
|
||||
| Environmental Variable | Type | Default | Description |
|
||||
| ---------------------- | ------- | ------------------- | ------------------------------------------------- |
|
||||
| _**`AZURA_ID`**_ | string | | A globally unique ID EX `myComponentId` |
|
||||
| `AZURA_NAME` | string | Value of `AZURA_ID` | A vanity name EX `My Cool Component` |
|
||||
| `AZURA_ENABLE` | boolean | true | Should this component be used? |
|
||||
| _**`AZURA_STATION`**_ | string | | The specific station to monitor |
|
||||
| _**`AZURA_URL`**_ | string | | Base URL of the Azuracast instance |
|
||||
| `AZURA_KEY` | string | | API Key used to access data about private streams |
|
||||
| `AZURA_LISTENERS_NUM` | string | | |
|
||||
| `AZURA_LIVE` | boolean | | |
|
||||
@@ -0,0 +1,9 @@
|
||||
| Environmental Variable | Type | Default | Description |
|
||||
| ---------------------- | ------- | ---------------- | ----------------------------------------------------------------------------------------------- |
|
||||
| _**`CC_ID`**_ | string | | A globally unique ID EX `myComponentId` |
|
||||
| `CC_NAME` | string | Value of `CC_ID` | A vanity name EX `My Cool Component` |
|
||||
| `CC_ENABLE` | boolean | true | Should this component be used? |
|
||||
| `CC_BLACKLIST_DEVICES` | string | | DO NOT scrobble from any cast devices on this comma-delimited list that START WITH these values |
|
||||
| `CC_WHITELIST_DEVICES` | string | | ONLY scrobble from any cast device on this comma-delimited list that START WITH these values |
|
||||
| `CC_BLACKLIST_APPS` | string | | DO NOT scrobble from any application on this comma-delimited list that START WITH these values |
|
||||
| `CC_WHITELIST_APPS` | string | | ONLY scrobble from any application on this comma-delimited list that START WITH these values |
|
||||
@@ -0,0 +1,8 @@
|
||||
| Environmental Variable | Type | Default | Description |
|
||||
| ---------------------- | ------- | -------------------------------------------------------------------- | -------------------------------------------------- |
|
||||
| _**`DEEZER_ID`**_ | string | | A globally unique ID EX `myComponentId` |
|
||||
| `DEEZER_NAME` | string | Value of `DEEZER_ID` | A vanity name EX `My Cool Component` |
|
||||
| `DEEZER_ENABLE` | boolean | true | Should this component be used? |
|
||||
| _**`DEEZER_ARL`**_ | string | | ARL retrieved from Deezer response header |
|
||||
| `DEEZER_ACCOUNT_ID` | string | | The ID (USER_ID) of the linked account to monitor. |
|
||||
| `DEEZER_USER_AGENT` | string | Mozilla/5.0 (X11; Linux i686; rv:135.0) Gecko/20100101 Firefox/135.0 | User agent |
|
||||
@@ -0,0 +1,6 @@
|
||||
| Environmental Variable | Type | Default | Description |
|
||||
| ---------------------- | ------- | ----------------- | ------------------------------------------------------------------------ |
|
||||
| _**`LFM_ID`**_ | string | | A globally unique ID EX `myComponentId` |
|
||||
| `LFM_NAME` | string | Value of `LFM_ID` | A vanity name EX `My Cool Component` |
|
||||
| `LFM_ENABLE` | boolean | true | Should this component be used? |
|
||||
| `LFM_SLUG` | string | | The URL ending that should be used to identify scrobbles for this source |
|
||||
@@ -0,0 +1,8 @@
|
||||
| Environmental Variable | Type | Default | Description |
|
||||
| ---------------------- | ------- | ----------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| _**`LZE_ID`**_ | string | | A globally unique ID EX `myComponentId` |
|
||||
| `LZE_NAME` | string | Value of `LZE_ID` | A vanity name EX `My Cool Component` |
|
||||
| `LZE_ENABLE` | boolean | true | Should this component be used? |
|
||||
| `LZE_SLUG` | string | | The URL ending that should be used to identify scrobbles for this source |
|
||||
| `LZE_TOKEN` | string | | If an LZ submission request contains this token in the Authorization Header it will be used to match the submission with this Source |
|
||||
| `LZE_USERNAME` | string | | The listenbrainz "username" to associate with this Source |
|
||||
@@ -0,0 +1,7 @@
|
||||
| Environmental Variable | Type | Default | Description |
|
||||
| ---------------------- | ------- | --------------------- | --------------------------------------- |
|
||||
| _**`ICECAST_ID`**_ | string | | A globally unique ID EX `myComponentId` |
|
||||
| `ICECAST_NAME` | string | Value of `ICECAST_ID` | A vanity name EX `My Cool Component` |
|
||||
| `ICECAST_ENABLE` | boolean | true | Should this component be used? |
|
||||
| _**`ICECAST_URL`**_ | string | | The Icecast stream URL |
|
||||
| `ICECAST_AUTO_MONITOR` | boolean | | |
|
||||
@@ -0,0 +1,17 @@
|
||||
| Environmental Variable | Type | Default | Description |
|
||||
| -------------------------------- | -------------- | ---------------------- | --------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| _**`JELLYFIN_ID`**_ | string | | A globally unique ID EX `myComponentId` |
|
||||
| `JELLYFIN_NAME` | string | Value of `JELLYFIN_ID` | A vanity name EX `My Cool Component` |
|
||||
| `JELLYFIN_ENABLE` | boolean | true | Should this component be used? |
|
||||
| _**`JELLYFIN_USER`**_ | string | | The username of the user to authenticate for or track scrobbles for |
|
||||
| `JELLYFIN_PASSWORD` | string | | Password of the username to authenticate for |
|
||||
| `JELLYFIN_APIKEY` | string | | API Key to authenticate with. |
|
||||
| _**`JELLYFIN_URL`**_ | string | | HOST:PORT of the Jellyfin server to connect to |
|
||||
| `JELLYFIN_USERS_ALLOW` | string OR true | | Only scrobble for specific users from this comma-delimited list. If `true`, scrobble for all users. |
|
||||
| `JELLYFIN_USERS_BLOCK` | string | | Do not scrobble for users from this comma-delimited list |
|
||||
| `JELLYFIN_DEVICES_ALLOW` | string | | Only scrobble if device or application name contains strings from this comma-delimited list |
|
||||
| `JELLYFIN_DEVICES_BLOCK` | string | | Do not scrobble if device or application name contains strings from this comma-delimited list |
|
||||
| `JELLYFIN_LIBRARIES_ALLOW` | string | | Only scrobble if library name contains string from this comma-delimited list |
|
||||
| `JELLYFIN_LIBRARIES_BLOCK` | string | | Do not scrobble if library name contains strings from this comma-delimited list |
|
||||
| `JELLYFIN_FRONTEND_URL_OVERRIDE` | string | | HOST:PORT of the Jellyfin server that your browser will be able to access from the frontend (and thus load images and links from) |
|
||||
| `JELLYFIN_MEDIATYPES_ALLOW` | string | | Allow media types from this comma-delimited list to be scrobbled |
|
||||
@@ -0,0 +1,8 @@
|
||||
| Environmental Variable | Type | Default | Description |
|
||||
| ---------------------- | ------- | ------------------------------- | -------------------------------------------------------- |
|
||||
| _**`JRIVER_ID`**_ | string | | A globally unique ID EX `myComponentId` |
|
||||
| `JRIVER_NAME` | string | Value of `JRIVER_ID` | A vanity name EX `My Cool Component` |
|
||||
| `JRIVER_ENABLE` | boolean | true | Should this component be used? |
|
||||
| _**`JRIVER_URL`**_ | string | http://localhost:52199/MCWS/v1/ | URL of the JRiver HTTP server to connect to |
|
||||
| `JRIVER_USER` | string | | If you have enabled authentication, the username you set |
|
||||
| `JRIVER_PASSWORD` | string | | If you have enabled authentication, the password you set |
|
||||
@@ -0,0 +1,8 @@
|
||||
| Environmental Variable | Type | Default | Description |
|
||||
| ---------------------- | ------- | ----------------------------- | ------------------------------------------------- |
|
||||
| _**`KODI_ID`**_ | string | | A globally unique ID EX `myComponentId` |
|
||||
| `KODI_NAME` | string | Value of `KODI_ID` | A vanity name EX `My Cool Component` |
|
||||
| `KODI_ENABLE` | boolean | true | Should this component be used? |
|
||||
| _**`KODI_URL`**_ | string | http://localhost:8080/jsonrpc | URL of the Kodi HTTP server to connect to |
|
||||
| _**`KODI_USER`**_ | string | | The username set for Remote Control via Web Sever |
|
||||
| _**`KODI_PASSWORD`**_ | string | | The password set for Remote Control via Web Sever |
|
||||
@@ -0,0 +1,8 @@
|
||||
| Environmental Variable | Type | Default | Description |
|
||||
| -------------------------- | ------- | -------------------------- | --------------------------------------- |
|
||||
| _**`SOURCE_KOITO_ID`**_ | string | | A globally unique ID EX `myComponentId` |
|
||||
| `SOURCE_KOITO_NAME` | string | Value of `SOURCE_KOITO_ID` | A vanity name EX `My Cool Component` |
|
||||
| `SOURCE_KOITO_ENABLE` | boolean | true | Should this component be used? |
|
||||
| _**`SOURCE_KOITO_URL`**_ | string | | URL for the Koito server |
|
||||
| _**`SOURCE_KOITO_TOKEN`**_ | string | | User token for the user to scrobble for |
|
||||
| _**`SOURCE_KOITO_USER`**_ | string | | Username of the user to scrobble for |
|
||||
@@ -0,0 +1,9 @@
|
||||
| Environmental Variable | Type | Default | Description |
|
||||
| ----------------------------- | ------- | ------------------------------------- | ------------------------------------------------------- |
|
||||
| _**`SOURCE_LASTFM_ID`**_ | string | | A globally unique ID EX `myComponentId` |
|
||||
| `SOURCE_LASTFM_NAME` | string | Value of `SOURCE_LASTFM_ID` | A vanity name EX `My Cool Component` |
|
||||
| `SOURCE_LASTFM_ENABLE` | boolean | true | Should this component be used? |
|
||||
| _**`SOURCE_LASTFM_API_KEY`**_ | string | | API Key generated from Last.fm/Libre.fm account |
|
||||
| _**`SOURCE_LASTFM_SECRET`**_ | string | | Secret generated from Last.fm/Libre.fm account |
|
||||
| `SOURCE_LASTFM_REDIRECT_URI` | string | http://localhost:9078/lastfm/callback | Optional URI to use for callback. |
|
||||
| `SOURCE_LASTFM_SESSION` | string | | Optional session id returned from a completed auth flow |
|
||||
@@ -0,0 +1,10 @@
|
||||
| Environmental Variable | Type | Default | Description |
|
||||
| ----------------------------- | ------- | -------------------------------------- | -------------------------------------------------------------- |
|
||||
| _**`SOURCE_LIBREFM_ID`**_ | string | | A globally unique ID EX `myComponentId` |
|
||||
| `SOURCE_LIBREFM_NAME` | string | Value of `SOURCE_LIBREFM_ID` | A vanity name EX `My Cool Component` |
|
||||
| `SOURCE_LIBREFM_ENABLE` | boolean | true | Should this component be used? |
|
||||
| `SOURCE_LIBREFM_API_KEY` | string | | Optional Secret for Libre.fm account |
|
||||
| `SOURCE_LIBREFM_SECRET` | string | | Optional Secret for Libre.fm account |
|
||||
| `SOURCE_LIBREFM_REDIRECT_URI` | string | http://localhost:9078/librefm/callback | Optional URI to use for callback. |
|
||||
| `SOURCE_LIBREFM_SESSION` | string | | Optional session id returned from a completed auth flow |
|
||||
| `SOURCE_LIBREFM_URLBASE` | string | https://libre.fm/2.0/ | (Optional) The host and path prefix for your Libre.fm instance |
|
||||
@@ -0,0 +1,8 @@
|
||||
| Environmental Variable | Type | Default | Description |
|
||||
| ----------------------- | ------- | ----------------------------- | --------------------------------------------------------- |
|
||||
| _**`SOURCE_LZ_ID`**_ | string | | A globally unique ID EX `myComponentId` |
|
||||
| `SOURCE_LZ_NAME` | string | Value of `SOURCE_LZ_ID` | A vanity name EX `My Cool Component` |
|
||||
| `SOURCE_LZ_ENABLE` | boolean | true | Should this component be used? |
|
||||
| `SOURCE_LZ_URL` | string | https://api.listenbrainz.org/ | URL for the ListenBrainz server, if not using the default |
|
||||
| _**`SOURCE_LZ_TOKEN`**_ | string | | User token for the user to scrobble for |
|
||||
| _**`SOURCE_LZ_USER`**_ | string | | Username of the user to scrobble for |
|
||||
@@ -0,0 +1,7 @@
|
||||
| Environmental Variable | Type | Default | Description |
|
||||
| ----------------------------- | ------- | --------------------------- | --------------------------------------- |
|
||||
| _**`SOURCE_MALOJA_ID`**_ | string | | A globally unique ID EX `myComponentId` |
|
||||
| `SOURCE_MALOJA_NAME` | string | Value of `SOURCE_MALOJA_ID` | A vanity name EX `My Cool Component` |
|
||||
| `SOURCE_MALOJA_ENABLE` | boolean | true | Should this component be used? |
|
||||
| _**`SOURCE_MALOJA_URL`**_ | string | | URL for maloja server |
|
||||
| _**`SOURCE_MALOJA_API_KEY`**_ | string | | API Key for Maloja server |
|
||||
@@ -0,0 +1,9 @@
|
||||
| Environmental Variable | Type | Default | Description |
|
||||
| ----------------------- | ------- | ------------------------------ | ------------------------------------------------------------------------------------------ |
|
||||
| _**`MOPIDY_ID`**_ | string | | A globally unique ID EX `myComponentId` |
|
||||
| `MOPIDY_NAME` | string | Value of `MOPIDY_ID` | A vanity name EX `My Cool Component` |
|
||||
| `MOPIDY_ENABLE` | boolean | true | Should this component be used? |
|
||||
| `MOPIDY_URL` | string | ws://localhost:6680/mopidy/ws/ | URL of the Mopidy HTTP server to connect to |
|
||||
| `MOPIDY_URI_DENYLIST` | string | | Do not scrobble tracks whose URI STARTS WITH any of these strings, case-insensitive |
|
||||
| `MOPIDY_URI_ALLOWLIST` | string | | Only scrobble tracks whose URI STARTS WITH any of these strings, case-insensitive |
|
||||
| `MOPIDY_ALBUM_DENYLIST` | string | Soundcloud | Remove album data that matches any case-insensitive string from this list when scrobbling, |
|
||||
@@ -0,0 +1,7 @@
|
||||
| Environmental Variable | Type | Default | Description |
|
||||
| ---------------------- | ------- | ----------------- | -------------------------------------------------------------------------------------------------------- |
|
||||
| _**`MPD_ID`**_ | string | | A globally unique ID EX `myComponentId` |
|
||||
| `MPD_NAME` | string | Value of `MPD_ID` | A vanity name EX `My Cool Component` |
|
||||
| `MPD_ENABLE` | boolean | true | Should this component be used? |
|
||||
| `MPD_URL` | string | localhost:6600 | URL:PORT of the MPD server to connect to |
|
||||
| `MPD_PASSWORD` | string | | Password for the server, if set https://mpd.readthedocs.io/en/stable/user.html#permissions-and-passwords |
|
||||
@@ -0,0 +1,7 @@
|
||||
| Environmental Variable | Type | Default | Description |
|
||||
| ---------------------- | ------- | ------------------- | -------------------------------------------------------------------------------------- |
|
||||
| _**`MPRIS_ID`**_ | string | | A globally unique ID EX `myComponentId` |
|
||||
| `MPRIS_NAME` | string | Value of `MPRIS_ID` | A vanity name EX `My Cool Component` |
|
||||
| `MPRIS_ENABLE` | boolean | true | Should this component be used? |
|
||||
| `MPRIS_BLACKLIST` | string | | DO NOT scrobble from any players that START WITH values from this comma-delimited list |
|
||||
| `MPRIS_WHITELIST` | string | | ONLY scrobble from any players that START WITH values from this comma-delimited list |
|
||||
@@ -0,0 +1,6 @@
|
||||
| Environmental Variable | Type | Default | Description |
|
||||
| ---------------------- | ------- | ------------------- | ------------------------------------------------------------ |
|
||||
| _**`MCAST_ID`**_ | string | | A globally unique ID EX `myComponentId` |
|
||||
| `MCAST_NAME` | string | Value of `MCAST_ID` | A vanity name EX `My Cool Component` |
|
||||
| `MCAST_ENABLE` | boolean | true | Should this component be used? |
|
||||
| _**`MCAST_URL`**_ | string | | The host or URL of the YamahaExtendedControl endpoint to use |
|
||||
@@ -0,0 +1,7 @@
|
||||
| Environmental Variable | Type | Default | Description |
|
||||
| ---------------------- | ------- | ------------------- | -------------------------------------------------------------------------------------------- |
|
||||
| _**`MC_ID`**_ | string | | A globally unique ID EX `myComponentId` |
|
||||
| `MC_NAME` | string | Value of `MC_ID` | A vanity name EX `My Cool Component` |
|
||||
| `MC_ENABLE` | boolean | true | Should this component be used? |
|
||||
| `MC_URL` | string | ws://localhost:7905 | URL of the Musikcube Websocket (Metadata) server to connect to |
|
||||
| _**`MC_PASSWORD`**_ | string | | Password set in Musikcube https://github.com/clangen/musikcube/wiki/remote-api-documentation |
|
||||
@@ -0,0 +1,13 @@
|
||||
| Environmental Variable | Type | Default | Description |
|
||||
| ---------------------- | ------- | ------------------ | --------------------------------------------------------------------------------------------- |
|
||||
| _**`PLEX_ID`**_ | string | | A globally unique ID EX `myComponentId` |
|
||||
| `PLEX_NAME` | string | Value of `PLEX_ID` | A vanity name EX `My Cool Component` |
|
||||
| `PLEX_ENABLE` | boolean | true | Should this component be used? |
|
||||
| _**`PLEX_URL`**_ | string | | http(s)://HOST:PORT of the Plex server to connect to |
|
||||
| `PLEX_TOKEN` | string | | |
|
||||
| `PLEX_USERS_ALLOW` | string | | Only scrobble for specific users from this comma-delimited list |
|
||||
| `PLEX_USERS_BLOCK` | string | | Do not scrobble for users from this comma-delimited list |
|
||||
| `PLEX_DEVICES_ALLOW` | string | | Do not scrobble if device or application name contains strings from this comma-delimited list |
|
||||
| `PLEX_DEVICES_BLOCK` | string | | Only scrobble if device or application name contains strings from this comma-delimited list |
|
||||
| `PLEX_LIBRARIES_ALLOW` | string | | Only scrobble if library name contains string from this comma-delimited list |
|
||||
| `PLEX_LIBRARIES_BLOCK` | string | | Do not scrobble if library name contains strings from this comma-delimited list |
|
||||
@@ -0,0 +1,7 @@
|
||||
| Environmental Variable | Type | Default | Description |
|
||||
| ----------------------------- | ------- | ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| _**`SOURCE_ROCKSKY_ID`**_ | string | | A globally unique ID EX `myComponentId` |
|
||||
| `SOURCE_ROCKSKY_NAME` | string | Value of `SOURCE_ROCKSKY_ID` | A vanity name EX `My Cool Component` |
|
||||
| `SOURCE_ROCKSKY_ENABLE` | boolean | true | Should this component be used? |
|
||||
| `SOURCE_ROCKSKY_KEY` | string | | API Key generated from [API Applications](https://docs.rocksky.app/migrating-from-listenbrainz-to-rocksky-1040189m0) in Rocksky for your account |
|
||||
| _**`SOURCE_ROCKSKY_HANDLE`**_ | string | | The **fully-qualified** handle for your ATPRoto/Bluesky account, like: |
|
||||
@@ -0,0 +1,10 @@
|
||||
| Environmental Variable | Type | Default | Description |
|
||||
| ---------------------- | ------- | ------------------- | -------------------------------------------------------------------------------------------------------------------- |
|
||||
| _**`SONOS_ID`**_ | string | | A globally unique ID EX `myComponentId` |
|
||||
| `SONOS_NAME` | string | Value of `SONOS_ID` | A vanity name EX `My Cool Component` |
|
||||
| `SONOS_ENABLE` | boolean | true | Should this component be used? |
|
||||
| _**`SONOS_HOST`**_ | string | | IP address of any connected Sonos speaker or device |
|
||||
| `SONOS_DEVICES_ALLOW` | string | | Only scrobble if device name contains strings from this comma-delimited list |
|
||||
| `SONOS_DEVICES_BLOCK` | string | | Do not scrobble if device name contains strings from this comma-delimited list |
|
||||
| `SONOS_GROUPS_ALLOW` | string | | Only scrobble if the name of a group the playing device belongs to contains strings from this comma-delimited list |
|
||||
| `SONOS_GROUPS_BLOCK` | string | | Do not scrobble if the name of a group the playing device belongs to contains strings from this comma-delimited list |
|
||||
@@ -0,0 +1,8 @@
|
||||
| Environmental Variable | Type | Default | Description |
|
||||
| ----------------------------- | ------- | ------------------------------ | -------------------------------------------------------------------- |
|
||||
| _**`SPOTIFY_ID`**_ | string | | A globally unique ID EX `myComponentId` |
|
||||
| `SPOTIFY_NAME` | string | Value of `SPOTIFY_ID` | A vanity name EX `My Cool Component` |
|
||||
| `SPOTIFY_ENABLE` | boolean | true | Should this component be used? |
|
||||
| _**`SPOTIFY_CLIENT_ID`**_ | string | | spotify client id |
|
||||
| _**`SPOTIFY_CLIENT_SECRET`**_ | string | | spotify client secret |
|
||||
| `SPOTIFY_REDIRECT_URI` | string | http://localhost:9078/callback | spotify redirect URI -- required only if not the default shown here. |
|
||||
@@ -0,0 +1,8 @@
|
||||
| Environmental Variable | Type | Default | Description |
|
||||
| ------------------------- | ------- | ---------------------- | ------------------------------------------------- |
|
||||
| _**`SUBSONIC_ID`**_ | string | | A globally unique ID EX `myComponentId` |
|
||||
| `SUBSONIC_NAME` | string | Value of `SUBSONIC_ID` | A vanity name EX `My Cool Component` |
|
||||
| `SUBSONIC_ENABLE` | boolean | true | Should this component be used? |
|
||||
| _**`SUBSONIC_USER`**_ | string | | Username to login to the server with |
|
||||
| _**`SUBSONIC_PASSWORD`**_ | string | | Password for the user to login to the server with |
|
||||
| _**`SUBSONIC_URL`**_ | string | | URL of the subsonic media server to query |
|
||||
@@ -0,0 +1,7 @@
|
||||
| Environmental Variable | Type | Default | Description |
|
||||
| -------------------------------- | ------- | --------------------------- | --------------------------------------- |
|
||||
| _**`SOURCE_TEALFM_ID`**_ | string | | A globally unique ID EX `myComponentId` |
|
||||
| `SOURCE_TEALFM_NAME` | string | Value of `SOURCE_TEALFM_ID` | A vanity name EX `My Cool Component` |
|
||||
| `SOURCE_TEALFM_ENABLE` | boolean | true | Should this component be used? |
|
||||
| _**`SOURCE_TEALFM_IDENTIFIER`**_ | string | | Identify the account to login as |
|
||||
| `SOURCE_TEALFM_APP_PW` | string | | |
|
||||
@@ -0,0 +1,7 @@
|
||||
| Environmental Variable | Type | Default | Description |
|
||||
| ---------------------- | ------- | ----------------- | ---------------------------------------- |
|
||||
| _**`VLC_ID`**_ | string | | A globally unique ID EX `myComponentId` |
|
||||
| `VLC_NAME` | string | Value of `VLC_ID` | A vanity name EX `My Cool Component` |
|
||||
| `VLC_ENABLE` | boolean | true | Should this component be used? |
|
||||
| `VLC_URL` | string | localhost:8080 | URL:PORT of the VLC server to connect to |
|
||||
| _**`VLC_PASSWORD`**_ | string | | Password for the server |
|
||||
@@ -0,0 +1,7 @@
|
||||
| Environmental Variable | Type | Default | Description |
|
||||
| ---------------------- | ------- | ---------------- | ----------------------------------------------------------- |
|
||||
| _**`WS_ID`**_ | string | | A globally unique ID EX `myComponentId` |
|
||||
| `WS_NAME` | string | Value of `WS_ID` | A vanity name EX `My Cool Component` |
|
||||
| `WS_ENABLE` | boolean | true | Should this component be used? |
|
||||
| `WS_BLACKLIST` | string | | Block scrobbling from specific WebScrobbler Connectors |
|
||||
| `WS_WHITELIST` | string | | Only allow scrobbling from specific WebScrobbler Connectors |
|
||||
@@ -0,0 +1,7 @@
|
||||
| Environmental Variable | Type | Default | Description |
|
||||
| ---------------------- | ------- | ---------------------- | --------------------------------------------------------------------------- |
|
||||
| _**`YMBRIDGE_ID`**_ | string | | A globally unique ID EX `myComponentId` |
|
||||
| `YMBRIDGE_NAME` | string | Value of `YMBRIDGE_ID` | A vanity name EX `My Cool Component` |
|
||||
| `YMBRIDGE_ENABLE` | boolean | true | Should this component be used? |
|
||||
| _**`YMBRIDGE_URL`**_ | string | | URL of the local Python bridge, for example http://yandex-music-bridge:9980 |
|
||||
| `YMBRIDGE_API_KEY` | string | | Optional API key sent as X-API-Key to the bridge |
|
||||
@@ -0,0 +1,9 @@
|
||||
| Environmental Variable | Type | Default | Description |
|
||||
| ---------------------- | ------- | ----------------- | ------------------------------------------------------------------------------------ |
|
||||
| _**`YTM_ID`**_ | string | | A globally unique ID EX `myComponentId` |
|
||||
| `YTM_NAME` | string | Value of `YTM_ID` | A vanity name EX `My Cool Component` |
|
||||
| `YTM_ENABLE` | boolean | true | Should this component be used? |
|
||||
| `YTM_REDIRECT_URI` | string | | Google Cloud Console project OAuth Client Authorized redirect URI |
|
||||
| `YTM_CLIENT_ID` | string | | Google Cloud Console project OAuth Client ID |
|
||||
| `YTM_CLIENT_SECRET` | string | | Google Cloud Console project OAuth Client Secret |
|
||||
| `YTM_COOKIE` | string | | The cookie retrieved from the Request Headers of music.youtube.com after logging in. |
|
||||
@@ -0,0 +1,251 @@
|
||||
---
|
||||
title: Apple Music
|
||||
toc_min_heading_level: 2
|
||||
toc_max_heading_level: 5
|
||||
---
|
||||
|
||||
import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
import CodeBlock from '@theme/CodeBlock';
|
||||
import AppleMusicConfig from '!!raw-loader!@site/../config/applemusic.json.example';
|
||||
import ENVConfig from "@site/docs/configuration/sources/_env_configs/_applemusic.md"
|
||||
|
||||
This Source **monitors your Apple Music listening history** via the official Apple Music API and scrobbles new activity to your configured [Clients](/configuration/clients).
|
||||
|
||||
Because of how the Apple Music API works, Multi-Scrobbler (MS) requires two different tokens to function: a **Media User Token** (identifies your personal account) and an **Authentication Token** (authorizes API access).
|
||||
|
||||
### 1. Getting a Media User Token
|
||||
|
||||
The `mediaUserToken` is required to access your recently played history. You can extract it directly from the Apple Music web app:
|
||||
|
||||
1. Visit [music.apple.com](https://music.apple.com) in your browser and log in.
|
||||
2. Open your browser's Developer Tools (usually `F12` or <kbd>⌘</kbd> + <kbd>⌥</kbd> + <kbd>I</kbd>).
|
||||
3. Navigate to the **Application** tab (Chrome/Edge) or **Storage** tab (Safari/Firefox).
|
||||
4. Expand **Cookies** in the left sidebar and select `https://music.apple.com`.
|
||||
5. Find the cookie named `media-user-token` and copy its value (it typically starts with `0.`).
|
||||
|
||||
:::caution[Token Expiry]
|
||||
The `mediaUserToken` will eventually expire. If Multi-Scrobbler begins throwing authentication errors in the logs, simply repeat these steps to obtain and configure a fresh token.
|
||||
:::
|
||||
|
||||
### 2. Authentication
|
||||
|
||||
To authorize API access, Multi-Scrobbler requires an Authentication Token (JWT). Because the official Apple Music API is designed for developers, there are two ways to provide this token depending on your situation:
|
||||
|
||||
* **Browser Token (Free & Most Common):** Best for 99% of users. You can easily extract a temporary token from the Apple Music web player without needing an Apple Developer account.
|
||||
* **MusicKit Key (Requires Paid Apple Developer Account):** If you happen to be enrolled in the paid Apple Developer Program ($99/year), you can provide a private key to automatically generate permanent tokens.
|
||||
|
||||
Choose your preferred method below:
|
||||
|
||||
<Tabs groupId="appleMusicAuth" queryString>
|
||||
<TabItem value="token" label="Browser Token (Free)">
|
||||
|
||||
Since most users don't have a paid developer account, extracting the token from the web player is the standard approach.
|
||||
|
||||
Behind the scenes, the Apple Music website makes a lot of background requests, which can make finding the right token confusing. To filter out the noise and grab the exact token we need, follow the steps for your browser below:
|
||||
|
||||
<details>
|
||||
<summary>Chrome, Edge & Firefox</summary>
|
||||
|
||||
1. Visit [music.apple.com](https://music.apple.com) and log in.
|
||||
2. Open Developer Tools (`F12` or `Ctrl+Shift+I` / <kbd>⌘</kbd> + <kbd>⌥</kbd> + <kbd>I</kbd>) and navigate to the **Network** tab.
|
||||
3. In the filter box at the top left, paste exactly: `https://amp-api.music.apple.com/v1/me/account` (**Label 1**).
|
||||
4. Click the **Fetch/XHR** filter button to hide irrelevant requests (**Label 2**).
|
||||
5. Reload the page (**Label 3**).
|
||||
6. Under the "Name" column, click the request starting with `account?meta=` (**Label 4**).
|
||||
7. In the panel that opens, scroll down to the **Request Headers** section.
|
||||
8. Find the `authorization` header. Copy the long string of text **after** the `Bearer ` prefix (**Label 5**).
|
||||
|
||||

|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>Safari</summary>
|
||||
|
||||
Before you can extract the token in Safari, you must enable developer tools.
|
||||
|
||||
{/* This weird formatting is because ⌘ is usually incredibly tiny */}
|
||||
1. Open Safari Settings (<kbd>⌘</kbd> + <kbd>,</kbd>), navigate to the **Advanced** tab, and check **"Show features for web developers"** at the very bottom.
|
||||
|
||||

|
||||
|
||||
2. Visit [music.apple.com](https://music.apple.com) and log in.
|
||||
3. Open the Web Inspector (<kbd>⌘</kbd>+<kbd>⌥</kbd>+<kbd>I</kbd> or Develop > Show Web Inspector) and navigate to the **Network** tab.
|
||||
4. In the filter bar on the left side of the inspector, paste exactly: `https://amp-api.music.apple.com/v1/me/account` (**Label 1**).
|
||||
5. Reload the page (**Label 2**).
|
||||
6. Click the `account` request that appears in the Name list (**Label 3**).
|
||||
7. In the details sidebar, look under the **Request** section for the `Authorization` header. Copy the long string of text **after** the `Bearer ` prefix (**Label 4**).
|
||||
|
||||

|
||||
|
||||
</details>
|
||||
|
||||
<br />
|
||||
|
||||
Once you have your token, add it to your configuration file along with the origin header:
|
||||
|
||||
```json title="applemusic.json"
|
||||
{
|
||||
"data": {
|
||||
"token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiIsIm...",
|
||||
"mediaUserToken": "your-media-user-token-here",
|
||||
"origin": "https://music.apple.com"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
:::info[Origin Header Required]
|
||||
When using a JWT extracted from the browser, Apple requires the request to match the domain it was issued to. You **must** include the `origin` field in your config as shown above.
|
||||
:::
|
||||
|
||||
*Note: Browser-generated JWTs are valid for a maximum of 35 days and must be updated manually when they expire.*
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="key" label="MusicKit Key (Paid Account)">
|
||||
|
||||
:::warning[Apple Developer Account Required]
|
||||
To generate JWTs automatically, you must be enrolled in the paid [Apple Developer Program](https://developer.apple.com/programs/) ($99/year) and create a MusicKit key. If you don't have an account, use the **Browser Token (Free)** tab instead.
|
||||
:::
|
||||
|
||||
To generate JWTs automatically and avoid manual token refreshes, you need an Apple Music API key:
|
||||
|
||||
1. Go to the [Apple Developer portal](https://developer.apple.com/account/resources/authkeys/list) and create a **MusicKit** key.
|
||||
2. Download the `.p8` file — this is your private key.
|
||||
3. Note your **Key ID** and **Team ID** (found in your Apple Developer account Membership details).
|
||||
|
||||
Add these details to your config:
|
||||
|
||||
```json title="applemusic.json"
|
||||
{
|
||||
"data": {
|
||||
"key": {
|
||||
"id": "2HPSNJZ88N",
|
||||
"teamId": "SN6YASW8G4",
|
||||
"p8": "-----BEGIN PRIVATE KEY-----\nMIGTAgEAMBMGByqGSM49AgEG...-----END PRIVATE KEY-----"
|
||||
},
|
||||
"mediaUserToken": "your-media-user-token-here"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
:::tip
|
||||
When pasting the contents of your `.p8` file into JSON, make sure to replace physical line breaks with `\n` so it remains a valid, single-line JSON string.
|
||||
:::
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
---
|
||||
|
||||
### How Multi-Scrobbler handles Apple Music quirks
|
||||
|
||||
#### Timestamp Estimation
|
||||
|
||||
The Apple Music API **does not provide timestamps** for when tracks were played. Multi-Scrobbler estimates play times by taking the current time and subtracting track durations backwards:
|
||||
* The most recent track is assumed to have finished playing **now**.
|
||||
* Each older track is estimated to have played `duration` seconds before the previous one.
|
||||
|
||||
*For the most accurate scrobble timestamps, it is highly recommended to keep the polling interval (`APPLEMUSIC_INTERVAL`) low (the default is 60 seconds).*
|
||||
|
||||
#### Duplicate Play Recovery
|
||||
|
||||
The Apple Music history API strictly deduplicates tracks. Instead of showing the same song multiple times in a row, it simply bumps the re-played track back to the #1 spot and removes the older entry.
|
||||
|
||||
For example, if you listen to **Song A** → **Song B**, your history is `[Song B, Song A]`. If you then listen to **Song A** again, the API returns `[Song A, Song B]` (Song A was bumped to the top).
|
||||
|
||||
If Multi-Scrobbler polled when the top track was Song A, and polls again after it's bumped back to the top, the top track appears functionally unchanged. This usually confuses standard scrobblers into ignoring the update entirely. By default, MS correctly detects this "top-rebound" pattern, extracts the intermediate tracks that were squeezed in (Song B), and scrobbles Song A again as a re-listen.
|
||||
|
||||
*Note: Because of this strict deduplication, **"pure loops"** (listening to Song A continuously on repeat without playing anything else in between) cannot be tracked. The history list never changes shape, so MS has no way of knowing it was played again.*
|
||||
|
||||
If you ever experience false positives (tracks being scrobbled that you didn't actually re-listen to), you can disable this recovery behavior with `"recoverUnchangedTopHistory": false` in your config options or by setting the `APPLEMUSIC_RECOVER_UNCHANGED_TOP_HISTORY=false` env var.
|
||||
|
||||
#### Album name normalization
|
||||
|
||||
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.
|
||||
|
||||
By default, Multi-Scrobbler strips these suffixes out so only the official name is used.
|
||||
|
||||
If you do not want this behavior it can be disabled with ENV `APPLEMUSIC_NORMALIZE_ALBUM=false` or File/AIO option `"normalizeAlbum": false`.
|
||||
|
||||
<DetailsAdmo type="tip" summary="Stripping Suffix with User Stage">
|
||||
|
||||
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).
|
||||
|
||||
Here is an example of creating a User Stage to only strip suffixes for a specific scrobble client:
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Example</summary>
|
||||
|
||||
```json5 title="config.json"
|
||||
{
|
||||
// ...
|
||||
"transformers": [
|
||||
{
|
||||
"type": "user",
|
||||
"name": "AppleAlbumStip",
|
||||
"defaults": {
|
||||
"album": [
|
||||
"/ - (EP|Single)$/i"
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
```json5 title="applemusic.json"
|
||||
{
|
||||
{
|
||||
"id": "myAppleMusic",
|
||||
"name": "My Apple Music",
|
||||
"data": {
|
||||
// ...
|
||||
},
|
||||
// highlight-start
|
||||
"options": {
|
||||
"normalizeAlbum": false
|
||||
}
|
||||
// highlight-end
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```json5 title="lastfm.json"
|
||||
[
|
||||
{
|
||||
"name": "Foxx LFM Client",
|
||||
"id": "myLastFmClient",
|
||||
"enable": true,
|
||||
"configureAs": "client",
|
||||
"data": {
|
||||
"apiKey": "a89cba1569901a0671d5a9875fed4be1",
|
||||
"secret": "ec42e09d5ae0ee0f0816ca151008412a",
|
||||
"redirectUri": "http://localhost:9078/lastfm/callback"
|
||||
},
|
||||
// highlight-start
|
||||
"options": {
|
||||
"playTransform": {
|
||||
"preCompare": [
|
||||
{
|
||||
"type": "user",
|
||||
"name": "AppleAlbumStip",
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
// highlight-end
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
</DetailsAdmo>
|
||||
|
||||
## Configuration Reference
|
||||
|
||||
<Config config="AppleMusicSourceConfig" fileContent={AppleMusicConfig} name="applemusic">
|
||||
<ENVConfig/>
|
||||
</Config>
|
||||
@@ -8,6 +8,7 @@ import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
import CodeBlock from '@theme/CodeBlock';
|
||||
import AzuracastConfig from '!!raw-loader!@site/../config/azuracast.json.example';
|
||||
import ENVConfig from "@site/docs/configuration/sources/_env_configs/_azuracast.md"
|
||||
import ShouldScrobble from "@site/src/components/snippets/_should-scrobble-details.mdx"
|
||||
|
||||
:::tip[Scrobbling Threshold]
|
||||
@@ -38,14 +39,14 @@ URL From Config => MS Uses
|
||||
|
||||
<ShouldScrobble filename="azuracast"/>
|
||||
|
||||
Multi-scrobbler will set the default **scrobbling behavior** based on if either of these settings is configured:
|
||||
When `autoMonitor` is not explicitly set, Multi-scrobbler will set the **default monitoring behavior** based on if either of these settings is configured:
|
||||
|
||||
* live status (`AZURA_LIVE` or `monitorWhenLive`) or
|
||||
* listener count (`AZURA_LISTENERS_NUM` or `monitorWhenListeners`)
|
||||
|
||||
If either is configured then MS will automatically scrobble based on when these conditions are met.
|
||||
If either is configured then MS will automatically monitor based on when these conditions are met.
|
||||
|
||||
If neither is configured automatic scrobble defaults to **off** and you should either manually initiate it or explicitly set the default behavior.
|
||||
If neither is configured automatic monitoring defaults to **off** and you should either manually initiate it or explicitly set the default behavior.
|
||||
|
||||
### Station
|
||||
|
||||
@@ -112,12 +113,5 @@ For users who aren't administrators of Azuracast: if you can access the station
|
||||
## Configuration
|
||||
|
||||
<Config config="AzuracastSourceConfig" fileContent={AzuracastConfig} name="azuracast">
|
||||
| Environmental Variable | Required? | Default | Description |
|
||||
| :--------------------- | :-------- | :------ | ---------------------------------------------------------------------------------------------- |
|
||||
| `AZURA_ID` | Yes | | A unique ID |
|
||||
| `AZURA_URL` | Yes | | Azuracast URL *without station name* |
|
||||
| `AZURA_STATION` | Yes | | The station URL Stub or shortcode |
|
||||
| `AZURA_LIVE` | No | Yes | Only scrobble when station status is ONLINE |
|
||||
| `AZURA_LISTENERS_NUM` | No | `true` | Only scrobble if station has any listeners (`true`) or listeners are equal-to/greater-than `X` |
|
||||
| `AZURA_NAME` | No | | A vanity name different than ID |
|
||||
<ENVConfig/>
|
||||
</Config>
|
||||
@@ -9,6 +9,7 @@ import TabItem from '@theme/TabItem';
|
||||
import CodeBlock from '@theme/CodeBlock';
|
||||
import DeezerConfig from '!!raw-loader!@site/../config/deezer.json.example';
|
||||
import DeezerDeprecatedConfig from '!!raw-loader!@site/../config/deezer-deprecated.json.example';
|
||||
import ENVConfig from "@site/docs/configuration/sources/_env_configs/_deezer.md"
|
||||
|
||||
<Tabs groupId="deezerSource" queryString>
|
||||
<TabItem value="arl" label="Unofficial ARL">
|
||||
@@ -134,9 +135,7 @@ import DeezerDeprecatedConfig from '!!raw-loader!@site/../config/deezer-deprecat
|
||||
## Configuration
|
||||
|
||||
<Config config="DeezerCompatConfig" fileContent={DeezerConfig} name="deezer">
|
||||
| Environmental Variable | Required? | Default | Description |
|
||||
| :--------------------- | --------- | ------- | ------------------------------------------------ |
|
||||
| `DEEZER_ARL` | Yes | | The ARL cookie value retrieved from your browser |
|
||||
<ENVConfig/>
|
||||
</Config>
|
||||
|
||||
</TabItem>
|
||||
|
||||
@@ -8,6 +8,7 @@ import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
import CodeBlock from '@theme/CodeBlock';
|
||||
import ChromecastConfig from '!!raw-loader!@site/../config/chromecast.json.example';
|
||||
import ENVConfig from "@site/docs/configuration/sources/_env_configs/_chromecast.md"
|
||||
|
||||
If your media device can be **Cast** to using this button  on your phone/computer then multi-scrobbler can monitor it in order to scrobble music you play.
|
||||
|
||||
@@ -149,13 +150,5 @@ To diagnose bad/incomplete track information or strange MS player behavior pleas
|
||||
[Manually configuring cast device connections](#connecting-devices) is only available through file-based config.
|
||||
:::
|
||||
|
||||
| Environmental Variable | Required? | Default | Description |
|
||||
| ---------------------- | --------- | ------- | ------------------------------------------------------------------------------------ |
|
||||
| `CC_ID` | Yes | | A unique ID |
|
||||
| `CC_ENABLE` | No | | Set to 'true' to enable Cast monitoring without needing to define other ENVs |
|
||||
| `CC_WHITELIST_DEVICES` | No | | Only scrobble from these Cast devices. Comma-delimited list. EX mini-home, family-tv |
|
||||
| `CC_BLACKLIST_DEVICES` | No | | Do not scrobble from these Cast devices. Comma-delimited list |
|
||||
| `CC_WHITELIST_APPS` | No | | Only scrobble from these casted Apps. Comma-delimited list. EX spotify, pandora |
|
||||
| `CC_BLACKLIST_APPS` | No | | Do not scrobble from these casted Apps. Comma-delimited list |
|
||||
| `CC_NAME` | No | | A vanity name different than ID |
|
||||
<ENVConfig/>
|
||||
</Config>
|
||||
@@ -9,6 +9,7 @@ import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
import CodeBlock from '@theme/CodeBlock';
|
||||
import IcecastConfig from '!!raw-loader!@site/../config/icecast.json.example';
|
||||
import ENVConfig from "@site/docs/configuration/sources/_env_configs/_icecast.md"
|
||||
import ShouldScrobble from "@site/src/components/snippets/_should-scrobble-details.mdx"
|
||||
|
||||
Parse metadata from any Icecast Station (streams) to use for scrobbling.
|
||||
@@ -21,9 +22,9 @@ Multi-scrobbler will do its best to parse Artist/Album/Track information from th
|
||||
|
||||
:::
|
||||
|
||||
Multi-scrobbler cannot automatically determine if you are listening to a Station. Therefore, **automatic scrobbling for Icecast Sources is off by default.** Use **Should Scrobble Behavior** to initiate scrobbling or configure automatic scrobble.
|
||||
Multi-scrobbler cannot automatically determine if you are listening to a Station. Therefore, **automatic monitoring for Icecast Sources is off by default.** Use **Monitoring Behavior** to initiate scrobbling or configure automatic scrobble.
|
||||
|
||||
<ShouldScrobble filename="icecast"/>
|
||||
<ShouldScrobble filename="icecast" defaultBehavior={false}/>
|
||||
|
||||
:::tip[Scrobbling Threshold]
|
||||
|
||||
@@ -64,9 +65,5 @@ If no `sources` are configured for multi-scrobbler it will automatically try to
|
||||
## Configuration
|
||||
|
||||
<Config config="IcecastSourceConfig" fileContent={IcecastConfig} name="icecast">
|
||||
| Environmental Variable | Required? | Default | Description |
|
||||
| :--------------------- | :-------- | :------ | ------------------------------- |
|
||||
| `ICECAST_ID` | Yes | | A unique ID |
|
||||
| `ICECAST_URL` | Yes | | Icecast URL |
|
||||
| `ICECAST_NAME` | No | | A vanity name different than ID |
|
||||
<ENVConfig/>
|
||||
</Config>
|
||||
@@ -8,6 +8,7 @@ import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
import CodeBlock from '@theme/CodeBlock';
|
||||
import JellyfinConfig from '!!raw-loader!@site/../config/jellyfin.json.example';
|
||||
import ENVConfig from "@site/docs/configuration/sources/_env_configs/_jellyfin.md"
|
||||
|
||||
Must be using Jellyfin 10.7 or greater
|
||||
|
||||
@@ -52,20 +53,5 @@ Use `JELLYFIN_FRONTEND_URL_OVERRIDE=https://jellyfin.mydomain.com` in order for
|
||||
#### Configuration
|
||||
|
||||
<Config config="JellyApiSourceConfig" fileContent={JellyfinConfig} name="jellyfin">
|
||||
| Environmental Variable | Required? | Default | Description |
|
||||
| -------------------------------- | --------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `JELLYFIN_ID` | **Yes** | | A unique ID |
|
||||
| `JELLYFIN_URL` | **Yes** | | The URL of the Jellyfin server IE `http://localhost:8096` |
|
||||
| `JELLYFIN_USER` | **Yes** | | The user to authenticate with the API |
|
||||
| `JELLYFIN_APIKEY` | No | | The API Key to use for authentication **(Must provide either apikey or password)** |
|
||||
| `JELLYFIN_PASSWORD` | No | | The password of the user to authenticate for. **(Must provide either apikey or password)** |
|
||||
| `JELLYFIN_USERS_ALLOW` | No | | Comma-separated list of usernames (from Jellyfin) to scrobble for |
|
||||
| `JELLYFIN_USERS_BLOCK` | No | | Comma-separated list of usernames (from Jellyfin) to disallow scrobble for |
|
||||
| `JELLYFIN_DEVICES_ALLOW` | No | | Comma-separated list of devices to scrobble from |
|
||||
| `JELLYFIN_DEVICES_BLOCK` | No | | Comma-separated list of devices to disallow scrobbles from |
|
||||
| `JELLYFIN_LIBRARIES_ALLOW` | No | | Comma-separated list of libraries to allow scrobbles from |
|
||||
| `JELLYFIN_LIBRARIES_BLOCK` | No | | Comma-separated list of libraries to disallow scrobbles from |
|
||||
| `JELLYFIN_MEDIATYPES_ALLOW` | No | | Comma-separated list of [media types](https://github.com/jellyfin/jellyfin-sdk-typescript/blob/master/src/generated-client/models/media-type.ts#L22) to allow scrobbling. Defaults to `audio` |
|
||||
| `JELLYFIN_FRONTEND_URL_OVERRIDE` | No | | The external URL to use for album art assets instead of `JELLYFIN_URL` |
|
||||
| `JELLYFIN_NAME` | No | | A vanity name different than ID |
|
||||
<ENVConfig/>
|
||||
</Config>
|
||||
@@ -8,6 +8,7 @@ import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
import CodeBlock from '@theme/CodeBlock';
|
||||
import JriverConfig from '!!raw-loader!@site/../config/jriver.json.example';
|
||||
import ENVConfig from "@site/docs/configuration/sources/_env_configs/_jriver.md"
|
||||
|
||||
In order for multi-scrobbler to communicate with JRiver you must have [Web Server Interface](https://wiki.jriver.com/index.php/Web_Service_Interface#Documentation_of_Functions) enabled. This can be found in the JRiver GUI:
|
||||
|
||||
@@ -50,11 +51,5 @@ If any part of this URL is missing multi-scrobbler will use a default value. Thi
|
||||
## Configuration
|
||||
|
||||
<Config config="JRiverSourceConfig" fileContent={JriverConfig} name="jriver">
|
||||
| Environmental Variable | Required | Default | Description |
|
||||
| ---------------------- | -------- | ------------------------------- | ---------------------------------------------- |
|
||||
| JRIVER_ID | Yes | | A unique ID |
|
||||
| JRIVER_URL | Yes | http://localhost:52199/MCWS/v1/ | The URL of the JRiver server |
|
||||
| JRIVER_USERNAME | No | | If authentication is enabled, the username set |
|
||||
| JRIVER_PASSWORD | No | | If authenticated is enabled, the password set |
|
||||
| JRIVER_NAME | No | | A vanity name different than ID |
|
||||
<ENVConfig/>
|
||||
</Config>
|
||||
@@ -9,6 +9,7 @@ import TabItem from '@theme/TabItem';
|
||||
import CodeBlock from '@theme/CodeBlock';
|
||||
import KodiConfig from '!!raw-loader!@site/../config/kodi.json.example';
|
||||
import Config from '@site/src/components/GenericConfiguration.mdx';
|
||||
import ENVConfig from "@site/docs/configuration/sources/_env_configs/_kodi.md"
|
||||
|
||||
In order for multi-scrobbler to communicate with Kodi you must have the [Web Interface](https://kodi.wiki/view/Web_interface) enabled. This can be done in the Kodi GUI:
|
||||
|
||||
@@ -51,11 +52,5 @@ If any part of this URL is missing multi-scrobbler will use a default value. Thi
|
||||
## Configuration
|
||||
|
||||
<Config config="KodiSourceConfig" fileContent={KodiConfig} name="kodi">
|
||||
| Environmental Variable | Required | Default | Description |
|
||||
| ---------------------- | -------- | ----------------------------- | ------------------------------- |
|
||||
| KODI_ID | Yes | | A unique ID |
|
||||
| KODI_URL | Yes | http://localhost:8080/jsonrpc | The URL of the Kodi server |
|
||||
| KODI_USERNAME | No | | The username set |
|
||||
| KODI_PASSWORD | No | | The password set |
|
||||
| KODI_NAME | No | | A vanity name different than ID |
|
||||
<ENVConfig/>
|
||||
</Config>
|
||||
@@ -9,6 +9,7 @@ import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
import CodeBlock from '@theme/CodeBlock';
|
||||
import KoitoConfig from '!!raw-loader!@site/../config/koito.json.example';
|
||||
import ENVConfig from "@site/docs/configuration/sources/_env_configs/_koito.md"
|
||||
|
||||
This Source monitors a Koito account's scrobble history and then re-scrobbles discovered tracks to configured [Clients.](/configuration/clients)
|
||||
|
||||
@@ -25,11 +26,5 @@ See the [Koito (Client)](/configuration/clients/koito) configuration for general
|
||||
#### Configuration
|
||||
|
||||
<Config config="KoitoSourceConfig" fileContent={KoitoConfig} name="koito">
|
||||
| Environmental Variable | Required? | Default | Description |
|
||||
| :--------------------- | --------- | ------- | --------------------------------- |
|
||||
| `SOURCE_KOITO_ID` | Yes | | A unique ID |
|
||||
| `SOURCE_KOITO_TOKEN` | Yes | | API Key from your Koito Account |
|
||||
| `SOURCE_KOITO_USER` | Yes | | Your Koito username |
|
||||
| `SOURCE_KOITO_URL` | No | | The base URL for the Koito server |
|
||||
| `SOURCE_KOITO_NAME` | No | | A vanity name differen than ID |
|
||||
<ENVConfig/>
|
||||
</Config>
|
||||
@@ -8,6 +8,7 @@ import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
import CodeBlock from '@theme/CodeBlock';
|
||||
import LastfmEndpointConfig from '!!raw-loader!@site/../config/endpointlfm.json.example';
|
||||
import ENVConfig from "@site/docs/configuration/sources/_env_configs/_endpointlfm.md"
|
||||
|
||||
This Source enables multi-scrobbler to accept scrobbles from outside applications as if it was a Last.fm server.
|
||||
|
||||
@@ -39,10 +40,5 @@ http://localhost:9078/api/lastfm/mySlug
|
||||
## Configuration
|
||||
|
||||
<Config config="LastFMEndpointSourceConfig" fileContent={LastfmEndpointConfig} name="endpointlfm">
|
||||
| Environmental Variable | Required? | Default | Description |
|
||||
| :--------------------- | :-------- | ------- | ------------------------------------------------------------------------------------------------------------------ |
|
||||
| `LFM_ID` | Yes | | A unique ID |
|
||||
| `LFM_ENABLE` | No | | Use LFM Endpoint as a Source without any other configuration. Only required if slug/token are not provided as ENVs |
|
||||
| `LFM_SLUG` | No | | (Optional) The URL suffix to use for accepting LFM scrobbles |
|
||||
| `LFM_NAME` | No | | A vanity name different than ID |
|
||||
<ENVConfig/>
|
||||
</Config>
|
||||
@@ -9,6 +9,7 @@ import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
import CodeBlock from '@theme/CodeBlock';
|
||||
import LastfmConfig from '!!raw-loader!@site/../config/lastfm.json.example';
|
||||
import ENVConfig from "@site/docs/configuration/sources/_env_configs/_lastfm.md"
|
||||
|
||||
This Source **monitors your Last.fm scrobble history** and re-scrobbles new activity to configured [Clients.](/configuration/clients)
|
||||
|
||||
@@ -24,12 +25,5 @@ To configure this Source use the same registration instructions and configuratio
|
||||
## Configuration
|
||||
|
||||
<Config config="LastfmSourceConfig" fileContent={LastfmConfig} name="lastfm">
|
||||
| Environmental Variable | Required? | Default | Description |
|
||||
| ---------------------------- | --------- | --------------------------------------- | ----------------------------------------------------------------------------- |
|
||||
| `SOURCE_LASTFM_ID` | Yes | | A unique ID |
|
||||
| `SOURCE_LASTFM_API_KEY` | Yes | | Api Key from your API Account |
|
||||
| `SOURCE_LASTFM_SECRET` | Yes | | Shared secret from your API Account |
|
||||
| `SOURCE_LASTFM_REDIRECT_URI` | No | `http://localhost:9078/lastfm/callback` | Url to use for authentication. Must include `lastfm/callback` somewhere in it |
|
||||
| `SOURCE_LASTFM_SESSION` | No | | Session id. Will be generated by authentication flow if not provided. |
|
||||
| `SOURCE_LASTFM_NAME` | No | | A vanity name different than ID |
|
||||
<ENVConfig/>
|
||||
</Config>
|
||||
@@ -9,6 +9,7 @@ import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
import CodeBlock from '@theme/CodeBlock';
|
||||
import JsonConfig from '!!raw-loader!@site/../config/librefm.json.example';
|
||||
import ENVConfig from "@site/docs/configuration/sources/_env_configs/_librefm.md"
|
||||
|
||||
This Source **monitors your Libre.fm scrobble history** and re-scrobbles new activity to configured [Clients.](/configuration/clients)
|
||||
|
||||
@@ -23,14 +24,5 @@ To configure this Source use the same registration instructions and configuratio
|
||||
## Configuration
|
||||
|
||||
<Config config="LibrefmSourceConfig" fileContent={JsonConfig} name="librefm">
|
||||
| Environmental Variable | Required? | Default | Description |
|
||||
| ----------------------------- | --------- | ---------------------------------------- | ------------------------------------------------------------------------------------------------ |
|
||||
| `SOURCE_LIBREFM_ID` | Yes | | A unique ID |
|
||||
| `SOURCE_LIBREFM_ENABLE` | No | | Set to `true` to enable Libre.fm, if not using any of the below variables |
|
||||
| `SOURCE_LIBREFM_API_KEY` | No | `anything` | Optional API Key |
|
||||
| `SOURCE_LIBREFM_SECRET` | No | `anything` | Optional shared secret |
|
||||
| `SOURCE_LIBREFM_REDIRECT_URI` | No | `http://localhost:9078/librefm/callback` | Url to use for authentication. Must include `librefm/callback` somewhere in it |
|
||||
| `SOURCE_LIBREFM_SESSION` | No | | Session id. Will be generated by authentication flow if not provided. |
|
||||
| `SOURCE_LIBREFM_URLBASE` | No | | Use for custom Libre.fm instance only. The host + path prefix EX `https://my.libre.example/2.0/` |
|
||||
| `SOURCE_LIBREFM_NAME` | No | | A vanity name different than ID |
|
||||
<ENVConfig/>
|
||||
</Config>
|
||||
@@ -8,6 +8,7 @@ import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
import CodeBlock from '@theme/CodeBlock';
|
||||
import ListenbrainzEndpointConfig from '!!raw-loader!@site/../config/endpointlz.json.example';
|
||||
import ENVConfig from "@site/docs/configuration/sources/_env_configs/_endpointlz.md"
|
||||
|
||||
This Source enables multi-scrobbler to accept scrobbles from outside applications **as if it was a Listenbrainz server.**
|
||||
|
||||
@@ -109,12 +110,5 @@ To troubleshoot any errors, and assuming you are using Home Assistant, view the
|
||||
## Configuration
|
||||
|
||||
<Config config="ListenbrainzEndpointSourceConfig" fileContent={ListenbrainzEndpointConfig} name="endpointlz">
|
||||
| Environmental Variable | Required? | Default | Description |
|
||||
| :--------------------- | :-------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `LZE_ID` | Yes | | A unique ID |
|
||||
| `LZE_ENABLE` | No | | Use LZ Endpoint as a Source without any other configuration. Only required if slug/token are not provided as ENVs |
|
||||
| `LZE_TOKEN` | No | | LZ "Authentication Token" you provided to the scrobbling application |
|
||||
| `LZE_SLUG` | No | | (Optional) The URL suffix to use for accepting LZ scrobbles |
|
||||
| `LZE_USERNAME` | No | | (Optional) A fake username that will be returned for token validation and on now-playing responses. If none is provided the Source's name is used instead. |
|
||||
| `LZE_NAME` | No | | A vanity name different than ID |
|
||||
<ENVConfig/>
|
||||
</Config>
|
||||
@@ -9,6 +9,7 @@ import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
import CodeBlock from '@theme/CodeBlock';
|
||||
import ListenbrainzConfig from '!!raw-loader!@site/../config/listenbrainz.json.example';
|
||||
import ENVConfig from "@site/docs/configuration/sources/_env_configs/_listenbrainz.md"
|
||||
|
||||
This Source monitors a Listenbrainz account's scrobble history and then re-scrobbles discovered tracks to configured clients.
|
||||
|
||||
@@ -26,11 +27,5 @@ On your [profile page](https://listenbrainz.org/profile/) find your **User Token
|
||||
## Configuration
|
||||
|
||||
<Config config="ListenBrainzSourceConfig" fileContent={ListenbrainzConfig} name="listenbrainz">
|
||||
| Environmental Variable | Required? | Default | Description |
|
||||
| ---------------------- | --------- | ----------------------------- | ------------------------------- |
|
||||
| `SOURCE_LZ_ID` | Yes | | A unique ID |
|
||||
| `SOURCE_LZ_TOKEN` | Yes | | User token from your LZ profile |
|
||||
| `SOURCE_LZ_USER` | Yes | | Your LZ username |
|
||||
| `SOURCE_LZ_URL` | No | https://api.listenbrainz.org/ | The base URL for the LZ server |
|
||||
| `SOURCE_LZ_NAME` | No | | A vanity name different than ID |d
|
||||
<ENVConfig/>
|
||||
</Config>
|
||||
@@ -8,6 +8,7 @@ import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
import CodeBlock from '@theme/CodeBlock';
|
||||
import MalojaConfig from '!!raw-loader!@site/../config/maloja.json.example';
|
||||
import ENVConfig from "@site/docs/configuration/sources/_env_configs/_maloja.md"
|
||||
|
||||
:::tip[Other Uses]
|
||||
|
||||
@@ -22,10 +23,5 @@ See the [Maloja (Client)](/configuration/clients/maloja) configuration for gener
|
||||
## Configuration
|
||||
|
||||
<Config config="MalojaSourceConfig" fileContent={MalojaConfig} name="maloja">
|
||||
| Environmental Variable | Required? | Default | Description |
|
||||
| ----------------------- | --------- | ------- | ------------------------------- |
|
||||
| `SOURCE_MALOJA_ID` | Yes | | A unique ID |
|
||||
| `SOURCE_MALOJA_URL` | Yes | | Base URL of your installation |
|
||||
| `SOURCE_MALOJA_API_KEY` | Yes | | Api Key |
|
||||
| `SOURCE_MALOJA_NAME` | Yes | | A vanity name different than ID |
|
||||
<ENVConfig/>
|
||||
</Config>
|
||||
@@ -8,6 +8,7 @@ import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
import CodeBlock from '@theme/CodeBlock';
|
||||
import MopidyConfig from '!!raw-loader!@site/../config/mopidy.json.example';
|
||||
import ENVConfig from "@site/docs/configuration/sources/_env_configs/_mopidy.md"
|
||||
|
||||
Mopidy is a headless music server that supports playing music from many [standard and non-standard sources such as Pandora, Bandcamp, and Tunein.](https://mopidy.com/ext/)
|
||||
|
||||
@@ -98,5 +99,5 @@ For certain sources (Soundcloud) Mopidy does not have all track info (Album) and
|
||||
## Configuration
|
||||
|
||||
<Config config="MopidySourceConfig" fileContent={MopidyConfig} name="mopidy">
|
||||
No ENV support
|
||||
<ENVConfig/>
|
||||
</Config>
|
||||
@@ -8,6 +8,7 @@ import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
import CodeBlock from '@theme/CodeBlock';
|
||||
import MPDConfig from '!!raw-loader!@site/../config/mpd.json.example';
|
||||
import ENVConfig from "@site/docs/configuration/sources/_env_configs/_mpd.md"
|
||||
|
||||
MS communicates with MPD using the [TCP client connection.](https://mpd.readthedocs.io/en/stable/user.html#client-connections)
|
||||
|
||||
@@ -23,10 +24,5 @@ Multi-scrobbler requires only the [`read`](https://mpd.readthedocs.io/en/stable/
|
||||
## Configuration
|
||||
|
||||
<Config config="MPDSourceConfig" fileContent={MPDConfig} name="mpd">
|
||||
| Environmental Variable | Required? | Default | Description |
|
||||
| ---------------------- | --------- | ---------------- | ------------------------------- |
|
||||
| `MPD_ID` | Yes | | A unique ID |
|
||||
| `MPD_URL` | No | `localhost:6600` | |
|
||||
| `MPD_PASSWORD` | No | | |
|
||||
| `MPD_NAME` | No | | A vanity name different than ID |
|
||||
<ENVConfig/>
|
||||
</Config>
|
||||
@@ -8,6 +8,7 @@ import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
import CodeBlock from '@theme/CodeBlock';
|
||||
import MPRISConfig from '!!raw-loader!@site/../config/mpris.json.example';
|
||||
import ENVConfig from "@site/docs/configuration/sources/_env_configs/_mpris.md"
|
||||
|
||||
[MPRIS](https://specifications.freedesktop.org/mpris-spec/latest) is a standard interface for communicating with Music Players on **linux operating systems.**
|
||||
|
||||
@@ -71,11 +72,5 @@ MPRIS communication requires multi-scrobbler to have access to the host's dbus-d
|
||||
## Configuration
|
||||
|
||||
<Config config="MPRISSourceConfig" fileContent={MPRISConfig} name="mpris">
|
||||
| Environmental Variable | Required? | Default | Description |
|
||||
| ---------------------- | --------- | ------- | -------------------------------------------------------------------------------- |
|
||||
| MPRIS_ID | Yes | | A unique ID |
|
||||
| MPRIS_ENABLE | No | | Use MPRIS as a Source (useful when you don't need any other options) |
|
||||
| MPRIS_BLACKLIST | No | | Comma-delimited list of player names not to scrobble from |
|
||||
| MPRIS_WHITELIST | No | | Comma-delimited list of players names to ONLY scrobble from. Overrides blacklist |
|
||||
| MPRIS_NAME | No | | A vanity name different than ID |
|
||||
<ENVConfig/>
|
||||
</Config>
|
||||
@@ -8,6 +8,7 @@ import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
import CodeBlock from '@theme/CodeBlock';
|
||||
import MusikcubeConfig from '!!raw-loader!@site/../config/musikcube.json.example';
|
||||
import ENVConfig from "@site/docs/configuration/sources/_env_configs/_musikcube.md"
|
||||
|
||||
In order to use [Musikcube](https://musikcube.com) configure it to accept [websocket connections](https://github.com/clangen/musikcube/wiki/remote-api-documentation) in **server setup**:
|
||||
|
||||
@@ -31,10 +32,5 @@ If no URL is provided to MS it will try to use `ws://localhost:7905`
|
||||
## Configuration
|
||||
|
||||
<Config config="MusikcubeSourceConfig" fileContent={MusikcubeConfig} name="musikcube">
|
||||
| Environmental Variable | Required? | Default | Description |
|
||||
| ---------------------- | --------- | --------------------- | ------------------------------------ |
|
||||
| `MC_ID` | Yes | | A unique ID |
|
||||
| `MC_URL` | No | `ws://localhost:7905` | Use port set for **metadata server** |
|
||||
| `MC_PASSWORD` | Yes | | |
|
||||
| `MC_NAME` | No | | A vanity name different than ID |
|
||||
<ENVConfig/>
|
||||
</Config>
|
||||
@@ -9,6 +9,7 @@ import TabItem from '@theme/TabItem';
|
||||
import CodeBlock from '@theme/CodeBlock';
|
||||
import AzuracastConfig from '!!raw-loader!@site/../config/azuracast.json.example';
|
||||
import PlexConfig from '!!raw-loader!@site/../config/plex.json.example';
|
||||
import ENVConfig from "@site/docs/configuration/sources/_env_configs/_plex.md"
|
||||
|
||||
Find your [**Plex Token**](https://support.plex.tv/articles/204059436-finding-an-authentication-token-x-plex-token/) and make note of the **URL** and **Port** used to connect to your Plex instance.
|
||||
|
||||
@@ -194,16 +195,5 @@ To configure MS to use Musicbrainz with your Plex metadata use one of the method
|
||||
#### Configuration
|
||||
|
||||
<Config config="PlexApiSourceConfig" fileContent={PlexConfig} name="plex">
|
||||
| Environmental Variable | Required? | Default | Description |
|
||||
| ---------------------- | --------- | ------- | ---------------------------------------------------------------------- |
|
||||
| `PLEX_ID` | **Yes** | | A unique ID |
|
||||
| `PLEX_URL` | **Yes** | | The URL of the Plex server IE `http://localhost:32400` |
|
||||
| `PLEX_TOKEN` | **Yes** | | The **Plex Token** to use with the API |
|
||||
| `PLEX_USERS_ALLOW` | No | | Comma-separated list of usernames (from Plex) to scrobble for |
|
||||
| `PLEX_USERS_BLOCK` | No | | Comma-separated list of usernames (from Plex) to disallow scrobble for |
|
||||
| `PLEX_DEVICES_ALLOW` | No | | Comma-separated list of devices to scrobble from |
|
||||
| `PLEX_DEVICES_BLOCK` | No | | Comma-separated list of devices to disallow scrobbles from |
|
||||
| `PLEX_LIBRARIES_ALLOW` | No | | Comma-separated list of libraries to allow scrobbles from |
|
||||
| `PLEX_LIBRARIES_BLOCK` | No | | Comma-separated list of libraries to disallow scrobbles from |
|
||||
| `PLEX_NAME` | No | | A vanity name different than ID |
|
||||
<ENVConfig/>
|
||||
</Config>
|
||||
@@ -9,6 +9,7 @@ import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
import CodeBlock from '@theme/CodeBlock';
|
||||
import JsonConfig from '!!raw-loader!@site/../config/rocksky.json.example';
|
||||
import ENVConfig from "@site/docs/configuration/sources/_env_configs/_rocksky.md"
|
||||
|
||||
:::tip[Other Uses]
|
||||
|
||||
@@ -33,10 +34,5 @@ See the [Rocksky (Client)](/configuration/clients/rocksky#setup) configuration f
|
||||
* [File/AIO config](/configuration?configType=file#configuration-types) must include `"configureAs": "source"`
|
||||
|
||||
<Config config="RockskySourceConfig" fileContent={JsonConfig} name="rocksky">
|
||||
| Environmental Variable | Required? | Default | Description |
|
||||
| :---------------------- | --------- | ------- | ----------------------------------------------------------------------------------- |
|
||||
| `SOURCE_ROCKSKY_ID` | Yes | | A unique ID |
|
||||
| `SOURCE_ROCKSKY_HANDLE` | Yes | | Your **full** ATProto handle. For Bluesky account this is like `myUser.bsky.social` |
|
||||
| `SOURCE_ROCKSKY_KEY` | Yes | | API Key obtained from Rocksky developer dashboard |
|
||||
| `SOURCE_ROCKSKY_NAME` | No | | A vanity name different than ID |
|
||||
<ENVConfig/>
|
||||
</Config>
|
||||
@@ -8,6 +8,7 @@ import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
import CodeBlock from '@theme/CodeBlock';
|
||||
import JsonConfig from '!!raw-loader!@site/../config/sonos.json.example';
|
||||
import ENVConfig from "@site/docs/configuration/sources/_env_configs/_sonos.md"
|
||||
|
||||
Multi-scrobbler can use the [Sonos](https://www.sonos.com) [local API](https://docs.sonos.com/docs/control) to monitor what your Sonos system is playing.
|
||||
|
||||
@@ -90,13 +91,5 @@ The **optional** `devices` and `groups` related properties found in the config b
|
||||
You **must** define the IP address of at least one Sonos/accessory in order for Multi-scrobbler to connect to your Sonos system.
|
||||
|
||||
<Config config="SonosSourceConfig" fileContent={JsonConfig} name="sonos">
|
||||
| Environmental Variable | Required? | Default | Description |
|
||||
| ---------------------- | --------- | ------- | :--------------------------------------------------------------------- |
|
||||
| `SONOS_ID` | Yes | | A unique ID |
|
||||
| `SONOS_HOST` | Yes | | The IP address of any active Sonos device/accessory EX `192.168.0.150` |
|
||||
| `SONOS_DEVICES_ALLOW` | No | | Comma-separated list of Sonos device names to scrobble from |
|
||||
| `SONOS_DEVICES_BLOCK` | No | | Comma-separated list of Sonos device names to disallow scrobbles from |
|
||||
| `SONOS_GROUPS_ALLOW` | No | | Comma-separated list of device group names to scrobble from |
|
||||
| `SONOS_GROUPS_BLOCK` | No | | Comma-separated list of devices group names to disallow scrobbles from |
|
||||
| `SONOS_NAME` | No | | A vanity name different than ID |
|
||||
<ENVConfig/>
|
||||
</Config>
|
||||
@@ -13,36 +13,37 @@ A **Source** is a data source that contains information about tracks you are pla
|
||||
|
||||
## Sources
|
||||
|
||||
| Name | Networking | Scrobble SOT | [Multi Device/User](#multi-deviceuser) | [Scrobble Destination](#limiting-scrobble-destination) | [Thresholds](#scrobble-thresholds) | [Should Scrobble](#should-scrobble-behavior) |
|
||||
| :---------------------------------------------------------------------- | :------------------------------------------------------- | :-------------------------------------------------- | :------------------------------------- | :----------------------------------------------------- | :--------------------------------- | :------------------------------------------- |
|
||||
| [Azuracast](/configuration/sources/azuracast) | [Active](./?sourceComm=active#by-communication-method) | [Activity](./?sot=activity#by-data-source-of-truth) | ❌ | ✅ | ✅ | ✅ |
|
||||
| [Deezer](/configuration/sources/deezer) | [Active](./?sourceComm=active#by-communication-method) | [History](./?sot=history#by-data-source-of-truth) | ✅ | ✅ | ❌ | ❌ |
|
||||
| [Google Cast (Chromecast)](/configuration/sources/google-cast) | [Active](./?sourceComm=active#by-communication-method) | [Activity](./?sot=activity#by-data-source-of-truth) | ✅ | ✅ | ✅ | ❌ |
|
||||
| [Icecast](/configuration/sources/icecast) | [Active](./?sourceComm=active#by-communication-method) | [Activity](./?sot=activity#by-data-source-of-truth) | ❌ | ✅ | ✅ | ✅ |
|
||||
| [Jellyfin](/configuration/sources/jellyfin) | [Active](./?sourceComm=active#by-communication-method) | [Activity](./?sot=activity#by-data-source-of-truth) | ✅ | ✅ | ✅ | ❌ |
|
||||
| [JRiver](/configuration/sources/jriver) | [Active](./?sourceComm=active#by-communication-method) | [Activity](./?sot=activity#by-data-source-of-truth) | ❌ | ✅ | ✅ | ❌ |
|
||||
| [Kodi](/configuration/sources/kodi) | [Active](./?sourceComm=active#by-communication-method) | [Activity](./?sot=activity#by-data-source-of-truth) | ❌ | ✅ | ✅ | ❌ |
|
||||
| [Koito](/configuration/sources/koito-source) | [Active](./?sourceComm=active#by-communication-method) | [History](./?sot=history#by-data-source-of-truth) | ❌ | ✅ | ❌ | ❌ |
|
||||
| [Last.fm](/configuration/sources/lastfm-source) | [Active](./?sourceComm=active#by-communication-method) | [History](./?sot=history#by-data-source-of-truth) | ❌ | ✅ | ❌ | ❌ |
|
||||
| [Libre.fm](/configuration/sources/librefm-source) | [Active](./?sourceComm=active#by-communication-method) | [History](./?sot=history#by-data-source-of-truth) | ❌ | ✅ | ❌ | ❌ |
|
||||
| [Last.fm (Endpoint)](/configuration/sources/lastfm-endpoint) | [Ingress](./?sourceComm=ingress#by-communication-method) | [History](./?sot=history#by-data-source-of-truth) | ❌ | ✅ | ❌ | ❌ |
|
||||
| [ListenBrainz](/configuration/sources/listenbrainz-source) | [Active](./?sourceComm=active#by-communication-method) | [History](./?sot=history#by-data-source-of-truth) | ❌ | ✅ | ❌ | ❌ |
|
||||
| [ListenBrainz (Endpoint)](/configuration/sources/listenbrainz-endpoint) | [Ingress](./?sourceComm=ingress#by-communication-method) | [History](./?sot=history#by-data-source-of-truth) | ❌ | ✅ | ❌ | ❌ |
|
||||
| [Maloja](/configuration/sources/maloja) | [Active](./?sourceComm=active#by-communication-method) | [History](./?sot=history#by-data-source-of-truth) | ❌ | ✅ | ❌ | ❌ |
|
||||
| [Mopidy](/configuration/sources/mopidy) | [Active](./?sourceComm=active#by-communication-method) | [Activity](./?sot=activity#by-data-source-of-truth) | ❌ | ✅ | ✅ | ❌ |
|
||||
| [MPD (Music Player Daemon)](/configuration/sources/mpd) | [Active](./?sourceComm=active#by-communication-method) | [Activity](./?sot=activity#by-data-source-of-truth) | ❌ | ✅ | ✅ | ❌ |
|
||||
| [Musikcube](/configuration/sources/musikcube) | [Active](./?sourceComm=active#by-communication-method) | [Activity](./?sot=activity#by-data-source-of-truth) | ❌ | ✅ | ✅ | ❌ |
|
||||
| [Plex](/configuration/sources/plex) | [Active](./?sourceComm=active#by-communication-method) | [Activity](./?sot=activity#by-data-source-of-truth) | ✅ | ✅ | ✅ | ❌ |
|
||||
| [Rocksky](/configuration/sources/rocksky-source) | [Active](./?sourceComm=active#by-communication-method) | [History](./?sot=history#by-data-source-of-truth) | ❌ | ✅ | ❌ | ❌ |
|
||||
| [Sonos](/configuration/sources/sonos) | [Active](./?sourceComm=active#by-communication-method) | [Activity](./?sot=activity#by-data-source-of-truth) | ✅ | ✅ | ✅ | ❌ |
|
||||
| [Spotify](/configuration/sources/spotify) | [Active](./?sourceComm=active#by-communication-method) | [Activity](./?sot=activity#by-data-source-of-truth) | ✅ | ✅ | ✅ | ❌ |
|
||||
| [Subsonic-compatible APIs](/configuration/sources/subsonic) | [Active](./?sourceComm=active#by-communication-method) | [Activity](./?sot=activity#by-data-source-of-truth) | ✅ | ✅ | ✅ | ❌ |
|
||||
| [teal.fm](/configuration/sources/tealfm-source) | [Active](./?sourceComm=active#by-communication-method) | [History](./?sot=history#by-data-source-of-truth) | ❌ | ✅ | ❌ | ❌ |
|
||||
| [WebScrobbler](/configuration/sources/webscrobbler) | [Ingress](./?sourceComm=active#by-communication-method) | [History](./?sot=history#by-data-source-of-truth) | ❌ | ✅ | ❌ | ❌ |
|
||||
| [VLC](/configuration/sources/vlc) | [Active](./?sourceComm=active#by-communication-method) | [Activity](./?sot=activity#by-data-source-of-truth) | ❌ | ✅ | ✅ | ❌ |
|
||||
| [Yamaha MusicCast](/configuration/sources/yamaha-musiccast) | [Active](./?sourceComm=active#by-communication-method) | [Activity](./?sot=activity#by-data-source-of-truth) | ❌ | ✅ | ✅ | ❌ |
|
||||
| [Yandex Music](/configuration/sources/yandex-music) | [Active](./?sourceComm=active#by-communication-method) | [Activity](./?sot=activity#by-data-source-of-truth) | | ✅ | ✅ | ❌ |
|
||||
| [Youtube Music](/configuration/sources/youtube-music) | [Active](./?sourceComm=active#by-communication-method) | [History](./?sot=history#by-data-source-of-truth) | ❌ | ✅ | ❌ | ❌ |
|
||||
| Name | Networking | Scrobble SOT | [Multi Device/User](#multi-deviceuser) | [Scrobble Destination](#limiting-scrobble-destination) | [Thresholds](#scrobble-thresholds) | [Auto Monitoring](#monitoring) |
|
||||
| :---------------------------------------------------------------------- | :------------------------------------------------------- | :-------------------------------------------------- | :------------------------------------- | :----------------------------------------------------- | :--------------------------------- | :----------------------------- |
|
||||
| [Apple Music](/configuration/sources/applemusic) | [Active](./?sourceComm=active#by-communication-method) | [History](./?sot=history#by-data-source-of-truth) | ❌ | ✅ | ❌ | ✅ |
|
||||
| [Azuracast](/configuration/sources/azuracast) | [Active](./?sourceComm=active#by-communication-method) | [Activity](./?sot=activity#by-data-source-of-truth) | ❌ | ✅ | ✅ | ⚠️ |
|
||||
| [Deezer](/configuration/sources/deezer) | [Active](./?sourceComm=active#by-communication-method) | [History](./?sot=history#by-data-source-of-truth) | ✅ | ✅ | ❌ | ✅ |
|
||||
| [Google Cast (Chromecast)](/configuration/sources/google-cast) | [Active](./?sourceComm=active#by-communication-method) | [Activity](./?sot=activity#by-data-source-of-truth) | ✅ | ✅ | ✅ | ✅ |
|
||||
| [Icecast](/configuration/sources/icecast) | [Active](./?sourceComm=active#by-communication-method) | [Activity](./?sot=activity#by-data-source-of-truth) | ❌ | ✅ | ✅ | ⚠️ |
|
||||
| [Jellyfin](/configuration/sources/jellyfin) | [Active](./?sourceComm=active#by-communication-method) | [Activity](./?sot=activity#by-data-source-of-truth) | ✅ | ✅ | ✅ | ✅ |
|
||||
| [JRiver](/configuration/sources/jriver) | [Active](./?sourceComm=active#by-communication-method) | [Activity](./?sot=activity#by-data-source-of-truth) | ❌ | ✅ | ✅ | ✅ |
|
||||
| [Kodi](/configuration/sources/kodi) | [Active](./?sourceComm=active#by-communication-method) | [Activity](./?sot=activity#by-data-source-of-truth) | ❌ | ✅ | ✅ | ✅ |
|
||||
| [Koito](/configuration/sources/koito-source) | [Active](./?sourceComm=active#by-communication-method) | [History](./?sot=history#by-data-source-of-truth) | ❌ | ✅ | ❌ | ✅ |
|
||||
| [Last.fm](/configuration/sources/lastfm-source) | [Active](./?sourceComm=active#by-communication-method) | [History](./?sot=history#by-data-source-of-truth) | ❌ | ✅ | ❌ | ✅ |
|
||||
| [Libre.fm](/configuration/sources/librefm-source) | [Active](./?sourceComm=active#by-communication-method) | [History](./?sot=history#by-data-source-of-truth) | ❌ | ✅ | ❌ | ✅ |
|
||||
| [Last.fm (Endpoint)](/configuration/sources/lastfm-endpoint) | [Ingress](./?sourceComm=ingress#by-communication-method) | [History](./?sot=history#by-data-source-of-truth) | ❌ | ✅ | ❌ | ✅ |
|
||||
| [ListenBrainz](/configuration/sources/listenbrainz-source) | [Active](./?sourceComm=active#by-communication-method) | [History](./?sot=history#by-data-source-of-truth) | ❌ | ✅ | ❌ | ✅ |
|
||||
| [ListenBrainz (Endpoint)](/configuration/sources/listenbrainz-endpoint) | [Ingress](./?sourceComm=ingress#by-communication-method) | [History](./?sot=history#by-data-source-of-truth) | ❌ | ✅ | ❌ | ✅ |
|
||||
| [Maloja](/configuration/sources/maloja) | [Active](./?sourceComm=active#by-communication-method) | [History](./?sot=history#by-data-source-of-truth) | ❌ | ✅ | ❌ | ✅ |
|
||||
| [Mopidy](/configuration/sources/mopidy) | [Active](./?sourceComm=active#by-communication-method) | [Activity](./?sot=activity#by-data-source-of-truth) | ❌ | ✅ | ✅ | ✅ |
|
||||
| [MPD (Music Player Daemon)](/configuration/sources/mpd) | [Active](./?sourceComm=active#by-communication-method) | [Activity](./?sot=activity#by-data-source-of-truth) | ❌ | ✅ | ✅ | ✅ |
|
||||
| [Musikcube](/configuration/sources/musikcube) | [Active](./?sourceComm=active#by-communication-method) | [Activity](./?sot=activity#by-data-source-of-truth) | ❌ | ✅ | ✅ | ✅ |
|
||||
| [Plex](/configuration/sources/plex) | [Active](./?sourceComm=active#by-communication-method) | [Activity](./?sot=activity#by-data-source-of-truth) | ✅ | ✅ | ✅ | ✅ |
|
||||
| [Rocksky](/configuration/sources/rocksky-source) | [Active](./?sourceComm=active#by-communication-method) | [History](./?sot=history#by-data-source-of-truth) | ❌ | ✅ | ❌ | ✅ |
|
||||
| [Sonos](/configuration/sources/sonos) | [Active](./?sourceComm=active#by-communication-method) | [Activity](./?sot=activity#by-data-source-of-truth) | ✅ | ✅ | ✅ | ✅ |
|
||||
| [Spotify](/configuration/sources/spotify) | [Active](./?sourceComm=active#by-communication-method) | [Activity](./?sot=activity#by-data-source-of-truth) | ✅ | ✅ | ✅ | ✅ |
|
||||
| [Subsonic-compatible APIs](/configuration/sources/subsonic) | [Active](./?sourceComm=active#by-communication-method) | [Activity](./?sot=activity#by-data-source-of-truth) | ✅ | ✅ | ✅ | ✅ |
|
||||
| [teal.fm](/configuration/sources/tealfm-source) | [Active](./?sourceComm=active#by-communication-method) | [History](./?sot=history#by-data-source-of-truth) | ❌ | ✅ | ❌ | ✅ |
|
||||
| [WebScrobbler](/configuration/sources/webscrobbler) | [Ingress](./?sourceComm=active#by-communication-method) | [History](./?sot=history#by-data-source-of-truth) | ❌ | ✅ | ❌ | ✅ |
|
||||
| [VLC](/configuration/sources/vlc) | [Active](./?sourceComm=active#by-communication-method) | [Activity](./?sot=activity#by-data-source-of-truth) | ❌ | ✅ | ✅ | ✅ |
|
||||
| [Yamaha MusicCast](/configuration/sources/yamaha-musiccast) | [Active](./?sourceComm=active#by-communication-method) | [Activity](./?sot=activity#by-data-source-of-truth) | ❌ | ✅ | ✅ | ✅ |
|
||||
| [Yandex Music](/configuration/sources/yandex-music) | [Active](./?sourceComm=active#by-communication-method) | [Activity](./?sot=activity#by-data-source-of-truth) | | ✅ | ✅ | ✅ |
|
||||
| [Youtube Music](/configuration/sources/youtube-music) | [Active](./?sourceComm=active#by-communication-method) | [History](./?sot=history#by-data-source-of-truth) | ❌ | ✅ | ❌ | ✅ |
|
||||
|
||||
## Features
|
||||
|
||||
@@ -122,7 +123,23 @@ Otherwise, use the `name` property you gave the client in it's File/AIO config.
|
||||
|
||||
:::
|
||||
|
||||
### Scrobble Thresholds
|
||||
### When Is Activity Scrobbled?
|
||||
|
||||
##### From Listening History
|
||||
|
||||
For [**Listening History**](./?sot=history#by-data-source-of-truth) Source-Of-Truth based Sources, like Listenbrainz and Last.fm, newely discovered history is immediately forwarded to relevant Clients.
|
||||
|
||||
##### From Ingress
|
||||
|
||||
For [**Ingress**](./?sot=activity&sourceComm=ingress#by-communication-method) communication based Sources, like [Listenbrainz (Endpoint)](/configuration/sources/listenbrainz-endpoint) and [Webscrobbler](/configuration/sources/webscrobbler), the client sending data to Multi-Scrobbler is what determines when activity is scrobbled. This means that it up to the behavior and implementation of whatever application you point at these Source endpoints: when the client sends "this is scrobbled", MS immediately forwards it to relevant Clients.
|
||||
|
||||
##### From Listening Activity
|
||||
|
||||
For Sources that use [**Active**](./?sot=activity&sourceComm=active#by-communication-method) communication with [**Listening Activity**](./?sot=activity#by-data-source-of-truth) as the Source-Of-Truth -- like Jellyfin, Plex, Spotify, Subsonic, etc... -- *Multi-Scrobbler waits until the track changes or the active player becomes stale/disappears* before determining if the activity should be scrobbled.
|
||||
|
||||
This allows MS to record how long you listened to the track for as well as more accurately determine if **Scrobble Thresholds** have been met.
|
||||
|
||||
#### Scrobble Thresholds
|
||||
|
||||
<ScrobbleThreshold filename="spotify"/>
|
||||
|
||||
@@ -133,7 +150,7 @@ SOURCE_SCROBBLE_DURATION=40
|
||||
SOURCE_SCROBBLE_PERCENT=20
|
||||
```
|
||||
|
||||
### Should Scrobble Behavior
|
||||
### Monitoring
|
||||
|
||||
:::note
|
||||
|
||||
@@ -141,7 +158,7 @@ This feature is currently available only for some Sources. Check each Source's d
|
||||
|
||||
:::
|
||||
|
||||
For _most_ Sources multi-scrobbler can determine if a user is listening and scrobble automatically. For Sources which multi-scrobbler cannot do this or require additional configuration, a user can indicate to MS that it should or should not scrobble. This action can be taken on the Web Dashboard by clicking the link next to **Should Scrobble** found in each Source's status card.
|
||||
For _most_ Sources multi-scrobbler can determine if a user is listening and monitor activity automatically. For Sources which multi-scrobbler cannot do this or require additional configuration, a user can indicate to MS that it should or should not monitor activity. This action can be taken on the Web Dashboard by clicking the link next to **Monitoring** found in each Source's status card.
|
||||
|
||||
Additionally, for these Sources, the default behavior for Scrobbling can be explicitly set by adding the following value to a Source's `options` in [file or aio config](/configuration?configType=file#configuration-types):
|
||||
|
||||
@@ -153,7 +170,7 @@ Additionally, for these Sources, the default behavior for Scrobbling can be expl
|
||||
"options": {
|
||||
// set to true to always scrobble automatically
|
||||
// set to false to never scrobble automatically
|
||||
"systemScrobble": true
|
||||
"autoMonitor": true
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -8,6 +8,7 @@ import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
import CodeBlock from '@theme/CodeBlock';
|
||||
import SpotifyConfig from '!!raw-loader!@site/../config/spotify.json.example';
|
||||
import ENVConfig from "@site/docs/configuration/sources/_env_configs/_spotify.md"
|
||||
import IconWarning from '@theme/Admonition/Icon/Warning';
|
||||
|
||||
<DetailsAdmo type="note" summary="Spotify and Automix">
|
||||
@@ -111,11 +112,5 @@ Use **one** of the following methods to specify a valid Redirect URI and complet
|
||||
## Configuration
|
||||
|
||||
<Config config="SpotifySourceConfig" fileContent={SpotifyConfig} name="spotify">
|
||||
| Environmental Variable | Required? | Default | Description |
|
||||
| ----------------------- | --------- | -------------------------------- | ------------------------------- |
|
||||
| `SPOTIFY_ID` | Yes | | A unique ID |
|
||||
| `SPOTIFY_CLIENT_ID` | Yes | | |
|
||||
| `SPOTIFY_CLIENT_SECRET` | Yes | | |
|
||||
| `SPOTIFY_REDIRECT_URI` | No | `http://localhost:9078/callback` | URI must end in `callback` |
|
||||
| `SPOTIFY_NAME` | No | | A vantiy name different than ID |
|
||||
<ENVConfig/>
|
||||
</Config>
|
||||
@@ -8,6 +8,7 @@ import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
import CodeBlock from '@theme/CodeBlock';
|
||||
import SubsonicConfig from '!!raw-loader!@site/../config/subsonic.json.example';
|
||||
import ENVConfig from "@site/docs/configuration/sources/_env_configs/_subsonic.md"
|
||||
|
||||
This Source can be used for any application that implements the [Subsonic API](http://www.subsonic.org/pages/api.jsp) and supports the [`getNowPlaying`](http://www.subsonic.org/pages/api.jsp#getNowPlaying) endpoint (such as [Airsonic](https://airsonic.github.io/) and [Navidrome](https://www.navidrome.org/))
|
||||
|
||||
@@ -20,7 +21,7 @@ This Source can be used for any application that implements the [Subsonic API](h
|
||||
|
||||
<DetailsAdmo type="tip" summary="Recommended Alternative Sources">
|
||||
|
||||
If your serivce supports scrobbling to **Listenbrainz** (such as Navidrome), considering using a [**Listenbrainz (Endpoint)** Source](/configuration/sources/listenbrainz-endpoint) instead of this one.
|
||||
If your service supports scrobbling to **Listenbrainz** (such as Navidrome), considering using a [**Listenbrainz (Endpoint)** Source](/configuration/sources/listenbrainz-endpoint) instead of this one.
|
||||
|
||||
Service-specific scrobble implementations tend to be more accurate and provide more information (multiple artists) compared to the Subsonic API.
|
||||
|
||||
@@ -28,14 +29,24 @@ Service-specific scrobble implementations tend to be more accurate and provide m
|
||||
|
||||
Use the optional `usersAllow` property with **File** or **AIO** configuration to restrict scrobbling to a list of defined users.
|
||||
|
||||
## Enhanced Playback Reporting
|
||||
|
||||
Multi-Scrobbler supports the new [Open Subsonic](https://opensubsonic.netlify.app) extension, [Playback Report](https://opensubsonic.netlify.app/docs/extensions/playbackreport/), that enables millisecond-accurate player position and state reporting.
|
||||
|
||||
To use this new data, your Subsonic server must support the extension **and** the active playback Client must report it. The UI for your Subsonic Source and active Player will indicate support using contextual icons.
|
||||
|
||||
Usage of Enhanced Playback Reporting is optional: MS will fallback to classic, less accurate Subsonic Now Playing when it is not available.
|
||||
|
||||
<DetailsAdmo type="info" summary="Stale Players without Playback Reporting">
|
||||
|
||||
For Subsonic server/client combinations that do not support [Enhanced Playback Reporting](#enhanced-playback-reporting), multi-scrobbler will cleanup players that report they are playing for much longer period of time than the track's length (when length is reported). This prevents repeated scrobbles from Subsonic-compatible servers that continue returning a track after playback stops.
|
||||
|
||||
If the server properly reports no playing song when playback has stopped or this causes issues for your setup, the detection can be disabled by setting `detectStaleNowPlayingFromMinutesAgo` to `false` in File/AIO config.
|
||||
|
||||
</DetailsAdmo>
|
||||
|
||||
## Configuration
|
||||
|
||||
<Config config="SubSonicSourceConfig" fileContent={SubsonicConfig} name="subsonic">
|
||||
| Environmental Variable | Required? | Default | Description |
|
||||
| ---------------------- | --------- | ------- | ------------------------------------ |
|
||||
| `SUBSONIC_ID` | Yes | | A unique ID |
|
||||
| `SUBSONIC_USER` | Yes | | |
|
||||
| `SUBSONIC_PASSWORD` | Yes | | |
|
||||
| `SUBSONIC_URL` | Yes | | Base url of your subsonic-api server |
|
||||
| `SUBSONIC_NAME` | No | | A vanity name different than ID |
|
||||
</Config>
|
||||
<ENVConfig/>
|
||||
</Config>
|
||||
|
||||
@@ -9,6 +9,7 @@ import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
import CodeBlock from '@theme/CodeBlock';
|
||||
import JsonConfig from '!!raw-loader!@site/../config/tealfm.json.example';
|
||||
import ENVConfig from "@site/docs/configuration/sources/_env_configs/_tealfm.md"
|
||||
|
||||
:::tip[Other Uses]
|
||||
|
||||
@@ -104,10 +105,5 @@ Allow scrobbles from plyr.fm and unknown services:
|
||||
</details>
|
||||
|
||||
<Config config="TealClientConfig" fileContent={JsonConfig} name="tealfm">
|
||||
| Environmental Variable | Required? | Default | Description |
|
||||
| :------------------------- | --------- | ------- | ------------------------------------------------------------------------------------------ |
|
||||
| `SOURCE_TEALFM_ID` | Yes | | A unique ID |
|
||||
| `SOURCE_TEALFM_IDENTIFIER` | Yes | | Your **full** ATProto handle or DID. For Bluesky account this is like `myUser.bsky.social` |
|
||||
| `SOURCE_TEALFM_APP_PW` | Yes | | Bluesky/ATProto network App Password |
|
||||
| `SORUCE_TEALFM_NAME` | No | | A vanity name different than ID |
|
||||
<ENVConfig/>
|
||||
</Config>
|
||||
@@ -8,6 +8,7 @@ import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
import CodeBlock from '@theme/CodeBlock';
|
||||
import JsonConfig from '!!raw-loader!@site/../config/vlc.json.example';
|
||||
import ENVConfig from "@site/docs/configuration/sources/_env_configs/_vlc.md"
|
||||
|
||||
MS communicates with [VLC](https://www.videolan.org/vlc/) using the [Web (`http`) interface module](https://wiki.videolan.org/VLC_HTTP_requests/)
|
||||
|
||||
@@ -99,10 +100,5 @@ If you find that VLC is incorrectly reporting track information (in its interfac
|
||||
## Configuration
|
||||
|
||||
<Config config="VLCSourceConfig" fileContent={JsonConfig} name="vlc">
|
||||
| Environmental Variable | Required? | Default | Description |
|
||||
| ---------------------- | --------- | ---------------- | ------------------------------- |
|
||||
| `VLC_ID` | Yes | | A unique ID |
|
||||
| `VLC_URL` | No | `localhost:8080` | |
|
||||
| `VLC_PASSWORD` | Yes | | |
|
||||
| `VLC_NAME` | No | | A vanity name different than ID |
|
||||
<ENVConfig/>
|
||||
</Config>
|
||||
@@ -8,6 +8,7 @@ import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
import CodeBlock from '@theme/CodeBlock';
|
||||
import JsonConfig from '!!raw-loader!@site/../config/webscrobbler.json.example';
|
||||
import ENVConfig from "@site/docs/configuration/sources/_env_configs/_webscrobbler.md"
|
||||
|
||||
After installing the [Webscrobbler extension](https://web-scrobbler.com/) open the preferences/settings for it:
|
||||
|
||||
@@ -87,11 +88,5 @@ This affects **only** MS's behavior and does not affect the general connector be
|
||||
## Configuration
|
||||
|
||||
<Config config="WebScrobblerSourceConfig" fileContent={JsonConfig} name="webscrobbler">
|
||||
| Environmental Variable | Required? | Default | Description |
|
||||
| ---------------------- | --------- | ------- | ------------------------------------------------------------------------ |
|
||||
| WS_ID | Yes | | A unique ID |
|
||||
| WS_ENABLE | No | | Set to 'true' to enable WS without needing to define other ENVs |
|
||||
| WS_WHITELIST | No | | Only scrobble from these WebScrobbler Connectors. Comma-delimited list |
|
||||
| WS_BLACKLIST | No | | Do not scrobble from these WebScrobbler Connectors. Comma-delimited list |
|
||||
| WS_NAME | No | | A vanity name different than ID |
|
||||
<ENVConfig/>
|
||||
</Config>
|
||||
@@ -8,6 +8,7 @@ import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
import CodeBlock from '@theme/CodeBlock';
|
||||
import JsonConfig from '!!raw-loader!@site/../config/musiccast.json.example';
|
||||
import ENVConfig from "@site/docs/configuration/sources/_env_configs/_musiccast.md"
|
||||
|
||||
Monitor [MusicCast](https://usa.yamaha.com/products/contents/audio_visual/musiccast/index.html) device/receivers for music played on Network/USB/CD inputs.
|
||||
|
||||
@@ -31,9 +32,5 @@ EX
|
||||
## Configuration
|
||||
|
||||
<Config config="MusicCastSourceConfig" fileContent={JsonConfig} name="musiccast">
|
||||
| Environmental Variable | Required? | Default | Description |
|
||||
| :--------------------- | :-------- | ------- | :------------------------------ |
|
||||
| `MCAST_ID` | Yes | | A unique ID |
|
||||
| `MCAST_URL` | Yes | | The Musiccast device URL |
|
||||
| `MCAST_NAME` | No | | A vanity name different than ID |
|
||||
<ENVConfig/>
|
||||
</Config>
|
||||
@@ -8,6 +8,7 @@ import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
import CodeBlock from '@theme/CodeBlock';
|
||||
import JsonConfig from '!!raw-loader!@site/../config/ymbridge.json.example';
|
||||
import ENVConfig from "@site/docs/configuration/sources/_env_configs/_ymbridge.md"
|
||||
|
||||
Monitor your [**Yandex Music**](https://music.yandex.com) listening activity in real-time.
|
||||
|
||||
@@ -72,10 +73,5 @@ If you have issues specifically with the MS Source please mention [**Druidblack*
|
||||
## Configuration
|
||||
|
||||
<Config config="YandexMusicBridgeSourceConfig" fileContent={JsonConfig} name="ymbridge">
|
||||
| Environmental Variable | Required? | Default | Description |
|
||||
| :--------------------- | :-------- | ------- | :------------------------------------------------------------------------ |
|
||||
| `YMBRIDGE_ID` | Yes | | A unique ID |
|
||||
| `YMBRIDGE_URL` | Yes | | `http://URL:PORT` for the `yandex-music-bridge` container |
|
||||
| `YMBRIDGE_API_KEY` | No | | The same key used for `YM_API_KEY` on the `yandex-music-bridge` container |
|
||||
| `YMBRIDGE_NAME` | No | | A vanity name different than ID |
|
||||
<ENVConfig/>
|
||||
</Config>
|
||||
@@ -8,6 +8,7 @@ import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
import CodeBlock from '@theme/CodeBlock';
|
||||
import JsonConfig from '!!raw-loader!@site/../config/ytmusic.json.example';
|
||||
import ENVConfig from "@site/docs/configuration/sources/_env_configs/_ytmusic.md"
|
||||
|
||||
:::warning
|
||||
|
||||
@@ -179,13 +180,5 @@ Only one of these methods needs to be used.
|
||||
## Configuration
|
||||
|
||||
<Config config="YTMusicSourceConfig" fileContent={JsonConfig} name="ytmusic">
|
||||
| Environmental Variable | Required? | Default | Description |
|
||||
| ---------------------- | --------- | ------- | --------------------------------------------- |
|
||||
| YTM_ID | Yes | | A unique ID |
|
||||
| YTM_COOKIE | No | | Value for Cookie Authentication |
|
||||
| YTM_CLIENT_ID | No | | Client ID for OAuth Athentication |
|
||||
| YTM_CLIENT_SECRET | No | | Client Secret for OAuth Athentication |
|
||||
| YTM_REDIRECT_URI | No | | A custom redirect URI for OAuth Athentication |
|
||||
| YTM_LOG_DIFF | No | false | Log YTM history changes |
|
||||
| YTM_NAME | No | | A vanity name different than ID |
|
||||
<ENVConfig/>
|
||||
</Config>
|
||||
@@ -67,7 +67,6 @@ In a [Subsonic](/configuration/sources/subsonic) [File Config](/configuration?co
|
||||
"preCompare": [
|
||||
{
|
||||
"type": "user",
|
||||
// do not include name, the default user stage will be used
|
||||
"title": [
|
||||
// removes badterm from track title
|
||||
"badterm"
|
||||
@@ -139,9 +138,9 @@ Each [Rule](/configuration/transforms#stage-rules) must be an array of [search-a
|
||||
},
|
||||
"options": {
|
||||
"playTransform": {
|
||||
"type": "user",
|
||||
"preCompare": [
|
||||
{
|
||||
"type": "user",
|
||||
"title": [
|
||||
// removes "badTerm" from title
|
||||
"badTerm",
|
||||
@@ -182,6 +181,7 @@ Using `when` for [Conditional Modification](/configuration/transforms#conditiona
|
||||
//
|
||||
// Run live|remastered regex remove on title
|
||||
{
|
||||
"type": "user",
|
||||
"title": [
|
||||
{
|
||||
"search": "/\\s\\-\\s滾石40\\s滾石撞樂隊\\s40團拚經典(.+)$/i",
|
||||
@@ -210,6 +210,7 @@ Removes the phrase `(Album Version)` from the Title of a Play
|
||||
|
||||
```json5
|
||||
{
|
||||
"type": "user",
|
||||
"title": [
|
||||
"(Album Version)"
|
||||
]
|
||||
@@ -227,11 +228,13 @@ Removes the phrase `(Album Version)` from the Title of a Play
|
||||
{
|
||||
"compare": {
|
||||
"candidate": {
|
||||
"type": "user",
|
||||
"title": [
|
||||
"/(\(.+\))\s*$/"
|
||||
]
|
||||
},
|
||||
"existing": {
|
||||
"type": "user",
|
||||
"title": [
|
||||
"/(\(.+\))\s*$/"
|
||||
]
|
||||
@@ -248,6 +251,7 @@ Removes the phrase `(Album Version)` from the Title of a Play
|
||||
<summary>Example</summary>
|
||||
```json5
|
||||
{
|
||||
"type": "user",
|
||||
"artists": [
|
||||
{
|
||||
"search": "Boz Skaggs",
|
||||
@@ -265,6 +269,7 @@ Removes the phrase `(Album Version)` from the Title of a Play
|
||||
<summary>Example</summary>
|
||||
```json5
|
||||
{
|
||||
"type": "user",
|
||||
"album": [
|
||||
{
|
||||
"search": "Various Artists",
|
||||
@@ -299,6 +304,7 @@ Removes the phrase `(Album Version)` from the Title of a Play
|
||||
<summary>Example</summary>
|
||||
```json
|
||||
{
|
||||
"type": "user",
|
||||
"artists": [
|
||||
{
|
||||
"search": "(.*?)(?<delim>\\s*\\/\\s*)(.*$)",
|
||||
|
||||
@@ -3,6 +3,8 @@ slug: /
|
||||
title: Overview
|
||||
sidebar_position: 1
|
||||
---
|
||||
import Carousel from '@site/src/components/Carousel/NextCarousel';
|
||||
import BrowserOnly from '@docusaurus/BrowserOnly';
|
||||
|
||||

|
||||

|
||||
@@ -13,6 +15,7 @@ sidebar_position: 1
|
||||
A dockerized app that monitors your music listening activity from *everywhere* and scrobbles it *anywhere*.
|
||||
|
||||
* Supports monitoring activity from many [**Sources**](/configuration/sources)
|
||||
* [Apple Music](/configuration/sources/applemusic)
|
||||
* [Azuracast](/configuration/sources/azuracast)
|
||||
* [Deezer](/configuration/sources/deezer)
|
||||
* [Google Cast (Chromecast)](/configuration/sources/google-cast)
|
||||
@@ -64,6 +67,18 @@ A dockerized app that monitors your music listening activity from *everywhere* a
|
||||
|
||||
[**Quick Start Guide**](/quickstart)
|
||||
|
||||
<DetailsAdmo type="tip" summary="New UI Preview">
|
||||
|
||||
A **full rewrite** of the UI is now available for preview. The new UI modernizes Multi-Scrobbler and gives you in depth insight into how your scrobbles are handled end-to-end.
|
||||
|
||||
<Carousel/>
|
||||
|
||||
To try out the stable-release preview navigate to `http://yourMSDomain:9078/next`
|
||||
|
||||
Or to try out the **latest preview snapshot** see the docker image pinned [in this comment.](https://github.com/FoxxMD/multi-scrobbler/issues/500#issuecomment-4917525794)
|
||||
|
||||
</DetailsAdmo>
|
||||
|
||||
<img src={require('/img/status-ui.png').default} width="800"/>
|
||||
|
||||
**Why should I use this over a browser extension and/or mobile app scrobbler?**
|
||||
|
||||
@@ -42,7 +42,7 @@ Cross-platform images are built for x86 (Intel/AMD) and ARM64 (IE Raspberry Pi)
|
||||
|
||||
<Tabs groupId="dockerSetting" queryString>
|
||||
<TabItem value="storage" label="Storage">
|
||||
You **should** bind a host directory into the container for storing configurations and credentials. Otherwise, these will be lost when the container is updated.
|
||||
You **should** bind a host directory into the container for storing configurations, credentials, database, and other files. Otherwise, these will be lost when the container is updated.
|
||||
|
||||
```yaml title="docker-compose.yml"
|
||||
services:
|
||||
@@ -54,6 +54,24 @@ services:
|
||||
// highlight-end
|
||||
```
|
||||
|
||||
Optionally, use a separate directory for data (database, cache, etc...) by mounting an additional directory and setting the `DATA_DIR` ENV to the directory that should be used inside the container:
|
||||
|
||||
```yaml title="docker-compose.yml"
|
||||
services:
|
||||
multi-scrobbler:
|
||||
# ...
|
||||
environment:
|
||||
# ...
|
||||
// highlight-start
|
||||
- DATA_DIR=/msData
|
||||
// highlight-end
|
||||
volumes:
|
||||
- "./config:/config" # used for config files
|
||||
// highlight-start
|
||||
- "./my/host/folder:/msData" # used for data files
|
||||
// highlight-end
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="networking" label="Networking">
|
||||
If you are using a [bridge network](https://www.appsdeveloperblog.com/docker-networking-bridging-host-and-overlay/) (default docker setup) you must map a port to the container in order to access the dashboard and use MS with some sources (Webscrobbler, LFM/LZ Endpoints). The default container port is `9078`.
|
||||
@@ -231,6 +249,33 @@ npm run docs:install && npm run build
|
||||
npm run start
|
||||
```
|
||||
|
||||
#### Config And Data Directories
|
||||
|
||||
The directories MS uses for **Configuration** (`config.json`, `jellyfin.json`, etc...) and **Data** (database, cache, etc...) can be specified by environmental variables passed directly to `npm`/`node`, or set in an `.env` file in the working directory.
|
||||
|
||||
When parsing these ENVs MS will resolve relative directories but *not* bash expansions like `~` for home. Examples:
|
||||
|
||||
* `CONFIG_DIR=/my/absolute/path` => sets directory to use for config files
|
||||
* `DATA_DIR=./relative/data` => sets directory relative to working directory for data files
|
||||
|
||||
If you do not set these environmental variables then MS will attempt to use OS-standardized directories:
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="linux" label="Linux">
|
||||
* Config => `$XDG_CONFIG_HOME/multi-scrobbler` or `~/.config/multi-scrobbler`
|
||||
* Data => `$XDG_DATA_HOME/multi-scrobbler` or `~/.local/share/multi-scrobbler`
|
||||
</TabItem>
|
||||
<TabItem value="mac" label="MacOS">
|
||||
* Config => `~/Library/Preferences/multi-scrobbler`
|
||||
* Data => `~/Library/Application Support/multi-scrobbler`
|
||||
</TabItem>
|
||||
<TabItem value="win" label="Windows">
|
||||
* Config => `%APPDATA%\multi-scrobbler\Config`
|
||||
* Data => `%LOCALAPPDATA%\multi-scrobbler\Data`
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
|
||||
#### Rollup build error
|
||||
|
||||
During building if you encounter an error like: `Your current platform "XXX" and architecture "XXX" combination is not yet supported by the native Rollup build.`
|
||||
|
||||
Generated
+30
@@ -22,6 +22,8 @@
|
||||
"clsx": "^2.0.0",
|
||||
"docusaurus-plugin-sass": "^0.2.6",
|
||||
"docusaurus-theme-github-codeblock": "^2.0.2",
|
||||
"embla-carousel": "^9.0.0-rc02",
|
||||
"embla-carousel-react": "^9.0.0-rc02",
|
||||
"json5": "^2.2.3",
|
||||
"micromark-extension-directive": "^3.0.1",
|
||||
"modern-react-json-editor": "^1.0.2",
|
||||
@@ -10863,6 +10865,34 @@
|
||||
"integrity": "sha512-/4t+AS1l4S3ZC0Ja7PHFIWeBIxGA3QGqV8/yKsP36v7NcyUCl+bIcmw6s5zVuMIECWwBrAK/6QLzTmbJChBboQ==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/embla-carousel": {
|
||||
"version": "9.0.0-rc02",
|
||||
"resolved": "https://registry.npmjs.org/embla-carousel/-/embla-carousel-9.0.0-rc02.tgz",
|
||||
"integrity": "sha512-GOQBX6v5cNk/ptfuHUoHhW9rvl5KeSGsBoppaUqtihu2kDmQAyzvnH/95r3TaSScFSJTj68V9AM6E5nq3jUVcQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/embla-carousel-react": {
|
||||
"version": "9.0.0-rc02",
|
||||
"resolved": "https://registry.npmjs.org/embla-carousel-react/-/embla-carousel-react-9.0.0-rc02.tgz",
|
||||
"integrity": "sha512-DpcD0kTv6L31KvBcrx5d57E6T2rP/YceTGAdq7llkpKFdfM1of8YotHVEQTNIU3I9o5mjE/QxLi1ndJmm1DikA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"embla-carousel": "9.0.0-rc02",
|
||||
"embla-carousel-reactive-utils": "9.0.0-rc02"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^16.8.0 || ^17.0.1 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc"
|
||||
}
|
||||
},
|
||||
"node_modules/embla-carousel-reactive-utils": {
|
||||
"version": "9.0.0-rc02",
|
||||
"resolved": "https://registry.npmjs.org/embla-carousel-reactive-utils/-/embla-carousel-reactive-utils-9.0.0-rc02.tgz",
|
||||
"integrity": "sha512-H1c+yUbcVST9eJoGU+05L1vSDyBs0hf/Gf1OadHYIJ3asBfyvn6oaGCs2wXq1D8/f09y0wwCxeRxT9UZU/TxJA==",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"embla-carousel": "9.0.0-rc02"
|
||||
}
|
||||
},
|
||||
"node_modules/emoji-regex": {
|
||||
"version": "9.2.2",
|
||||
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
|
||||
|
||||
@@ -30,6 +30,8 @@
|
||||
"clsx": "^2.0.0",
|
||||
"docusaurus-plugin-sass": "^0.2.6",
|
||||
"docusaurus-theme-github-codeblock": "^2.0.2",
|
||||
"embla-carousel": "^9.0.0-rc02",
|
||||
"embla-carousel-react": "^9.0.0-rc02",
|
||||
"json5": "^2.2.3",
|
||||
"micromark-extension-directive": "^3.0.1",
|
||||
"modern-react-json-editor": "^1.0.2",
|
||||
|
||||
@@ -11,7 +11,7 @@ index 0536c69..be6274b 100644
|
||||
|
||||
type JsonSchemaProps = Partial<JSVOptions> & {
|
||||
diff --git a/node_modules/cf-json-schema-viz/dist/index.js b/node_modules/cf-json-schema-viz/dist/index.js
|
||||
index b23316c..ef8be1e 100644
|
||||
index b23316c..d89b3ea 100644
|
||||
--- a/node_modules/cf-json-schema-viz/dist/index.js
|
||||
+++ b/node_modules/cf-json-schema-viz/dist/index.js
|
||||
@@ -41,19 +41,19 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
||||
@@ -3462,7 +3462,19 @@ index b23316c..ef8be1e 100644
|
||||
}
|
||||
return [makeChoice(schemaNode)];
|
||||
}, [schemaNode]);
|
||||
@@ -8468,22 +8501,6 @@ var TopLevelSchemaRow = ({
|
||||
@@ -8313,7 +8346,10 @@ var SchemaRow = React2.memo(
|
||||
);
|
||||
const { selectedChoice, setSelectedChoice, choices } = useChoices(schemaNode);
|
||||
const typeToShow = selectedChoice.type;
|
||||
- const description = isRegularNode(typeToShow) ? typeToShow.annotations.description : null;
|
||||
+ let description = isRegularNode(typeToShow) ? typeToShow.annotations.description : null;
|
||||
+ if ((description === null || description === void 0) && "annotations" in schemaNode && (schemaNode.annotations?.description !== null && schemaNode.annotations?.description !== void 0)) {
|
||||
+ description = schemaNode.annotations?.description;
|
||||
+ }
|
||||
const rootLevel = renderRootTreeLines ? 1 : 2;
|
||||
const childNodes = React2.useMemo(() => visibleChildren(typeToShow), [typeToShow]);
|
||||
const combiner = isRegularNode(schemaNode) && schemaNode.combiners?.length ? schemaNode.combiners[0] : null;
|
||||
@@ -8468,22 +8504,6 @@ var TopLevelSchemaRow = ({
|
||||
[schemaNode.fragment]
|
||||
);
|
||||
const hasVendorProperties = totalVendorExtensions > 0;
|
||||
@@ -3485,7 +3497,7 @@ index b23316c..ef8be1e 100644
|
||||
if (isRegularNode(schemaNode) && choices.length > 1) {
|
||||
const combiner = isRegularNode(schemaNode) && schemaNode.combiners?.length ? schemaNode.combiners[0] : null;
|
||||
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
||||
@@ -8517,6 +8534,22 @@ var TopLevelSchemaRow = ({
|
||||
@@ -8517,6 +8537,22 @@ var TopLevelSchemaRow = ({
|
||||
) : combiner ? /* @__PURE__ */ jsx(SchemaRow, { schemaNode: selectedChoice.type, nestingLevel }) : null
|
||||
] });
|
||||
}
|
||||
@@ -3508,7 +3520,7 @@ index b23316c..ef8be1e 100644
|
||||
if (isComplexArray(schemaNode) && isPureObjectNode(schemaNode.children[0])) {
|
||||
const validations = isRegularNode(schemaNode) ? getValidationsFromSchema(schemaNode) : {};
|
||||
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
||||
@@ -8550,6 +8583,7 @@ var JsonSchemaViewer = ({
|
||||
@@ -8550,6 +8586,7 @@ var JsonSchemaViewer = ({
|
||||
disableCrumbs,
|
||||
nodeHasChanged,
|
||||
skipTopLevelDescription,
|
||||
@@ -3516,7 +3528,7 @@ index b23316c..ef8be1e 100644
|
||||
...rest
|
||||
}) => {
|
||||
const options = React2.useMemo(
|
||||
@@ -8562,7 +8596,8 @@ var JsonSchemaViewer = ({
|
||||
@@ -8562,7 +8599,8 @@ var JsonSchemaViewer = ({
|
||||
hideExamples,
|
||||
renderRootTreeLines,
|
||||
disableCrumbs,
|
||||
@@ -3526,7 +3538,7 @@ index b23316c..ef8be1e 100644
|
||||
}),
|
||||
[
|
||||
defaultExpandedDepth,
|
||||
@@ -8573,7 +8608,8 @@ var JsonSchemaViewer = ({
|
||||
@@ -8573,7 +8611,8 @@ var JsonSchemaViewer = ({
|
||||
hideExamples,
|
||||
renderRootTreeLines,
|
||||
disableCrumbs,
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user