diff --git a/README.md b/README.md index 9b85d1a7..c18faedc 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,8 @@ [![Latest Release](https://img.shields.io/github/v/release/foxxmd/multi-scrobbler)](https://github.com/FoxxMD/multi-scrobbler/releases) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![Docker Pulls](https://img.shields.io/docker/pulls/foxxmd/multi-scrobbler)](https://hub.docker.com/r/foxxmd/multi-scrobbler) +[![Docs](https://img.shields.io/badge/Read%20The%20Docs-1082c2)](https://foxxmd.github.io/multi-scrobbler/) + multi-scrobbler logo @@ -37,6 +39,10 @@ A javascript app to scrobble music you listened to, to [Maloja](https://github.c * Easy configuration through ENVs or JSON * Install using [Docker images for x86/ARM](/docsite/docs/installation/installation.md#docker), [flatpak](/docsite/docs/installation/installation.md#flatpak), or [locally with NodeJS](/docsite/docs/installation/installation.md#nodejs) +[**Read The Docs to get started**](https://foxxmd.github.io/multi-scrobbler/docs/installation) + + + **Why should I use this over a browser extension and/or mobile app scrobbler?** * **Platform independent** -- Because multi-scrobbler communicates directly with service APIs it will scrobble everything you play regardless of where you play it. No more need for apps on every platform you use! @@ -48,8 +54,6 @@ A javascript app to scrobble music you listened to, to [Maloja](https://github.c Yes! You can use [Last.fm as a **Source**](/docsite/docs/configuration/configuration.md#lastfm--source-) or [Listenbrainz as a **Source**](/docsite/docs/configuration/configuration.md#listenbrainz--source-) to forward scrobbles from your profile to any other Client! That way you can keep your current scrobble setup as-is but still get the benefit of capturing your data to a self-hosted location. - - ## How Does multi-scrobbler (MS) Work? You set up configurations for one or more **Sources** and one or more **Clients**. MS monitors all of your configured **Sources**. When new tracks are played by a Source it grabs that information and then sends it (scrobbles it) to all **Clients** that Source is configured to scrobble to. diff --git a/docsite/src/pages/index.mdx b/docsite/src/pages/index.mdx index 697b7264..cf9ed2f9 100644 --- a/docsite/src/pages/index.mdx +++ b/docsite/src/pages/index.mdx @@ -40,6 +40,8 @@ A javascript app to scrobble music you listened to, to [Maloja](https://github.c * Easy configuration through ENVs or JSON * Install using [Docker images for x86/ARM](docs/installation#docker), [flatpak](docs/installation#flatpak), or [locally with NodeJS](docs/installation#nodejs) + + **Why should I use this over a browser extension and/or mobile app scrobbler?** * **Platform independent** -- Because multi-scrobbler communicates directly with service APIs it will scrobble everything you play regardless of where you play it. No more need for apps on every platform you use! @@ -51,8 +53,6 @@ A javascript app to scrobble music you listened to, to [Maloja](https://github.c Yes! You can use [Last.fm as a **Source**](docs/configuration#lastfm--source-) or [Listenbrainz as a **Source**](docs/configuration#listenbrainz--source-) to forward scrobbles from your profile to any other Client! That way you can keep your current scrobble setup as-is but still get the benefit of capturing your data to a self-hosted location. - - ## How Does multi-scrobbler (MS) Work? You set up configurations for one or more **Sources** and one or more **Clients**. MS monitors all of your configured **Sources**. When new tracks are played by a Source it grabs that information and then sends it (scrobbles it) to all **Clients** that Source is configured to scrobble to. -- 2.51.2 From d1a4a54d2a49703c2569f6f5daa17a6b717cd4fb Mon Sep 17 00:00:00 2001 From: FoxxMD Date: Mon, 15 Jul 2024 13:26:57 -0400 Subject: [PATCH 02/16] docs: Implement self-hosted docs * Add npm scripts for installing/building docusaurus from main project * Set base url based on ENV * Build docsite in docker image * Add link to doc in dashboard and link to github * Update nodejs install instructions to include doc build command * Update GH pages workflow to use correct base url * Add hint page to main app when docs are not built --- .github/workflows/docsDeploy.yml | 1 + Dockerfile | 3 +- codeshift/transform.ts | 217 ---------------------- docsite/docs/installation/installation.md | 1 + docsite/docusaurus.config.ts | 41 ++-- package-lock.json | 102 +--------- package.json | 10 +- src/backend/server/index.ts | 4 + src/client/App.tsx | 71 +++++-- src/client/Version.tsx | 4 +- src/client/components/CopyToClipboard.tsx | 30 +++ src/client/components/ExternalLink.tsx | 24 +++ 12 files changed, 147 insertions(+), 361 deletions(-) delete mode 100644 codeshift/transform.ts create mode 100644 src/client/components/CopyToClipboard.tsx create mode 100644 src/client/components/ExternalLink.tsx diff --git a/.github/workflows/docsDeploy.yml b/.github/workflows/docsDeploy.yml index f7b60f81..a782c597 100644 --- a/.github/workflows/docsDeploy.yml +++ b/.github/workflows/docsDeploy.yml @@ -27,6 +27,7 @@ jobs: env: ANALYTICS: ${{ vars.ANALYTICS }} ANALYTICS_DOMAIN: ${{ vars.ANALYTICS_DOMAIN }} + DOCS_BASE: '/multi-scrobbler' run: npm run build working-directory: ./docsite diff --git a/Dockerfile b/Dockerfile index 09294b53..97a3d478 100644 --- a/Dockerfile +++ b/Dockerfile @@ -84,7 +84,7 @@ COPY --chown=abc:abc . /app # need to set before build so server/client build is optimized and has constants (if needed) ENV NODE_ENV=production -RUN npm run build && rm -rf node_modules +RUN npm run docs:install && npm run build && rm -rf node_modules && rm -rf docsite/node_modules FROM base as app @@ -92,6 +92,7 @@ COPY --chown=abc:abc package*.json ./ COPY --chown=abc:abc patches ./patches COPY --from=build --chown=abc:abc /app/dist /app/dist COPY --from=build --chown=abc:abc /app/src /app/src +COPY --from=build --chown=abc:abc /app/docsite /app/docsite COPY --from=base /usr/bin /usr/bin COPY --from=base /usr/lib /usr/lib diff --git a/codeshift/transform.ts b/codeshift/transform.ts deleted file mode 100644 index 3862b143..00000000 --- a/codeshift/transform.ts +++ /dev/null @@ -1,217 +0,0 @@ -import {API, Collection, FileInfo, Options} from 'jscodeshift'; -import path from 'path'; -import fs from 'fs'; - -export type TransformFrom = 'none' | 'any' | string; -export type TransformTo = 'none' | 'any' | string; -export type ImportTypes = 'any' | 'relative' | 'alias'; - -const base = process.cwd(); -export default function transformer( - file: FileInfo, - { jscodeshift: j }: API, - options: Options, -) { - - const tf = options.transformFrom as string | undefined; - if(tf === undefined) { - throw new Error(`arg '--transformFrom' must be defined.`); - } - const transformFrom = tf.split(',').map(x => x.toLocaleLowerCase()) as TransformFrom[]; - const tfIsAny = transformFrom.includes('any'); - - const tt = options.transformTo as string | undefined; - if(tt === undefined) { - throw new Error(`arg '--transformTo' must be defined.`); - } - const transformTo = tt.split(',').map(x => x.toLocaleLowerCase()) as TransformTo[]; - - if(transformTo.length > 1 && transformFrom.length !== transformTo.length) { - throw new Error('When more than one Transform To is specified then number of Transform From arguments must match'); - } - - const itypes = options.importTypes as string | undefined; - if(itypes === undefined) { - throw new Error(`arg '--importTypes' must be defined.`); - } - const importTypes = itypes.split(',').map(x => x.toLocaleLowerCase()) as ImportTypes[]; - const importsIsAny = importTypes.includes('any'); - - const fileDir = path.dirname(path.join(base, file.path)); - const processingFilePath = file.path; - console.log(`Processing => ${processingFilePath}`); - let source: Collection; - try { - source = j(file.source); - } catch (e) { - console.error(`Failed to parse ${processingFilePath}, will skip`); - console.error(e); - } - - const imports = source.find(j.ImportDeclaration) - imports.forEach((x) => { - const importPath = x.value.source.value as string; - const importPathPrefix = `${importPath.padEnd(60, ' ')} =>`; - - const pathInfo = path.parse(importPath); - const hasNoExt = pathInfo.ext === ''; - let filenameFromDir: string; - if(tfIsAny || (hasNoExt && transformFrom.includes('none')) || (transformFrom.includes(pathInfo.ext.replace('.', '').toLocaleLowerCase()))) { - const pathFull = path.join(fileDir, importPath); - const dir = path.dirname(pathFull); - const normalExt = pathInfo.ext.replace('.', ''); - let isRelative: boolean | undefined; - let dirExists: boolean | undefined; - let fileExists: boolean | undefined; - try { - // is dir path real? - fs.realpathSync(dir); - dirExists = true; - } catch (e) { - isRelative = false; - dirExists = false; - } - - if(isRelative === undefined) { - // if extension is none we need to check for any file in dir with this name - if(hasNoExt) { - const dirFiles = fs.readdirSync(dir) - filenameFromDir = dirFiles.find(x => path.parse(x).name === pathInfo.name); - if(filenameFromDir === undefined) { - fileExists = false; - isRelative = false; - } else { - fileExists = true; - isRelative = true; - } - } else { - try { - // does a file exist? - fs.realpathSync(pathFull); - isRelative = true; - } catch (e) { - isRelative = false; - fileExists = false; - } - } - } - - if(!importsIsAny) { - if(!isRelative && !importTypes.includes('alias')) { - console.log(`${importPathPrefix} Import looks like an alias ${dirExists ? '(dir exists, file does not)' : '(dir does not exist)'} but import types does specify alias`); - return; - } else if(isRelative && !importTypes.includes('relative')) { - console.log(`${pathFull} => Import is relative but import types does not specify relative`); - return; - } - } - - // determine transformTo - - // if there is only one TO then use it - let derivedTT: undefined | string = transformTo.length === 1 ? transformTo[0] : undefined; - if(derivedTT === undefined) { - // otherwise we find the TO by using the same index as the matching FROM extension type - const tfIndex = transformFrom.findIndex((x) => { - if(x === 'any') { - return true; - } - if(x === 'none' && hasNoExt) { - return true; - } - if(x === normalExt) { - return true; - } - }); - if(tfIndex === -1) { - console.warn(`${importPathPrefix} did not match a Transform From type. Will not transform`); - return; - } - derivedTT = transformTo[tfIndex]; - } - - let transformPrefix = ` --> ${hasNoExt ? '(None)' : normalExt} TO ${derivedTT} <--`; - - let transformedImport: string; - - switch(derivedTT) { - case 'none': - if(hasNoExt) { - console.log(`${importPathPrefix} ${transformPrefix} => Import already has no extension, nothing to do`); - return; - } - transformedImport = combineDirFile(pathInfo.dir, pathInfo.name); // path.join(pathInfo.root, pathInfo.dir, pathInfo.name); - break; - case 'any': - if(hasNoExt && filenameFromDir) { - transformedImport = filenameFromDir; - } else { - const otherFilename = fs.readdirSync(dir).find(x => { - const pinfo = path.parse(x); - return pinfo.name === pathInfo.name && pinfo.ext !== pathInfo.ext; - }); - if(otherFilename === undefined) { - console.warn(`${importPathPrefix} ${transformPrefix} => Could not find another file in directory that had same name but different extension. Will not transform.`); - return; - } - transformedImport = combineDirFile(pathInfo.dir, otherFilename); // path.join(pathInfo.root, dir, otherFilename); - transformPrefix = `${transformPrefix} (${path.parse(otherFilename).ext})` - } - break; - default: - transformedImport = combineDirFile(pathInfo.dir, `${path.parse(filenameFromDir).name}.${derivedTT}`); // path.join(pathInfo.root, dir, pathInfo.name, `.${derivedTT}`); - break; - } - - console.log(`${importPathPrefix} ${transformPrefix} => Replacing with ${transformedImport}`); - j(x).replaceWith( - j.importDeclaration( - x.node.specifiers, - j.stringLiteral(transformedImport) - ) - ); - - } else { - console.log(`${importPathPrefix} Import did not match transformFrom ('${tf}')`); - return; - } - }); - - /** - * Early exit condition - * ----- - * It is often good practice to exit early and return the original source file - * if it does not contain code relevant to the codemod. - * See this page for more information: - * https://codeshiftcommunity.github.io/CodeshiftCommunity/docs/your-first-codemod#output - */ - // if (/* Some condition here */ true) { - // return file.source; - // } - - /** - * Codemod logic goes here 👇 - * ----- - * This is where the core logic for your codemod will go, - * consider grouping specific actions into 'motions' and running them in sequence - * - * See this page for more information: - * https://codeshiftcommunity.github.io/CodeshiftCommunity/docs/authoring#motions - */ - //source.findVariableDeclarators('foo').renameTo('bar'); - - /** - * Return your modified AST here 👇 - * ----- - * This is where your modified AST will be transformed back into a string - * and written back to the file. - */ - return source.toSource(options.printOptions); -} - -const combineDirFile = (dir: string, file: string) => { - if(dir === '') { - return file; - } - return `${dir}${path.sep}${file}`; -} diff --git a/docsite/docs/installation/installation.md b/docsite/docs/installation/installation.md index 41e6ba59..46c031cd 100644 --- a/docsite/docs/installation/installation.md +++ b/docsite/docs/installation/installation.md @@ -16,6 +16,7 @@ git clone https://github.com/FoxxMD/multi-scrobbler.git . cd multi-scrobbler nvm use # optional, to set correct Node version npm install +npm run docs:install && npm run build npm run start ``` diff --git a/docsite/docusaurus.config.ts b/docsite/docusaurus.config.ts index 09329498..42bd1fd9 100644 --- a/docsite/docusaurus.config.ts +++ b/docsite/docusaurus.config.ts @@ -12,7 +12,7 @@ const config: Config = { url: 'https://foxxmd.github.io', // Set the // pathname under which your site is served // For GitHub pages deployment, it is often '//' - baseUrl: '/multi-scrobbler', + baseUrl: process.env.DOCS_BASE !== undefined && process.env.DOCS_BASE !== '' ? process.env.DOCS_BASE : '/docs', // GitHub pages deployment config. // If you aren't using GitHub pages, you don't need these. @@ -21,7 +21,7 @@ const config: Config = { trailingSlash: false, - onBrokenLinks: 'throw', + onBrokenLinks: 'warn', onBrokenMarkdownLinks: 'warn', // Even if you don't use internalization, you can use this field to set useful @@ -105,6 +105,11 @@ const config: Config = { label: 'GitHub', position: 'right', }, + { + href: 'https://foxxmd.github.io/multi-scrobbler/', + label: 'Website', + position: 'right', + }, ], }, footer: { @@ -119,31 +124,18 @@ const config: Config = { }, { label: 'Installation', - to: '/docs/installation', + to: 'docs/installation', }, { label: 'Configuration', - to: '/docs/configuration', - }, - ], - }, -/* { - title: 'Community', - items: [ - { - label: 'Stack Overflow', - href: 'https://stackoverflow.com/questions/tagged/docusaurus', - }, - { - label: 'Discord', - href: 'https://discordapp.com/invite/docusaurus', + to: 'docs/configuration', }, { - label: 'Twitter', - href: 'https://twitter.com/docusaurus', + label: 'Development', + to: 'docs/development/dev-common', }, ], - },*/ + }, { title: 'More', items: [ @@ -151,6 +143,10 @@ const config: Config = { label: 'GitHub', href: 'https://github.com/foxxmd/multi-scrobbler', }, + { + label: 'Website', + href: 'https://foxxmd.github.io/multi-scrobbler/', + }, ], }, ], @@ -160,6 +156,11 @@ const config: Config = { theme: themes.themes.github, darkTheme: themes.themes.dracula, }, + colorMode: { + defaultMode: 'dark', + disableSwitch: false, + respectPrefersColorScheme: false, + }, } satisfies Preset.ThemeConfig, }; diff --git a/package-lock.json b/package-lock.json index 7b72e889..fead4ad6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -114,14 +114,13 @@ "msw": "^2.1.2", "nodemon": "^3.0.3", "ts-essentials": "^9.1.2", - "typedoc": "^0.25", "typescript": "^5.3.3", "typescript-eslint": "^7.0.1", "typescript-json-schema": "~0.55", "vite": "^5.2.12" }, "engines": { - "node": ">=18.0.0", + "node": ">=18.19.1", "npm": ">=9.1.0" } }, @@ -3012,12 +3011,6 @@ "node": ">=8" } }, - "node_modules/ansi-sequence-parser": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ansi-sequence-parser/-/ansi-sequence-parser-1.1.1.tgz", - "integrity": "sha512-vJXt3yiaUL4UU546s3rPXlsry/RnM730G1+HkpKE012AN0sx1eOrxSu95oKDIonskeLTijMgqWZ3uDEe3NFvyg==", - "dev": true - }, "node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -6445,12 +6438,6 @@ "node": ">=6" } }, - "node_modules/jsonc-parser": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.1.tgz", - "integrity": "sha512-AilxAyFOAcK5wA1+LeaySVBrHsGQvUFCDWXKpZjzaL0PqW+xfBOttn8GNtWKFWqneyMZj41MWF9Kl6iPWLwgOA==", - "dev": true - }, "node_modules/jsonfile": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", @@ -6661,12 +6648,6 @@ "yallist": "^3.0.2" } }, - "node_modules/lunr": { - "version": "2.3.9", - "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz", - "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==", - "dev": true - }, "node_modules/lz-string": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz", @@ -6698,18 +6679,6 @@ "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", "devOptional": true }, - "node_modules/marked": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz", - "integrity": "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==", - "dev": true, - "bin": { - "marked": "bin/marked.js" - }, - "engines": { - "node": ">= 12" - } - }, "node_modules/media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", @@ -9202,18 +9171,6 @@ "node": ">=8" } }, - "node_modules/shiki": { - "version": "0.14.7", - "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.14.7.tgz", - "integrity": "sha512-dNPAPrxSc87ua2sKJ3H5dQ/6ZaY8RNnaAqK+t0eG7p0Soi2ydiqbGOTaZCqaYvA/uZYfS1LJnemt3Q+mSfcPCg==", - "dev": true, - "dependencies": { - "ansi-sequence-parser": "^1.1.0", - "jsonc-parser": "^3.2.0", - "vscode-oniguruma": "^1.7.0", - "vscode-textmate": "^8.0.0" - } - }, "node_modules/side-channel": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", @@ -9968,51 +9925,6 @@ "is-typedarray": "^1.0.0" } }, - "node_modules/typedoc": { - "version": "0.25.13", - "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.25.13.tgz", - "integrity": "sha512-pQqiwiJ+Z4pigfOnnysObszLiU3mVLWAExSPf+Mu06G/qsc3wzbuM56SZQvONhHLncLUhYzOVkjFFpFfL5AzhQ==", - "dev": true, - "dependencies": { - "lunr": "^2.3.9", - "marked": "^4.3.0", - "minimatch": "^9.0.3", - "shiki": "^0.14.7" - }, - "bin": { - "typedoc": "bin/typedoc" - }, - "engines": { - "node": ">= 16" - }, - "peerDependencies": { - "typescript": "4.6.x || 4.7.x || 4.8.x || 4.9.x || 5.0.x || 5.1.x || 5.2.x || 5.3.x || 5.4.x" - } - }, - "node_modules/typedoc/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/typedoc/node_modules/minimatch": { - "version": "9.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", - "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/typescript": { "version": "5.4.5", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", @@ -10379,18 +10291,6 @@ "picocolors": "^1.0.0" } }, - "node_modules/vscode-oniguruma": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/vscode-oniguruma/-/vscode-oniguruma-1.7.0.tgz", - "integrity": "sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA==", - "dev": true - }, - "node_modules/vscode-textmate": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-8.0.0.tgz", - "integrity": "sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg==", - "dev": true - }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", diff --git a/package.json b/package.json index b2a16b30..e19c3cff 100644 --- a/package.json +++ b/package.json @@ -10,16 +10,17 @@ "schema-aio": "typescript-json-schema src/backend/tsconfig.json AIOConfig --out src/backend/common/schema/aio.json --required --titles --tsNodeRegister --refs --validationKeywords deprecationMessage", "schema-aiosource": "typescript-json-schema src/backend/tsconfig.json AIOSourceConfig --out src/backend/common/schema/aio-source.json --titles --required --tsNodeRegister --refs --validationKeywords deprecationMessage", "schema-aioclient": "typescript-json-schema src/backend/tsconfig.json AIOClientConfig --out src/backend/common/schema/aio-client.json --titles --required --tsNodeRegister --refs --validationKeywords deprecationMessage", - "typedoc": "typedoc", "circular": "madge --circular --extensions ts src/index.ts", "test": "npm run -s test:backend", "test:backend": "mocha --reporter spec --recursive src/backend/tests/**/*.test.ts", - "fileEndings": "jscodeshift --transformFrom js --transformTo none --importTypes relative --extensions=ts --parser tsx --transform codeshift/transform.ts src/backend", "dev": "nodemon -w src/backend -x tsx src/backend/index.ts", "start": "NODE_ENV=production tsx src/backend/index.ts", - "build:frontend": "APP_VERSION=$npm_package_version vite build", + "build:frontend": "vite build", "build:backend": "tsc -p src/backend", - "build": "npm run -s build:backend && npm run -s build:frontend", + "build": "npm run -s build:backend && npm run -s build:frontend && npm run -s docs:build", + "docs:install": "cd docsite && npm ci", + "docs:start": "cd docsite && npm start", + "docs:build": "cd docsite && npm run build", "postinstall": "patch-package" }, "exports": { @@ -148,7 +149,6 @@ "msw": "^2.1.2", "nodemon": "^3.0.3", "ts-essentials": "^9.1.2", - "typedoc": "^0.25", "typescript": "^5.3.3", "typescript-eslint": "^7.0.1", "typescript-json-schema": "~0.55", diff --git a/src/backend/server/index.ts b/src/backend/server/index.ts index 822f53aa..90baa9db 100644 --- a/src/backend/server/index.ts +++ b/src/backend/server/index.ts @@ -6,7 +6,9 @@ import express from 'express'; import session from 'express-session'; import { PassThrough } from "node:stream"; import passport from 'passport'; +import path from "path"; import ViteExpress from "vite-express"; +import { projectDir } from "../common/index.js"; import { getRoot } from "../ioc.js"; import { getAddress, parseBool } from "../utils.js"; import { setupApi } from "./api.js"; @@ -72,6 +74,8 @@ export const initServer = async (parentLogger: Logger, appLoggerStream: PassThro } } + app.use('/docs', express.static(path.resolve(projectDir, `./docsite/build`))); + if(process.env.USE_HASH_ROUTER === undefined) { process.env.USE_HASH_ROUTER = root.get('isSubPath'); } diff --git a/src/client/App.tsx b/src/client/App.tsx index b1c449e2..9ef8da7d 100644 --- a/src/client/App.tsx +++ b/src/client/App.tsx @@ -6,6 +6,8 @@ import { } from "react-router-dom"; import {connect, ConnectedProps, Provider} from 'react-redux' import './App.css'; +import CopyToClipboard from "./components/CopyToClipboard"; +import ExternalLink from "./components/ExternalLink"; import {store} from './store'; import Dashboard from "./dashboard/dashboard"; import RecentPage from "./recent/RecentPage"; @@ -16,7 +18,7 @@ import {useEventSource, useEventSourceListener} from "@react-nano/use-event-sour import Version from "./Version"; function NoMatch() { - let location = useLocation(); + const location = useLocation(); return (
@@ -25,22 +27,52 @@ function NoMatch() { ); } +// https://tailwindflex.com/@sienna/copy-code-block +function MissingDocs() { + return ( +
+
Oops! You need to build docs first. Run the following commands to build:
+ + + + $ + + + + + npm run docs:install && npm run docs:build + + + + + + +
+ ); +} + const routes: RouteObject[] = [ { path: "/", - element: , + element: , }, { path: "/recent", - element: , + element: , }, { path: "/scrobbled", - element: , + element: , }, { path: "/dead", - element: , + element: , + }, + { + path: "/docs", + element: }, { path: "*", @@ -93,18 +125,27 @@ function App() {
-
- - -
+
+ + +
); diff --git a/src/client/Version.tsx b/src/client/Version.tsx index 0d3bd125..bc91880d 100644 --- a/src/client/Version.tsx +++ b/src/client/Version.tsx @@ -18,8 +18,8 @@ const Version = () => { data = undefined, } = useGetVersionQuery(undefined); - return - Multi Scrobbler {data === undefined ? null : `${data.version}`} + return + {data === undefined ? null : `${data.version}`} ; } diff --git a/src/client/components/CopyToClipboard.tsx b/src/client/components/CopyToClipboard.tsx new file mode 100644 index 00000000..55519702 --- /dev/null +++ b/src/client/components/CopyToClipboard.tsx @@ -0,0 +1,30 @@ +import clsx from "clsx"; + +export interface Props { + classNames?: string[] + style?: object + text?: string +} + +const defaultStyle = {} +const defaultClassNames: string[] = ['shrink-0', 'h-5', 'w-5', 'transition', 'text-gray-500', 'hover:text-white', 'cursor-pointer']; + +const CopyToClipboard = (props: Props) => { + const {classNames = [], style = defaultStyle, text } = props; + const classes = defaultClassNames; + clsx(classes.concat(classNames)) + return ( + {navigator.clipboard.writeText(text)}} + className={clsx(classes.concat(classNames))} style={style} + xmlns="http://www.w3.org/2000/svg" + viewBox="0 0 20 20" fill="currentColor" aria-hidden="true"> + + + + +) +} + +export default CopyToClipboard; diff --git a/src/client/components/ExternalLink.tsx b/src/client/components/ExternalLink.tsx new file mode 100644 index 00000000..a05e3aee --- /dev/null +++ b/src/client/components/ExternalLink.tsx @@ -0,0 +1,24 @@ +import {PropsWithChildren} from "react"; +import clsx from "clsx"; + +export interface TooltipProps { + classNames?: string[] + style?: object +} + +const defaultStyle = {marginLeft: '2px', display: 'inline-block'}; + +const ExternalLink = (props: PropsWithChildren) => { + const {classNames = [], style = defaultStyle } = props; + const classes = []; + clsx(classes.concat(classNames)) + return ( + + ) +} + +export default ExternalLink; -- 2.51.2 From 8d124a20acda03ab68703f417314a5eeb9e35208 Mon Sep 17 00:00:00 2001 From: FoxxMD Date: Mon, 15 Jul 2024 13:44:07 -0400 Subject: [PATCH 03/16] docs(fix): Update package scripts to use npx to invoke docusarus --- docsite/package.json | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/docsite/package.json b/docsite/package.json index 0d7dd9db..4f2e7b07 100644 --- a/docsite/package.json +++ b/docsite/package.json @@ -3,15 +3,14 @@ "version": "0.0.0", "private": true, "scripts": { - "docusaurus": "docusaurus", - "start": "docusaurus start", - "build": "docusaurus build", - "swizzle": "docusaurus swizzle", - "deploy": "docusaurus deploy", - "clear": "docusaurus clear", - "serve": "docusaurus serve", - "write-translations": "docusaurus write-translations", - "write-heading-ids": "docusaurus write-heading-ids", + "start": "npx docusaurus start", + "build": "npx docusaurus build", + "swizzle": "npx docusaurus swizzle", + "deploy": "npx docusaurus deploy", + "clear": "npx docusaurus clear", + "serve": "npx docusaurus serve", + "write-translations": "npx docusaurus write-translations", + "write-heading-ids": "npx docusaurus write-heading-ids", "typecheck": "tsc" }, "dependencies": { -- 2.51.2 From b2e7f58e14797c753d0680ab2b7621fee20262fe Mon Sep 17 00:00:00 2001 From: FoxxMD Date: Mon, 15 Jul 2024 13:50:37 -0400 Subject: [PATCH 04/16] docs(fix): Add missing docsite build steps to alpine docker variant --- alpine.Dockerfile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/alpine.Dockerfile b/alpine.Dockerfile index 795aeb38..b82f45a5 100644 --- a/alpine.Dockerfile +++ b/alpine.Dockerfile @@ -40,7 +40,7 @@ COPY --chown=abc:abc . /app # need to set before build so server/client build is optimized and has constants (if needed) ENV NODE_ENV=production -RUN npm run build && rm -rf node_modules +RUN npm run docs:install && npm run build && rm -rf node_modules && rm -rf docsite/node_modules FROM base as app @@ -49,6 +49,7 @@ COPY --chown=abc:abc package*.json ./ COPY --chown=abc:abc patches ./patches COPY --from=build --chown=abc:abc /app/dist /app/dist COPY --from=build --chown=abc:abc /app/src /app/src +COPY --from=build --chown=abc:abc /app/docsite /app/docsite COPY --from=base /usr/local/bin /usr/local/bin COPY --from=base /usr/local/lib /usr/local/lib -- 2.51.2 From 815a774e3d4a051703940905d0ca1812f5879c1e Mon Sep 17 00:00:00 2001 From: FoxxMD Date: Mon, 15 Jul 2024 14:24:00 -0400 Subject: [PATCH 05/16] docs(fix): Fix broken links/anchors --- README.md | 2 +- docsite/docs/FAQ.md | 4 ++-- docsite/docs/configuration/configuration.md | 8 +++---- docsite/docs/development/dev-common.md | 23 ++++++++++----------- docsite/docs/installation/service.md | 2 +- docsite/src/pages/index.mdx | 6 +++--- 6 files changed, 22 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index c18faedc..367881a1 100644 --- a/README.md +++ b/README.md @@ -52,7 +52,7 @@ A javascript app to scrobble music you listened to, to [Maloja](https://github.c **But I already scrobble my music to Last.fm/ListenBrainz, is multi-scrobbler for me?** -Yes! You can use [Last.fm as a **Source**](/docsite/docs/configuration/configuration.md#lastfm--source-) or [Listenbrainz as a **Source**](/docsite/docs/configuration/configuration.md#listenbrainz--source-) to forward scrobbles from your profile to any other Client! That way you can keep your current scrobble setup as-is but still get the benefit of capturing your data to a self-hosted location. +Yes! You can use [Last.fm as a **Source**](/docsite/docs/configuration/configuration.md#lastfm-source) or [Listenbrainz as a **Source**](/docsite/docs/configuration/configuration.md#listenbrainz-source) to forward scrobbles from your profile to any other Client! That way you can keep your current scrobble setup as-is but still get the benefit of capturing your data to a self-hosted location. ## How Does multi-scrobbler (MS) Work? diff --git a/docsite/docs/FAQ.md b/docsite/docs/FAQ.md index b30ebb96..339fa177 100644 --- a/docsite/docs/FAQ.md +++ b/docsite/docs/FAQ.md @@ -10,7 +10,7 @@ toc_max_heading_level: 5 * [Connection Issues](#connection-issues) * [Plex/Tautulli/Jellyfin/Webscrobbler don't connect](#plextautullijellyfinwebscrobbler-dont-connect) - * [Troubleshooting](#troubleshooting-) + * [Troubleshooting](#troubleshooting) * [Turn on Debug Logging](#turn-on-debug-logging) * [Check Host name and URL](#check-host-name-and-url) * [Check Firewall and Port Forwarding](#check-firewall-and-port-forwarding) @@ -54,7 +54,7 @@ It also logs if a server tries to connect to a URL that it does not recognize: This is not something multi-scrobbler can fix and means you have an issue in your network. -#### Troubleshooting +#### Troubleshooting Check or try all these steps before submitting an issue: diff --git a/docsite/docs/configuration/configuration.md b/docsite/docs/configuration/configuration.md index de75ab88..e951454c 100644 --- a/docsite/docs/configuration/configuration.md +++ b/docsite/docs/configuration/configuration.md @@ -24,8 +24,8 @@ toc_max_heading_level: 3 * [Tautulli](#tautulli) * [Subsonic](#subsonic) * [Jellyfin](#jellyfin) - * [Last.fm (Source)](#lastfm--source-) - * [Listenbrainz (Source)](#listenbrainz--source-) + * [Last.fm (Source)](#lastfm-source) + * [Listenbrainz (Source)](#listenbrainz-source) * [Deezer](#deezer) * [Youtube Music](#youtube-music) * [MPRIS](#mpris) @@ -34,7 +34,7 @@ toc_max_heading_level: 3 * [Kodi](#kodi) * [WebScrobbler](#webscrobbler) * [Multiple Users](#multiple-users) - * [Google Cast (Chromecast)](#google-cast--chromecast-) + * [Google Cast (Chromecast)](#google-cast-chromecast) * [Connecting Devices](#connecting-devices) * [What Media Does MS Scrobble?](#what-media-does-ms-scrobble) * [Cast Troubleshooting](#cast-troubleshooting) @@ -417,7 +417,7 @@ If you run Linux and have a notification tray that shows what media you are list multi-scrobbler can listen to this interface and scrobble tracks played by **any media player** that communicates to the operating system with MPRIS. -**NOTE:** multi-scrobbler needs to be running as a [**Local Installation**](../installation/installation.md#local) in order to use MPRIS. This cannot be used from docker. +**NOTE:** multi-scrobbler needs to be running as a [**Local Installation**](../installation/installation.md#nodejs) in order to use MPRIS. This cannot be used from docker. #### ENV-Based diff --git a/docsite/docs/development/dev-common.md b/docsite/docs/development/dev-common.md index 23e13eb2..90568c4a 100644 --- a/docsite/docs/development/dev-common.md +++ b/docsite/docs/development/dev-common.md @@ -13,18 +13,17 @@ description: Start here for MS development Table of Contents -* [Development](#development) - * [Architecture](#architecture) - * [Project Setup](#project-setup) - * [Common Development](#common-development) - * [Config](#config) - * [Concrete Class](#concrete-class) - * [Stages](#stages) - * [Stage: Build Data](#stage-build-data) - * [Stage: Check Connection](#stage-check-connection) - * [Stage: Test Auth](#stage-test-auth) - * [Play Object](#play-object) - * [Creating Clients and Sources](#creating-clients-and-sources) +* [Architecture](#architecture) +* [Project Setup](#project-setup) +* [Common Development](#common-development) + * [Config](#config) + * [Concrete Class](#concrete-class) + * [Stages](#stages) + * [Stage: Build Data](#stage-build-data) + * [Stage: Check Connection](#stage-check-connection) + * [Stage: Test Auth](#stage-test-auth) + * [Play Object](#play-object) +* [Creating Clients and Sources](#creating-clients-and-sources) diff --git a/docsite/docs/installation/service.md b/docsite/docs/installation/service.md index 9a2abc4f..40137944 100644 --- a/docsite/docs/installation/service.md +++ b/docsite/docs/installation/service.md @@ -3,7 +3,7 @@ sidebar_position: 2 title: 'As a Service' --- -If you have multi-scrobbler installed [locally](installation.md#local) you can enable it to run as a background service when you login. +If you have multi-scrobbler installed [locally](installation.md#nodejs) you can enable it to run as a background service when you login. Before running as a service you should run it at least once in the foreground to ensure it can start up correctly! diff --git a/docsite/src/pages/index.mdx b/docsite/src/pages/index.mdx index cf9ed2f9..7904d6d0 100644 --- a/docsite/src/pages/index.mdx +++ b/docsite/src/pages/index.mdx @@ -20,13 +20,13 @@ A javascript app to scrobble music you listened to, to [Maloja](https://github.c * [WebScrobbler](docs/configuration#webscrobbler) * [Youtube Music](docs/configuration#youtube-music) * [Last.fm](docs/configuration#lastfm-source) - * [ListenBrainz](docs/configuration#listenbrainz--source-) + * [ListenBrainz](docs/configuration#listenbrainz-source) * [Deezer](docs/configuration#deezer) * [MPRIS (Linux Desktop)](docs/configuration#mpris) * [Mopidy](docs/configuration#mopidy) * [JRiver](docs/configuration#jriver) * [Kodi](docs/configuration#kodi) - * [Google Cast (Chromecast)](/docs/configuration#google-cast--chromecast-) + * [Google Cast (Chromecast)](docs/configuration#google-cast-chromecast) * [Musikcube](docs/configuration#musikcube) * Supports scrobbling to many **Clients** * [Maloja](docs/configuration#maloja) @@ -51,7 +51,7 @@ A javascript app to scrobble music you listened to, to [Maloja](https://github.c **But I already scrobble my music to Last.fm/ListenBrainz, is multi-scrobbler for me?** -Yes! You can use [Last.fm as a **Source**](docs/configuration#lastfm--source-) or [Listenbrainz as a **Source**](docs/configuration#listenbrainz--source-) to forward scrobbles from your profile to any other Client! That way you can keep your current scrobble setup as-is but still get the benefit of capturing your data to a self-hosted location. +Yes! You can use [Last.fm as a **Source**](docs/configuration#lastfm-source) or [Listenbrainz as a **Source**](docs/configuration#listenbrainz-source) to forward scrobbles from your profile to any other Client! That way you can keep your current scrobble setup as-is but still get the benefit of capturing your data to a self-hosted location. ## How Does multi-scrobbler (MS) Work? -- 2.51.2 From 040de4b00074d01be56c6adc85ebbefb0a58090e Mon Sep 17 00:00:00 2001 From: FoxxMD Date: Tue, 16 Jul 2024 11:34:15 -0400 Subject: [PATCH 06/16] docs(flatpak): Implement bash setup script and move flatpak instructions to docsite * setup.sh takes care of building generated sources for project/docsite and building flatpak app * Modify flatpak manifest to include two generated sources files and build docsite files * Update flatpak docs with script usage and generated sources changes, move to docusauraus doc site --- .dockerignore | 2 +- .gitignore | 1 + docsite/docs/development/flatpak.md | 104 ++++++++++++++++++++ flatpak/README.md | 49 +-------- flatpak/io.github.foxxmd.multiscrobbler.yml | 9 +- flatpak/setup.sh | 101 +++++++++++++++++++ 6 files changed, 215 insertions(+), 51 deletions(-) create mode 100644 docsite/docs/development/flatpak.md create mode 100755 flatpak/setup.sh diff --git a/.dockerignore b/.dockerignore index 698f33a6..95c03cbd 100644 --- a/.dockerignore +++ b/.dockerignore @@ -15,7 +15,7 @@ config/*.p8 /docs /logs .flatpak-builder -flatpak/generated-sources.json +**/generated-sources.* flatpak/.flatpak-builder docsite/build docsite/node_modules diff --git a/.gitignore b/.gitignore index 7954a998..ead98818 100644 --- a/.gitignore +++ b/.gitignore @@ -132,3 +132,4 @@ flatpak/generated-sources.json build !setupProxy.js +**/generated-sources.* diff --git a/docsite/docs/development/flatpak.md b/docsite/docs/development/flatpak.md new file mode 100644 index 00000000..7f37a73a --- /dev/null +++ b/docsite/docs/development/flatpak.md @@ -0,0 +1,104 @@ +--- +toc_min_heading_level: 2 +toc_max_heading_level: 5 +sidebar_position: 4 +title: Flatpak +description: Building Flatpak App locally +--- + +:::note + +These steps are for building the flatpak from source. If you want to install the application normally then [get it through flathub](../installation/installation.md#flatpak) + +::: + +The final build repo for the flathub version can be found at [flathub/io.github.foxxmd.multiscrobbler](https://github.com/flathub/io.github.foxxmd.multiscrobbler) + +## Install Requirements + +### Flatpak and flatpak-builder + +Install [Flatpak](https://flatpak.org/setup/) + +Install [flatpak-builder](https://docs.flatpak.org/en/latest/first-build.html#building-your-first-flatpak) + +#### [flatpak-node-generator](https://github.com/flatpak/flatpak-builder-tools/tree/master/node) + +Requires python 3.7+, [pip](https://pip.pypa.io/en/stable/)/[pipx](https://pypa.github.io/pipx/) + +## Update Project source + +Set the `branch` `tag` or `commit` to use for MS in the `source` section of [`io.github.foxxmd.multiscrobbler.yml`](https://github.com/FoxxMD/multi-scrobbler/blob/master/flatpak/io.github.foxxmd.multiscrobbler.yml) + +## Generate Sources and Build + +### Use Setup Script + +A convenience bash script is provided that automates generating offline sources and building the flatpak app for you. This is the recommend method to use. + +Located in the project at [`flatpak/setup.sh`](https://github.com/FoxxMD/multi-scrobbler/blob/master/flatpak/setup.sh), run it from the `flatpak` directory with this syntax: + +```shell +./setup.sh -o -b /path/to/flatpak/build/dir +``` + +``` +Args: + +-o => Delete and overwrite any existing generated sources +-b => The absolute path to the directory that should be used for flatpak build/artifacts. If not defined will use `CWD/build` +-y => Proceed without confirming settings +``` + +### Manual Setup + +If you cannot use `setup.sh` follow the below to manually generate sources and build the flatpak app: + +
+ +Instructions + +#### Use `flatpak-node-generator` to generate sources + +First, [make sure `node_modules` is deleted or empty](https://github.com/flatpak/flatpak-builder-tools/issues/354#issuecomment-1478518442) for both the project and `docsite` directories. + +Then, from MS project root: + +```shell title="PROJECT_DIR" +flatpak-node-generator npm package-lock.json +``` + +Move `generated-sources.json` into `PROJECT_DIR/flatpak` and rename `generated-sources.0.json` + +Then, generate `docsite` sources: + +```shell title="PROJECT_DIR" +flatpak-node-generator npm docsite/package-lock.json +``` + +Move `generated-sources.json` into `PROJECT_DIR/flatpak` and rename `generated-sources.1.json` + +#### Build flatpak + +In the below command replace `/home/yourUser/multi-scrobbler-flatpak` with a directory to use for storing flatpak build/artifacts. + +```shell title="PROJECT_DIR/flatpak" +flatpak-builder --repo=/home/yourUser/multi-scrobbler-flatpak/repo --state-dir=/home/yourUser/multi-scrobbler-flatpak/state /home/yourUser/multi-scrobbler-flatpak/build io.github.foxxmd.multiscrobbler.yml --force-clean +``` + +:::info + +Append `--install --user` to the above command to have the app installed immediately. + +:::: + +
+ + +# Run App + +If built with `--install --user` (default when using `setup.sh`) you can now run MS using the command + +```shell +flatpak run -u io.github.foxxmd.multiscrobbler +``` diff --git a/flatpak/README.md b/flatpak/README.md index b22923b9..99c42ab1 100644 --- a/flatpak/README.md +++ b/flatpak/README.md @@ -1,48 +1 @@ -NOTE: This steps are for building the flatpak entirely locally, from source. If you want to install the application normally then [get it through flathub](/docs/installation.md#flatpak) - -The final build repo for the flathub version can be found at [flathub/io.github.foxxmd.multiscrobbler](https://github.com/flathub/io.github.foxxmd.multiscrobbler) - -# 1. Install Requirements - -## Flatpak and flatpak-builder - -Install [Flatpak](https://flatpak.org/setup/) - -Install [flatpak-builder](https://docs.flatpak.org/en/latest/first-build.html#building-your-first-flatpak) - -## [flatpak-node-generator](https://github.com/flatpak/flatpak-builder-tools/tree/master/node) - -Requires python 3.7+, [pip](https://pip.pypa.io/en/stable/)/[pipx](https://pypa.github.io/pipx/) - -# 2. Update Project source - -Set the `branch` `tag` or `commit` to use for MS in the `git` source in [`io.github.foxxmd.multiscrobbler.yml`](/flatpak/io.github.foxxmd.multiscrobbler.yml) - -# 3. Use `flatpak-node-generator` to generate sources - -First, [make sure `node_modules` is deleted or empty.](https://github.com/flatpak/flatpak-builder-tools/issues/354#issuecomment-1478518442) - -Then, from MS project root: - -```shell -flatpak-node-generator npm package-lock.json -``` - -Move `generated-sources.json` into [`/flatpak`](/flatpak) - -# 4. Build flatpak - -From MS project root: - -```shell -cd flatpak -flatpak-builder --repo=/home/yourUser/multi-scrobbler-flatpak/repo --state-dir=/home/yourUser/multi-scrobbler-flatpak/state /home/yourUser/multi-scrobbler-flatpak/build io.github.foxxmd.multiscrobbler.yml --force-clean --install --user -``` -Add `--install --user` to have the app installed immediately. -# 5. Run (Locally) - -If built with `--install --user` you can now run MS using the command - -```shell -flatpak run -u io.github.foxxmd.multiscrobbler -``` +See flatpak docs on the [docs website](https://foxxmd.github.io/multi-scrobbler/docs/development/dev-client) or at [`/docsite/docs/development/flatpak.md`](../docsite/docs/development/flatpak.md) diff --git a/flatpak/io.github.foxxmd.multiscrobbler.yml b/flatpak/io.github.foxxmd.multiscrobbler.yml index a3fe0585..2e442be9 100644 --- a/flatpak/io.github.foxxmd.multiscrobbler.yml +++ b/flatpak/io.github.foxxmd.multiscrobbler.yml @@ -21,7 +21,8 @@ modules: npm_config_offline: 'true' build-commands: # install npm dependencies - - npm install --offline + - npm ci --offline + - cd docsite && npm ci --offline && cd ../ # build app - NODE_ENV=production npm run build @@ -34,6 +35,8 @@ modules: # remove dev dependencies - npm prune --production + # remove docsite dependencies since we've built static site + - rm -r docsite/node_modules # copy node_modules needed to run app - cp -r node_modules/. /app/lib/node_modules @@ -45,6 +48,7 @@ modules: # copy app files to runtime dir - cp -r dist/. /app/lib/dist - cp -r src/. /app/lib/src + - cp -r docsite/. /app/lib/docsite - cp -r config /app/lib/config - cp -r assets /app/lib/assets - cp -r public /app/lib/public @@ -89,4 +93,5 @@ modules: fi - cd /app/lib && CONFIG_DIR=$XDG_CONFIG_HOME LOG_DIR=$XDG_CONFIG_HOME IS_LOCAL=true NODE_ENV=production node_modules/.bin/tsx src/backend/index.ts - - generated-sources.json + - generated-sources.0.json + - generated-sources.1.json diff --git a/flatpak/setup.sh b/flatpak/setup.sh new file mode 100755 index 00000000..e01021af --- /dev/null +++ b/flatpak/setup.sh @@ -0,0 +1,101 @@ +#!/bin/bash + +OVERWRITE="0" +CONFIRM="1" +# https://stackoverflow.com/a/14203146 +POSITIONAL_ARGS=() + +while [[ $# -gt 0 ]]; do + case $1 in + -b|--buildpath) + BUILDPATH="$2" + shift # past argument + shift # past value + ;; + -o|--overwrite) + OVERWRITE="1" + shift # past argument + ;; + -y|--yes) + CONFIRM="0" + shift # past argument + ;; + -*|--*) + echo "Unknown option $1" + exit 1 + ;; + *) + POSITIONAL_ARGS+=("$1") # save positional arg + shift # past argument + ;; + esac +done + +set -- "${POSITIONAL_ARGS[@]}" + +if [ ! -f "./io.github.foxxmd.multiscrobbler.yml" ]; then + echo "Run this script inside the 'flatpak' directory!" + exit 1 +fi + +if [ -z "${BUILDPATH}" ]; then + printf "\nNo build path set, using ./build\n" + BUILDPATH="${PWD##*/}/build" +fi + +printf '\nBuild Path: %s' "${BUILDPATH}" +if [ "$OVERWRITE" = "1" ]; then echo 'Overwrite Sources: True'; else printf 'Overwrite Sources: False\n'; fi + +if [ "$CONFIRM" = "1" ]; then + read -p "Continue? (Y/N): " confirm && [[ $confirm == [yY] || $confirm == [yY][eE][sS] ]] || exit 1 +fi + +printf '\n' + +cd ../ + +if [ -d ./node_modules ]; then + echo 'Project node_modules exists, deleting...' + rm -r node_modules +fi + +if [ -d ./docsite/node_modules ]; then + echo 'Docsite node_modules exists, deleting...' + rm -r docsite/node_modules +fi + +GENERATE_SOURCES="1" + +if [ -f "flatpak/generated-sources.0.json" ] || [ -f "flatpak/generated-sources.1.json" ]; then + if [ "$OVERWRITE" = "0" ]; then + echo 'Generated sources exist, will not overwrite.'; + GENERATE_SOURCES=0 + else + echo 'Deleting existing sources...'; + rm -f flatpak/generated-sources.0.json + rm -f flatpak/generated-sources.1.json + fi +fi + +if [ "$GENERATE_SOURCES" = "1" ]; then + printf '\nGenerating project sources...\n' + rm -f generated-sources.json + flatpak-node-generator npm package-lock.json + mv generated-sources.json flatpak/generated-sources.0.json + + printf '\nGenerating docsite sources...\n' + flatpak-node-generator npm docsite/package-lock.json + mv generated-sources.json flatpak/generated-sources.1.json +fi + +cd flatpak || exit + +mkdir -p "$BUILDPATH" + +printf '\nBuilding flatpak app...\n' +set -x +flatpak-builder --repo="$BUILDPATH"/repo --state-dir="$BUILDPATH"/state "$BUILDPATH"/build io.github.foxxmd.multiscrobbler.yml --force-clean --install --user +# https://stackoverflow.com/questions/2853803/how-to-echo-shell-commands-as-they-are-executed#comment135696350_13718771 +{ set +x; } &> /dev/null + +echo 'Done!' -- 2.51.2 From d56c5720ebe545da71866bbbe7cee3e5902f769f Mon Sep 17 00:00:00 2001 From: FoxxMD Date: Tue, 16 Jul 2024 11:46:13 -0400 Subject: [PATCH 07/16] docs(flatpak): Fix typo in docs website link --- flatpak/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flatpak/README.md b/flatpak/README.md index 99c42ab1..087a5279 100644 --- a/flatpak/README.md +++ b/flatpak/README.md @@ -1 +1 @@ -See flatpak docs on the [docs website](https://foxxmd.github.io/multi-scrobbler/docs/development/dev-client) or at [`/docsite/docs/development/flatpak.md`](../docsite/docs/development/flatpak.md) +See flatpak docs on the [docs website](https://foxxmd.github.io/multi-scrobbler/docs/development/flatpak) or at [`/docsite/docs/development/flatpak.md`](../docsite/docs/development/flatpak.md) -- 2.51.2 From ab54422acfa3aceb59ca61e68bcd20c3b6e73ab1 Mon Sep 17 00:00:00 2001 From: FoxxMD Date: Tue, 16 Jul 2024 11:58:09 -0400 Subject: [PATCH 08/16] docs: Replace manual notes with admonitions --- docsite/docs/configuration/configuration.md | 76 +++++++++++++++++---- docsite/docs/installation/installation.md | 6 +- 2 files changed, 67 insertions(+), 15 deletions(-) diff --git a/docsite/docs/configuration/configuration.md b/docsite/docs/configuration/configuration.md index e951454c..ae693054 100644 --- a/docsite/docs/configuration/configuration.md +++ b/docsite/docs/configuration/configuration.md @@ -216,7 +216,13 @@ Useful when running with [docker](../installation/installation.md#docker) so tha #### Disable Web -If you do not need the dashboard and/or ingress sources, or have security concerns about ingress and cannot control their hosting environment, the web server and API can be disabled. Note that any **ingress-based sources will be unusable** (Plex, Jellyfin, Tautulli, etc...) if this is disabled. +If you do not need the dashboard and/or ingress sources, or have security concerns about ingress and cannot control their hosting environment, the web server and API can be disabled. + +:::warning + +Any **ingress-based sources will be unusable** (Plex, Jellyfin, Tautulli, etc...) if this is disabled. + +:::: Disable using either: @@ -230,7 +236,11 @@ Disable using either: To access your Spotify history you must [register an application](https://developer.spotify.com/dashboard) to get a Client ID/Secret. Make sure to also whitelist your redirect URI in the application settings. -**NOTE:** If your Spotify player has [Automix](https://community.spotify.com/t5/FAQs/What-is-Automix/ta-p/5257278) enabled and Spotify uses it for your playlist/queue then MS cannot accurately determine when a track will end. This is because the track is "mixed" in your queue with a shorter play time than its actual length and [Spotify does not report this modified play time in its API.](https://community.spotify.com/t5/Spotify-for-Developers/Wrong-duration-ms-of-track-with-Automix/m-p/5429147) This **does not affect MS's ability to scrobble** from Spotify but it will affect the accuracy of the duration MS reports was played. +:::note + +If your Spotify player has [Automix](https://community.spotify.com/t5/FAQs/What-is-Automix/ta-p/5257278) enabled and Spotify uses it for your playlist/queue then MS cannot accurately determine when a track will end. This is because the track is "mixed" in your queue with a shorter play time than its actual length and [Spotify does not report this modified play time in its API.](https://community.spotify.com/t5/Spotify-for-Developers/Wrong-duration-ms-of-track-with-Automix/m-p/5429147) This **does not affect MS's ability to scrobble** from Spotify but it will affect the accuracy of the duration MS reports was played. + +:::: #### ENV-Based @@ -312,8 +322,12 @@ Must be using Jellyfin 10.7 or greater * Check `Send All Properties` * Save +:::note + If you see errors in the MS logs regarding `missing headers` when using Jellyfin [see this workaround.](../FAQ.md#jellyfin-has-warnings-about-missing-headers) +:::: + #### ENV-Based | Environmental Variable | Required? | Default | Description | @@ -343,7 +357,11 @@ You will need to run your own Listenbrainz server or have an account [on the off On your [profile page](https://listenbrainz.org/profile/) find your **User Token** to use in the configuration. -**NOTE:** You cannot use ENV variables shown in the [Listenbrainz Client config](#listenbrainz) -- multi-scrobbler assumes Listenbrainz ENVs are always used for the **client** configuration. You must use the file-based config from below to setup Listenbrainz as a Source. +:::note + +You cannot use ENV variables shown in the [Listenbrainz Client config](#listenbrainz) -- multi-scrobbler assumes Listenbrainz ENVs are always used for the **client** configuration. You must use the file-based config from below to setup Listenbrainz as a Source. + +:::: #### File-Based @@ -383,6 +401,13 @@ See [`deezer.json.example`](https://github.com/FoxxMD/multi-scrobbler/blob/maste ### [Youtube Music](https://music.youtube.com) +:::note + +* YT Music authentication is "browser based" which means your credentials may expire after a (long?) period of time OR if you log out of https://music.youtube.com. In the event this happens just repeat the steps below to get new credentials. +* Communication to YT Music is **unofficial** and not supported or endorsed by Google. This means that **this integration may stop working at any time** if Google decides to change how YT Music works in the browser. + +:::: + Credentials for YT Music are obtained from a browser request to https://music.youtube.com **once you are logged in.** [Specific requirements are here and summarized below:](https://github.com/nickp10/youtube-music-ts-api/blob/master/DOCUMENTATION.md#authenticate) * Open a new tab @@ -398,10 +423,6 @@ Then... ![Google Headers](google-header.jpg) -NOTES: - -* YT Music authentication is "browser based" which means your credentials may expire after a (long?) period of time OR if you log out of https://music.youtube.com. In the event this happens just repeat the steps above to get new credentials. -* Communication to YT Music is **unofficial** and not supported or endorsed by Google. This means that **this integration may stop working at any time** if Google decides to change how YT Music works in the browser. #### File-Based @@ -417,7 +438,11 @@ If you run Linux and have a notification tray that shows what media you are list multi-scrobbler can listen to this interface and scrobble tracks played by **any media player** that communicates to the operating system with MPRIS. -**NOTE:** multi-scrobbler needs to be running as a [**Local Installation**](../installation/installation.md#nodejs) in order to use MPRIS. This cannot be used from docker. +:::note + +multi-scrobbler needs to be running as a [**Local Installation**](../installation/installation.md#nodejs) in order to use MPRIS. This cannot be used from docker. + +:::: #### ENV-Based @@ -715,11 +740,21 @@ In `webscrobbler.json` * To use `aUserWS` source set **API URL** to `http://localhost:9078/api/webscrobbler/usera` * To use `bUserWS` source set **API URL** to `http://localhost:9078/api/webscrobbler/userb` -Note: `http://localhost:9078/api/webscrobbler` is matched with the first source that _that does not have a slug defined._ +:::note + +`http://localhost:9078/api/webscrobbler` is matched with the first source that _that does not have a slug defined._ + +:::: ###### Connectors Black/Whitelist -MS can be configured to only scrobble, or NOT scrobble, from some WS connectors. Use the name of the website from the [supported websites](https://web-scrobbler.com/) or from the **Connectors** tab in the extension. Note that this **only** affects MS's behavior and does not affect the general connector behavior you have configured within the WebScrobbler extension. +MS can be configured to only scrobble, or NOT scrobble, from some WS connectors. Use the name of the website from the [supported websites](https://web-scrobbler.com/) or from the **Connectors** tab in the extension. + +:::note + +This affects **only** MS's behavior and does not affect the general connector behavior you have configured within the WebScrobbler extension. + +:::: #### ENV-Based @@ -735,11 +770,20 @@ See [`webscrobbler.json.example`](https://github.com/FoxxMD/multi-scrobbler/blob ### [Google Cast (Chromecast)](https://www.google.com/chromecast/built-in/) -**NOTE:** Google Cast support is **experimental**. You may experience crashes and errors while using this Source. Please open an issue if you experience problems and include all information detailed in the issue template to help debug your issue. - If your media device can be **Cast** to using this button ![Chromecast Icon](https://upload.wikimedia.org/wikipedia/commons/2/26/Chromecast_cast_button_icon.svg) on your phone/computer then multi-scrobbler can monitor it in order to scrobble music you play. -**Note:** This source relies on common, **basic** music data provided by the cast device which will always be less exhaustive than data parsed from full source integrations. If there is an existing [Source](#source-configurations) it is recommended to configure for it and blacklist the app on Google Cast, rather than relying solely on Google Cast for scrobbling. + +:::note + +Google Cast support is **experimental**. You may experience crashes and errors while using this Source. Please open an issue if you experience problems and include all information detailed in the issue template to help debug your issue. + +:::: + +:::note + +This source relies on common, **basic** music data provided by the cast device which will always be less exhaustive than data parsed from full source integrations. If there is an existing [Source](#source-configurations) it is recommended to configure for it and blacklist the app on Google Cast, rather than relying solely on Google Cast for scrobbling. + +:::: #### Connecting Devices @@ -840,7 +884,11 @@ To diagnose bad/incomplete track information or strange MS player behavior pleas #### ENV-Based -Note: [Manually configuring cast device connections](#connecting-devices) is only available through [File-based config.](#file-based-14) +:::note + +[Manually configuring cast device connections](#connecting-devices) is only available through [File-based config.](#file-based-14) + +:::: | Environmental Variable | Required? | Default | Description | |------------------------|-----------|---------|--------------------------------------------------------------------------------------| diff --git a/docsite/docs/installation/installation.md b/docsite/docs/installation/installation.md index 46c031cd..bb097714 100644 --- a/docsite/docs/installation/installation.md +++ b/docsite/docs/installation/installation.md @@ -63,11 +63,15 @@ You must have [Flatpak](https://flatpak.org/) installed on your system. flatpak install flathub io.github.foxxmd.multiscrobbler ``` -**Note:** Flatpak users have experienced issues when using multi-scrobbler as a long-running process. Due to the relative difficulty in debugging issues with flatpak installations it is recommended: +:::warning + +Flatpak users have experienced issues when using multi-scrobbler as a long-running process. Due to the relative difficulty in debugging issues with flatpak installations it is recommended: * to use a [Docker](#docker) installation if possible or * only if you need access to host-level resources like dbus for [MPRIS](https://foxxmd.github.io/multi-scrobbler/docs/configuration#mpris) and cannot run a [nodejs](#nodejs) installation +:::: + ### Usage Examples #### Using [file-based](../configuration/configuration.md#file-based-configuration) configuration -- 2.51.2 From ee399136a9f0bb335ca17ad64034d3feca6ff6c8 Mon Sep 17 00:00:00 2001 From: FoxxMD Date: Tue, 16 Jul 2024 14:09:28 -0400 Subject: [PATCH 09/16] docs: Lean 100% into docusaurus documentation Since docs are now generated alongside builds and hosted on the app server there is no longer a barrier to using docusaurus docs as the main documentation presentation. Any user looking for docs can use the GH Pages hosted site or a "versioned" docs site hosted on their MS app. Due to this we can fully commit to docusaurus and take advantage of MDX layouts to simplify docs. * Replace env/file configs headings in configuration with MDX tabs to make reading easier * Remove superfluous TOCs * Replace internal links in repo readme with links to docsite --- .github/workflows/publishImage.yml | 3 +- README.md | 50 +- config/README.md | 2 +- docsite/docs/FAQ.md | 42 +- docsite/docs/configuration/configuration.md | 1113 ---------------- docsite/docs/configuration/configuration.mdx | 1208 ++++++++++++++++++ docsite/docs/development/dev-common.md | 20 - docsite/docs/development/dev-source.md | 28 - docsite/docs/installation/installation.md | 16 +- 9 files changed, 1249 insertions(+), 1233 deletions(-) delete mode 100644 docsite/docs/configuration/configuration.md create mode 100644 docsite/docs/configuration/configuration.mdx diff --git a/.github/workflows/publishImage.yml b/.github/workflows/publishImage.yml index 11e8d3ea..1bc5d156 100644 --- a/.github/workflows/publishImage.yml +++ b/.github/workflows/publishImage.yml @@ -10,9 +10,8 @@ on: - '*.*.*' # don't trigger if just updating docs paths-ignore: - - '**.md' + - 'README.md' - '.github/**' - - 'docsite/**' - 'flatpak/**' # use release instead of tags once version is correctly parsed # https://github.com/docker/metadata-action/issues/422 diff --git a/README.md b/README.md index 367881a1..db651089 100644 --- a/README.md +++ b/README.md @@ -12,32 +12,32 @@ alt="multi-scrobbler logo" width="180" height="180"> A javascript app to scrobble music you listened to, to [Maloja](https://github.com/krateng/maloja), [Last.fm](https://www.last.fm), and [ListenBrainz](https://listenbrainz.org) * Supports scrobbling from many **Sources** - * [Spotify](/docsite/docs/configuration/configuration.md#spotify) - * [Plex](/docsite/docs/configuration/configuration.md#plex) or [Tautulli](/docsite/docs/configuration/configuration.md#tautulli) - * [Subsonic-compatible APIs](/docsite/docs/configuration/configuration.md#subsonic) (like [Airsonic](https://airsonic.github.io/) and [Navidrome](https://www.navidrome.org/)) - * [Jellyfin](/docsite/docs/configuration/configuration.md#jellyfin) - * [WebScrobbler](/docsite/docs/configuration/configuration.md#webscrobbler) - * [Youtube Music](/docsite/docs/configuration/configuration.md#youtube-music) - * [Last.fm](/docsite/docs/configuration/configuration.md#lastfm-source) - * [ListenBrainz](/docsite/docs/configuration/configuration.md#listenbrainz--source-) - * [Deezer](/docsite/docs/configuration/configuration.md#deezer) - * [MPRIS (Linux Desktop)](/docsite/docs/configuration/configuration.md#mpris) - * [Mopidy](/docsite/docs/configuration/configuration.md#mopidy) - * [JRiver](/docsite/docs/configuration/configuration.md#jriver) - * [Kodi](/docsite/docs/configuration/configuration.md#kodi) - * [Google Cast (Chromecast)](/docsite/docs/configuration/configuration.md#google-cast--chromecast-) - * [Musikcube](/docsite/docs/configuration/configuration.md#muikcube) + * [Spotify](https://foxxmd.github.io/multi-scrobbler/docs/configuration#spotify) + * [Plex](https://foxxmd.github.io/multi-scrobbler/docs/configuration#plex) or [Tautulli](https://foxxmd.github.io/multi-scrobbler/docs/configuration#tautulli) + * [Subsonic-compatible APIs](https://foxxmd.github.io/multi-scrobbler/docs/configuration#subsonic) (like [Airsonic](https://airsonic.github.io/) and [Navidrome](https://www.navidrome.org/)) + * [Jellyfin](https://foxxmd.github.io/multi-scrobbler/docs/configuration#jellyfin) + * [WebScrobbler](https://foxxmd.github.io/multi-scrobbler/docs/configuration#webscrobbler) + * [Youtube Music](https://foxxmd.github.io/multi-scrobbler/docs/configuration#youtube-music) + * [Last.fm](https://foxxmd.github.io/multi-scrobbler/docs/configuration#lastfm-source) + * [ListenBrainz](https://foxxmd.github.io/multi-scrobbler/docs/configuration#listenbrainz-source) + * [Deezer](https://foxxmd.github.io/multi-scrobbler/docs/configuration#deezer) + * [MPRIS (Linux Desktop)](https://foxxmd.github.io/multi-scrobbler/docs/configuration#mpris) + * [Mopidy](https://foxxmd.github.io/multi-scrobbler/docs/configuration#mopidy) + * [JRiver](https://foxxmd.github.io/multi-scrobbler/docs/configuration#jriver) + * [Kodi](https://foxxmd.github.io/multi-scrobbler/docs/configuration#kodi) + * [Google Cast (Chromecast)](https://foxxmd.github.io/multi-scrobbler/docs/configuration#google-cast-chromecast) + * [Musikcube](https://foxxmd.github.io/multi-scrobbler/docs/configuration#muikcube) * Supports scrobbling to many **Clients** - * [Maloja](/docsite/docs/configuration/configuration.md#maloja) - * [Last.fm](/docsite/docs/configuration/configuration.md#lastfm) - * [ListenBrainz](/docsite/docs/configuration/configuration.md#listenbrainz) -* Monitor status of Sources and Clients using [webhooks (Gotify, Ntfy, Apprise)](/docsite/docs/configuration/configuration.md#webhook-configurations) or [healthcheck endpoint](/docsite/docs/configuration/configuration.md#health-endpoint) + * [Maloja](https://foxxmd.github.io/multi-scrobbler/docs/configuration#maloja) + * [Last.fm](https://foxxmd.github.io/multi-scrobbler/docs/configuration#lastfm) + * [ListenBrainz](https://foxxmd.github.io/multi-scrobbler/docs/configuration#listenbrainz) +* Monitor status of Sources and Clients using [webhooks (Gotify, Ntfy, Apprise)](https://foxxmd.github.io/multi-scrobbler/docs/configuration#webhook-configurations) or [healthcheck endpoint](https://foxxmd.github.io/multi-scrobbler/docs/configuration#health-endpoint) * Supports configuring for single or multiple users (scrobbling for your friends and family!) * Web server interface for stats, basic control, and detailed logs * Graceful network and client failure handling (queued scrobbles that auto-retry) * Smart handling of credentials (persistent, authorization through app) * Easy configuration through ENVs or JSON -* Install using [Docker images for x86/ARM](/docsite/docs/installation/installation.md#docker), [flatpak](/docsite/docs/installation/installation.md#flatpak), or [locally with NodeJS](/docsite/docs/installation/installation.md#nodejs) +* Install using [Docker images for x86/ARM](https://foxxmd.github.io/multi-scrobbler/docs/installation#docker#docker), [flatpak](https://foxxmd.github.io/multi-scrobbler/docs/installation#docker#flatpak), or [locally with NodeJS](https://foxxmd.github.io/multi-scrobbler/docs/installation#docker#nodejs) [**Read The Docs to get started**](https://foxxmd.github.io/multi-scrobbler/docs/installation) @@ -52,7 +52,7 @@ A javascript app to scrobble music you listened to, to [Maloja](https://github.c **But I already scrobble my music to Last.fm/ListenBrainz, is multi-scrobbler for me?** -Yes! You can use [Last.fm as a **Source**](/docsite/docs/configuration/configuration.md#lastfm-source) or [Listenbrainz as a **Source**](/docsite/docs/configuration/configuration.md#listenbrainz-source) to forward scrobbles from your profile to any other Client! That way you can keep your current scrobble setup as-is but still get the benefit of capturing your data to a self-hosted location. +Yes! You can use [Last.fm as a **Source**](https://foxxmd.github.io/multi-scrobbler/docs/configuration#lastfm-source) or [Listenbrainz as a **Source**](https://foxxmd.github.io/multi-scrobbler/docs/configuration#listenbrainz-source) to forward scrobbles from your profile to any other Client! That way you can keep your current scrobble setup as-is but still get the benefit of capturing your data to a self-hosted location. ## How Does multi-scrobbler (MS) Work? @@ -79,11 +79,11 @@ Client configurations consist of: ## Installation -[See the **Installation** documentation](/docsite/docs/installation/installation.md) +[See the **Installation** documentation](https://foxxmd.github.io/multi-scrobbler/docs/installation) ## Configuration -[See the **Configuration** documentation](/docsite/docs/configuration/configuration.md) +[See the **Configuration** documentation](https://foxxmd.github.io/multi-scrobbler/docs/configuration) ## Usage @@ -98,11 +98,11 @@ On first startup you may need to authorize Spotify and/or Last.fm by visiting th ## Help/FAQ -Having issues with connections or configuration? Check the [FAQ](/docsite/docs/FAQ.md) before creating an issue! +Having issues with connections or configuration? Check the [FAQ](https://foxxmd.github.io/multi-scrobbler/docs/FAQ) before creating an issue! ## Development -[Detailed architecture and development guides for Sources/Clients](/docsite/docs/development/dev-common.md) +[Detailed architecture and development guides for Sources/Clients](https://foxxmd.github.io/multi-scrobbler/docs/development/dev-common) ## License diff --git a/config/README.md b/config/README.md index 66c9c584..4b14e9c2 100644 --- a/config/README.md +++ b/config/README.md @@ -8,5 +8,5 @@ These are **NOT** exhaustive examples. You should consult the **configuration** Documentation at -* [internal docs](../docsite/docs/configuration/configuration.md) +* [internal docs](../docsite/docs/configuration/configuration.mdx) * External Link: https://foxxmd.github.io/multi-scrobbler/docs/configuration diff --git a/docsite/docs/FAQ.md b/docsite/docs/FAQ.md index 339fa177..9114799c 100644 --- a/docsite/docs/FAQ.md +++ b/docsite/docs/FAQ.md @@ -3,36 +3,6 @@ toc_min_heading_level: 2 toc_max_heading_level: 5 --- -
- -Table of Contents - - - * [Connection Issues](#connection-issues) - * [Plex/Tautulli/Jellyfin/Webscrobbler don't connect](#plextautullijellyfinwebscrobbler-dont-connect) - * [Troubleshooting](#troubleshooting) - * [Turn on Debug Logging](#turn-on-debug-logging) - * [Check Host name and URL](#check-host-name-and-url) - * [Check Firewall and Port Forwarding](#check-firewall-and-port-forwarding) - * [Check Source Service Logs](#check-source-service-logs) - * [Plex](#plex) - * [Tautulli](#tautulli) - * [Jellyfin](#jellyfin) - * [Webscrobbler](#webscrobbler) - * [Jellyfin has warnings about undefined or missing data](#jellyfin-has-warnings-about-undefined-or-missing-data) - * [Jellyfin has warnings about missing headers](#jellyfin-has-warnings-about-missing-headers) - * [Spotify/Deezer/LastFM won't authenticate](#spotifydeezerlastfm-wont-authenticate) - * [Configuration Issues](#configuration-issues) - * [Config could not be parsed](#config-could-not-be-parsed) - * [Scrobbling Issues](#scrobbling-issues) - * [Last.fm does not scrobble tracks with multiple artists correctly](#lastfm-does-not-scrobble-tracks-with-multiple-artists-correctly) - * [Jellyfin does not scrobble tracks with multiple artists correctly](#jellyfin-does-not-scrobble-tracks-with-multiple-artists-correctly) - * [Google Cast track information is missing/incorrect or MS player has weird times](#google-cast-track-information-is-missingincorrect-or-ms-player-has-weird-times) - * [Google Cast device does not track media](#google-cast-device-does-not-track-media) - - -
- ## Connection Issues ### Plex/Tautulli/Jellyfin/Webscrobbler don't connect @@ -69,7 +39,7 @@ Check the output for any additional information. ##### Check Host name and URL -The URLs examples in the [configuration](configuration/configuration.md) documentation assume you are running Plex/Tautulli/Jellyfin/Webscrobbler on the same server as multi-scrobbler. If these are not the same machine then you need to determine the IP address or domain name that multi-scrobbler is reachable at and use that instead of `localhost` when configuring these sources. **This is likely the same host name that you would use to access the web interface for multi-scrobbler.** +The URLs examples in the [configuration](configuration/configuration.mdx) documentation assume you are running Plex/Tautulli/Jellyfin/Webscrobbler on the same server as multi-scrobbler. If these are not the same machine then you need to determine the IP address or domain name that multi-scrobbler is reachable at and use that instead of `localhost` when configuring these sources. **This is likely the same host name that you would use to access the web interface for multi-scrobbler.** EX `http://localhost:9078/plex` -> `http://192.168.0.140:9078/plex` @@ -100,7 +70,7 @@ See [Debugging the extension](https://github.com/web-scrobbler/web-scrobbler/wik ### Jellyfin has warnings about undefined or missing data Make sure you have -* [Configured the webhook plugin correctly](configuration/configuration.md#jellyfin) +* [Configured the webhook plugin correctly](configuration/configuration.mdx#jellyfin) * Checked the **Send All Properties(ignores template)** option in the webhook settings and **Saved** multi-scrobbler is known to work on Jellyfin `10.8.9` with Webhook version `11.0.0.0`. @@ -135,7 +105,7 @@ If you experience issues trying to scrobble with Jellyfin and find this in your A workaround that may fix this: * In Webhook settings: - * [In the webhook you have already configured...](configuration/configuration.md#jellyfin) + * [In the webhook you have already configured...](configuration/configuration.mdx#jellyfin) * Add Request Header... * **Key:** `Content-Type` * **Value:** `application/json` @@ -184,7 +154,7 @@ This is a limitation caused by the [Jellyfin webhook plugin](https://github.com/ The Google Cast integration relies on a few common fields in the data it receives from your casting device. Every platform that can cast (Spotify, Pandora, etc...) *should* use these fields the same but there are slight differences between their implementations that may confuse multi-scrobbler. Specific platforms may also return more information in non-common fields that are undocumented. -To diagnose these issues you [**must enable payload logging**](configuration/configuration.md#cast-troubleshooting) for your google cast Source, run MS, and then include logs with this output from that run. Without the raw data logged from your cast device it will be nearly impossible to resolve your issue. +To diagnose these issues you [**must enable payload logging**](configuration/configuration.mdx#cast-troubleshooting) for your google cast Source, run MS, and then include logs with this output from that run. Without the raw data logged from your cast device it will be nearly impossible to resolve your issue. ### Google Cast device does not track media @@ -196,10 +166,10 @@ MS logs will tell you what type the media is reported as with lines like: My Artist - Example Track has 'unknown' media type and allowUnknownMedia=false, will not track ``` -Refer to [Allow Unknown Media Type](configuration/configuration.md#allow-unknown-media-type) section to fix this +Refer to [Allow Unknown Media Type](configuration/configuration.mdx#allow-unknown-media-type) section to fix this ``` My Artist - Example Track has 'movie' media type so will not track ``` -Refer to [Force Media Tracking](configuration/configuration.md#forcing-media-tracking) section to fix this +Refer to [Force Media Tracking](configuration/configuration.mdx#forcing-media-tracking) section to fix this diff --git a/docsite/docs/configuration/configuration.md b/docsite/docs/configuration/configuration.md deleted file mode 100644 index ae693054..00000000 --- a/docsite/docs/configuration/configuration.md +++ /dev/null @@ -1,1113 +0,0 @@ ---- -sidebar_position: 2 -title: Overview -toc_max_heading_level: 3 ---- - -# Configuration - -
- -Table of Contents - - -* [Overview](#overview) - * [ENV-Based Configuration](#env-based-configuration) - * [File-Based Configuration](#file-based-configuration) - * [All-in-One File Configuration](#all-in-one-file-configuration) - * [Specific File Configuration](#specific-file-configuration) -* [Application Options](#application-options) - * [Base URL](#base-url) -* [Source Configurations](#source-configurations) - * [Spotify](#spotify) - * [Plex](#plex) - * [Tautulli](#tautulli) - * [Subsonic](#subsonic) - * [Jellyfin](#jellyfin) - * [Last.fm (Source)](#lastfm-source) - * [Listenbrainz (Source)](#listenbrainz-source) - * [Deezer](#deezer) - * [Youtube Music](#youtube-music) - * [MPRIS](#mpris) - * [Mopidy](#mopidy) - * [JRiver](#jriver) - * [Kodi](#kodi) - * [WebScrobbler](#webscrobbler) - * [Multiple Users](#multiple-users) - * [Google Cast (Chromecast)](#google-cast-chromecast) - * [Connecting Devices](#connecting-devices) - * [What Media Does MS Scrobble?](#what-media-does-ms-scrobble) - * [Cast Troubleshooting](#cast-troubleshooting) - * [Musikcube](#musikcube) -* [Client Configurations](#client-configurations) - * [Maloja](#maloja) - * [Last.fm](#lastfm) - * [Listenbrainz](#listenbrainz) -* [Monitoring](#monitoring) - * [Webhook Configurations](#webhook-configurations) - * [Gotify](#gotify) - * [Ntfy](#ntfy) - * [Health Endpoint](#health-endpoint) - - -
- -## Overview - -[**Sources** and **Clients**](/#how-does-multi-scrobbler-ms-work) are configured using environmental (ENV) variables and/or json files. - -**MS will parse configuration from both configuration types.** You can mix and match configurations but it is generally better to stick to one or the other. - -TIP: Check the [**FAQ**](../FAQ.md) if you have any issues after configuration! - -### ENV-Based Configuration - -This is done by passing environmental variables and so does not require any files to run MS. - -* Using a docker container EX `docker run -e "SPOTIFY_CLIENT_ID=yourId" -e "SPOTIFY_CLIENT_SECRET=yourSecret" ...` -* Using a local installations by exporting variables before running MS EX `SPOTIFY_CLIENT_ID=yourId SPOTIFY_CLIENT_SECRET=yourSecret node index.js` - -Use ENV-based configuration if: - -* You are the only person for whom MS is scrobbling for -* You have a very simple setup for MS such as one scrobble [Client](/#client) and one [Source](/#source) IE Plex -> Maloja - -### File-Based Configuration - -MS will parse configuration files located in the directory specified by the `CONFIG_DIR` environmental variable. This variable defaults to: - -* Local installation -> `PROJECT_DIR/config` -* Docker -> `/config` (in the container) -- see the [install docs](../installation/installation.md#docker) for how to configure this correctly - -Use File-based configuration if: - -* You have many [Sources](/#source) -* You have many of each type of **Source** you want to scrobble from IE 2x Plex accounts, 3x Spotify accounts, 1x - Funkwhale... -* You have more than one scrobble **Client** you want to scrobble to IE multiple Maloja servers -* You want only some **Sources** to scrobble to some **Clients** IE Fred's Spotify account scrobbles to Fred's Maloja - server, but not Mary's Maloja server - -File-based configurations located in the `CONFIG_DIR` directory can be parsed from - -* an **all-in-one** config file named `config.json` that contains information for all Sources and Clients and/or -* many **specific** files named based on the client/source to configure IE `plex.json` `spotify.json` - -There are **example configurations** for all Source/Client types and AIO config located in the [/config](https://github.com/FoxxMD/multi-scrobbler/tree/master/config) directory of this project. These can be used as-is by renaming them to `.json`. -For docker installations these examples are copied to your configuration directory on first-time use. - -There is also a [**kitchensink example**](kitchensink.md) that provides examples of using all sources/clients in a complex configuration. - -#### All-in-One File 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) - -Example directory structure: - -``` -/CONFIG_DIR - config.json -``` - -
-Config Example - -```json5 title="config.json" -{ - //... - "sources": [ - { - "name": "myConfig", - "type": "spotify", - "clients": [ - "myMalojaClient" - ], - "data": { - "clientId": "anExample" - //... - } - } - ], - "clients": [ - { - "name": "myFirstMalojaClient", - "type": "maloja", - "data": { - "url": "http://myMalojaServer.example", - // ... - } - } - ] -} -``` - -
- -`config.json` can also be used to set default behavior for all sources/clients using `sourceDefaults` and `clientDefaults` properties. - -See [config.json.example](https://github.com/FoxxMD/multi-scrobbler/blob/master/config/config.json.example) for an annotated example or check out [the kitchen sink example](kitchensink.md). - -#### Specific File Configuration - -Each file is named by the **type** of the Client/Source found in below sections. Each file as an **array** of that type of Client/Source. - -Example directory structure: - -``` -/CONFIG_DIR - plex.json - spotify.json - maloja.json -``` - -
-Config Example - -```json5 -// in maloja.json -[ - { - "name": "myFirstMalojaClient", - "data": { - "url": "http://myMalojaServer.example", - "apiKey": "myKey" - } - }, - { - "name": "mySecondMalojaClient", - "data": { - "url": "http://my2ndMalojaServer.example", - "apiKey": "myKey" - } - } -] - -``` - -
- -See the [/config](https://github.com/FoxxMD/multi-scrobbler/blob/master/config) directory of this project for examples of each type of config file or reference specific files below. - -## Application Options - -These options affect multi-scrobbler's behavior and are not specific to any source/client. - -#### Base URL - -Defines the URL that is used to generate default redirect URLs for authentication on [spotify](#spotify), [lastfm](#lastfm), and [deezer](#deezer) -- as well as some logging hints. - -* Default => `http://localhost:9078` -* Set with [ENV](#env-based-configuration) `BASE_URL` or `baseUrl` [all-in-one configuration](#all-in-one-file-configuration) -* If protocol is `http` or no protocol is specified MS will try to use port `9078` -- to override this explicitly set the port or use `https` - -EX Lastfm Redirect Url is `BASE_URL:PORT/lastfm/callback` (when no other redirectUri is specified for [lastfm configuration](#lastfm)) - -* `BASE_URL=192.168.0.101` => Redirect URL is `http://192.168.0.101:9078/lastfm/callback` -* `BASE_URL=http://my.domain.local` => Redirect URL is `http://my.domain.local:9078/lastfm/callback` -* `BASE_URL=http://192.168.0.101/my/subfolder` => Redirect URL is `http://192.168.0.101:9078/my/subfolder/lastfm/callback` - -* `BASE_URL=my.domain.local:80` => Redirect URL is `http://my.domain.local:80/lastfm/callback` -* `BASE_URL=my.domain.local:9000` => Redirect URL is `http://my.domain.local:9000/lastfm/callback` -* `BASE_URL=192.168.0.101:4000/my/subfolder` => Redirect URL is `http://192.168.0.101:4000/my/subfolder/lastfm/callback` -* `BASE_URL=https://192.168.0.101` => Redirect URL is `https://192.168.0.101:443/lastfm/callback` - - -Useful when running with [docker](../installation/installation.md#docker) so that you do not need to specify redirect URLs for each configuration. - -#### Disable Web - -If you do not need the dashboard and/or ingress sources, or have security concerns about ingress and cannot control their hosting environment, the web server and API can be disabled. - -:::warning - -Any **ingress-based sources will be unusable** (Plex, Jellyfin, Tautulli, etc...) if this is disabled. - -:::: - -Disable using either: - -* ENV `DISABLE_WEB=true` -* In [All-in-One File](#all-in-one-file-configuration) use the top-level property `"disableWeb": true` - -## Source Configurations - -### [Spotify](https://www.spotify.com) - -To access your Spotify history you must [register an application](https://developer.spotify.com/dashboard) to get a -Client ID/Secret. Make sure to also whitelist your redirect URI in the application settings. - -:::note - -If your Spotify player has [Automix](https://community.spotify.com/t5/FAQs/What-is-Automix/ta-p/5257278) enabled and Spotify uses it for your playlist/queue then MS cannot accurately determine when a track will end. This is because the track is "mixed" in your queue with a shorter play time than its actual length and [Spotify does not report this modified play time in its API.](https://community.spotify.com/t5/Spotify-for-Developers/Wrong-duration-ms-of-track-with-Automix/m-p/5429147) This **does not affect MS's ability to scrobble** from Spotify but it will affect the accuracy of the duration MS reports was played. - -:::: - -#### ENV-Based - -| Environmental Variable | Required? | Default | Description | -|----------------------------|-----------|----------------------------------|----------------------------------------------------| -| `SPOTIFY_CLIENT_ID` | Yes | | | -| `SPOTIFY_CLIENT_SECRET` | Yes | | | -| `SPOTIFY_REDIRECT_URI` | No | `http://localhost:9078/callback` | URI must end in `callback` | - -#### File-Based - -See [`spotify.json.example`](https://github.com/FoxxMD/multi-scrobbler/blob/master/config/spotify.json.example) or [explore the schema with an example and live editor/validator](https://json-schema.app/view/%23/%23%2Fdefinitions%2FSpotifySourceConfig?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fmulti-scrobbler%2Fmaster%2Fsrc%2Fbackend%2Fcommon%2Fschema%2Fsource.json) - -### [Plex](https://plex.tv) - -Check the [instructions](plex.md) on how to setup a [webhooks](https://support.plex.tv/articles/115002267687-webhooks) to scrobble your plays. - -#### ENV-Based - -| Environmental Variable | Required | Default | Description | -|------------------------|----------|---------|-------------------------------------------------| -| `PLEX_USER` | No | | The a comma-delimited list of usernames to scrobble tracks for. No usernames specified means all tracks by all users will be scrobbled. | - -#### File-Based - -See [`plex.json.example`](https://github.com/FoxxMD/multi-scrobbler/blob/master/config/plex.json.example) or [explore the schema with an example and live editor/validator](https://json-schema.app/view/%23/%23%2Fdefinitions%2FPlexSourceConfig?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fmulti-scrobbler%2Fmaster%2Fsrc%2Fbackend%2Fcommon%2Fschema%2Fsource.json) - -### [Tautulli](https://tautulli.com) - -Check the [instructions](plex.md) on how to setup a notification agent. - -#### ENV-Based - -| Environmental Variable | Required | Default | Description | -|------------------------|----------|---------|-------------------------------------------------| -| `TAUTULLI_USER` | No | | The a comma-delimited list of usernames to scrobble tracks for. No usernames specified means all tracks by all users will be scrobbled. | - -####File-Based - -See [`tautulli.json.example`](https://github.com/FoxxMD/multi-scrobbler/blob/master/config/tautulli.json.example) or [explore the schema with an example and live editor/validator](https://json-schema.app/view/%23/%23%2Fdefinitions%2FTautulliSourceConfig?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fmulti-scrobbler%2Fmaster%2Fsrc%2Fbackend%2Fcommon%2Fschema%2Fsource.json) - -### [Subsonic](http://www.subsonic.org/) - -Can use this source 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/)) - -**Known Issues:** -* "Time played at" is somewhat inaccurate since the api only reports "played X minutes ago" so... - * All scrobble times are therefore "on the minute" and you may experience occasional duplicate scrobbles - * "played X minutes ago" sometimes is also not reported correctly -* Multiple artists are reported as one value and cannot be separated -* If using [Airsonic Advanced](https://github.com/airsonic-advanced/airsonic-advanced) the password used (under **Credentials**) must be **Decodable** - -#### ENV-Based - -| Environmental Variable | Required? | Default | Description | -|----------------------------|-----------|----------------------------------|----------------------------------------------------| -| `SUBSONIC_USER` | Yes | | | -| `SUBSONIC_PASSWORD` | Yes | | | -| `SUBSONIC_URL` | Yes | | Base url of your subsonic-api server | - -#### File-Based - -See [`subsonic.json.example`](https://github.com/FoxxMD/multi-scrobbler/blob/master/config/subsonic.json.example) or [explore the schema with an example and live editor/validator](https://json-schema.app/view/%23/%23%2Fdefinitions%2FSubSonicSourceConfig?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fmulti-scrobbler%2Fmaster%2Fsrc%2Fbackend%2Fcommon%2Fschema%2Fsource.json) - -### [Jellyfin](https://jellyfin.org/) - -Must be using Jellyfin 10.7 or greater - -* In the Jellyfin desktop web UI Navigate to -> Administration -> Dashboard -> Plugins -> Catalog - * Under Notifications -> **Webhook** -> Install, then restart your server -* Navigate back to -> Administration -> Dashboard -> Plugins -> My Plugins -> Webhook - * Click "..." -> Settings -* In Webhook settings: - * `Add Generic Destination` - * In the new `Generic` dropdown: - * Webhook Url: `http://localhost:9078/jellyfin` - * Notification Type: `Playback Progress` - * Item Type: `Songs` - * Check `Send All Properties` - * Save - -:::note - -If you see errors in the MS logs regarding `missing headers` when using Jellyfin [see this workaround.](../FAQ.md#jellyfin-has-warnings-about-missing-headers) - -:::: - -#### ENV-Based - -| Environmental Variable | Required? | Default | Description | -|------------------------|-----------|---------|-------------------------------------------------------------------| -| `JELLYFIN_USER` | | | Comma-separated list of usernames (from Jellyfin) to scrobble for | -| `JELLYFIN_SERVER` | | | Comma-separated list of Jellyfin server names to scrobble from | - -#### File-Based - -See [`jellyfin.json.example`](https://github.com/FoxxMD/multi-scrobbler/blob/master/config/jellyfin.json.example) or [explore the schema with an example and live editor/validator](https://json-schema.app/view/%23/%23%2Fdefinitions%2FJellySourceConfig?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fmulti-scrobbler%2Fmaster%2Fsrc%2Fbackend%2Fcommon%2Fschema%2Fsource.json) - -### [Last.fm (Source)](https://www.last.fm) - -See the [Last.fm (Client)](#lastfm) setup for registration instructions. - -#### ENV-Based - -No support for ENV based for Last.fm as a client (only source) - -#### File-Based - -See [`lastfm.json.example`](https://github.com/FoxxMD/multi-scrobbler/blob/master/config/lastfm.json.example), change `configureAs` to `source`. Or [explore the schema with an example and live editor/validator](https://json-schema.app/view/%23/%23%2Fdefinitions%2FLastfmSourceConfig?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fmulti-scrobbler%2Fmaster%2Fsrc%2Fbackend%2Fcommon%2Fschema%2Fsource.json) - -### [Listenbrainz (Source)](https://listenbrainz.org) - -You will need to run your own Listenbrainz server or have an account [on the official instance](https://listenbrainz.org/login/) - -On your [profile page](https://listenbrainz.org/profile/) find your **User Token** to use in the configuration. - -:::note - -You cannot use ENV variables shown in the [Listenbrainz Client config](#listenbrainz) -- multi-scrobbler assumes Listenbrainz ENVs are always used for the **client** configuration. You must use the file-based config from below to setup Listenbrainz as a Source. - -:::: - -#### File-Based - -See [`listenbrainz.json.example`](https://github.com/FoxxMD/multi-scrobbler/blob/master/config/listenbrainz.json.example) or [explore the schema with an example and live editor/validator](https://json-schema.app/view/%23%2Fdefinitions%2FListenBrainzSourceConfig?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fmulti-scrobbler%2Fmaster%2Fsrc%2Fbackend%2Fcommon%2Fschema%2Fsource.json) - -**Change `configureAs` to `source`** - -### [Deezer](https://deezer.com/) - -Create a new application at [Deezer Developers](https://developers.deezer.com/myapps) - -* Application Domain must be the same as your multi-scrobbler domain. Default is `localhost:9078` -* Redirect URL must end in `deezer/callback` - * Default would be `http://localhost:9078/deezer/callback` - -After application creation you should have credentials displayed in the "My Apps" dashboard. You will need: - -* **Application ID** -* **Secret Key** -* **Redirect URL** (if not the default) - -**If no access token is provided...** - -After starting multi-scrobbler with credentials in-place open the dashboard (`http://localhost:9078`) and find your Deezer source. Click **(Re)authenticate and (re)start polling** to start the login process. After login is complete polling will begin automatically. - -#### ENV-Based - -| Environmental Variable | Required? | Default | Description | -|----------------------------|-----------|-----------------------------------------|----------------------------------------------------| -| `DEEZER_CLIENT_ID` | Yes | | Your **Application ID** | -| `DEEZER_CLIENT_SECRET` | Yes | | Your **Secret Key** | -| `DEEZER_REDIRECT_URI` | No | `http://localhost:9078/deezer/callback` | URI must end in `deezer/callback` | - -#### File-Based - -See [`deezer.json.example`](https://github.com/FoxxMD/multi-scrobbler/blob/master/config/deezer.json.example) or [explore the schema with an example and live editor/validator](https://json-schema.app/view/%23/%23%2Fdefinitions%2FDeezerSourceConfig?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fmulti-scrobbler%2Fmaster%2Fsrc%2Fbackend%2Fcommon%2Fschema%2Fsource.json) - -### [Youtube Music](https://music.youtube.com) - -:::note - -* YT Music authentication is "browser based" which means your credentials may expire after a (long?) period of time OR if you log out of https://music.youtube.com. In the event this happens just repeat the steps below to get new credentials. -* Communication to YT Music is **unofficial** and not supported or endorsed by Google. This means that **this integration may stop working at any time** if Google decides to change how YT Music works in the browser. - -:::: - -Credentials for YT Music are obtained from a browser request to https://music.youtube.com **once you are logged in.** [Specific requirements are here and summarized below:](https://github.com/nickp10/youtube-music-ts-api/blob/master/DOCUMENTATION.md#authenticate) - -* Open a new tab -* Open the developer tools (Ctrl-Shift-I) and select the “Network” tab -* Go to https://music.youtube.com and ensure you are logged in - -Then... - -1. Find and select an authenticated POST request. The simplest way is to filter by /browse using the search bar of the developer tools. If you don’t see the request, try scrolling down a bit or clicking on the library button in the top bar. -2. **Make sure **Headers** pane is selected and open -3. In the **Request Headers** section find and copy the **entire value** found after `Cookie:` and use this as the `cookie` value in your multi-scrobbler config -4. If present, in the **Request Headers** section find and copy the number found in `X-google-AuthUser` and use this as the value for `authUser` in your multi-scrobbler config - -![Google Headers](google-header.jpg) - - -#### File-Based - -See [`ytmusic.json.example`](https://github.com/FoxxMD/multi-scrobbler/blob/master/config/ytmusic.json.example) or [explore the schema with an example and live editor/validator](https://json-schema.app/view/%23/%23%2Fdefinitions%2FYTMusicSourceConfig?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fmulti-scrobbler%2Fmaster%2Fsrc%2Fbackend%2Fcommon%2Fschema%2Fsource.json) - -### [MPRIS](https://specifications.freedesktop.org/mpris-spec/latest/) - -MPRIS is a standard interface for communicating with Music Players on **linux operating systems.** - -If you run Linux and have a notification tray that shows what media you are listening to, you likely have access to MPRIS. - -![Notification Tray](mpris.jpg) - -multi-scrobbler can listen to this interface and scrobble tracks played by **any media player** that communicates to the operating system with MPRIS. - -:::note - -multi-scrobbler needs to be running as a [**Local Installation**](../installation/installation.md#nodejs) in order to use MPRIS. This cannot be used from docker. - -:::: - -#### ENV-Based - -| Environmental Variable | Required? | Default | Description | -|------------------------|-----------|---------|----------------------------------------------------------------------------------| -| 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 | - -#### File-Based - -See [`mpris.json.example`](https://github.com/FoxxMD/multi-scrobbler/blob/master/config/mpris.json.example) or [explore the schema with an example and live editor/validator](https://json-schema.app/view/%23%2Fdefinitions%2FMPRISSourceConfig?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fmulti-scrobbler%2Fmaster%2Fsrc%2Fbackend%2Fcommon%2Fschema%2Fsource.json) - -### [Mopidy](https://mopidy.com/) - -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/) - -multi-scrobbler can scrobble tracks played from any Mopidy backend source, regardless of where you listen to them. - -#### File-Based - -See [`mopidy.json.example`](https://github.com/FoxxMD/multi-scrobbler/blob/master/config/mopidy.json.example) or [explore the schema with an example and live editor/validator](https://json-schema.app/view/%23%2Fdefinitions%2FMopidySourceConfig/%23%2Fdefinitions%2FMopidyData?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fmulti-scrobbler%2Fmaster%2Fsrc%2Fbackend%2Fcommon%2Fschema%2Fsource.json) - -Configuration Options: - -###### `url` - -The URL used to connect to the Mopidy server. You MUST have [Mopidy-HTTP extension](https://mopidy.com/ext/http) enabled. - -If no `url` is provided a default is used which assumes Mopidy is installed on the same server as multi-scrobbler: `ws://localhost:6680/mopidy/ws/` - -Make sure the hostname and port number match what is found in the Mopidy configuration file `mopidy.conf`: - -``` -... - -[http] -hostname = localhost -port = 6680 - -... -``` - -The URL used to connect ultimately must be formed like this: `[protocol]://[hostname]:[port]/[path]` -If any part of this URL is missing multi-scrobbler will use a default value, for your convenience. This also means that if any part of your URL is **not** standard you must explicitly define it. - -Part => Default Value - -* Protocol => `ws://` -* Hostname => `localhost` -* Port => `6680` -* Path => `/mopidy/ws/` - -
-URL Transform Examples - -```json -{ - "url": "mopidy.mydomain.com" -} -``` - -MS transforms this to: `ws://mopidy.mydomain.com:6680/mopidy/ws/` - -```json -{ - "url": "192.168.0.101:3456" -} -``` - -MS transforms this to: `ws://192.168.0.101:3456/mopidy/ws/` - -```json -{ - "url": "mopidy.mydomain.com:80/MOPWS" -} -``` - -MS transforms this to: `ws://mopidy.mydomain.com:80/MOPWS` - -
- - -##### URI Blacklist/Whitelist - -If you wish to disallow or only allow scrobbling from some sources played through Mopidy you can specify these using `uriBlacklist` or `uriWhitelist` in your config. multi-scrobbler will check the list to see if any string matches the START of the `uri` on a track. If whitelist is used then blacklist is ignored. All strings are case-insensitive. - -EX: - -```json -{ - "uriBlacklist": ["soundcloud"] -} -``` - -Will prevent multi-scrobbler from scrobbling any Mopidy track that start with a `uri` like `soundcloud:song:MySong-1234` - -##### Album Blacklist - -For certain sources (Soundcloud) Mopidy does not have all track info (Album) and will instead use "Soundcloud" as the Album name. You can prevent multi-scrobbler from using this bad Album data by adding the fake Album name to this list. Multi-scrobbler will still scrobble the track, just without the bad data. All strings are case-insensitive. - -EX: - -```json -{ - "albumBlacklist": ["SoundCloud", "Mixcloud"] -} -``` - -If a track would be scrobbled like `Album: Soundcloud, Track: My Cool Track, Artist: A Cool Artist` -then multi-scrobbler will instead scrobble `Track: My Cool Track, Artist: A Cool Artist` - -### [JRiver](https://jriver.com/) - -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 can be in the JRiver GUI: - -* Tools -> Options -> Media Network - * Check `Use Media Network to share this library...` - * If you have `Authentication` checked you will need to provide the **Username** and **Password** in the ENV/File configuration below. - -##### URL - -If you do not provide a URL then a default is used which assumes JRiver is installed on the same server as multi-scrobbler: `http://localhost:52199/MCWS/v1/` - -* Make sure the port number matches what is found in `Advanced` section in the [Media Network](#jriver) options. -* If your installation is on the same machine but you cannot connect using `localhost` try `0.0.0.0` instead. - -The URL used to connect ultimately must be formed like this: `[protocol]://[hostname]:[port]/[path]` -If any part of this URL is missing multi-scrobbler will use a default value, for your convenience. This also means that if any part of your URL is **not** standard you must explicitly define it. - -Part => Default Value - -* Protocol => `http://` -* Hostname => `localhost` -* Port => `52199` -* Path => `/MCWS/v1/` - -
-URL Transform Examples - -```json -{ - "url": "jriver.mydomain.com" -} -``` - -MS transforms this to: `http://jriver.mydomain.com:52199/MCWS/v1/` - -```json -{ - "url": "192.168.0.101:3456" -} -``` - -MS transforms this to: `http://192.168.0.101:3456/MCWS/v1/` - -```json -{ - "url": "mydomain.com:80/jriverReverse/MCWS/v1/" -} -``` - -MS transforms this to: `http://mydomain.com:80/jriverReverse/MCWS/v1/` - -
- -#### ENV-Based - - -| Environmental Variable | Required | Default | Description | -|------------------------|----------|---------------------------------|------------------------------------------------| -| 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 | - - -#### File-Based - -See [`jriver.json.example`](https://github.com/FoxxMD/multi-scrobbler/blob/master/config/jriver.json.example) or [explore the schema with an example and live editor/validator](https://json-schema.app/view/%23%2Fdefinitions%2FJRiverSourceConfig/%23%2Fdefinitions%2FJRiverData?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fmulti-scrobbler%2Fmaster%2Fsrc%2Fbackend%2Fcommon%2Fschema%2Fsource.json) - -### [Kodi](https://kodi.tv/) - -In order for multi-scrobbler to communicate with Kodi you must have the [Web Interface](https://kodi.wiki/view/Web_interface) enabled. This can can be in the Kodi GUI: - -* Settings -> Services -> Control - * Check `Allow remote control via HTTP` - * Ensure you have a **Username** and **Password** set, you will need to provide them in the ENV/File configuration below. - -##### URL - -If you do not provide a URL then a default is used which assumes Kodi is installed on the same server as multi-scrobbler: `http://localhost:8080/jsonrpc` - -* Make sure the port number matches what is found in **Port** in the [Control](#kodi) section mentioned above. -* If your installation is on the same machine but you cannot connect using `localhost` try `0.0.0.0` instead. - -The URL used to connect ultimately must be formed like this: `[protocol]://[hostname]:[port]/[path]` -If any part of this URL is missing multi-scrobbler will use a default value, for your convenience. This also means that if any part of your URL is **not** standard you must explicitly define it. - -Part => Default Value - -* Protocol => `http://` -* Hostname => `localhost` -* Port => `8080` -* Path => `/jsonrpc` - -
-URL Transform Examples - -```json -{ - "url": "kodi.mydomain.com" -} -``` - -MS transforms this to: `http://kodi.mydomain.com:8080/jsonrpc` - -```json -{ - "url": "192.168.0.101:3456" -} -``` - -MS transforms this to: `http://192.168.0.101:3456/jsonprc` - -```json -{ - "url": "mydomain.com:80/kodiReverse/jsonrpc" -} -``` - -MS transforms this to: `http://mydomain.com:80/kodiReverse/jsonrpc` - -
- -#### ENV-Based - - -| Environmental Variable | Required | Default | Description | -|------------------------|----------|-------------------------------|----------------------------| -| 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 | - - -#### File-Based - -See [`kodi.json.example`](https://github.com/FoxxMD/multi-scrobbler/blob/master/config/kodi.json.example) or [explore the schema with an example and live editor/validator](https://json-schema.app/view/%23%2Fdefinitions%2FKodiSourceConfig/%23%2Fdefinitions%2FKodiData?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fmulti-scrobbler%2Fmaster%2Fsrc%2Fbackend%2Fcommon%2Fschema%2Fsource.json) - -### [WebScrobbler](https://web-scrobbler.com/) - -After installing the extension open the preferences/settings for it: - -* Under **Accounts** - * **Add Webhook** - * API URL: `http://localhost:9078/api/webscrobbler` - * Application name: `(whatever you want)` - -Reload the extension after adding the webhook. - -* **On Firefox** - Only FQNs (domain.tld), `localhost`, and `127.0.0.1` are supported for API URL due to [firefox requiring https](https://github.com/web-scrobbler/web-scrobbler/issues/4183#issuecomment-1749222006) -* **On Chromium-based Browsers** - Any domain will work for API URL -* All Other browsers are untested - -##### Multiple Users - -If you would like use multiple WebScrobbler sources they can be matched using a **slug** at the end of the **API URL.** This requires using [a file-based config.](#file-based-configuration) - -Example: - -In `webscrobbler.json` - -```json -[ - { - "name": "aUserWS", - "clients": [ - "client1Maloja" - ], - "data": { - "slug": "usera" - } - }, - { - "name": "bUserWS", - "clients": [ - "client2Maloja" - ], - "data": { - "slug": "userb" - } - } -] -``` - -* To use `aUserWS` source set **API URL** to `http://localhost:9078/api/webscrobbler/usera` -* To use `bUserWS` source set **API URL** to `http://localhost:9078/api/webscrobbler/userb` - -:::note - -`http://localhost:9078/api/webscrobbler` is matched with the first source that _that does not have a slug defined._ - -:::: - -###### Connectors Black/Whitelist - -MS can be configured to only scrobble, or NOT scrobble, from some WS connectors. Use the name of the website from the [supported websites](https://web-scrobbler.com/) or from the **Connectors** tab in the extension. - -:::note - -This affects **only** MS's behavior and does not affect the general connector behavior you have configured within the WebScrobbler extension. - -:::: - -#### ENV-Based - -| Environmental Variable | Required? | Default | Description | -|------------------------|-----------|---------|--------------------------------------------------------------------------| -| 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 | - -#### File-Based - -See [`webscrobbler.json.example`](https://github.com/FoxxMD/multi-scrobbler/blob/master/config/webscrobbler.json.example) or [explore the schema with an example and live editor/validator](https://json-schema.app/view/%23%2Fdefinitions%2FWebScrobblerSourceConfig/%23%2Fdefinitions%2FWebScrobblerData?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fmulti-scrobbler%2Fmaster%2Fsrc%2Fbackend%2Fcommon%2Fschema%2Fsource.json) - -### [Google Cast (Chromecast)](https://www.google.com/chromecast/built-in/) - -If your media device can be **Cast** to using this button ![Chromecast Icon](https://upload.wikimedia.org/wikipedia/commons/2/26/Chromecast_cast_button_icon.svg) on your phone/computer then multi-scrobbler can monitor it in order to scrobble music you play. - - -:::note - -Google Cast support is **experimental**. You may experience crashes and errors while using this Source. Please open an issue if you experience problems and include all information detailed in the issue template to help debug your issue. - -:::: - -:::note - -This source relies on common, **basic** music data provided by the cast device which will always be less exhaustive than data parsed from full source integrations. If there is an existing [Source](#source-configurations) it is recommended to configure for it and blacklist the app on Google Cast, rather than relying solely on Google Cast for scrobbling. - -:::: - -#### Connecting Devices - -Cast devices can be manually configured using [File-based configuration](#file-based-14) OR automatically discovered using **mDNS.** - -###### mDNS Discovery - -The host machine running multi-scrobbler must be configured to allow [mDNS traffic on port 5353/UDP](https://book.hacktricks.xyz/network-services-pentesting/5353-udp-multicast-dns-mdns). - -###### Linux - -**Docker** - -The host machine must have [avahi-daemon](https://avahi.org/) running to circumvent limitations with DNS resolution due to musl in Alpine. Most major linux distributions package avahi and many have it built-in. Once avahi is running you must pass D-Bus and the avahi daemon socket to your container like so: - -``` -docker run ... -v /var/run/dbus:/var/run/dbus -v /var/run/avahi-daemon/socket:/var/run/avahi-daemon/socket ... foxxmd/multi-scrobbler -``` - -**Flatpak/Nodejs** - -No additional steps are required. - -###### Windows - -**Docker** - -Unsupported at this time. - -**Nodejs** - -No additional steps are required. - -#### What Media Does MS Scrobble? - -Cast devices report what type of media the current activity is [(see `metadata` property here)](https://developers.google.com/cast/docs/media/messages#MediaInformation). The reported type is dependent on the application playing the media to correctly report it, the cast device does not magically know what the media is. If an application does not report a type it is always classified as `unknown`. - -**By default, MS will only track media that is reported as `MusicTrack`.** - -##### Allow Unknown Media Type - -Media with an Unknown (`Generic`) media type can be explicitly allowed by setting `"allowUnknownMedia": true` in the [file-based configuration.](#file-based-14) This can also be configured to only allow unknown media types for specific applications by using a list of application names like: - -```json5 -// in chromecast.json or config.json sources -[ - { - "name": "MyCast", - "type": "chromecast", - "data": { - // only allow unknown if app name contains any of these phrases - "allowUnknownMedia": ["smarttube", "default media receiver"] - }, - } -] -``` - -##### Forcing Media Tracking - -MS can be forced to track media from an application regardless of media type. This is useful if an application incorrectly reports a media type you are sure should be music. Set `"forceMediaRecognitionOn"` in the [file-based configuration.](#file-based-14) to a list of application names that should always be tracked like: - -```json5 -// in chromecast.json or config.json sources -[ - { - "name": "MyCast", - "type": "chromecast", - "data": { - // media from applications that contains these phrases will always be tracked, regardless of media type reported - "forceMediaRecognitionOn": ["smarttube", "default media receiver"] - }, - } -] -``` - - -#### Cast Troubleshooting - -Please include any/all logs with raw output if there are any errors encountered as this is critical to diagnosing issues. - -To diagnose bad/incomplete track information or strange MS player behavior please turn on **payload logging** and include log output of the source running to help diagnose this issue: - -```json5 -// in chromecast.json or config.json sources -[ - { - "name": "MyCast", - "type": "chromecast", - "data": { - //... - }, - "options": { - "logPayload": true - } - } -] -``` - -#### ENV-Based - -:::note - -[Manually configuring cast device connections](#connecting-devices) is only available through [File-based config.](#file-based-14) - -:::: - -| Environmental Variable | Required? | Default | Description | -|------------------------|-----------|---------|--------------------------------------------------------------------------------------| -| 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 | - -#### File-Based - -See [`chromecast.json.example`](https://github.com/FoxxMD/multi-scrobbler/blob/master/config/chromecast.json.example) or [explore the schema with an example and live editor/validator](https://json-schema.app/view/%23%2Fdefinitions%2FChromecastSourceConfig/%23%2Fdefinitions%2FChromecastData?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fmulti-scrobbler%2Fmaster%2Fsrc%2Fbackend%2Fcommon%2Fschema%2Fsource.json) - -### [Musikcube](https://musikcube.com) - -In order to use Musikcube configure it to accept [websocket connections](https://github.com/clangen/musikcube/wiki/remote-api-documentation) in **server setup**: - -* Enable the **Metadata Server** -* Set a **Password** - -Both of these settings are found in _Musikcube -> (s)ettings -> server setup_ - -![Server Setup](musikcube.jpg) - -The URL used by MS has the syntax: - -``` -[ws|wss]://HOST:[PORT] -``` - -The **port** is the same as shown in the server setup screenshot from above, under **metadata server enabled**. If no port is provided to MS it will default to `7905`. - -If no URL is provided to MS it will try to use `ws://localhost:7905` - -#### ENV-Based - -| Environmental Variable | Required? | Default | Description | -|------------------------|-----------|-----------------------|--------------------------------------| -| `MC_URL` | No | `ws://localhost:7905` | Use port set for **metadata server** | -| `MC_PASSWORD` | Yes | | | - -#### File-Based - -See [`musikcube.json.example`](https://github.com/FoxxMD/multi-scrobbler/blob/master/config/chromecast.json.example) or [explore the schema with an example and live editor/validator](https://json-schema.app/view/%23%2Fdefinitions%2FMuikcubeSourceConfig/%23%2Fdefinitions%2FMuikcubeData?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fmulti-scrobbler%2Fmaster%2Fsrc%2Fbackend%2Fcommon%2Fschema%2Fsource.json) - -## Client Configurations - -### [Maloja](https://github.com/krateng/maloja) - -#### ENV-Based - -| Environmental Variable | Required? | Default | Description | -|----------------------------|-----------|---------|-------------------------------| -| `MALOJA_URL` | Yes | | Base URL of your installation | -| `MALOJA_API_KEY` | Yes | | Api Key | - -#### File-Based - -See [`maloja.json.example`](https://github.com/FoxxMD/multi-scrobbler/blob/master/config/maloja.json.example) or [explore the schema with an example and live editor/validator](https://json-schema.app/view/%23/%23%2Fdefinitions%2FMalojaClientConfig?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fmulti-scrobbler%2Fmaster%2Fsrc%2Fbackend%2Fcommon%2Fschema%2Fclient.json) - -### [Last.fm](https://www.last.fm) - -[Register for an API account here.](https://www.last.fm/api/account/create) - -The Callback URL is actually specified by multi-scrobbler but to keep things consistent you should use -``` -http://localhost:9078/lastfm/callback -``` -or replace `localhost:9078` with your own base URL - -#### ENV-Based - -| Environmental Variable | Required? | Default | Description | -|----------------------------|-----------|-----------------------------------------|-------------------------------| -| `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. | - -#### File-Based - -See [`lastfm.json.example`](https://github.com/FoxxMD/multi-scrobbler/blob/master/config/lastfm.json.example) or [explore the schema with an example and live editor/validator](https://json-schema.app/view/%23/%23%2Fdefinitions%2FLastfmClientConfig?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fmulti-scrobbler%2Fmaster%2Fsrc%2Fbackend%2Fcommon%2Fschema%2Fclient.json) - -### [Listenbrainz](https://listenbrainz.org) - -You will need to run your own Listenbrainz server or have an account [on the official instance](https://listenbrainz.org/login/) - -On your [profile page](https://listenbrainz.org/profile/) find your **User Token** to use in the configuration. - -#### ENV-Based - - -| Environmental Variable | Required? | Default | Description | -|------------------------|-----------|-------------------------------|---------------------------------| -| 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 | - -#### File-Based - -See [`listenbrainz.json.example`](https://github.com/FoxxMD/multi-scrobbler/blob/master/config/listenbrainz.json.example) or [explore the schema with an example and live editor/validator](https://json-schema.app/view/%23%2Fdefinitions%2FListenBrainzClientConfig?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fmulti-scrobbler%2Fmaster%2Fsrc%2Fbackend%2Fcommon%2Fschema%2Fclient.json) - -## Monitoring - -multi-scrobbler supports some common webhooks and a healthcheck endpoint in order to monitor Sources and Clients for errors. - -### Webhook Configurations - -Webhooks will **push** a notification to your configured servers on these events: - -* Source polling started -* Source polling retry -* Source polling stopped on error -* Scrobble client scrobble failure - -Webhooks are configured in the main [config.json](#all-in-one-file-configuration) file under the `webhook` top-level property. Multiple webhooks may be configured for each webhook type. EX: - -```json5 -{ - "sources": [ - //... - ], - "clients": [ - //... - ], - "webhooks": [ - { - "name": "FirstGotifyServer", - "type": "gotify", - "url": "http://192.168.0.100:8070", - "token": "abcd" - }, - { - "name": "SecondGotifyServer", - "type": "gotify", - //... - }, - { - "name": "NtfyServerOne", - "type": "ntfy", - //... - }, - //... - ] -} -``` - -#### [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) - -multi-scrobbler optionally supports setting message notification priority via `info` `warn` and `error` mappings. - -EX - -```json -{ - "type": "gotify", - "name": "MyGotifyFriendlyNameForLogs", - "url": "http://192.168.0.100:8070", - "token": "AQZI58fA.rfSZbm", - "priorities": { - "info": 5, - "warn": 7, - "error": 10 - } -} -``` - -#### [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) - -multi-scrobbler optionally supports setting message notification priority via `info` `warn` and `error` mappings. - -EX - -```json -{ - "type": "ntfy", - "name": "MyNtfyFriendlyNameForLogs", - "url": "http://192.168.0.100:9991", - "topic": "RvOwKJ1XtIVMXGLR", - "username": "Optional", - "password": "Optional", - "priorities": { - "info": 3, - "warn": 4, - "error": 5 - } -} -``` - -#### [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) - -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)/ - -EX - -```json5 -{ - "type": "apprise", - "name": "MyAppriseFriendlyNameForLogs", - "host": "http://192.168.0.100:8080", - "urls": ["gotify://192.168.0.101:8070/MyToken"], // stateless endpoints - "keys": ["e90b20526808373353afad7fb98a201198c0c3e0555bea19f182df3388af7b17"], //persistent storage endpoints - "tags": ["my","optional","tags"] -} -``` - -### Health Endpoint - -An endpoint for monitoring the health of sources/clients is available at GET `http://YourMultiScrobblerDomain/health` - -* Returns `200 OK` when **everything** is working or `500 Internal Server Error` if **anything** is not -* The plain url (`/health`) aggregates status of **all clients/sources** -- so any failing client/source will make status return 500 - * Use query params `type` or `name` to restrict client/sources aggregated IE `/health?type=spotify` or `/health?name=MyMaloja` -* On 500 the response returns a JSON payload with `messages` array that describes any issues - * For any clients/sources that require authentication `/health` will return 500 if they are **not authenticated** - * For sources that poll (spotify, yt music, subsonic) `/health` will 500 if they are **not polling** diff --git a/docsite/docs/configuration/configuration.mdx b/docsite/docs/configuration/configuration.mdx new file mode 100644 index 00000000..0e19cef6 --- /dev/null +++ b/docsite/docs/configuration/configuration.mdx @@ -0,0 +1,1208 @@ +--- +sidebar_position: 2 +title: Overview +toc_max_heading_level: 3 +--- +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; +import Admonition from '@theme/Admonition'; + +# Configuration + +:::tip + +Check the [**FAQ**](../FAQ.md) if you have any issues after configuration! + +::: + +## Configuration Types + +[**Sources** and **Clients**](/#how-does-multi-scrobbler-ms-work) are configured using: + +* environmental (ENV) variables +* client/source specific json config files +* an all-in-one json config file + +**MS will parse configuration from all configuration types.** You can mix and match configurations but it is generally better to stick to one or the other. + + + + This is done by passing environmental variables and so does not require any files to run MS. + + * Using a docker container EX `docker run -e "SPOTIFY_CLIENT_ID=yourId" -e "SPOTIFY_CLIENT_SECRET=yourSecret" ...` + * Using a local installations by exporting variables before running MS EX `SPOTIFY_CLIENT_ID=yourId SPOTIFY_CLIENT_SECRET=yourSecret node index.js` + + Use ENV-based configuration if: + + * You are the only person for whom MS is scrobbling for + * You have a very simple setup for MS such as one scrobble [Client](/#client) and one [Source](/#source) IE Plex -> Maloja + + + MS will parse configuration files located in the directory specified by the `CONFIG_DIR` environmental variable. This variable defaults to: + + * Local installation -> `PROJECT_DIR/config` + * Docker -> `/config` (in the container) -- see the [install docs](../installation/installation.md#docker) for how to configure this correctly + +
+ + Use File-based configuration if... + + * You have many [Sources](/#source) + * You have many of each type of **Source** you want to scrobble from IE 2x Plex accounts, 3x Spotify accounts, 1x + Funkwhale... + * You have more than one scrobble **Client** you want to scrobble to IE multiple Maloja servers + * You want only some **Sources** to scrobble to some **Clients** IE Fred's Spotify account scrobbles to Fred's Maloja + server, but not Mary's Maloja server + +
+ + There are **example configurations** for all Source/Client types and AIO config located in the [`/config`](https://github.com/FoxxMD/multi-scrobbler/tree/master/config) directory of this project. These can be used as-is by renaming them to `.json`. + For docker installations these examples are copied to your configuration directory on first-time use. There is also a [**kitchensink example**](kitchensink.md) that provides examples of using all sources/clients in a complex configuration. + + Each file is named by the **type** of the Client/Source found in below sections. Each file as an **array** of that type of Client/Source. + + Example directory structure: + + ``` + /CONFIG_DIR + plex.json + spotify.json + maloja.json + ``` + +
+ Config Example + + ```json5 title="/CONFIG_DIR/maloja.json" + [ + { + "name": "myFirstMalojaClient", + "data": { + "url": "http://myMalojaServer.example", + "apiKey": "myKey" + } + }, + { + "name": "mySecondMalojaClient", + "data": { + "url": "http://my2ndMalojaServer.example", + "apiKey": "myKey" + } + } + ] + + ``` + +
+
+ + MS will parse an **all-in-one** configuration file located in the directory specified by the `CONFIG_DIR` environmental variable. This variable defaults to: + + * Local installation -> `PROJECT_DIR/config/config.json` + * Docker -> `/config/config.json` (in the container) -- see the [install docs](../installation/installation.md#docker) for how to configure this correctly + +
+ + Use AIO-based configuration if... + + * You have many [Sources](/#source) + * You have many of each type of **Source** you want to scrobble from IE 2x Plex accounts, 3x Spotify accounts, 1x + Funkwhale... + * You have more than one scrobble **Client** you want to scrobble to IE multiple Maloja servers + * You want only some **Sources** to scrobble to some **Clients** IE Fred's Spotify account scrobbles to Fred's Maloja + server, but not Mary's Maloja server + +
+ + **The AIO config also enables setting default options for sources/clients as well as global options for MS itself.** + + An example AIO config files can be found at [/config/config.json.example](https://github.com/FoxxMD/multi-scrobbler/tree/master/config/config.json.example) in the project directory. For docker installations theis example is copied to your configuration directory on first-time use. There is also a [**kitchensink example**](kitchensink.md) that provides examples of using all sources/clients in a complex AOI 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) + +
+ + Config Example + + ```json title="/CONFIG_DIR/config.json" + { + "sources": [ + { + "name": "myConfig", + "type": "spotify", + "clients": [ + "myMalojaClient" + ], + "data": { + "clientId": "anExample" + "clientSecret": "anExample", + "redirectUri": "http://localhost:9078/callback" + } + } + ], + "clients": [ + { + "name": "myMalojaClient", + "type": "maloja", + "data": { + "url": "http://myMalojaServer.example", + "apiKey": "myKey" + } + } + ] + } + ``` + +
+
+
+ +## Application Options + +These options affect multi-scrobbler's behavior and are not specific to any source/client. + +#### Base URL + +Defines the URL that is used to generate default redirect URLs for authentication on [spotify](#spotify), [lastfm](#lastfm), and [deezer](#deezer) -- as well as some logging hints. + +* Default => `http://localhost:9078` +* Set with [ENV](./configuration?configType=env#configuration-types) `BASE_URL` or `baseUrl` [all-in-one configuration](./configuration?configType=aio#configuration-types) +* If protocol is `http` or no protocol is specified MS will try to use port `9078` -- to override this explicitly set the port or use `https` + +Useful when running with [docker](../installation/installation.md#docker) so that you do not need to specify redirect URLs for each configuration. + +
+ + Example + + EX Lastfm Redirect Url is `BASE_URL:PORT/lastfm/callback` (when no other redirectUri is specified for [lastfm configuration](#lastfm)) + + | `BASE_URL` | Redirect URL | + |-------------------------------------|----------------------------------------------------------| + | `192.168.0.101` | `http://192.168.0.101:9078/lastfm/callback` | + | `http://my.domain.local` | `http://my.domain.local:9078/lastfm/callback` | + | `http://192.168.0.101/my/subfolder` | `http://192.168.0.101:9078/my/subfolder/lastfm/callback` | + + | `BASE_URL` | Redirect URL | + |-----------------------------------|----------------------------------------------------------| + | `my.domain.local:80` | `http://192.168.0.101:9078/lastfm/callback` | + | `my.domain.local:9000` | `http://my.domain.local:9078/lastfm/callback` | + | `192.168.0.101:4000/my/subfolder` | `http://192.168.0.101:9078/my/subfolder/lastfm/callback` | + | `https://192.168.0.101` | `https://192.168.0.101:443/lastfm/callback` | + +
+ +#### Disable Web + +If you do not need the dashboard and/or ingress sources, or have security concerns about ingress and cannot control their hosting environment, the web server and API can be disabled. + +:::warning + +Any **ingress-based sources will be unusable** (Plex, Jellyfin, Tautulli, etc...) if this is disabled. + +::: + +Disable using either: + +* ENV `DISABLE_WEB=true` +* In [All-in-One File](./configuration?configType=aio#configuration-types) use the top-level property `"disableWeb": true` + +## Source Configurations + +### [Spotify](https://www.spotify.com) + +To access your Spotify history you must [register an application](https://developer.spotify.com/dashboard) to get a +Client ID/Secret. Make sure to also whitelist your redirect URI in the application settings. + +:::note + +If your Spotify player has [Automix](https://community.spotify.com/t5/FAQs/What-is-Automix/ta-p/5257278) enabled and Spotify uses it for your playlist/queue then MS cannot accurately determine when a track will end. This is because the track is "mixed" in your queue with a shorter play time than its actual length and [Spotify does not report this modified play time in its API.](https://community.spotify.com/t5/Spotify-for-Developers/Wrong-duration-ms-of-track-with-Automix/m-p/5429147) This **does not affect MS's ability to scrobble** from Spotify but it will affect the accuracy of the duration MS reports was played. + +::: + +#### Configuration + + + + | Environmental Variable | Required? | Default | Description | + |----------------------------|-----------|----------------------------------|----------------------------------------------------| + | `SPOTIFY_CLIENT_ID` | Yes | | | + | `SPOTIFY_CLIENT_SECRET` | Yes | | | + | `SPOTIFY_REDIRECT_URI` | No | `http://localhost:9078/callback` | URI must end in `callback` | + + + See [`spotify.json.example`](https://github.com/FoxxMD/multi-scrobbler/blob/master/config/spotify.json.example) or [explore the schema with an example and live editor/validator](https://json-schema.app/view/%23/%23%2Fdefinitions%2FSpotifySourceConfig?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fmulti-scrobbler%2Fmaster%2Fsrc%2Fbackend%2Fcommon%2Fschema%2Fsource.json) + + + See [`spotify.json.example`](https://github.com/FoxxMD/multi-scrobbler/blob/master/config/spotify.json.example) or [explore the schema with an example and live editor/validator](https://json-schema.app/view/%23/%23%2Fdefinitions%2FSpotifySourceConfig?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fmulti-scrobbler%2Fmaster%2Fsrc%2Fbackend%2Fcommon%2Fschema%2Fsource.json) + + + +### [Plex](https://plex.tv) + +Check the [instructions](plex.md) on how to setup a [webhooks](https://support.plex.tv/articles/115002267687-webhooks) to scrobble your plays. + +#### Configuration + + + + | Environmental Variable | Required | Default | Description | + |------------------------|----------|---------|-----------------------------------------------------------------------------------------------------------------------------------------| + | `PLEX_USER` | No | | The a comma-delimited list of usernames to scrobble tracks for. No usernames specified means all tracks by all users will be scrobbled. | + + + See [`plex.json.example`](https://github.com/FoxxMD/multi-scrobbler/blob/master/config/plex.json.example) or [explore the schema with an example and live editor/validator](https://json-schema.app/view/%23/%23%2Fdefinitions%2FPlexSourceConfig?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fmulti-scrobbler%2Fmaster%2Fsrc%2Fbackend%2Fcommon%2Fschema%2Fsource.json) + + + See [`plex.json.example`](https://github.com/FoxxMD/multi-scrobbler/blob/master/config/plex.json.example) or [explore the schema with an example and live editor/validator](https://json-schema.app/view/%23/%23%2Fdefinitions%2FPlexSourceConfig?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fmulti-scrobbler%2Fmaster%2Fsrc%2Fbackend%2Fcommon%2Fschema%2Fsource.json) + + + +### [Tautulli](https://tautulli.com) + +Check the [instructions](plex.md) on how to setup a notification agent. + +#### Configuration + + + + | Environmental Variable | Required | Default | Description | + |------------------------|----------|---------|-----------------------------------------------------------------------------------------------------------------------------------------| + | `TAUTULLI_USER` | No | | The a comma-delimited list of usernames to scrobble tracks for. No usernames specified means all tracks by all users will be scrobbled. | + + + See [`tautulli.json.example`](https://github.com/FoxxMD/multi-scrobbler/blob/master/config/tautulli.json.example) or [explore the schema with an example and live editor/validator](https://json-schema.app/view/%23/%23%2Fdefinitions%2FTautulliSourceConfig?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fmulti-scrobbler%2Fmaster%2Fsrc%2Fbackend%2Fcommon%2Fschema%2Fsource.json) + + + See [`tautulli.json.example`](https://github.com/FoxxMD/multi-scrobbler/blob/master/config/tautulli.json.example) or [explore the schema with an example and live editor/validator](https://json-schema.app/view/%23/%23%2Fdefinitions%2FTautulliSourceConfig?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fmulti-scrobbler%2Fmaster%2Fsrc%2Fbackend%2Fcommon%2Fschema%2Fsource.json) + + + +### [Subsonic](http://www.subsonic.org/) + +Can use this source 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/)) + +**Known Issues:** +* "Time played at" is somewhat inaccurate since the api only reports "played X minutes ago" so... + * All scrobble times are therefore "on the minute" and you may experience occasional duplicate scrobbles + * "played X minutes ago" sometimes is also not reported correctly +* Multiple artists are reported as one value and cannot be separated +* If using [Airsonic Advanced](https://github.com/airsonic-advanced/airsonic-advanced) the password used (under **Credentials**) must be **Decodable** + +#### Configuration + + + + | Environmental Variable | Required? | Default | Description | + |------------------------|-----------|---------|--------------------------------------| + | `SUBSONIC_USER` | Yes | | | + | `SUBSONIC_PASSWORD` | Yes | | | + | `SUBSONIC_URL` | Yes | | Base url of your subsonic-api server | + + + See [`subsonic.json.example`](https://github.com/FoxxMD/multi-scrobbler/blob/master/config/subsonic.json.example) or [explore the schema with an example and live editor/validator](https://json-schema.app/view/%23/%23%2Fdefinitions%2FSubSonicSourceConfig?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fmulti-scrobbler%2Fmaster%2Fsrc%2Fbackend%2Fcommon%2Fschema%2Fsource.json) + + + See [`subsonic.json.example`](https://github.com/FoxxMD/multi-scrobbler/blob/master/config/subsonic.json.example) or [explore the schema with an example and live editor/validator](https://json-schema.app/view/%23/%23%2Fdefinitions%2FSubSonicSourceConfig?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fmulti-scrobbler%2Fmaster%2Fsrc%2Fbackend%2Fcommon%2Fschema%2Fsource.json) + + + +### [Jellyfin](https://jellyfin.org/) + +Must be using Jellyfin 10.7 or greater + +* In the Jellyfin desktop web UI Navigate to -> Administration -> Dashboard -> Plugins -> Catalog + * Under Notifications -> **Webhook** -> Install, then restart your server +* Navigate back to -> Administration -> Dashboard -> Plugins -> My Plugins -> Webhook + * Click "..." -> Settings +* In Webhook settings: + * `Add Generic Destination` + * In the new `Generic` dropdown: + * Webhook Url: `http://localhost:9078/jellyfin` + * Notification Type: `Playback Progress` + * Item Type: `Songs` + * Check `Send All Properties` + * Save + +:::note + +If you see errors in the MS logs regarding `missing headers` when using Jellyfin [see this workaround.](../FAQ.md#jellyfin-has-warnings-about-missing-headers) + +::: + +#### Configuration + + + + | Environmental Variable | Required? | Default | Description | + |------------------------|-----------|---------|-------------------------------------------------------------------| + | `JELLYFIN_USER` | | | Comma-separated list of usernames (from Jellyfin) to scrobble for | + | `JELLYFIN_SERVER` | | | Comma-separated list of Jellyfin server names to scrobble from | + + + See [`jellyfin.json.example`](https://github.com/FoxxMD/multi-scrobbler/blob/master/config/jellyfin.json.example) or [explore the schema with an example and live editor/validator](https://json-schema.app/view/%23/%23%2Fdefinitions%2FJellySourceConfig?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fmulti-scrobbler%2Fmaster%2Fsrc%2Fbackend%2Fcommon%2Fschema%2Fsource.json) + + + See [`jellyfin.json.example`](https://github.com/FoxxMD/multi-scrobbler/blob/master/config/jellyfin.json.example) or [explore the schema with an example and live editor/validator](https://json-schema.app/view/%23/%23%2Fdefinitions%2FJellySourceConfig?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fmulti-scrobbler%2Fmaster%2Fsrc%2Fbackend%2Fcommon%2Fschema%2Fsource.json) + + + +### [Last.fm (Source)](https://www.last.fm) + +See the [Last.fm (Client)](#lastfm) setup for registration instructions. + +#### Configuration + + + + No support for ENV based for Last.fm as a client (only source) + + + See [`lastfm.json.example`](https://github.com/FoxxMD/multi-scrobbler/blob/master/config/lastfm.json.example), change `configureAs` to `source`. Or [explore the schema with an example and live editor/validator](https://json-schema.app/view/%23/%23%2Fdefinitions%2FLastfmSourceConfig?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fmulti-scrobbler%2Fmaster%2Fsrc%2Fbackend%2Fcommon%2Fschema%2Fsource.json) + + + See [`lastfm.json.example`](https://github.com/FoxxMD/multi-scrobbler/blob/master/config/lastfm.json.example), change `configureAs` to `source`. Or [explore the schema with an example and live editor/validator](https://json-schema.app/view/%23/%23%2Fdefinitions%2FLastfmSourceConfig?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fmulti-scrobbler%2Fmaster%2Fsrc%2Fbackend%2Fcommon%2Fschema%2Fsource.json) + + + +### [Listenbrainz (Source)](https://listenbrainz.org) + +You will need to run your own Listenbrainz server or have an account [on the official instance](https://listenbrainz.org/login/) + +On your [profile page](https://listenbrainz.org/profile/) find your **User Token** to use in the configuration. + + +#### Configuration + + + + + You cannot use ENV variables shown in the [Listenbrainz Client config](#listenbrainz) -- multi-scrobbler assumes Listenbrainz ENVs are always used for the **client** configuration. You must use the file-based config from below to setup Listenbrainz as a Source. + + + + See [`listenbrainz.json.example`](https://github.com/FoxxMD/multi-scrobbler/blob/master/config/listenbrainz.json.example) or [explore the schema with an example and live editor/validator](https://json-schema.app/view/%23%2Fdefinitions%2FListenBrainzSourceConfig?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fmulti-scrobbler%2Fmaster%2Fsrc%2Fbackend%2Fcommon%2Fschema%2Fsource.json) + + **Change `configureAs` to `source`** + + + See [`listenbrainz.json.example`](https://github.com/FoxxMD/multi-scrobbler/blob/master/config/listenbrainz.json.example) or [explore the schema with an example and live editor/validator](https://json-schema.app/view/%23%2Fdefinitions%2FListenBrainzSourceConfig?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fmulti-scrobbler%2Fmaster%2Fsrc%2Fbackend%2Fcommon%2Fschema%2Fsource.json) + + **Change `configureAs` to `source`** + + + +### [Deezer](https://deezer.com/) + +Create a new application at [Deezer Developers](https://developers.deezer.com/myapps) + +* Application Domain must be the same as your multi-scrobbler domain. Default is `localhost:9078` +* Redirect URL must end in `deezer/callback` + * Default would be `http://localhost:9078/deezer/callback` + +After application creation you should have credentials displayed in the "My Apps" dashboard. You will need: + +* **Application ID** +* **Secret Key** +* **Redirect URL** (if not the default) + +**If no access token is provided...** + +After starting multi-scrobbler with credentials in-place open the dashboard (`http://localhost:9078`) and find your Deezer source. Click **(Re)authenticate and (re)start polling** to start the login process. After login is complete polling will begin automatically. + +#### Configuration + + + + | Environmental Variable | Required? | Default | Description | + |------------------------|-----------|-----------------------------------------|-----------------------------------| + | `DEEZER_CLIENT_ID` | Yes | | Your **Application ID** | + | `DEEZER_CLIENT_SECRET` | Yes | | Your **Secret Key** | + | `DEEZER_REDIRECT_URI` | No | `http://localhost:9078/deezer/callback` | URI must end in `deezer/callback` | + + + See [`deezer.json.example`](https://github.com/FoxxMD/multi-scrobbler/blob/master/config/deezer.json.example) or [explore the schema with an example and live editor/validator](https://json-schema.app/view/%23/%23%2Fdefinitions%2FDeezerSourceConfig?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fmulti-scrobbler%2Fmaster%2Fsrc%2Fbackend%2Fcommon%2Fschema%2Fsource.json) + + + See [`deezer.json.example`](https://github.com/FoxxMD/multi-scrobbler/blob/master/config/deezer.json.example) or [explore the schema with an example and live editor/validator](https://json-schema.app/view/%23/%23%2Fdefinitions%2FDeezerSourceConfig?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fmulti-scrobbler%2Fmaster%2Fsrc%2Fbackend%2Fcommon%2Fschema%2Fsource.json) + + + +### [Youtube Music](https://music.youtube.com) + +:::note + +* YT Music authentication is "browser based" which means your credentials may expire after a (long?) period of time OR if you log out of https://music.youtube.com. In the event this happens just repeat the steps below to get new credentials. +* Communication to YT Music is **unofficial** and not supported or endorsed by Google. This means that **this integration may stop working at any time** if Google decides to change how YT Music works in the browser. + +::: + +Credentials for YT Music are obtained from a browser request to https://music.youtube.com **once you are logged in.** [Specific requirements are here and summarized below:](https://github.com/nickp10/youtube-music-ts-api/blob/master/DOCUMENTATION.md#authenticate) + +* Open a new tab +* Open the developer tools (Ctrl-Shift-I) and select the “Network” tab +* Go to https://music.youtube.com and ensure you are logged in + +Then... + +1. Find and select an authenticated POST request. The simplest way is to filter by /browse using the search bar of the developer tools. If you don’t see the request, try scrolling down a bit or clicking on the library button in the top bar. +2. **Make sure **Headers** pane is selected and open +3. In the **Request Headers** section find and copy the **entire value** found after `Cookie:` and use this as the `cookie` value in your multi-scrobbler config +4. If present, in the **Request Headers** section find and copy the number found in `X-google-AuthUser` and use this as the value for `authUser` in your multi-scrobbler config + +![Google Headers](google-header.jpg) + +#### Configuration + + + + No ENV support + + + See [`ytmusic.json.example`](https://github.com/FoxxMD/multi-scrobbler/blob/master/config/ytmusic.json.example) or [explore the schema with an example and live editor/validator](https://json-schema.app/view/%23/%23%2Fdefinitions%2FYTMusicSourceConfig?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fmulti-scrobbler%2Fmaster%2Fsrc%2Fbackend%2Fcommon%2Fschema%2Fsource.json) + + + See [`ytmusic.json.example`](https://github.com/FoxxMD/multi-scrobbler/blob/master/config/ytmusic.json.example) or [explore the schema with an example and live editor/validator](https://json-schema.app/view/%23/%23%2Fdefinitions%2FYTMusicSourceConfig?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fmulti-scrobbler%2Fmaster%2Fsrc%2Fbackend%2Fcommon%2Fschema%2Fsource.json) + + + +### [MPRIS](https://specifications.freedesktop.org/mpris-spec/latest/) + +MPRIS is a standard interface for communicating with Music Players on **linux operating systems.** + +If you run Linux and have a notification tray that shows what media you are listening to, you likely have access to MPRIS. + +![Notification Tray](mpris.jpg) + +multi-scrobbler can listen to this interface and scrobble tracks played by **any media player** that communicates to the operating system with MPRIS. + +:::note + +multi-scrobbler needs to be running as a [**Local Installation**](../installation/installation.md#nodejs) in order to use MPRIS. This cannot be used from docker. + +::: + +#### Configuration + + + + | Environmental Variable | Required? | Default | Description | + |------------------------|-----------|---------|----------------------------------------------------------------------------------| + | 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 | + + + See [`mpris.json.example`](https://github.com/FoxxMD/multi-scrobbler/blob/master/config/mpris.json.example) or [explore the schema with an example and live editor/validator](https://json-schema.app/view/%23%2Fdefinitions%2FMPRISSourceConfig?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fmulti-scrobbler%2Fmaster%2Fsrc%2Fbackend%2Fcommon%2Fschema%2Fsource.json) + + + See [`mpris.json.example`](https://github.com/FoxxMD/multi-scrobbler/blob/master/config/mpris.json.example) or [explore the schema with an example and live editor/validator](https://json-schema.app/view/%23%2Fdefinitions%2FMPRISSourceConfig?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fmulti-scrobbler%2Fmaster%2Fsrc%2Fbackend%2Fcommon%2Fschema%2Fsource.json) + + + +### [Mopidy](https://mopidy.com/) + +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/) + +multi-scrobbler can scrobble tracks played from any Mopidy backend source, regardless of where you listen to them. + +#### Configuration + + + + No ENV support + + + See [`mopidy.json.example`](https://github.com/FoxxMD/multi-scrobbler/blob/master/config/mopidy.json.example) or [explore the schema with an example and live editor/validator](https://json-schema.app/view/%23%2Fdefinitions%2FMopidySourceConfig/%23%2Fdefinitions%2FMopidyData?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fmulti-scrobbler%2Fmaster%2Fsrc%2Fbackend%2Fcommon%2Fschema%2Fsource.json) + + + See [`mopidy.json.example`](https://github.com/FoxxMD/multi-scrobbler/blob/master/config/mopidy.json.example) or [explore the schema with an example and live editor/validator](https://json-schema.app/view/%23%2Fdefinitions%2FMopidySourceConfig/%23%2Fdefinitions%2FMopidyData?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fmulti-scrobbler%2Fmaster%2Fsrc%2Fbackend%2Fcommon%2Fschema%2Fsource.json) + + + +#### Configuration Options + +###### `url` + +The URL used to connect to the Mopidy server. You MUST have [Mopidy-HTTP extension](https://mopidy.com/ext/http) enabled. + +If no `url` is provided a default is used which assumes Mopidy is installed on the same server as multi-scrobbler: `ws://localhost:6680/mopidy/ws/` + +Make sure the hostname and port number match what is found in the Mopidy configuration file `mopidy.conf`: + +``` +... + +[http] +hostname = localhost +port = 6680 + +... +``` + +The URL used to connect ultimately must be formed like this: `[protocol]://[hostname]:[port]/[path]` +If any part of this URL is missing multi-scrobbler will use a default value, for your convenience. This also means that if any part of your URL is **not** standard you must explicitly define it. + +Part => Default Value + +* Protocol => `ws://` +* Hostname => `localhost` +* Port => `6680` +* Path => `/mopidy/ws/` + +
+URL Transform Examples + +```json +{ + "url": "mopidy.mydomain.com" +} +``` + +MS transforms this to: `ws://mopidy.mydomain.com:6680/mopidy/ws/` + +```json +{ + "url": "192.168.0.101:3456" +} +``` + +MS transforms this to: `ws://192.168.0.101:3456/mopidy/ws/` + +```json +{ + "url": "mopidy.mydomain.com:80/MOPWS" +} +``` + +MS transforms this to: `ws://mopidy.mydomain.com:80/MOPWS` + +
+ + +##### URI Blacklist/Whitelist + +If you wish to disallow or only allow scrobbling from some sources played through Mopidy you can specify these using `uriBlacklist` or `uriWhitelist` in your config. multi-scrobbler will check the list to see if any string matches the START of the `uri` on a track. If whitelist is used then blacklist is ignored. All strings are case-insensitive. + +```json +{ + "uriBlacklist": ["soundcloud"] +} +``` + +Will prevent multi-scrobbler from scrobbling any Mopidy track that start with a `uri` like `soundcloud:song:MySong-1234` + +##### Album Blacklist + +For certain sources (Soundcloud) Mopidy does not have all track info (Album) and will instead use "Soundcloud" as the Album name. You can prevent multi-scrobbler from using this bad Album data by adding the fake Album name to this list. Multi-scrobbler will still scrobble the track, just without the bad data. All strings are case-insensitive. + +```json +{ + "albumBlacklist": ["SoundCloud", "Mixcloud"] +} +``` + +If a track would be scrobbled like `Album: Soundcloud, Track: My Cool Track, Artist: A Cool Artist` +then multi-scrobbler will instead scrobble `Track: My Cool Track, Artist: A Cool Artist` + +### [JRiver](https://jriver.com/) + +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 can be in the JRiver GUI: + +* Tools -> Options -> Media Network + * Check `Use Media Network to share this library...` + * If you have `Authentication` checked you will need to provide the **Username** and **Password** in the ENV/File configuration below. + +##### URL + +If you do not provide a URL then a default is used which assumes JRiver is installed on the same server as multi-scrobbler: `http://localhost:52199/MCWS/v1/` + +* Make sure the port number matches what is found in `Advanced` section in the [Media Network](#jriver) options. +* If your installation is on the same machine but you cannot connect using `localhost` try `0.0.0.0` instead. + +The URL used to connect ultimately must be formed like this: `[protocol]://[hostname]:[port]/[path]` +If any part of this URL is missing multi-scrobbler will use a default value, for your convenience. This also means that if any part of your URL is **not** standard you must explicitly define it. + +Part => Default Value + +* Protocol => `http://` +* Hostname => `localhost` +* Port => `52199` +* Path => `/MCWS/v1/` + +
+URL Transform Examples + +```json +{ + "url": "jriver.mydomain.com" +} +``` + +MS transforms this to: `http://jriver.mydomain.com:52199/MCWS/v1/` + +```json +{ + "url": "192.168.0.101:3456" +} +``` + +MS transforms this to: `http://192.168.0.101:3456/MCWS/v1/` + +```json +{ + "url": "mydomain.com:80/jriverReverse/MCWS/v1/" +} +``` + +MS transforms this to: `http://mydomain.com:80/jriverReverse/MCWS/v1/` + +
+ +#### Configuration + + + + | Environmental Variable | Required | Default | Description | + |------------------------|----------|---------------------------------|------------------------------------------------| + | 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 | + + + See [`jriver.json.example`](https://github.com/FoxxMD/multi-scrobbler/blob/master/config/jriver.json.example) or [explore the schema with an example and live editor/validator](https://json-schema.app/view/%23%2Fdefinitions%2FJRiverSourceConfig/%23%2Fdefinitions%2FJRiverData?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fmulti-scrobbler%2Fmaster%2Fsrc%2Fbackend%2Fcommon%2Fschema%2Fsource.json) + + + See [`jriver.json.example`](https://github.com/FoxxMD/multi-scrobbler/blob/master/config/jriver.json.example) or [explore the schema with an example and live editor/validator](https://json-schema.app/view/%23%2Fdefinitions%2FJRiverSourceConfig/%23%2Fdefinitions%2FJRiverData?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fmulti-scrobbler%2Fmaster%2Fsrc%2Fbackend%2Fcommon%2Fschema%2Fsource.json) + + + +### [Kodi](https://kodi.tv/) + +In order for multi-scrobbler to communicate with Kodi you must have the [Web Interface](https://kodi.wiki/view/Web_interface) enabled. This can can be in the Kodi GUI: + +* Settings -> Services -> Control + * Check `Allow remote control via HTTP` + * Ensure you have a **Username** and **Password** set, you will need to provide them in the ENV/File configuration below. + +##### URL + +If you do not provide a URL then a default is used which assumes Kodi is installed on the same server as multi-scrobbler: `http://localhost:8080/jsonrpc` + +* Make sure the port number matches what is found in **Port** in the [Control](#kodi) section mentioned above. +* If your installation is on the same machine but you cannot connect using `localhost` try `0.0.0.0` instead. + +The URL used to connect ultimately must be formed like this: `[protocol]://[hostname]:[port]/[path]` +If any part of this URL is missing multi-scrobbler will use a default value, for your convenience. This also means that if any part of your URL is **not** standard you must explicitly define it. + +Part => Default Value + +* Protocol => `http://` +* Hostname => `localhost` +* Port => `8080` +* Path => `/jsonrpc` + +
+URL Transform Examples + +```json +{ + "url": "kodi.mydomain.com" +} +``` + +MS transforms this to: `http://kodi.mydomain.com:8080/jsonrpc` + +```json +{ + "url": "192.168.0.101:3456" +} +``` + +MS transforms this to: `http://192.168.0.101:3456/jsonprc` + +```json +{ + "url": "mydomain.com:80/kodiReverse/jsonrpc" +} +``` + +MS transforms this to: `http://mydomain.com:80/kodiReverse/jsonrpc` + +
+ +#### Configuration + + + + | Environmental Variable | Required | Default | Description | + |------------------------|----------|-------------------------------|----------------------------| + | 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 | + + + See [`kodi.json.example`](https://github.com/FoxxMD/multi-scrobbler/blob/master/config/kodi.json.example) or [explore the schema with an example and live editor/validator](https://json-schema.app/view/%23%2Fdefinitions%2FKodiSourceConfig/%23%2Fdefinitions%2FKodiData?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fmulti-scrobbler%2Fmaster%2Fsrc%2Fbackend%2Fcommon%2Fschema%2Fsource.json) + + + See [`kodi.json.example`](https://github.com/FoxxMD/multi-scrobbler/blob/master/config/kodi.json.example) or [explore the schema with an example and live editor/validator](https://json-schema.app/view/%23%2Fdefinitions%2FKodiSourceConfig/%23%2Fdefinitions%2FKodiData?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fmulti-scrobbler%2Fmaster%2Fsrc%2Fbackend%2Fcommon%2Fschema%2Fsource.json) + + + +### [WebScrobbler](https://web-scrobbler.com/) + +After installing the extension open the preferences/settings for it: + +* Under **Accounts** + * **Add Webhook** + * API URL: `http://localhost:9078/api/webscrobbler` + * Application name: `(whatever you want)` + +Reload the extension after adding the webhook. + +* **On Firefox** - Only FQNs (domain.tld), `localhost`, and `127.0.0.1` are supported for API URL due to [firefox requiring https](https://github.com/web-scrobbler/web-scrobbler/issues/4183#issuecomment-1749222006) +* **On Chromium-based Browsers** - Any domain will work for API URL +* All Other browsers are untested + +##### Multiple Users + +If you would like use multiple WebScrobbler sources they can be matched using a **slug** at the end of the **API URL.** This requires using [a file-based config.](./configuration?configType=file#webscrobbler) + +Example: + +In `webscrobbler.json` + +```json +[ + { + "name": "aUserWS", + "clients": [ + "client1Maloja" + ], + "data": { + "slug": "usera" + } + }, + { + "name": "bUserWS", + "clients": [ + "client2Maloja" + ], + "data": { + "slug": "userb" + } + } +] +``` + +* To use `aUserWS` source set **API URL** to `http://localhost:9078/api/webscrobbler/usera` +* To use `bUserWS` source set **API URL** to `http://localhost:9078/api/webscrobbler/userb` + +:::note + +`http://localhost:9078/api/webscrobbler` is matched with the first source that _that does not have a slug defined._ + +::: + +###### Connectors Black/Whitelist + +MS can be configured to only scrobble, or NOT scrobble, from some WS connectors. Use the name of the website from the [supported websites](https://web-scrobbler.com/) or from the **Connectors** tab in the extension. + +:::note + +This affects **only** MS's behavior and does not affect the general connector behavior you have configured within the WebScrobbler extension. + +::: + +#### Configuration + + + + | Environmental Variable | Required? | Default | Description | + |------------------------|-----------|---------|--------------------------------------------------------------------------| + | 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 | + + + See [`webscrobbler.json.example`](https://github.com/FoxxMD/multi-scrobbler/blob/master/config/webscrobbler.json.example) or [explore the schema with an example and live editor/validator](https://json-schema.app/view/%23%2Fdefinitions%2FWebScrobblerSourceConfig/%23%2Fdefinitions%2FWebScrobblerData?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fmulti-scrobbler%2Fmaster%2Fsrc%2Fbackend%2Fcommon%2Fschema%2Fsource.json) + + + See [`webscrobbler.json.example`](https://github.com/FoxxMD/multi-scrobbler/blob/master/config/webscrobbler.json.example) or [explore the schema with an example and live editor/validator](https://json-schema.app/view/%23%2Fdefinitions%2FWebScrobblerSourceConfig/%23%2Fdefinitions%2FWebScrobblerData?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fmulti-scrobbler%2Fmaster%2Fsrc%2Fbackend%2Fcommon%2Fschema%2Fsource.json) + + + +### [Google Cast (Chromecast)](https://www.google.com/chromecast/built-in/) + +If your media device can be **Cast** to using this button ![Chromecast Icon](https://upload.wikimedia.org/wikipedia/commons/2/26/Chromecast_cast_button_icon.svg) on your phone/computer then multi-scrobbler can monitor it in order to scrobble music you play. + + +:::note + +Google Cast support is **experimental**. You may experience crashes and errors while using this Source. Please open an issue if you experience problems and include all information detailed in the issue template to help debug your issue. + +::: + +:::note + +This source relies on common, **basic** music data provided by the cast device which will always be less exhaustive than data parsed from full source integrations. If there is an existing [Source](#source-configurations) it is recommended to configure for it and blacklist the app on Google Cast, rather than relying solely on Google Cast for scrobbling. + +::: + +#### Connecting Devices + +Cast devices can be manually configured using file-based configuration OR automatically discovered using **mDNS.** + +###### mDNS Discovery + +The host machine running multi-scrobbler must be configured to allow [mDNS traffic on port 5353/UDP](https://book.hacktricks.xyz/network-services-pentesting/5353-udp-multicast-dns-mdns). + +:::info[OS Specific Instructions] + + + + **Docker** + + The host machine must have [avahi-daemon](https://avahi.org/) running to circumvent limitations with DNS resolution due to musl in Alpine. Most major linux distributions package avahi and many have it built-in. Once avahi is running you must pass D-Bus and the avahi daemon socket to your container like so: + + ``` + docker run ... -v /var/run/dbus:/var/run/dbus -v /var/run/avahi-daemon/socket:/var/run/avahi-daemon/socket ... foxxmd/multi-scrobbler + ``` + + **Flatpak/Nodejs** + + No additional steps are required. + + + **Docker** + + Unsupported at this time. + + **Nodejs** + + No additional steps are required. + + + +::: + +#### What Media Does MS Scrobble? + +Cast devices report what type of media the current activity is [(see `metadata` property here)](https://developers.google.com/cast/docs/media/messages#MediaInformation). The reported type is dependent on the application playing the media to correctly report it, the cast device does not magically know what the media is. If an application does not report a type it is always classified as `unknown`. + +**By default, MS will only track media that is reported as `MusicTrack`.** + +##### Allow Unknown Media Type + +Media with an Unknown (`Generic`) media type can be explicitly allowed by setting `"allowUnknownMedia": true` in the file-based configuration. This can also be configured to only allow unknown media types for specific applications by using a list of application names like: + +```json5 title="chromecast.json" +[ + { + "name": "MyCast", + "type": "chromecast", + "data": { + // only allow unknown if app name contains any of these phrases + "allowUnknownMedia": ["smarttube", "default media receiver"] + }, + } +] +``` + +##### Forcing Media Tracking + +MS can be forced to track media from an application regardless of media type. This is useful if an application incorrectly reports a media type you are sure should be music. Set `"forceMediaRecognitionOn"` in the file-based configuration. to a list of application names that should always be tracked like: + +```json5 +// in chromecast.json or config.json sources +[ + { + "name": "MyCast", + "type": "chromecast", + "data": { + // media from applications that contains these phrases will always be tracked, regardless of media type reported + "forceMediaRecognitionOn": ["smarttube", "default media receiver"] + }, + } +] +``` + + +#### Cast Troubleshooting + +Please include any/all logs with raw output if there are any errors encountered as this is critical to diagnosing issues. + +To diagnose bad/incomplete track information or strange MS player behavior please turn on **payload logging** and include log output of the source running to help diagnose this issue: + +```json5 +// in chromecast.json or config.json sources +[ + { + "name": "MyCast", + "type": "chromecast", + "data": { + //... + }, + "options": { + "logPayload": true + } + } +] +``` + +#### Configuration + + + + + [Manually configuring cast device connections](#connecting-devices) is only available through file-based config. + + + | Environmental Variable | Required? | Default | Description | + |------------------------|-----------|---------|--------------------------------------------------------------------------------------| + | 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 | + + + See [`chromecast.json.example`](https://github.com/FoxxMD/multi-scrobbler/blob/master/config/chromecast.json.example) or [explore the schema with an example and live editor/validator](https://json-schema.app/view/%23%2Fdefinitions%2FChromecastSourceConfig/%23%2Fdefinitions%2FChromecastData?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fmulti-scrobbler%2Fmaster%2Fsrc%2Fbackend%2Fcommon%2Fschema%2Fsource.json) + + + See [`chromecast.json.example`](https://github.com/FoxxMD/multi-scrobbler/blob/master/config/chromecast.json.example) or [explore the schema with an example and live editor/validator](https://json-schema.app/view/%23%2Fdefinitions%2FChromecastSourceConfig/%23%2Fdefinitions%2FChromecastData?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fmulti-scrobbler%2Fmaster%2Fsrc%2Fbackend%2Fcommon%2Fschema%2Fsource.json) + + + +### [Musikcube](https://musikcube.com) + +In order to use Musikcube configure it to accept [websocket connections](https://github.com/clangen/musikcube/wiki/remote-api-documentation) in **server setup**: + +* Enable the **Metadata Server** +* Set a **Password** + +Both of these settings are found in _Musikcube -> (s)ettings -> server setup_ + +![Server Setup](musikcube.jpg) + +The URL used by MS has the syntax: + +``` +[ws|wss]://HOST:[PORT] +``` + +The **port** is the same as shown in the server setup screenshot from above, under **metadata server enabled**. If no port is provided to MS it will default to `7905`. + +If no URL is provided to MS it will try to use `ws://localhost:7905` + +#### Configuration + + + + | Environmental Variable | Required? | Default | Description | + |------------------------|-----------|-----------------------|--------------------------------------| + | `MC_URL` | No | `ws://localhost:7905` | Use port set for **metadata server** | + | `MC_PASSWORD` | Yes | | | + + + See [`musikcube.json.example`](https://github.com/FoxxMD/multi-scrobbler/blob/master/config/chromecast.json.example) or [explore the schema with an example and live editor/validator](https://json-schema.app/view/%23%2Fdefinitions%2FMuikcubeSourceConfig/%23%2Fdefinitions%2FMuikcubeData?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fmulti-scrobbler%2Fmaster%2Fsrc%2Fbackend%2Fcommon%2Fschema%2Fsource.json) + + + See [`musikcube.json.example`](https://github.com/FoxxMD/multi-scrobbler/blob/master/config/chromecast.json.example) or [explore the schema with an example and live editor/validator](https://json-schema.app/view/%23%2Fdefinitions%2FMuikcubeSourceConfig/%23%2Fdefinitions%2FMuikcubeData?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fmulti-scrobbler%2Fmaster%2Fsrc%2Fbackend%2Fcommon%2Fschema%2Fsource.json) + + + +## Client Configurations + +### [Maloja](https://github.com/krateng/maloja) + +#### Configuration + + + + | Environmental Variable | Required? | Default | Description | + |------------------------|-----------|---------|-------------------------------| + | `MALOJA_URL` | Yes | | Base URL of your installation | + | `MALOJA_API_KEY` | Yes | | Api Key | + + + See [`maloja.json.example`](https://github.com/FoxxMD/multi-scrobbler/blob/master/config/maloja.json.example) or [explore the schema with an example and live editor/validator](https://json-schema.app/view/%23/%23%2Fdefinitions%2FMalojaClientConfig?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fmulti-scrobbler%2Fmaster%2Fsrc%2Fbackend%2Fcommon%2Fschema%2Fclient.json) + + + See [`maloja.json.example`](https://github.com/FoxxMD/multi-scrobbler/blob/master/config/maloja.json.example) or [explore the schema with an example and live editor/validator](https://json-schema.app/view/%23/%23%2Fdefinitions%2FMalojaClientConfig?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fmulti-scrobbler%2Fmaster%2Fsrc%2Fbackend%2Fcommon%2Fschema%2Fclient.json) + + + +### [Last.fm](https://www.last.fm) + +[Register for an API account here.](https://www.last.fm/api/account/create) + +The Callback URL is actually specified by multi-scrobbler but to keep things consistent you should use +``` +http://localhost:9078/lastfm/callback +``` +or replace `localhost:9078` with your own base URL + +#### Configuration + + + + | Environmental Variable | Required? | Default | Description | + |------------------------|-----------|-----------------------------------------|-------------------------------------------------------------------------------| + | `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. | + + + See [`lastfm.json.example`](https://github.com/FoxxMD/multi-scrobbler/blob/master/config/lastfm.json.example) or [explore the schema with an example and live editor/validator](https://json-schema.app/view/%23/%23%2Fdefinitions%2FLastfmClientConfig?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fmulti-scrobbler%2Fmaster%2Fsrc%2Fbackend%2Fcommon%2Fschema%2Fclient.json) + + + See [`lastfm.json.example`](https://github.com/FoxxMD/multi-scrobbler/blob/master/config/lastfm.json.example) or [explore the schema with an example and live editor/validator](https://json-schema.app/view/%23/%23%2Fdefinitions%2FLastfmClientConfig?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fmulti-scrobbler%2Fmaster%2Fsrc%2Fbackend%2Fcommon%2Fschema%2Fclient.json) + + + +### [Listenbrainz](https://listenbrainz.org) + +You will need to run your own Listenbrainz server or have an account [on the official instance](https://listenbrainz.org/login/) + +On your [profile page](https://listenbrainz.org/profile/) find your **User Token** to use in the configuration. + +#### Configuration + + + + | Environmental Variable | Required? | Default | Description | + |------------------------|-----------|-------------------------------|---------------------------------| + | 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 | + + + See [`listenbrainz.json.example`](https://github.com/FoxxMD/multi-scrobbler/blob/master/config/listenbrainz.json.example) or [explore the schema with an example and live editor/validator](https://json-schema.app/view/%23%2Fdefinitions%2FListenBrainzClientConfig?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fmulti-scrobbler%2Fmaster%2Fsrc%2Fbackend%2Fcommon%2Fschema%2Fclient.json) + + + See [`listenbrainz.json.example`](https://github.com/FoxxMD/multi-scrobbler/blob/master/config/listenbrainz.json.example) or [explore the schema with an example and live editor/validator](https://json-schema.app/view/%23%2Fdefinitions%2FListenBrainzClientConfig?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fmulti-scrobbler%2Fmaster%2Fsrc%2Fbackend%2Fcommon%2Fschema%2Fclient.json) + + + +## Monitoring + +multi-scrobbler supports some common webhooks and a healthcheck endpoint in order to monitor Sources and Clients for errors. + +### Webhook Configurations + +Webhooks will **push** a notification to your configured servers on these events: + +* Source polling started +* Source polling retry +* Source polling stopped on error +* Scrobble client scrobble failure + +Webhooks are configured in the AIO [config.json](#configuration-types) file under the `webhook` top-level property. Multiple webhooks may be configured for each webhook type. EX: + +```json5 +{ + "sources": [ + //... + ], + "clients": [ + //... + ], + "webhooks": [ + { + "name": "FirstGotifyServer", + "type": "gotify", + "url": "http://192.168.0.100:8070", + "token": "abcd" + }, + { + "name": "SecondGotifyServer", + "type": "gotify", + //... + }, + { + "name": "NtfyServerOne", + "type": "ntfy", + //... + }, + //... + ] +} +``` + +#### [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) + +multi-scrobbler optionally supports setting message notification priority via `info` `warn` and `error` mappings. + +EX + +```json +{ + "type": "gotify", + "name": "MyGotifyFriendlyNameForLogs", + "url": "http://192.168.0.100:8070", + "token": "AQZI58fA.rfSZbm", + "priorities": { + "info": 5, + "warn": 7, + "error": 10 + } +} +``` + +#### [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) + +multi-scrobbler optionally supports setting message notification priority via `info` `warn` and `error` mappings. + +EX + +```json +{ + "type": "ntfy", + "name": "MyNtfyFriendlyNameForLogs", + "url": "http://192.168.0.100:9991", + "topic": "RvOwKJ1XtIVMXGLR", + "username": "Optional", + "password": "Optional", + "priorities": { + "info": 3, + "warn": 4, + "error": 5 + } +} +``` + +#### [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) + +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)/ + +EX + +```json5 +{ + "type": "apprise", + "name": "MyAppriseFriendlyNameForLogs", + "host": "http://192.168.0.100:8080", + "urls": ["gotify://192.168.0.101:8070/MyToken"], // stateless endpoints + "keys": ["e90b20526808373353afad7fb98a201198c0c3e0555bea19f182df3388af7b17"], //persistent storage endpoints + "tags": ["my","optional","tags"] +} +``` + +### Health Endpoint + +An endpoint for monitoring the health of sources/clients is available at GET `http://YourMultiScrobblerDomain/health` + +* Returns `200 OK` when **everything** is working or `500 Internal Server Error` if **anything** is not +* The plain url (`/health`) aggregates status of **all clients/sources** -- so any failing client/source will make status return 500 + * Use query params `type` or `name` to restrict client/sources aggregated IE `/health?type=spotify` or `/health?name=MyMaloja` +* On 500 the response returns a JSON payload with `messages` array that describes any issues + * For any clients/sources that require authentication `/health` will return 500 if they are **not authenticated** + * For sources that poll (spotify, yt music, subsonic) `/health` will 500 if they are **not polling** diff --git a/docsite/docs/development/dev-common.md b/docsite/docs/development/dev-common.md index 90568c4a..728899fa 100644 --- a/docsite/docs/development/dev-common.md +++ b/docsite/docs/development/dev-common.md @@ -8,26 +8,6 @@ description: Start here for MS development # Development -
- -Table of Contents - - -* [Architecture](#architecture) -* [Project Setup](#project-setup) -* [Common Development](#common-development) - * [Config](#config) - * [Concrete Class](#concrete-class) - * [Stages](#stages) - * [Stage: Build Data](#stage-build-data) - * [Stage: Check Connection](#stage-check-connection) - * [Stage: Test Auth](#stage-test-auth) - * [Play Object](#play-object) -* [Creating Clients and Sources](#creating-clients-and-sources) - - -
- ## Architecture Multi-scrobbler is written entirely in [Typescript](https://www.typescriptlang.org/). It consists of a backend and frontend. The backend handles all Source/Client logic, mounts web server endpoints that listen for Auth callbacks and Source ingress using [expressjs](https://expressjs.com/), and serves the frontend. The frontend is a standalone [Vitejs](https://vitejs.dev/) app that communicates via API to the backend in order to render the dashboard. diff --git a/docsite/docs/development/dev-source.md b/docsite/docs/development/dev-source.md index a02fe791..13b111b3 100644 --- a/docsite/docs/development/dev-source.md +++ b/docsite/docs/development/dev-source.md @@ -5,34 +5,6 @@ sidebar_position: 2 title: Source Development/Tutorial --- -
- -Table of Contents - - - * [Scenario](#scenario) - * [Minimal Implementation](#minimal-implementation) - * [Define and Implement Config](#define-and-implement-config) - * [Create CoolPlayer Source](#create-coolplayer-source) - * [Initialize Source from Config](#initialize-source-from-config) - * [Implement Play Object Transform](#implement-play-object-transform) - * [Implement Stages](#implement-stages) - * [Build Data](#build-data) - * [Check Connection](#check-connection) - * [Test Auth](#test-auth) - * [Implement Polling](#implement-polling) - * [Further Implementation](#further-implementation) - * [Backlog](#backlog) - * [Other Source Types](#other-source-types) - * [Music History Source](#music-history-source) - * [Non-Polling Source](#non-polling-source) - * [Basic Source](#basic-source) - * [Discovery](#discovery) - * [Scrobbling](#scrobbling) - - -
- This document will provide a step-by-step guide for creating a (trivial) new Source in MS alongside describing what aspects of the Source need to be implemented based on the service you use. Before using this document you should review [Common Development](dev-common.md#common-development). ## Scenario diff --git a/docsite/docs/installation/installation.md b/docsite/docs/installation/installation.md index bb097714..247a6727 100644 --- a/docsite/docs/installation/installation.md +++ b/docsite/docs/installation/installation.md @@ -43,13 +43,13 @@ See [this issue](https://github.com/FoxxMD/multi-scrobbler/issues/135#issuecomme * The web UI and API is served on port `9078`. This can be modified using the `PORT` environmental variable. -#### Using [file-based](../configuration/configuration.md#file-based-configuration) configuration +#### Using [file-based](../configuration/configuration.mdx?fileType=aio#configuration-types) configuration ```shell npm run start ``` -#### Using [env-based](../configuration/configuration.md#env-based-configuration) configuration +#### Using [env-based](../configuration/configuration.mdx?fileType=env#configuration-types) configuration ```shell SPOTIFY_CLIENT_ID=yourId SPOTIFY_CLIENT_SECRET=yourSecret MALOJA_URL="http://domain.tld" node src/index.js @@ -74,7 +74,7 @@ Flatpak users have experienced issues when using multi-scrobbler as a long-runni ### Usage Examples -#### Using [file-based](../configuration/configuration.md#file-based-configuration) configuration +#### Using [file-based](../configuration/configuration.mdx?fileType=aio#configuration-types) configuration The config directory for multi-scrobbler as a flatpak can be found under `/home/YourUser/.var/app/io.github.foxxmd.multiscrobbler/config` @@ -82,7 +82,7 @@ The config directory for multi-scrobbler as a flatpak can be found under `/home/ flatpak run io.github.foxxmd.multiscrobbler ``` -#### Using [env-based](../configuration/configuration.md#env-based-configuration) configuration +#### Using [env-based](../configuration/configuration.mdx?fileType=env#configuration-types) configuration There are a few [options for running flatpak applications with temporary or permanent environmental variables.](https://ardasevinc.dev/launch-flatpak-apps-with-custom-args-and-environment-variables) @@ -128,12 +128,12 @@ The default container port is `9078`. To map container to host port: Optionally, when -* using a [Source or Client](../configuration/configuration.md) that has a "Redirect URI" that you have not explicitly defined +* using a [Source or Client](../configuration/configuration.mdx) that has a "Redirect URI" that you have not explicitly defined * and * using a bridge network or * installing MS on a different machine than the one used to view the dashboard -set the [Base URL](../configuration/configuration.md#base-url) as the IP of the host machine. (This is the IP you would use to view the dashboard in a browser) +set the [Base URL](../configuration/configuration.mdx#base-url) as the IP of the host machine. (This is the IP you would use to view the dashboard in a browser) * With docker: `-e BASE_URL="http://hostMachineIP"` (first port is the port on the host to use) * With docker-compose: [see comments in docker-compose.yml](../../../docker-compose.yml) @@ -162,13 +162,13 @@ To get the UID and GID for the current user run these commands from a terminal: If installing on a different machine make sure all redirect URIs are defined or that you have set a [Base URL](#base-url). -### Using [env-based](../configuration/configuration.md#env-based-configuration) configuration +### Using [env-based](../configuration/configuration.mdx?fileType=env#configuration-types) configuration ```bash docker run -e "SPOTIFY_CLIENT_ID=yourId" -e "SPOTIFY_CLIENT_SECRET=yourSecret" -e "MALOJA_URL=http://domain.tld" -e "MALOJA_API_KEY=1234" -e "PUID=1000" -e "PGID=1000" -p 9078:9078 -v /path/on/host/config:/config foxxmd/multi-scrobbler ``` -### Using [file-based](../configuration/configuration.md#file-based-configuration) configuration +### Using [file-based](../configuration/configuration.mdx?fileType=aio#configuration-types) configuration ```bash docker run -e "PUID=1000" -e "PGID=1000" -p 9078:9078 -v /path/on/host/config:/config foxxmd/multi-scrobbler -- 2.51.2 From a94ac8284f7f7cd76b2c34a35d5e6246f0d5b53f Mon Sep 17 00:00:00 2001 From: FoxxMD Date: Tue, 16 Jul 2024 15:28:09 -0400 Subject: [PATCH 10/16] docs: refactor installation for docusaurus --- docsite/docs/development/flatpak.md | 2 +- docsite/docs/installation/installation.md | 177 ----------- docsite/docs/installation/installation.mdx | 338 +++++++++++++++++++++ docsite/docs/installation/service.md | 6 +- 4 files changed, 342 insertions(+), 181 deletions(-) delete mode 100644 docsite/docs/installation/installation.md create mode 100644 docsite/docs/installation/installation.mdx diff --git a/docsite/docs/development/flatpak.md b/docsite/docs/development/flatpak.md index 7f37a73a..522699df 100644 --- a/docsite/docs/development/flatpak.md +++ b/docsite/docs/development/flatpak.md @@ -8,7 +8,7 @@ description: Building Flatpak App locally :::note -These steps are for building the flatpak from source. If you want to install the application normally then [get it through flathub](../installation/installation.md#flatpak) +These steps are for building the flatpak from source. If you want to install the application normally then [get it through flathub](../installation/installation.mdx#flatpak) ::: diff --git a/docsite/docs/installation/installation.md b/docsite/docs/installation/installation.md deleted file mode 100644 index 247a6727..00000000 --- a/docsite/docs/installation/installation.md +++ /dev/null @@ -1,177 +0,0 @@ ---- -sidebar_position: 1 -title: 'Overview' ---- - -# Installation - -After installation see [service.md](service.md) to configure multi-scrobbler to run automatically in the background. - -## Nodejs - -Clone this repository somewhere and then install from the working directory - -```shell -git clone https://github.com/FoxxMD/multi-scrobbler.git . -cd multi-scrobbler -nvm use # optional, to set correct Node version -npm install -npm run docs:install && npm run build -npm run start -``` - -#### 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.` - -Modify `overrides` in `package.json` to use `@rollup/wasm-node` as a drop-in replacement for rollup: - -```json -"overrides": { - "spotify-web-api-node": { - "superagent": "$superagent" - } - "vite": { - "rollup": "npm:@rollup/wasm-node@^4.9.6" - } -} -``` - -See [this issue](https://github.com/FoxxMD/multi-scrobbler/issues/135#issuecomment-1927080260) for more detail. - -### Usage Examples - -* The web UI and API is served on port `9078`. This can be modified using the `PORT` environmental variable. - -#### Using [file-based](../configuration/configuration.mdx?fileType=aio#configuration-types) configuration - -```shell -npm run start -``` - -#### Using [env-based](../configuration/configuration.mdx?fileType=env#configuration-types) configuration - -```shell -SPOTIFY_CLIENT_ID=yourId SPOTIFY_CLIENT_SECRET=yourSecret MALOJA_URL="http://domain.tld" node src/index.js -``` - -## Flatpak - -You must have [Flatpak](https://flatpak.org/) installed on your system. - -```shell -flatpak install flathub io.github.foxxmd.multiscrobbler -``` - -:::warning - -Flatpak users have experienced issues when using multi-scrobbler as a long-running process. Due to the relative difficulty in debugging issues with flatpak installations it is recommended: - -* to use a [Docker](#docker) installation if possible or -* only if you need access to host-level resources like dbus for [MPRIS](https://foxxmd.github.io/multi-scrobbler/docs/configuration#mpris) and cannot run a [nodejs](#nodejs) installation - -:::: - -### Usage Examples - -#### Using [file-based](../configuration/configuration.mdx?fileType=aio#configuration-types) configuration - -The config directory for multi-scrobbler as a flatpak can be found under `/home/YourUser/.var/app/io.github.foxxmd.multiscrobbler/config` - -```shell -flatpak run io.github.foxxmd.multiscrobbler -``` - -#### Using [env-based](../configuration/configuration.mdx?fileType=env#configuration-types) configuration - -There are a few [options for running flatpak applications with temporary or permanent environmental variables.](https://ardasevinc.dev/launch-flatpak-apps-with-custom-args-and-environment-variables) - -```shell -flatpak run --env=SPOTIFY_CLIENT_ID=yourId --envSPOTIFY_CLIENT_SECRET=yourSecret --env=MALOJA_URL="http://domain.tld" io.github.foxxmd.multiscrobbler -``` - -## Docker - -Cross-platform images are built for x86 (Intel/AMD) and ARM64 (IE Raspberry Pi) - -[Dockerhub](https://hub.docker.com/r/foxxmd/multi-scrobbler) -``` -docker.io/foxxmd/multi-scrobbler:latest -``` - -[Github Packages](https://github.com/FoxxMD/multi-scrobbler/pkgs/container/multi-scrobbler) -``` -ghcr.io/foxxmd/multi-scrobbler:latest -``` - -Or use the provided [docker-compose.yml](../../../docker-compose.yml) after modifying it to fit your configuration. - -Recommended configuration steps for docker or docker-compose usage: - -#### Storage - -You **must** bind a host directory into the container for storing configurations and credentials. Otherwise, these will be lost when the container is updated. - -* [Using `-v` method for docker](https://docs.docker.com/storage/bind-mounts/#start-a-container-with-a-bind-mount): `-v /path/on/host/config:/config` -* [Using docker-compose](https://docs.docker.com/compose/compose-file/compose-file-v3/#short-syntax-3): `- /path/on/host/config:/config` - -#### 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 (Plex, Jellyfin). - -The default container port is `9078`. To map container to host port: - -* With [docker](https://docs.docker.com/engine/reference/commandline/run/#publish): `-p 9078:9078` (first port is the port on the host to use) -* With [docker-compose](https://docs.docker.com/compose/compose-file/compose-file-v3/#short-syntax-1): `- "9078:9078"` - -##### Base URL - -Optionally, when - -* using a [Source or Client](../configuration/configuration.mdx) that has a "Redirect URI" that you have not explicitly defined -* and - * using a bridge network or - * installing MS on a different machine than the one used to view the dashboard - -set the [Base URL](../configuration/configuration.mdx#base-url) as the IP of the host machine. (This is the IP you would use to view the dashboard in a browser) - -* With docker: `-e BASE_URL="http://hostMachineIP"` (first port is the port on the host to use) -* With docker-compose: [see comments in docker-compose.yml](../../../docker-compose.yml) - -#### Other - -* (Optionally) set the [timezone](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) for the container using the environmental variable `TZ` ([docker](https://docs.docker.com/engine/reference/commandline/run/#env)) ([docker-compose](https://docs.docker.com/compose/compose-file/compose-file-v3/#environment)) - -### Linux Host - -If you are - -* using [rootless containers with Podman](https://developers.redhat.com/blog/2020/09/25/rootless-containers-with-podman-the-basics#why_podman_) -* running docker on MacOS or Windows - -this **DOES NOT** apply to you. - -If you are running Docker on a **Linux Host** you must specify `user:group` permissions of the user who owns the **configuration directory** on the host to avoid [docker file permission problems.](https://ikriv.com/blog/?p=4698) These can be specified using the [environmental variables **PUID** and **PGID**.](https://docs.linuxserver.io/general/understanding-puid-and-pgid) - -To get the UID and GID for the current user run these commands from a terminal: - -* `id -u` -- prints UID -* `id -g` -- prints GID - -## Docker Usage Examples - -If installing on a different machine make sure all redirect URIs are defined or that you have set a [Base URL](#base-url). - -### Using [env-based](../configuration/configuration.mdx?fileType=env#configuration-types) configuration - -```bash -docker run -e "SPOTIFY_CLIENT_ID=yourId" -e "SPOTIFY_CLIENT_SECRET=yourSecret" -e "MALOJA_URL=http://domain.tld" -e "MALOJA_API_KEY=1234" -e "PUID=1000" -e "PGID=1000" -p 9078:9078 -v /path/on/host/config:/config foxxmd/multi-scrobbler -``` - -### Using [file-based](../configuration/configuration.mdx?fileType=aio#configuration-types) configuration - -```bash -docker run -e "PUID=1000" -e "PGID=1000" -p 9078:9078 -v /path/on/host/config:/config foxxmd/multi-scrobbler -``` - -See the [docker-compose.yml](../../../docker-compose.yml) file for how to use with docker-compose. diff --git a/docsite/docs/installation/installation.mdx b/docsite/docs/installation/installation.mdx new file mode 100644 index 00000000..9113deb6 --- /dev/null +++ b/docsite/docs/installation/installation.mdx @@ -0,0 +1,338 @@ +--- +sidebar_position: 1 +title: 'Overview' +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +:::tip + +For the difference between **ENV** and **File** examples in this document see [Configuration Types](../configuration/configuration.mdx#configuration-types). + +::: + +## Local Installation + +After installation see [service.md](service.md) to configure multi-scrobbler to run automatically in the background. + +### Nodejs + +Clone this repository somewhere and then install from the working directory + +```shell +git clone https://github.com/FoxxMD/multi-scrobbler.git . +cd multi-scrobbler +nvm use # optional, to set correct Node version +npm install +npm run docs:install && npm run build +npm run start +``` + +#### 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.` + +Modify `overrides` in `package.json` to use `@rollup/wasm-node` as a drop-in replacement for rollup: + +```json +"overrides": { + "spotify-web-api-node": { + "superagent": "$superagent" + } + "vite": { + "rollup": "npm:@rollup/wasm-node@^4.9.6" + } +} +``` + +See [this issue](https://github.com/FoxxMD/multi-scrobbler/issues/135#issuecomment-1927080260) for more detail. + +#### Usage Examples + + + +```shell +SPOTIFY_CLIENT_ID=yourId SPOTIFY_CLIENT_SECRET=yourSecret MALOJA_URL="http://domain.tld" node src/index.js +``` + + + +
+ `./config/config.json` + + ```json title="./config/config.json" + { + "sources": [ + { + "type": "spotify", + "clients": ["myConfig"], + "name": "mySpotifySource", + "data": { + "clientId": "a89cba1569901a0671d5a9875fed4be1", + "clientSecret": "ec42e09d5ae0ee0f0816ca151008412a", + } + } + ], + "clients": [ + { + "type": "maloja", + "name": "myConfig", + "data": { + "url": "http://localhost:42010", + "apiKey": "myMalojaKey" + } + } + ], + } + ``` + +
+ +```shell +npm run start +``` +
+
+ +:::tip + +The web UI and API is served on port `9078`. This can be modified using the `PORT` environmental variable. + +::: + +### Flatpak + +You must have [Flatpak](https://flatpak.org/) installed on your system. + +```shell +flatpak install flathub io.github.foxxmd.multiscrobbler +``` + +:::warning + +Flatpak users have experienced issues when using multi-scrobbler as a long-running process. Due to the relative difficulty in debugging issues with flatpak installations it is recommended: + +* to use a [Docker](#docker) installation if possible or +* only if you need access to host-level resources like dbus for [MPRIS](https://foxxmd.github.io/multi-scrobbler/docs/configuration#mpris) and cannot run a [nodejs](#nodejs) installation + +:::: + +#### Usage Examples + + + + There are a few [options for running flatpak applications with temporary or permanent environmental variables.](https://ardasevinc.dev/launch-flatpak-apps-with-custom-args-and-environment-variables) + + ```shell + flatpak run --env=SPOTIFY_CLIENT_ID=yourId --envSPOTIFY_CLIENT_SECRET=yourSecret --env=MALOJA_URL="http://domain.tld" io.github.foxxmd.multiscrobbler + ``` + + + The config directory for multi-scrobbler as a flatpak can be found under `/home/YourUser/.var/app/io.github.foxxmd.multiscrobbler/config` + + ```shell + flatpak run io.github.foxxmd.multiscrobbler + ``` + + + +## Docker + +Cross-platform images are built for x86 (Intel/AMD) and ARM64 (IE Raspberry Pi) + +:::info[Available Images] + + + + [Repository Page](https://hub.docker.com/r/foxxmd/multi-scrobbler) + ``` + docker.io/foxxmd/multi-scrobbler:latest + ``` + + + [Repository Page](https://github.com/FoxxMD/multi-scrobbler/pkgs/container/multi-scrobbler) + ``` + ghcr.io/foxxmd/multi-scrobbler:latest + ``` + + + +::: + +Or use the provided [docker-compose.yml](../../../docker-compose.yml) after modifying it to fit your configuration. + +Recommended configuration steps for docker or docker-compose usage: + +#### 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. + +
+ +Example + + + + [Using `-v` method for docker](https://docs.docker.com/storage/bind-mounts/#start-a-container-with-a-bind-mount): + ```shell + docker run ... -v /path/on/host/config:/config foxxmd/multi-scrobbler + ``` + + + [Using docker-compose](https://docs.docker.com/compose/compose-file/compose-file-v3/#short-syntax-3): + + ```yaml title="docker-compose.yml" + services: + multi-scrobbler: + # ... + volumes: + - /path/on/host/config:/config + ``` + + + +
+ +#### 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 (Plex, Jellyfin). The default container port is `9078`. + +
+ + Example + + + + [Docker `run` publish options](https://docs.docker.com/engine/reference/commandline/run/#publish): + ```shell + docker run ... -p 9078:9078 foxxmd/multi-scrobbler + ``` + + + [docker-compose](https://docs.docker.com/compose/compose-file/compose-file-v3/#short-syntax-1): + + ```yaml title="docker-compose.yml" + services: + multi-scrobbler: + # ... + ports: + - "9078:9078" + ``` + + + +
+ +##### Base URL + +Optionally, when + +* using a [Source or Client](../configuration/configuration.mdx) that has a "Redirect URI" that you have not explicitly defined +* and + * using a bridge network or + * installing MS on a different machine than the one used to view the dashboard + +set the [Base URL](../configuration/configuration.mdx#base-url) as the IP of the host machine. (This is the IP you would use to view the dashboard in a browser) + +
+ + Example + + + + ```shell + docker run ... -e BASE_URL="http://hostMachineIP" foxxmd/multi-scrobbler + ``` + + + [docker-compose](https://docs.docker.com/compose/compose-file/compose-file-v3/#short-syntax-1): + + ```yaml title="docker-compose.yml" + services: + multi-scrobbler: + # ... + environment: + - BASE_URL="http://hostMachineIP" + ``` + + + +
+ +#### Other + +* (Optionally) set the [timezone](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) for the container using the environmental variable `TZ` ([docker](https://docs.docker.com/engine/reference/commandline/run/#env)) ([docker-compose](https://docs.docker.com/compose/compose-file/compose-file-v3/#environment)) + +### Linux Host + +::::info + +:::note + +If you are using [rootless containers with Podman](https://developers.redhat.com/blog/2020/09/25/rootless-containers-with-podman-the-basics#why_podman_) or are running docker on MacOS/Windows this **DOES NOT** apply to you. + +::: + +If you are running Docker on a **Linux Host** you must specify `user:group` permissions of the user who owns the **configuration directory** on the host to avoid [docker file permission problems.](https://ikriv.com/blog/?p=4698) These can be specified using the [environmental variables **PUID** and **PGID**.](https://docs.linuxserver.io/general/understanding-puid-and-pgid) + +To get the UID and GID for the current user run these commands from a terminal: + +* `id -u` -- prints UID +* `id -g` -- prints GID + +:::: + +### Docker Usage Example + +The example scenario: + +* [Spotify **Source**](../configuration/configuration.mdx#spotify) +* [Maloja **Client**](../configuration/configuration.mdx#maloja) +* Serving app on port `9078` +* Docker container located on a different IP (`192.168.0.100`) so use [Base URL](../configuration/configuration.mdx#base-url) +* Config/data directory on host machine is at `/home/myUser/ms` +* Linux uid/gid is `1000:1000` + + + + + + ```bash + docker run -e "SPOTIFY_CLIENT_ID=yourId" -e "SPOTIFY_CLIENT_SECRET=yourSecret" -e "BASE_URL=192.168.0.100" -e "MALOJA_URL=http://domain.tld" -e "MALOJA_API_KEY=1234" -e "PUID=1000" -e "PGID=1000" -p 9078:9078 -v /home/myUser/ms:/config foxxmd/multi-scrobbler + ``` + + + ```bash + docker run -e "PUID=1000" -e "PGID=1000" -e "BASE_URL=192.168.0.100" -p 9078:9078 -v /home/myUser/ms:/config foxxmd/multi-scrobbler + ``` + + + + + See [`docker-compose.yml`](../../../docker-compose.yml) file for more options and annotations. + + ```yaml title="docker-compose.yml" + services: + multi-scrobbler: + image: foxxmd/multi-scrobbler + container_name: multi-scrobbler + environment: + - TZ=Etc/GMT # Specify timezone from TZ Database name found here https://en.wikipedia.org/wiki/List_of_tz_database_time_zones + - SPOTIFY_CLIENT_ID=yourId + - SPOTIFY_CLIENT_SECRET=yourSecret + - BASE_URL="http://192.168.0.100:9078" + - MALOJA_URL=http://domain.tld:42010 + - MALOJA_API_KEY=1234 + - PUID=1000 + - PGID=1000 + volumes: + - /home/myUser/ms:/config + ports: + - "9078:9078" + restart: unless-stopped + ``` + + + + diff --git a/docsite/docs/installation/service.md b/docsite/docs/installation/service.md index 40137944..d561b7f5 100644 --- a/docsite/docs/installation/service.md +++ b/docsite/docs/installation/service.md @@ -3,7 +3,7 @@ sidebar_position: 2 title: 'As a Service' --- -If you have multi-scrobbler installed [locally](installation.md#nodejs) you can enable it to run as a background service when you login. +If you have multi-scrobbler installed [locally](installation.mdx#nodejs) you can enable it to run as a background service when you login. Before running as a service you should run it at least once in the foreground to ensure it can start up correctly! @@ -38,11 +38,11 @@ Restart=no WantedBy=default.target ``` -The above assumes you [installed multi-scrobbler using flatpak](installation.md#flatpak) +The above assumes you [installed multi-scrobbler using flatpak](installation.mdx#flatpak) ### Node.js Installs -If you are running multi-scrobbler directly with [nodejs from a clone repository directory](installation.md#nodejs) you should modify the `[Service]`: +If you are running multi-scrobbler directly with [nodejs from a clone repository directory](installation.mdx#nodejs) you should modify the `[Service]`: ```ini [Service] -- 2.51.2 From 52b20e4c8e6b7780a51ee4403ea8ce273bb3d73f Mon Sep 17 00:00:00 2001 From: FoxxMD Date: Tue, 16 Jul 2024 15:37:09 -0400 Subject: [PATCH 11/16] docs: Update kitchensink code block titles --- docsite/docs/configuration/kitchensink.md | 28 ++++++----------------- 1 file changed, 7 insertions(+), 21 deletions(-) diff --git a/docsite/docs/configuration/kitchensink.md b/docsite/docs/configuration/kitchensink.md index 2168a6cb..2df29751 100644 --- a/docsite/docs/configuration/kitchensink.md +++ b/docsite/docs/configuration/kitchensink.md @@ -21,9 +21,7 @@ Scenario: ### All-in-one Config -Using just one config file located at `CONFIG_DIR/config.json`: - -```json5 +```json5 title="CONFIG_DIR/config.json" { "sourceDefaults": { "maxPollRetries": 0, // optional, default # of automatic polling restarts on error. can be overridden by property in individual config @@ -160,9 +158,7 @@ Using just one config file located at `CONFIG_DIR/config.json`: ### Separate JSON files -In `CONFIG_DIR/spotify.json`: - -```json5 +```json5 title="CONFIG_DIR/spotify.json" [ { // may omit 'type' property since app knows this is file is for spotify configs @@ -193,9 +189,7 @@ In `CONFIG_DIR/spotify.json`: ] ``` -In `CONFIG_DIR/plex.json` - -```json5 +```json5 title="CONFIG_DIR/plex.json" [ { "name": "fredPlex", @@ -221,9 +215,7 @@ In `CONFIG_DIR/plex.json` ] ``` -In `CONFIG_DIR/jellyfin.json` - -```json5 +```json5 title="CONFIG_DIR/jellyfin.json" [ { "name": "FredJelly", @@ -234,9 +226,7 @@ In `CONFIG_DIR/jellyfin.json` ] ``` -In `CONFIG_DIR/ytmusic.json` - -```json5 +```json5 title="CONFIG_DIR/ytmusic.json" [ { "type": "ytmusic", @@ -250,9 +240,7 @@ In `CONFIG_DIR/ytmusic.json` ] ``` -In `CONFIG_DIR/maloja.json`: - -```json5 +```json5 title="CONFIG_DIR/maloja.json" [ { "name": "foxxMaloja", @@ -278,9 +266,7 @@ In `CONFIG_DIR/maloja.json`: ] ``` -In `CONFIG_DIR/lastfm.json`: - -```json5 +```json5 title="CONFIG_DIR/lastfm.json" [ { "name": "maryLFM", -- 2.51.2 From b02c96ada832c3aa46062efb01fba8901b822313 Mon Sep 17 00:00:00 2001 From: FoxxMD Date: Wed, 17 Jul 2024 09:51:44 -0400 Subject: [PATCH 12/16] docs: Parse and render config examples from repository --- docsite/docs/configuration/configuration.mdx | 500 +++++++++++++++---- docsite/docusaurus.config.ts | 1 + docsite/package-lock.json | 72 ++- docsite/package.json | 2 + docsite/src/components/AIOExample.tsx | 50 ++ docsite/src/components/SchemaLink.tsx | 27 + 6 files changed, 545 insertions(+), 107 deletions(-) create mode 100644 docsite/src/components/AIOExample.tsx create mode 100644 docsite/src/components/SchemaLink.tsx diff --git a/docsite/docs/configuration/configuration.mdx b/docsite/docs/configuration/configuration.mdx index 0e19cef6..ad52731e 100644 --- a/docsite/docs/configuration/configuration.mdx +++ b/docsite/docs/configuration/configuration.mdx @@ -5,7 +5,28 @@ toc_max_heading_level: 3 --- import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; -import Admonition from '@theme/Admonition'; +import CodeBlock from '@theme/CodeBlock'; +import SchemaLink from "../../src/components/SchemaLink"; +import AIOExample from "../../src/components/AIOExample"; + +import AIOConfig from '!!raw-loader!../../../config/config.json.example'; +import ChromecastConfig from '!!raw-loader!../../../config/chromecast.json.example'; +import DeezerConfig from '!!raw-loader!../../../config/chromecast.json.example'; +import JellyfinConfig from '!!raw-loader!../../../config/jellyfin.json.example'; +import JriverfinConfig from '!!raw-loader!../../../config/jriver.json.example'; +import KodiConfig from '!!raw-loader!../../../config/kodi.json.example'; +import LastfmConfig from '!!raw-loader!../../../config/lastfm.json.example'; +import ListenbrainzConfig from '!!raw-loader!../../../config/listenbrainz.json.example'; +import MalojaConfig from '!!raw-loader!../../../config/maloja.json.example'; +import MopidyConfig from '!!raw-loader!../../../config/mopidy.json.example'; +import MprisConfig from '!!raw-loader!../../../config/mpris.json.example'; +import MusikcubeConfig from '!!raw-loader!../../../config/musikcube.json.example'; +import PlexConfig from '!!raw-loader!../../../config/plex.json.example'; +import SpotifyConfig from '!!raw-loader!../../../config/spotify.json.example'; +import SubsonicConfig from '!!raw-loader!../../../config/subsonic.json.example'; +import TautulliConfig from '!!raw-loader!../../../config/tautulli.json.example'; +import WebscrobblerConfig from '!!raw-loader!../../../config/webscrobbler.json.example'; +import YTMusicConfig from '!!raw-loader!../../../config/ytmusic.json.example'; # Configuration @@ -41,7 +62,7 @@ Check the [**FAQ**](../FAQ.md) if you have any issues after configuration! MS will parse configuration files located in the directory specified by the `CONFIG_DIR` environmental variable. This variable defaults to: * Local installation -> `PROJECT_DIR/config` - * Docker -> `/config` (in the container) -- see the [install docs](../installation/installation.md#docker) for how to configure this correctly + * Docker -> `/config` (in the container) -- see the [install docs](../installation/installation.mdx#docker) for how to configure this correctly
@@ -56,8 +77,11 @@ Check the [**FAQ**](../FAQ.md) if you have any issues after configuration!
- There are **example configurations** for all Source/Client types and AIO config located in the [`/config`](https://github.com/FoxxMD/multi-scrobbler/tree/master/config) directory of this project. These can be used as-is by renaming them to `.json`. - For docker installations these examples are copied to your configuration directory on first-time use. There is also a [**kitchensink example**](kitchensink.md) that provides examples of using all sources/clients in a complex configuration. + :::tip + * There are **example configurations** for all Source/Client types and AIO config located in the [`/config`](https://github.com/FoxxMD/multi-scrobbler/tree/master/config) directory of this project. These can be used as-is by renaming them to `.json`. + * For docker/flatpak installations these examples are copied to your configuration directory on first-time use. + * There is also a [**kitchensink example**](kitchensink.md) that provides examples of using all sources/clients in a complex configuration. + ::: Each file is named by the **type** of the Client/Source found in below sections. Each file as an **array** of that type of Client/Source. @@ -73,25 +97,7 @@ Check the [**FAQ**](../FAQ.md) if you have any issues after configuration!
Config Example - ```json5 title="/CONFIG_DIR/maloja.json" - [ - { - "name": "myFirstMalojaClient", - "data": { - "url": "http://myMalojaServer.example", - "apiKey": "myKey" - } - }, - { - "name": "mySecondMalojaClient", - "data": { - "url": "http://my2ndMalojaServer.example", - "apiKey": "myKey" - } - } - ] - - ``` + {SpotifyConfig}
@@ -99,7 +105,7 @@ Check the [**FAQ**](../FAQ.md) if you have any issues after configuration! MS will parse an **all-in-one** configuration file located in the directory specified by the `CONFIG_DIR` environmental variable. This variable defaults to: * Local installation -> `PROJECT_DIR/config/config.json` - * Docker -> `/config/config.json` (in the container) -- see the [install docs](../installation/installation.md#docker) for how to configure this correctly + * Docker -> `/config/config.json` (in the container) -- see the [install docs](../installation/installation.mdx#docker) for how to configure this correctly
@@ -116,7 +122,11 @@ Check the [**FAQ**](../FAQ.md) if you have any issues after configuration! **The AIO config also enables setting default options for sources/clients as well as global options for MS itself.** - An example AIO config files can be found at [/config/config.json.example](https://github.com/FoxxMD/multi-scrobbler/tree/master/config/config.json.example) in the project directory. For docker installations theis example is copied to your configuration directory on first-time use. There is also a [**kitchensink example**](kitchensink.md) that provides examples of using all sources/clients in a complex AOI configuration. + :::tip + * An example AIO config files can be found in the project directory at [`/config/config.json.example`](https://github.com/FoxxMD/multi-scrobbler/tree/master/config/config.json.example) + * For docker/flatpak installations this example is copied to your configuration directory on first-time use. + * There is also a [**kitchensink example**](kitchensink.md) 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) @@ -124,34 +134,7 @@ Check the [**FAQ**](../FAQ.md) if you have any issues after configuration! Config Example - ```json title="/CONFIG_DIR/config.json" - { - "sources": [ - { - "name": "myConfig", - "type": "spotify", - "clients": [ - "myMalojaClient" - ], - "data": { - "clientId": "anExample" - "clientSecret": "anExample", - "redirectUri": "http://localhost:9078/callback" - } - } - ], - "clients": [ - { - "name": "myMalojaClient", - "type": "maloja", - "data": { - "url": "http://myMalojaServer.example", - "apiKey": "myKey" - } - } - ] - } - ``` + {AIOConfig}
@@ -169,7 +152,7 @@ Defines the URL that is used to generate default redirect URLs for authenticatio * Set with [ENV](./configuration?configType=env#configuration-types) `BASE_URL` or `baseUrl` [all-in-one configuration](./configuration?configType=aio#configuration-types) * If protocol is `http` or no protocol is specified MS will try to use port `9078` -- to override this explicitly set the port or use `https` -Useful when running with [docker](../installation/installation.md#docker) so that you do not need to specify redirect URLs for each configuration. +Useful when running with [docker](../installation/installation.mdx#docker) so that you do not need to specify redirect URLs for each configuration.
@@ -231,10 +214,25 @@ If your Spotify player has [Automix](https://community.spotify.com/t5/FAQs/What- | `SPOTIFY_REDIRECT_URI` | No | `http://localhost:9078/callback` | URI must end in `callback` | - See [`spotify.json.example`](https://github.com/FoxxMD/multi-scrobbler/blob/master/config/spotify.json.example) or [explore the schema with an example and live editor/validator](https://json-schema.app/view/%23/%23%2Fdefinitions%2FSpotifySourceConfig?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fmulti-scrobbler%2Fmaster%2Fsrc%2Fbackend%2Fcommon%2Fschema%2Fsource.json) +
+ + Example + + {SpotifyConfig} + +
+ + or
- See [`spotify.json.example`](https://github.com/FoxxMD/multi-scrobbler/blob/master/config/spotify.json.example) or [explore the schema with an example and live editor/validator](https://json-schema.app/view/%23/%23%2Fdefinitions%2FSpotifySourceConfig?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fmulti-scrobbler%2Fmaster%2Fsrc%2Fbackend%2Fcommon%2Fschema%2Fsource.json) +
+ + Example + + + +
+ or
@@ -251,10 +249,27 @@ Check the [instructions](plex.md) on how to setup a [webhooks](https://support.p | `PLEX_USER` | No | | The a comma-delimited list of usernames to scrobble tracks for. No usernames specified means all tracks by all users will be scrobbled. | - See [`plex.json.example`](https://github.com/FoxxMD/multi-scrobbler/blob/master/config/plex.json.example) or [explore the schema with an example and live editor/validator](https://json-schema.app/view/%23/%23%2Fdefinitions%2FPlexSourceConfig?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fmulti-scrobbler%2Fmaster%2Fsrc%2Fbackend%2Fcommon%2Fschema%2Fsource.json) + +
+ + Example + + {PlexConfig} + +
+ + or
- See [`plex.json.example`](https://github.com/FoxxMD/multi-scrobbler/blob/master/config/plex.json.example) or [explore the schema with an example and live editor/validator](https://json-schema.app/view/%23/%23%2Fdefinitions%2FPlexSourceConfig?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fmulti-scrobbler%2Fmaster%2Fsrc%2Fbackend%2Fcommon%2Fschema%2Fsource.json) +
+ + Example + + + +
+ + or
@@ -271,10 +286,27 @@ Check the [instructions](plex.md) on how to setup a notification agent. | `TAUTULLI_USER` | No | | The a comma-delimited list of usernames to scrobble tracks for. No usernames specified means all tracks by all users will be scrobbled. | - See [`tautulli.json.example`](https://github.com/FoxxMD/multi-scrobbler/blob/master/config/tautulli.json.example) or [explore the schema with an example and live editor/validator](https://json-schema.app/view/%23/%23%2Fdefinitions%2FTautulliSourceConfig?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fmulti-scrobbler%2Fmaster%2Fsrc%2Fbackend%2Fcommon%2Fschema%2Fsource.json) + +
+ + Example + + {TautulliConfig} + +
+ + or
- See [`tautulli.json.example`](https://github.com/FoxxMD/multi-scrobbler/blob/master/config/tautulli.json.example) or [explore the schema with an example and live editor/validator](https://json-schema.app/view/%23/%23%2Fdefinitions%2FTautulliSourceConfig?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fmulti-scrobbler%2Fmaster%2Fsrc%2Fbackend%2Fcommon%2Fschema%2Fsource.json) +
+ + Example + + + +
+ + or
@@ -300,10 +332,26 @@ Can use this source for any application that implements the [Subsonic API](http: | `SUBSONIC_URL` | Yes | | Base url of your subsonic-api server | - See [`subsonic.json.example`](https://github.com/FoxxMD/multi-scrobbler/blob/master/config/subsonic.json.example) or [explore the schema with an example and live editor/validator](https://json-schema.app/view/%23/%23%2Fdefinitions%2FSubSonicSourceConfig?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fmulti-scrobbler%2Fmaster%2Fsrc%2Fbackend%2Fcommon%2Fschema%2Fsource.json) +
+ + Example + + {SubsonicConfig} + +
+ + or
- See [`subsonic.json.example`](https://github.com/FoxxMD/multi-scrobbler/blob/master/config/subsonic.json.example) or [explore the schema with an example and live editor/validator](https://json-schema.app/view/%23/%23%2Fdefinitions%2FSubSonicSourceConfig?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fmulti-scrobbler%2Fmaster%2Fsrc%2Fbackend%2Fcommon%2Fschema%2Fsource.json) +
+ + Example + + + +
+ + or
@@ -340,10 +388,27 @@ If you see errors in the MS logs regarding `missing headers` when using Jellyfin | `JELLYFIN_SERVER` | | | Comma-separated list of Jellyfin server names to scrobble from | - See [`jellyfin.json.example`](https://github.com/FoxxMD/multi-scrobbler/blob/master/config/jellyfin.json.example) or [explore the schema with an example and live editor/validator](https://json-schema.app/view/%23/%23%2Fdefinitions%2FJellySourceConfig?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fmulti-scrobbler%2Fmaster%2Fsrc%2Fbackend%2Fcommon%2Fschema%2Fsource.json) +
+ + Example + + {JellyfinConfig} + +
+ + or +
- See [`jellyfin.json.example`](https://github.com/FoxxMD/multi-scrobbler/blob/master/config/jellyfin.json.example) or [explore the schema with an example and live editor/validator](https://json-schema.app/view/%23/%23%2Fdefinitions%2FJellySourceConfig?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fmulti-scrobbler%2Fmaster%2Fsrc%2Fbackend%2Fcommon%2Fschema%2Fsource.json) +
+ + Example + + + +
+ + or
@@ -358,10 +423,28 @@ See the [Last.fm (Client)](#lastfm) setup for registration instructions. No support for ENV based for Last.fm as a client (only source) - See [`lastfm.json.example`](https://github.com/FoxxMD/multi-scrobbler/blob/master/config/lastfm.json.example), change `configureAs` to `source`. Or [explore the schema with an example and live editor/validator](https://json-schema.app/view/%23/%23%2Fdefinitions%2FLastfmSourceConfig?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fmulti-scrobbler%2Fmaster%2Fsrc%2Fbackend%2Fcommon%2Fschema%2Fsource.json) - +
+ Change `configureAs` to `source` + + Example + + {LastfmConfig} + +
+ + or + - See [`lastfm.json.example`](https://github.com/FoxxMD/multi-scrobbler/blob/master/config/lastfm.json.example), change `configureAs` to `source`. Or [explore the schema with an example and live editor/validator](https://json-schema.app/view/%23/%23%2Fdefinitions%2FLastfmSourceConfig?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fmulti-scrobbler%2Fmaster%2Fsrc%2Fbackend%2Fcommon%2Fschema%2Fsource.json) +
+ Change `configureAs` to `source` + + Example + + + +
+ + or
@@ -376,19 +459,33 @@ On your [profile page](https://listenbrainz.org/profile/) find your **User Token - + :::note You cannot use ENV variables shown in the [Listenbrainz Client config](#listenbrainz) -- multi-scrobbler assumes Listenbrainz ENVs are always used for the **client** configuration. You must use the file-based config from below to setup Listenbrainz as a Source. - + ::: - See [`listenbrainz.json.example`](https://github.com/FoxxMD/multi-scrobbler/blob/master/config/listenbrainz.json.example) or [explore the schema with an example and live editor/validator](https://json-schema.app/view/%23%2Fdefinitions%2FListenBrainzSourceConfig?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fmulti-scrobbler%2Fmaster%2Fsrc%2Fbackend%2Fcommon%2Fschema%2Fsource.json) +
+ Change `configureAs` to `source` + + Example - **Change `configureAs` to `source`** + {ListenbrainzConfig} + +
+ + or
- See [`listenbrainz.json.example`](https://github.com/FoxxMD/multi-scrobbler/blob/master/config/listenbrainz.json.example) or [explore the schema with an example and live editor/validator](https://json-schema.app/view/%23%2Fdefinitions%2FListenBrainzSourceConfig?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fmulti-scrobbler%2Fmaster%2Fsrc%2Fbackend%2Fcommon%2Fschema%2Fsource.json) +
+ Change `configureAs` to `source` + + Example + + + +
- **Change `configureAs` to `source`** + or
@@ -421,10 +518,26 @@ After starting multi-scrobbler with credentials in-place open the dashboard (`ht | `DEEZER_REDIRECT_URI` | No | `http://localhost:9078/deezer/callback` | URI must end in `deezer/callback` | - See [`deezer.json.example`](https://github.com/FoxxMD/multi-scrobbler/blob/master/config/deezer.json.example) or [explore the schema with an example and live editor/validator](https://json-schema.app/view/%23/%23%2Fdefinitions%2FDeezerSourceConfig?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fmulti-scrobbler%2Fmaster%2Fsrc%2Fbackend%2Fcommon%2Fschema%2Fsource.json) +
+ + Example + + {DeezerConfig} + +
+ + or
- See [`deezer.json.example`](https://github.com/FoxxMD/multi-scrobbler/blob/master/config/deezer.json.example) or [explore the schema with an example and live editor/validator](https://json-schema.app/view/%23/%23%2Fdefinitions%2FDeezerSourceConfig?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fmulti-scrobbler%2Fmaster%2Fsrc%2Fbackend%2Fcommon%2Fschema%2Fsource.json) +
+ + Example + + + +
+ + or
@@ -459,10 +572,26 @@ Then... No ENV support - See [`ytmusic.json.example`](https://github.com/FoxxMD/multi-scrobbler/blob/master/config/ytmusic.json.example) or [explore the schema with an example and live editor/validator](https://json-schema.app/view/%23/%23%2Fdefinitions%2FYTMusicSourceConfig?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fmulti-scrobbler%2Fmaster%2Fsrc%2Fbackend%2Fcommon%2Fschema%2Fsource.json) +
+ + Example + + {YTMusicConfig} + +
+ + or
- See [`ytmusic.json.example`](https://github.com/FoxxMD/multi-scrobbler/blob/master/config/ytmusic.json.example) or [explore the schema with an example and live editor/validator](https://json-schema.app/view/%23/%23%2Fdefinitions%2FYTMusicSourceConfig?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fmulti-scrobbler%2Fmaster%2Fsrc%2Fbackend%2Fcommon%2Fschema%2Fsource.json) +
+ + Example + + + +
+ + or
@@ -478,7 +607,7 @@ multi-scrobbler can listen to this interface and scrobble tracks played by **any :::note -multi-scrobbler needs to be running as a [**Local Installation**](../installation/installation.md#nodejs) in order to use MPRIS. This cannot be used from docker. +multi-scrobbler needs to be running as a [**Local Installation**](../installation/installation.mdx#nodejs) in order to use MPRIS. This cannot be used from docker. ::: @@ -493,10 +622,26 @@ multi-scrobbler needs to be running as a [**Local Installation**](../installatio | MPRIS_WHITELIST | No | | Comma-delimited list of players names to ONLY scrobble from. Overrides blacklist | - See [`mpris.json.example`](https://github.com/FoxxMD/multi-scrobbler/blob/master/config/mpris.json.example) or [explore the schema with an example and live editor/validator](https://json-schema.app/view/%23%2Fdefinitions%2FMPRISSourceConfig?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fmulti-scrobbler%2Fmaster%2Fsrc%2Fbackend%2Fcommon%2Fschema%2Fsource.json) +
+ + Example + + {MprisConfig} + +
+ + or
- See [`mpris.json.example`](https://github.com/FoxxMD/multi-scrobbler/blob/master/config/mpris.json.example) or [explore the schema with an example and live editor/validator](https://json-schema.app/view/%23%2Fdefinitions%2FMPRISSourceConfig?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fmulti-scrobbler%2Fmaster%2Fsrc%2Fbackend%2Fcommon%2Fschema%2Fsource.json) +
+ + Example + + + +
+ + or
@@ -513,10 +658,26 @@ multi-scrobbler can scrobble tracks played from any Mopidy backend source, regar No ENV support - See [`mopidy.json.example`](https://github.com/FoxxMD/multi-scrobbler/blob/master/config/mopidy.json.example) or [explore the schema with an example and live editor/validator](https://json-schema.app/view/%23%2Fdefinitions%2FMopidySourceConfig/%23%2Fdefinitions%2FMopidyData?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fmulti-scrobbler%2Fmaster%2Fsrc%2Fbackend%2Fcommon%2Fschema%2Fsource.json) +
+ + Example + + {MopidyConfig} + +
+ + or
- See [`mopidy.json.example`](https://github.com/FoxxMD/multi-scrobbler/blob/master/config/mopidy.json.example) or [explore the schema with an example and live editor/validator](https://json-schema.app/view/%23%2Fdefinitions%2FMopidySourceConfig/%23%2Fdefinitions%2FMopidyData?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fmulti-scrobbler%2Fmaster%2Fsrc%2Fbackend%2Fcommon%2Fschema%2Fsource.json) +
+ + Example + + + +
+ + or
@@ -670,10 +831,26 @@ MS transforms this to: `http://mydomain.com:80/jriverReverse/MCWS/v1/` | JRIVER_PASSWORD | No | | If authenticated is enabled, the password set | - See [`jriver.json.example`](https://github.com/FoxxMD/multi-scrobbler/blob/master/config/jriver.json.example) or [explore the schema with an example and live editor/validator](https://json-schema.app/view/%23%2Fdefinitions%2FJRiverSourceConfig/%23%2Fdefinitions%2FJRiverData?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fmulti-scrobbler%2Fmaster%2Fsrc%2Fbackend%2Fcommon%2Fschema%2Fsource.json) - +
+ + Example + + {JriverfinConfig} + +
+ + or + - See [`jriver.json.example`](https://github.com/FoxxMD/multi-scrobbler/blob/master/config/jriver.json.example) or [explore the schema with an example and live editor/validator](https://json-schema.app/view/%23%2Fdefinitions%2FJRiverSourceConfig/%23%2Fdefinitions%2FJRiverData?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fmulti-scrobbler%2Fmaster%2Fsrc%2Fbackend%2Fcommon%2Fschema%2Fsource.json) +
+ + Example + + + +
+ + or
@@ -742,10 +919,26 @@ MS transforms this to: `http://mydomain.com:80/kodiReverse/jsonrpc` | KODI_PASSWORD | No | | The password set | - See [`kodi.json.example`](https://github.com/FoxxMD/multi-scrobbler/blob/master/config/kodi.json.example) or [explore the schema with an example and live editor/validator](https://json-schema.app/view/%23%2Fdefinitions%2FKodiSourceConfig/%23%2Fdefinitions%2FKodiData?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fmulti-scrobbler%2Fmaster%2Fsrc%2Fbackend%2Fcommon%2Fschema%2Fsource.json) +
+ + Example + + {KodiConfig} + +
+ + or
- See [`kodi.json.example`](https://github.com/FoxxMD/multi-scrobbler/blob/master/config/kodi.json.example) or [explore the schema with an example and live editor/validator](https://json-schema.app/view/%23%2Fdefinitions%2FKodiSourceConfig/%23%2Fdefinitions%2FKodiData?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fmulti-scrobbler%2Fmaster%2Fsrc%2Fbackend%2Fcommon%2Fschema%2Fsource.json) +
+ + Example + + + +
+ + or
@@ -770,9 +963,7 @@ If you would like use multiple WebScrobbler sources they can be matched using a Example: -In `webscrobbler.json` - -```json +```json title="webscrobbler.json" [ { "name": "aUserWS", @@ -825,10 +1016,26 @@ This affects **only** MS's behavior and does not affect the general connector be | WS_BLACKLIST | No | | Do not scrobble from these WebScrobbler Connectors. Comma-delimited list | - See [`webscrobbler.json.example`](https://github.com/FoxxMD/multi-scrobbler/blob/master/config/webscrobbler.json.example) or [explore the schema with an example and live editor/validator](https://json-schema.app/view/%23%2Fdefinitions%2FWebScrobblerSourceConfig/%23%2Fdefinitions%2FWebScrobblerData?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fmulti-scrobbler%2Fmaster%2Fsrc%2Fbackend%2Fcommon%2Fschema%2Fsource.json) +
+ + Example + + {WebscrobblerConfig} + +
+ + or
- See [`webscrobbler.json.example`](https://github.com/FoxxMD/multi-scrobbler/blob/master/config/webscrobbler.json.example) or [explore the schema with an example and live editor/validator](https://json-schema.app/view/%23%2Fdefinitions%2FWebScrobblerSourceConfig/%23%2Fdefinitions%2FWebScrobblerData?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fmulti-scrobbler%2Fmaster%2Fsrc%2Fbackend%2Fcommon%2Fschema%2Fsource.json) +
+ + Example + + + +
+ + or
@@ -954,9 +1161,9 @@ To diagnose bad/incomplete track information or strange MS player behavior pleas - + :::note [Manually configuring cast device connections](#connecting-devices) is only available through file-based config. - + ::: | Environmental Variable | Required? | Default | Description | |------------------------|-----------|---------|--------------------------------------------------------------------------------------| @@ -967,10 +1174,27 @@ To diagnose bad/incomplete track information or strange MS player behavior pleas | CC_BLACKLIST_APPS | No | | Do not scrobble from these casted Apps. Comma-delimited list | - See [`chromecast.json.example`](https://github.com/FoxxMD/multi-scrobbler/blob/master/config/chromecast.json.example) or [explore the schema with an example and live editor/validator](https://json-schema.app/view/%23%2Fdefinitions%2FChromecastSourceConfig/%23%2Fdefinitions%2FChromecastData?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fmulti-scrobbler%2Fmaster%2Fsrc%2Fbackend%2Fcommon%2Fschema%2Fsource.json) + +
+ + Example + + {ChromecastConfig} + +
+ + or
- See [`chromecast.json.example`](https://github.com/FoxxMD/multi-scrobbler/blob/master/config/chromecast.json.example) or [explore the schema with an example and live editor/validator](https://json-schema.app/view/%23%2Fdefinitions%2FChromecastSourceConfig/%23%2Fdefinitions%2FChromecastData?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fmulti-scrobbler%2Fmaster%2Fsrc%2Fbackend%2Fcommon%2Fschema%2Fsource.json) +
+ + Example + + + +
+ + or
@@ -1005,10 +1229,26 @@ If no URL is provided to MS it will try to use `ws://localhost:7905` | `MC_PASSWORD` | Yes | | | - See [`musikcube.json.example`](https://github.com/FoxxMD/multi-scrobbler/blob/master/config/chromecast.json.example) or [explore the schema with an example and live editor/validator](https://json-schema.app/view/%23%2Fdefinitions%2FMuikcubeSourceConfig/%23%2Fdefinitions%2FMuikcubeData?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fmulti-scrobbler%2Fmaster%2Fsrc%2Fbackend%2Fcommon%2Fschema%2Fsource.json) +
+ + Example + + {MusikcubeConfig} + +
+ + or
- See [`musikcube.json.example`](https://github.com/FoxxMD/multi-scrobbler/blob/master/config/chromecast.json.example) or [explore the schema with an example and live editor/validator](https://json-schema.app/view/%23%2Fdefinitions%2FMuikcubeSourceConfig/%23%2Fdefinitions%2FMuikcubeData?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fmulti-scrobbler%2Fmaster%2Fsrc%2Fbackend%2Fcommon%2Fschema%2Fsource.json) +
+ + Example + + + +
+ + or
@@ -1026,10 +1266,27 @@ If no URL is provided to MS it will try to use `ws://localhost:7905` | `MALOJA_API_KEY` | Yes | | Api Key | - See [`maloja.json.example`](https://github.com/FoxxMD/multi-scrobbler/blob/master/config/maloja.json.example) or [explore the schema with an example and live editor/validator](https://json-schema.app/view/%23/%23%2Fdefinitions%2FMalojaClientConfig?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fmulti-scrobbler%2Fmaster%2Fsrc%2Fbackend%2Fcommon%2Fschema%2Fclient.json) + +
+ + Example + + {MalojaConfig} + +
+ + or
- See [`maloja.json.example`](https://github.com/FoxxMD/multi-scrobbler/blob/master/config/maloja.json.example) or [explore the schema with an example and live editor/validator](https://json-schema.app/view/%23/%23%2Fdefinitions%2FMalojaClientConfig?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fmulti-scrobbler%2Fmaster%2Fsrc%2Fbackend%2Fcommon%2Fschema%2Fclient.json) +
+ + Example + + + +
+ + or
@@ -1053,12 +1310,30 @@ or replace `localhost:9078` with your own base URL | `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. | + LastfmClientConfig - See [`lastfm.json.example`](https://github.com/FoxxMD/multi-scrobbler/blob/master/config/lastfm.json.example) or [explore the schema with an example and live editor/validator](https://json-schema.app/view/%23/%23%2Fdefinitions%2FLastfmClientConfig?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fmulti-scrobbler%2Fmaster%2Fsrc%2Fbackend%2Fcommon%2Fschema%2Fclient.json) + +
+ + Example + + {LastfmConfig} + +
+ + or
- See [`lastfm.json.example`](https://github.com/FoxxMD/multi-scrobbler/blob/master/config/lastfm.json.example) or [explore the schema with an example and live editor/validator](https://json-schema.app/view/%23/%23%2Fdefinitions%2FLastfmClientConfig?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fmulti-scrobbler%2Fmaster%2Fsrc%2Fbackend%2Fcommon%2Fschema%2Fclient.json) +
+ + Example + + + +
+ + or
@@ -1079,10 +1354,27 @@ On your [profile page](https://listenbrainz.org/profile/) find your **User Token | LZ_URL | No | https://api.listenbrainz.org/ | The base URL for the LZ server | - See [`listenbrainz.json.example`](https://github.com/FoxxMD/multi-scrobbler/blob/master/config/listenbrainz.json.example) or [explore the schema with an example and live editor/validator](https://json-schema.app/view/%23%2Fdefinitions%2FListenBrainzClientConfig?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fmulti-scrobbler%2Fmaster%2Fsrc%2Fbackend%2Fcommon%2Fschema%2Fclient.json) + +
+ + Example + + {ListenbrainzConfig} + +
+ + or
- See [`listenbrainz.json.example`](https://github.com/FoxxMD/multi-scrobbler/blob/master/config/listenbrainz.json.example) or [explore the schema with an example and live editor/validator](https://json-schema.app/view/%23%2Fdefinitions%2FListenBrainzClientConfig?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fmulti-scrobbler%2Fmaster%2Fsrc%2Fbackend%2Fcommon%2Fschema%2Fclient.json) +
+ + Example + + + +
+ + or
diff --git a/docsite/docusaurus.config.ts b/docsite/docusaurus.config.ts index 42bd1fd9..9771fa08 100644 --- a/docsite/docusaurus.config.ts +++ b/docsite/docusaurus.config.ts @@ -155,6 +155,7 @@ const config: Config = { prism: { theme: themes.themes.github, darkTheme: themes.themes.dracula, + additionalLanguages: ['json','json5','typescript'] }, colorMode: { defaultMode: 'dark', diff --git a/docsite/package-lock.json b/docsite/package-lock.json index 029a3bc8..3e072045 100644 --- a/docsite/package-lock.json +++ b/docsite/package-lock.json @@ -14,7 +14,9 @@ "@mdx-js/react": "^3.0.0", "clsx": "^2.0.0", "docusaurus-json-schema-plugin": "^1.12.1", + "micromark-extension-directive": "^3.0.1", "prism-react-renderer": "^2.3.0", + "raw-loader": "^4.0.2", "react": "^18.0.0", "react-dom": "^18.0.0" }, @@ -9137,9 +9139,9 @@ ] }, "node_modules/micromark-extension-directive": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/micromark-extension-directive/-/micromark-extension-directive-3.0.0.tgz", - "integrity": "sha512-61OI07qpQrERc+0wEysLHMvoiO3s2R56x5u7glHq2Yqq6EHbH4dW25G9GfDdGCDYqA21KE6DWgNSzxSwHc2hSg==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/micromark-extension-directive/-/micromark-extension-directive-3.0.1.tgz", + "integrity": "sha512-VGV2uxUzhEZmaP7NSFo2vtq7M2nUD+WfmYQD+d8i/1nHbzE+rMy9uzTvUybBbNiVbrhOZibg3gbyoARGqgDWyg==", "dependencies": { "devlop": "^1.0.0", "micromark-factory-space": "^2.0.0", @@ -12192,6 +12194,70 @@ "node": ">= 0.8" } }, + "node_modules/raw-loader": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/raw-loader/-/raw-loader-4.0.2.tgz", + "integrity": "sha512-ZnScIV3ag9A4wPX/ZayxL/jZH+euYb6FcUinPcgiQW0+UBtEv0O6Q3lGd3cqJ+GHH+rksEv3Pj99oxJ3u3VIKA==", + "dependencies": { + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" + } + }, + "node_modules/raw-loader/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/raw-loader/node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/raw-loader/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + }, + "node_modules/raw-loader/node_modules/schema-utils": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, "node_modules/rc": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", diff --git a/docsite/package.json b/docsite/package.json index 4f2e7b07..211a9aa6 100644 --- a/docsite/package.json +++ b/docsite/package.json @@ -20,7 +20,9 @@ "@mdx-js/react": "^3.0.0", "clsx": "^2.0.0", "docusaurus-json-schema-plugin": "^1.12.1", + "micromark-extension-directive": "^3.0.1", "prism-react-renderer": "^2.3.0", + "raw-loader": "^4.0.2", "react": "^18.0.0", "react-dom": "^18.0.0" }, diff --git a/docsite/src/components/AIOExample.tsx b/docsite/src/components/AIOExample.tsx new file mode 100644 index 00000000..df388432 --- /dev/null +++ b/docsite/src/components/AIOExample.tsx @@ -0,0 +1,50 @@ +import React, { Fragment } from "react" +import CodeBlock from '@theme/CodeBlock'; +import Admonition from '@theme/Admonition'; +import ErrorBoundary from "@docusaurus/ErrorBoundary" +import Error from "@theme/Error" +import { Simulate } from "react-dom/test-utils"; +import error = Simulate.error; + +export interface AIOProps { + data: string + client?: boolean + name: string +} + +const AIOExample = (props: AIOProps) => { + const { + data, + name, + client = false + } = props; + + let configObj; + // eslint-disable-next-line prefer-const + try { + configObj = JSON.parse(data); + } catch (e) { + console.error(e); + return +

Example component crashed because of error!

+ {e.message} +
+ } + configObj[0].type = name; + const configType = client ? 'clients' : 'sources'; + + const aio = {[configType]: configObj}; + return {JSON.stringify(aio, null, 2)} +} + +const WrappedAIOExample = (props: AIOProps) => { + return ( +
+

Example component crashed because of error: {error.message}.

+
+ )} + >
+} + +export default WrappedAIOExample; diff --git a/docsite/src/components/SchemaLink.tsx b/docsite/src/components/SchemaLink.tsx new file mode 100644 index 00000000..ad50983b --- /dev/null +++ b/docsite/src/components/SchemaLink.tsx @@ -0,0 +1,27 @@ +import React, {PropsWithChildren, Fragment} from "react" + +export interface SchemaLinkProps { + objectName: string + lower?: boolean + client?: boolean +} + +const sourceURL = 'https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fmulti-scrobbler%2Fmaster%2Fsrc%2Fbackend%2Fcommon%2Fschema%2Fsource.json'; +const clientURL = 'https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fmulti-scrobbler%2Fmaster%2Fsrc%2Fbackend%2Fcommon%2Fschema%2Fclient.json'; + +const SchemaLink = (props: PropsWithChildren) => { + const { + children, + lower, + client = false + } = props; + let content = children; + if(content === undefined) { + content = {lower ? 'explore' : 'Explore'} the schema with an example and live editor/validator + } + const definition = `https://json-schema.app/view/%23/%23%2Fdefinitions%2F${props.objectName}`; + const url = client ? clientURL : sourceURL; + return {content} +} + +export default SchemaLink; -- 2.51.2 From 8b0c7205b7fa4693b47149bfa0f17d7dff153226 Mon Sep 17 00:00:00 2001 From: FoxxMD Date: Wed, 17 Jul 2024 11:33:56 -0400 Subject: [PATCH 13/16] docs: Add quick start guide --- README.md | 6 +- docsite/docs/configuration/_category_.json | 2 +- docsite/docs/configuration/configuration.mdx | 3 +- docsite/docs/development/_category_.json | 2 +- docsite/docs/installation/_category_.json | 2 +- docsite/docs/installation/installation.mdx | 38 +++-- docsite/docs/installation/service.md | 4 +- docsite/docs/quickstart.mdx | 165 +++++++++++++++++++ docsite/docusaurus.config.ts | 9 +- docsite/package-lock.json | 9 + docsite/package.json | 1 + docsite/src/pages/index.mdx | 6 + 12 files changed, 223 insertions(+), 24 deletions(-) create mode 100644 docsite/docs/quickstart.mdx diff --git a/README.md b/README.md index db651089..affa2cb0 100644 --- a/README.md +++ b/README.md @@ -39,7 +39,7 @@ A javascript app to scrobble music you listened to, to [Maloja](https://github.c * Easy configuration through ENVs or JSON * Install using [Docker images for x86/ARM](https://foxxmd.github.io/multi-scrobbler/docs/installation#docker#docker), [flatpak](https://foxxmd.github.io/multi-scrobbler/docs/installation#docker#flatpak), or [locally with NodeJS](https://foxxmd.github.io/multi-scrobbler/docs/installation#docker#nodejs) -[**Read The Docs to get started**](https://foxxmd.github.io/multi-scrobbler/docs/installation) +[**Quick Start Guide**](https://foxxmd.github.io/multi-scrobbler/docs/quickstart) @@ -77,6 +77,10 @@ Client configurations consist of: * A friendly name. * Any data needed to communicate or authenticate with the Client. +## Quick Start + +[See the **Quick Start Guide**](https://foxxmd.github.io/multi-scrobbler/docs/quickstart) + ## Installation [See the **Installation** documentation](https://foxxmd.github.io/multi-scrobbler/docs/installation) diff --git a/docsite/docs/configuration/_category_.json b/docsite/docs/configuration/_category_.json index 18e70148..1ec2cf62 100644 --- a/docsite/docs/configuration/_category_.json +++ b/docsite/docs/configuration/_category_.json @@ -1,6 +1,6 @@ { "label": "Configuration", - "position": 2, + "position": 3, "link": { "type": "generated-index", "description": "Configuring Multi-Scrobbler and examples" diff --git a/docsite/docs/configuration/configuration.mdx b/docsite/docs/configuration/configuration.mdx index ad52731e..5eb6e645 100644 --- a/docsite/docs/configuration/configuration.mdx +++ b/docsite/docs/configuration/configuration.mdx @@ -357,6 +357,8 @@ Can use this source for any application that implements the [Subsonic API](http: ### [Jellyfin](https://jellyfin.org/) +#### Webhook Setup + Must be using Jellyfin 10.7 or greater * In the Jellyfin desktop web UI Navigate to -> Administration -> Dashboard -> Plugins -> Catalog @@ -1310,7 +1312,6 @@ or replace `localhost:9078` with your own base URL | `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. | - LastfmClientConfig diff --git a/docsite/docs/development/_category_.json b/docsite/docs/development/_category_.json index 6942c16c..10e299b6 100644 --- a/docsite/docs/development/_category_.json +++ b/docsite/docs/development/_category_.json @@ -1,6 +1,6 @@ { "label": "Development", - "position": 3, + "position": 4, "link": { "type": "generated-index", "description": "Developing for Multi-Scrobbler and tutorials" diff --git a/docsite/docs/installation/_category_.json b/docsite/docs/installation/_category_.json index 89454591..126765d8 100644 --- a/docsite/docs/installation/_category_.json +++ b/docsite/docs/installation/_category_.json @@ -1,6 +1,6 @@ { "label": "Installation", - "position": 1, + "position": 2, "link": { "type": "generated-index", "description": "Way to install Multi-Scrobbler" diff --git a/docsite/docs/installation/installation.mdx b/docsite/docs/installation/installation.mdx index 9113deb6..dbe1f40d 100644 --- a/docsite/docs/installation/installation.mdx +++ b/docsite/docs/installation/installation.mdx @@ -285,6 +285,12 @@ To get the UID and GID for the current user run these commands from a terminal: ### Docker Usage Example +:::tip + +See the [**Quick Start Guide**](../quickstart.mdx) for another guided docker-compose example + +::: + The example scenario: * [Spotify **Source**](../configuration/configuration.mdx#spotify) @@ -315,22 +321,22 @@ The example scenario: ```yaml title="docker-compose.yml" services: multi-scrobbler: - image: foxxmd/multi-scrobbler - container_name: multi-scrobbler - environment: - - TZ=Etc/GMT # Specify timezone from TZ Database name found here https://en.wikipedia.org/wiki/List_of_tz_database_time_zones - - SPOTIFY_CLIENT_ID=yourId - - SPOTIFY_CLIENT_SECRET=yourSecret - - BASE_URL="http://192.168.0.100:9078" - - MALOJA_URL=http://domain.tld:42010 - - MALOJA_API_KEY=1234 - - PUID=1000 - - PGID=1000 - volumes: - - /home/myUser/ms:/config - ports: - - "9078:9078" - restart: unless-stopped + image: foxxmd/multi-scrobbler + container_name: multi-scrobbler + environment: + - TZ=Etc/GMT # Specify timezone from TZ Database name found here https://en.wikipedia.org/wiki/List_of_tz_database_time_zones + - SPOTIFY_CLIENT_ID=yourId + - SPOTIFY_CLIENT_SECRET=yourSecret + - BASE_URL="http://192.168.0.100:9078" + - MALOJA_URL=http://domain.tld:42010 + - MALOJA_API_KEY=1234 + - PUID=1000 + - PGID=1000 + volumes: + - /home/myUser/ms:/config + ports: + - "9078:9078" + restart: unless-stopped ``` diff --git a/docsite/docs/installation/service.md b/docsite/docs/installation/service.md index d561b7f5..77bcdbbb 100644 --- a/docsite/docs/installation/service.md +++ b/docsite/docs/installation/service.md @@ -17,7 +17,7 @@ This setup will create a [user service](https://wiki.archlinux.org/title/systemd Create a new service file for multi-scrobbler under your HOME config: -```console +```bash mkdir -p ~/.config/systemd/user touch ~/.config/systemd/user/multi-scrobbler.service ``` @@ -56,7 +56,7 @@ Restart=no Save the file then run: -```console +```bash systemctl daemon-reload systemctl --user enable multi-scrobbler.service systemctl --user start multi-scrobbler.service diff --git a/docsite/docs/quickstart.mdx b/docsite/docs/quickstart.mdx new file mode 100644 index 00000000..2c2e0d50 --- /dev/null +++ b/docsite/docs/quickstart.mdx @@ -0,0 +1,165 @@ +--- +title: 'Quickstart' +sidebar_position: 1 +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +This guide will get you up and running with multi-scrobbler using [Docker](https://www.docker.com/) and [`docker compose`](https://docs.docker.com/compose/). At the end of the guide you will have: + +* the dashboard served on port `9078` of a host machine which has an IP of `192.168.0.100` +* data saved to the same directory as the `docker-compose.yml` file +* multi-scrobbler monitoring [Spotify](./configuration/configuration.mdx#spotify) and/or [Jellyfin](./configuration/configuration.mdx#jellyfin) for listening activity +* multi-scrobbler scrobbling to [Lastfm](./configuration/configuration.mdx#lastfm) and/or [Maloja](./configuration/configuration.mdx#maloja) + +:::note + +If the multi-scrobbler container is on the same machine you will be viewing the dashboard from (IE `localhost`) you can remove and ignore `BASE_URL` usage below. Additionally, replace usage of `192.168.0.100` with `localhost`. + +::: + +## Create Docker Compose File + +Create a new folder for multi-scrobbler related data and then create `docker-compose.yml` with this content: + +```yaml title="~/msData/docker-compose.yml" +services: + multi-scrobbler: + image: foxxmd/multi-scrobbler + container_name: multi-scrobbler + environment: + - TZ=Etc/GMT # Specify timezone from TZ Database name found here https://en.wikipedia.org/wiki/List_of_tz_database_time_zones + - BASE_URL="http://192.168.0.100:9078" + # all Environmental Variables in below examples go here! + + volumes: + - "$PWD/config:/config" + ports: + - "9078:9078" + restart: unless-stopped +``` + +## Setup Sources + +**Sources** are the services multi-scrobbler monitors to look for listening activity. + + + + Follow the Jellyfin configuration [instructions for setting up a **webhook**.](./configuration/configuration.mdx#jellyfin) + + After webhook is setup add **at least one** of these values to the `environment` section in the [`docker-compose.yml` you created.](#create-docker-compose-file) + + ```yaml title="~/msData/docker-compose.yml" + - JELLYFIN_USER=myUserName # comma-separated list of users to monitor + - JELLYFIN_SERVER=myServerName # comma-separated list of servers that should be monitored + ``` + + + To access your Spotify activity you must [register a Spotify application](https://developer.spotify.com/dashboard) to get a + **Client ID/Secret**. + + When creating the application add this to **Redirect URIs** + + ``` + http://192.168.0.100:9078/callback + ``` + + After the application is created add these values to the `environment` section in the [`docker-compose.yml` you created.](#create-docker-compose-file) + + ```yaml title="~/msData/docker-compose.yml" + - SPOTIFY_CLIENT_ID=yourClientId + - SPOTIFY_CLIENT_SECRET=yourClientSecret + ``` + + Later, after [starting multi-scrobbler](#start-multi-scrobbler), visit the dashboard at `http://192.168.0.100:9078` and click **(Re)authenticate** on the Spotify card to authorize multi-scrobbler to use your account. Monitoring will begin automatically after authorization is complete. + + + +## Setup Clients + +**Clients** are services that store scrobbles. Multi-scrobbler will scrobble all listening activity from the **Sources** you configured to all **Clients** you configure here. + + + + Setup a [Maloja server](https://github.com/krateng/maloja?tab=readme-ov-file#how-to-install) if you have not already done this. + +
+ + Maloja Setup Intructions + + Using Maloja's example `docker-compose.yml`: + + ```yaml reference title="~/malojaData/docker-compose.yml" + https://github.com/krateng/maloja/blob/master/example-compose.yml + ``` + + Uncomment `environment` and add `MALOJA_FORCE_PASSWORD=CHANGE_ME` to set an admin password + + Start the container: + + ```shell title="~/malojaData" + docker compose up -d + ``` +
+ + * Navigate to the Admin Panel (Cog in upper-right corner) -> API Keys (or at http://192.168.0.100:42010/admin_apikeys) + * Create a **New Key** and then copy the generated key value + + Finally, add these values to the `environment` section in the [`docker-compose.yml` you created for multi-scrobbler earlier.](#create-docker-compose-file) + + ```yaml title="~/msData/docker-compose.yml" + - MALOJA_URL="http://192.168.0.100:42010" + - MALOJA_API_KEY=myApiKey + ``` +
+ + [Register for an API account at Last.fm.](https://www.last.fm/api/account/create) + + Use the following for **Callback URL**: + + ``` + http://192.168.0.100:9078/lastfm/callback + ``` + + After account creation use the displayed information and add these values to the `environment` section in the [`docker-compose.yml` you created for multi-scrobbler earlier.](#create-docker-compose-file) + + ```yaml title="~/msData/docker-compose.yml" + - LASTFM_API_KEY=myApiKey + - LASTFM_SECRET=myApiSecret + ``` + +
+ +## Start Multi-Scrobbler + +:::tip + +If you are running your multi-scrobbler container on a Linux host see [these instructions for setting proper file permissions.](./installation/installation.mdx#linux-host) + +::: + +From the same directory as the [`docker-compose.yml` you created earlier](#create-docker-compose-file) start the container: + +```shell title="~/msData" +docker compose up -d +``` + +You're done! Multi-scrobbler is now running. It will monitor the sources you configured and scrobble to clients you set up. + +Visit `http://192.168.0.100:9078` to see the dashboard where + +* configured Sources/Clients + * show current status and authentication options + * display statistics about discovered/scrobbled tracks and Now Playing status +* a real-time log shows multi-scrobbler's activity + +## Next Steps + +* See more advanced docker options as well as other install methods in the [**Installation**](./installation/installation.mdx#docker) docs +* Review the [**Configuration**](./configuration/configuration.mdx) docs + * Learn about how to configure multi-scrobbler using files for more complicated Source/Client scenarios + * See all available Sources/Clients alongside configuration examples + * Learn how to set up [notification webhooks](./configuration/configuration.mdx#webhook-configurations) + * Check out the [kitchensink example](./configuration/kitchensink.md) +* Consult the [**FAQ**](./FAQ.md) for solutions to common problems diff --git a/docsite/docusaurus.config.ts b/docsite/docusaurus.config.ts index 9771fa08..04f48d10 100644 --- a/docsite/docusaurus.config.ts +++ b/docsite/docusaurus.config.ts @@ -75,6 +75,7 @@ const config: Config = { // ``` }, ], + 'docusaurus-theme-github-codeblock' ], plugins: [ ], @@ -155,13 +156,19 @@ const config: Config = { prism: { theme: themes.themes.github, darkTheme: themes.themes.dracula, - additionalLanguages: ['json','json5','typescript'] + additionalLanguages: ['json','json5','typescript', 'docker', 'bash', 'ini'] }, colorMode: { defaultMode: 'dark', disableSwitch: false, respectPrefersColorScheme: false, }, + codeblock: { + showGithubLink: true, + githubLinkLabel: 'View on GitHub', + showRunmeLink: false, + runmeLinkLabel: 'Checkout via Runme' + } } satisfies Preset.ThemeConfig, }; diff --git a/docsite/package-lock.json b/docsite/package-lock.json index 3e072045..baae91f4 100644 --- a/docsite/package-lock.json +++ b/docsite/package-lock.json @@ -14,6 +14,7 @@ "@mdx-js/react": "^3.0.0", "clsx": "^2.0.0", "docusaurus-json-schema-plugin": "^1.12.1", + "docusaurus-theme-github-codeblock": "^2.0.2", "micromark-extension-directive": "^3.0.1", "prism-react-renderer": "^2.3.0", "raw-loader": "^4.0.2", @@ -5991,6 +5992,14 @@ "react": ">=17 <= 18" } }, + "node_modules/docusaurus-theme-github-codeblock": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/docusaurus-theme-github-codeblock/-/docusaurus-theme-github-codeblock-2.0.2.tgz", + "integrity": "sha512-H2WoQPWOLjGZO6KS58Gsd+eUVjTFJemkReiSSu9chqokyLc/3Ih3+zPRYfuEZ/HsDvSMIarf7CNcp+Vt+/G+ig==", + "dependencies": { + "@docusaurus/types": "^3.0.0" + } + }, "node_modules/dom-converter": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz", diff --git a/docsite/package.json b/docsite/package.json index 211a9aa6..ef4958f8 100644 --- a/docsite/package.json +++ b/docsite/package.json @@ -20,6 +20,7 @@ "@mdx-js/react": "^3.0.0", "clsx": "^2.0.0", "docusaurus-json-schema-plugin": "^1.12.1", + "docusaurus-theme-github-codeblock": "^2.0.2", "micromark-extension-directive": "^3.0.1", "prism-react-renderer": "^2.3.0", "raw-loader": "^4.0.2", diff --git a/docsite/src/pages/index.mdx b/docsite/src/pages/index.mdx index 7904d6d0..e5f8137a 100644 --- a/docsite/src/pages/index.mdx +++ b/docsite/src/pages/index.mdx @@ -40,6 +40,8 @@ A javascript app to scrobble music you listened to, to [Maloja](https://github.c * Easy configuration through ENVs or JSON * Install using [Docker images for x86/ARM](docs/installation#docker), [flatpak](docs/installation#flatpak), or [locally with NodeJS](docs/installation#nodejs) +[**Quick Start Guide**](docs/quickstart) + **Why should I use this over a browser extension and/or mobile app scrobbler?** @@ -76,6 +78,10 @@ Client configurations consist of: * A friendly name. * Any data needed to communicate or authenticate with the Client. +## Quick Start + +[See the **Quick Start Guide**](docs/quickstart.mdx) + ## Installation [See the **Installation** documentation](docs/installation) -- 2.51.2 From 61c33da2b0d1e1db978ccbae6d727ef56d7f8c9b Mon Sep 17 00:00:00 2001 From: FoxxMD Date: Wed, 17 Jul 2024 11:39:41 -0400 Subject: [PATCH 14/16] docs: Fix quickstart link --- docsite/src/pages/index.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docsite/src/pages/index.mdx b/docsite/src/pages/index.mdx index e5f8137a..be25f971 100644 --- a/docsite/src/pages/index.mdx +++ b/docsite/src/pages/index.mdx @@ -80,7 +80,7 @@ Client configurations consist of: ## Quick Start -[See the **Quick Start Guide**](docs/quickstart.mdx) +[See the **Quick Start Guide**](docs/quickstart) ## Installation -- 2.51.2 From 12ff1f421e1ceb3bb0f5fa7aaeeedd8defba55ec Mon Sep 17 00:00:00 2001 From: FoxxMD Date: Wed, 17 Jul 2024 11:46:00 -0400 Subject: [PATCH 15/16] docs: Use relative paths for volume mounting --- docsite/docs/installation/installation.mdx | 10 +++++----- docsite/docs/quickstart.mdx | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/docsite/docs/installation/installation.mdx b/docsite/docs/installation/installation.mdx index dbe1f40d..6835847a 100644 --- a/docsite/docs/installation/installation.mdx +++ b/docsite/docs/installation/installation.mdx @@ -176,7 +176,7 @@ You **should** bind a host directory into the container for storing configuratio [Using `-v` method for docker](https://docs.docker.com/storage/bind-mounts/#start-a-container-with-a-bind-mount): ```shell - docker run ... -v /path/on/host/config:/config foxxmd/multi-scrobbler + docker run ... -v "$(pwd)/config:/config" foxxmd/multi-scrobbler ``` @@ -187,7 +187,7 @@ You **should** bind a host directory into the container for storing configuratio multi-scrobbler: # ... volumes: - - /path/on/host/config:/config + - "./config:/config" ``` @@ -297,7 +297,7 @@ The example scenario: * [Maloja **Client**](../configuration/configuration.mdx#maloja) * Serving app on port `9078` * Docker container located on a different IP (`192.168.0.100`) so use [Base URL](../configuration/configuration.mdx#base-url) -* Config/data directory on host machine is at `/home/myUser/ms` +* Config/data directory on host machine in a directory next to `docker-compose.yml` * Linux uid/gid is `1000:1000` @@ -310,7 +310,7 @@ The example scenario: ```bash - docker run -e "PUID=1000" -e "PGID=1000" -e "BASE_URL=192.168.0.100" -p 9078:9078 -v /home/myUser/ms:/config foxxmd/multi-scrobbler + docker run -e "PUID=1000" -e "PGID=1000" -e "BASE_URL=192.168.0.100" -p 9078:9078 -v "$(pwd)/config:/config" foxxmd/multi-scrobbler ``` @@ -333,7 +333,7 @@ The example scenario: - PUID=1000 - PGID=1000 volumes: - - /home/myUser/ms:/config + - "./config:/config" ports: - "9078:9078" restart: unless-stopped diff --git a/docsite/docs/quickstart.mdx b/docsite/docs/quickstart.mdx index 2c2e0d50..2bd55248 100644 --- a/docsite/docs/quickstart.mdx +++ b/docsite/docs/quickstart.mdx @@ -34,7 +34,7 @@ services: # all Environmental Variables in below examples go here! volumes: - - "$PWD/config:/config" + - "./config:/config" ports: - "9078:9078" restart: unless-stopped -- 2.51.2 From 16cef0ae653b878e437ffc0de2fb1d76101724f1 Mon Sep 17 00:00:00 2001 From: FoxxMD Date: Wed, 17 Jul 2024 12:46:18 -0400 Subject: [PATCH 16/16] chore: Bump versions for release --- flatpak/io.github.foxxmd.multiscrobbler.metainfo.xml | 1 + package-lock.json | 2 +- package.json | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/flatpak/io.github.foxxmd.multiscrobbler.metainfo.xml b/flatpak/io.github.foxxmd.multiscrobbler.metainfo.xml index 8110adaa..42531010 100644 --- a/flatpak/io.github.foxxmd.multiscrobbler.metainfo.xml +++ b/flatpak/io.github.foxxmd.multiscrobbler.metainfo.xml @@ -50,6 +50,7 @@ + diff --git a/package-lock.json b/package-lock.json index fead4ad6..04a84c8a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "multi-scrobbler", - "version": "0.8.0", + "version": "0.8.1", "lockfileVersion": 3, "requires": true, "packages": { diff --git a/package.json b/package.json index e19c3cff..4a161d5f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "multi-scrobbler", - "version": "0.8.0", + "version": "0.8.1", "type": "module", "description": "scrobble plays from multiple sources to multiple clients", "scripts": {