Skip to content

Commit 28910a9

Browse files
committed
Merge branch 'develop'
2 parents e369f9e + ee38252 commit 28910a9

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+1979
-132
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,13 @@ A javascript app to scrobble plays from multiple sources to [Maloja](https://git
1111
* [Plex](/docs/configuration.md#plex) or [Tautulli](/docs/configuration.md#tautulli)
1212
* [Subsonic-compatible APIs](/docs/configuration.md#subsonic) (like [Airsonic](https://airsonic.github.io/))
1313
* [Jellyfin](/docs/configuration.md#jellyfin)
14+
* [Youtube Music](/docs/configuration.md#youtube-music)
1415
* [Last.fm](/docs/configuration.md#lastfm-source)
1516
* [Deezer](/docs/configuration.md#deezer)
1617
* Supports scrobbling to many clients
1718
* [Maloja](/docs/configuration.md#maloja)
1819
* [Last.fm](/docs/configuration.md#lastfm)
20+
* Monitor status of sources and clients using [webhooks (Gotify or Ntfy)](/docs/configuration.md#webhook-configurations) or [healthcheck endpoint](/docs/configuration.md#health-endpoint)
1921
* Supports configuring for single or multiple users (scrobbling for your friends and family!)
2022
* Web server interface for stats, basic control, and detailed logs
2123
* Smart handling of credentials (persistent, authorization through app)

config/config.json.example

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@
1414
"clients": ["myConfig"],
1515
"name": "mySpotifySource",
1616
"data": {
17-
"clientId": "a89cba1569901a0671d5a9875fed4be1",
18-
"clientSecret": "ec42e09d5ae0ee0f0816ca151008412a",
19-
"redirectUri": "http://localhost:9078/callback"
17+
"clientId": "a89cba1569901a0671d5a9875fed4be1",
18+
"clientSecret": "ec42e09d5ae0ee0f0816ca151008412a",
19+
"redirectUri": "http://localhost:9078/callback"
2020
}
2121
}
2222
],
@@ -29,5 +29,31 @@
2929
"apiKey": "myMalojaKey"
3030
}
3131
}
32+
],
33+
"webhooks": [
34+
{
35+
"name": "FirstGotifyServer",
36+
"type": "gotify",
37+
"url": "http://localhost:8070",
38+
"token": "MyGotifyToken",
39+
"priorities": {
40+
"info": 5,
41+
"warn": 7,
42+
"error": 10
43+
}
44+
},
45+
{
46+
"type": "ntfy",
47+
"name": "MyNtfyFriendlyNameForLogs",
48+
"url": "http://localhost:9991",
49+
"topic": "MyMultiScrobblerTopic",
50+
"username": "Optional",
51+
"password": "Optional",
52+
"priorities": {
53+
"info": 3,
54+
"warn": 4,
55+
"error": 5
56+
}
57+
}
3258
]
3359
}

config/jellyfin.json.example

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@
44
"clients": [],
55
"data": {
66
"users": ["FoxxMD"],
7-
"servers": ["myServer","anotherServer"]
7+
"servers": ["myServer","anotherServer"],
8+
"options": {
9+
"logPayload": false
10+
}
811
}
912
}
1013
]

config/ytmusic.json.example

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
[
2+
{
3+
"name": "MyYTMusic",
4+
"clients": [],
5+
"data": {
6+
"cookie": "VISITOR_INFO1_LIVE=jMDXz2_L8rY; __Secure-3PAPISID=3AxsXpSXGqOInSDn1jEKn; DEVICE_INFO=ChxOekU0TmTBpjek5EWZ0G; YSC=7gZdl3Zdl3; SID=TwhNsaZRXYTAtXxzGyu6rZdpg2HvGROeW8J4Ym_FhkhoZMUYEQ.; __Secure-1PSID=TwhNOsaZRXYTyRBe4rxAtXRIKsIEtk_Qot2VLBNfHQrQ.; __Secure-3PSID=ZRXYTAtXRIKsIEtk_Qot2yRBerZdpg2HvvZRXYTAtXRIKsIEtk_Qot2yRBerkuZICFQ.; HSID=A1UMmELW79; SSID=AKhomOs; APISID=IlHHmuzkPdQzZZDhHn3; SAPISID=3AxsXpy0u75Qb/n1jEKn; __Secure-1PAPISID=3AxsXpQb/AkSDn1jEKn; LOGIN_INFO=AFmP6vFpyVCZZAIgDwbkhWMBBhluaIWAPP:QUQ314UW5NWMjNmd2ZUJnYnJsakdIMjZoaE5zVVMjNmd2ZZUiHRlb3ZlV3ZIcUVyRVIMjNmdjNmd2ZZUivYlNqX2ZNZUiHdUNFNFdaYmJIW1NkJRX3hqdlU2YnFESkFuSS1uTldnZVRmLXNjWFc5OUJuR3dTd3JsZGZYa2EtZFQ2a0k2Ry1KQQ==; PREF=volume=26; SIDCC=AFvI_94PxXwls-ndqpGfPgFX3FWj80y_94PxXwls-ndqfSh15sP; __Secure-1PSIDCC=AFvIBnUbRr96I96UCIp2U4T8HRVk2B0HfKzhzxwsiP; __Secure-3PSIDCC=AFvIB3bINuUN0ETDR9gO91wpwWIVmpGki3BxT3bINuUN0ETDR9gO91wCH",
7+
"authUser": "0",
8+
}
9+
}
10+
]

docs/FAQ.md

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
1+
* [Connection Issues](#connection-issues)
2+
* [Plex/Tautulli/Jellyfin don't connect](#plextautullijellyfin-dont-connect)
3+
* [Jellyfin has warnings about undefined or missing data](#jellyfin-has-warnings-about-undefined-or-missing-data)
4+
* [Spotify/Deezer/LastFM won't authenticate](#spotifydeezerlastfm-wont-authenticate)
5+
* [Configuration Issues](#configuration-issues)
6+
* [Config could not be parsed](#config-could-not-be-parsed)
7+
18
# Connection Issues
29

3-
## Plex/Tautulli/Jellyfin don't work
10+
## Plex/Tautulli/Jellyfin don't connect
411

512
These three [sources](/README.md#source) are **ingress-based** which means that multi-scrobbler waits for the Plex/Tautulli/Jellyfin server to contact multi-scrobbler, as opposed to multi-scrobbler contacting the server.
613

@@ -59,6 +66,34 @@ Check the command-line output of the application or docker logs.
5966

6067
Administration -> Dashboard -> Advanced -> Logs
6168

69+
## Jellyfin has warnings about undefined or missing data
70+
71+
Make sure you have
72+
* [Configured the webhook plugin correctly](/docs/configuration.md#jellyfin)
73+
* Checked the **Send All Properties(ignores template)** option in the webhook settings and **Saved**
74+
75+
multi-scrobbler is known to work on Jellyfin `10.8.9` with Webhook version `11.0.0.0`.
76+
77+
You can verify the payload sent from the webhook by modifying your jellyfin configuration to include `logPayload: true` which will output the raw payload to DEBUG level logging:
78+
79+
```json
80+
[
81+
{
82+
"name": "MyJellyfin",
83+
"clients": [],
84+
"data": {
85+
"users": ["FoxxMD"],
86+
"options": {
87+
"logPayload": true
88+
}
89+
}
90+
}
91+
]
92+
```
93+
94+
If your issue persists and you open an Issue for it please include the raw payload logs in your report.
95+
96+
6297
## Spotify/Deezer/LastFM won't authenticate
6398

6499
Ensure any **client id** or **secrets** are correct in your configuration.

docs/configuration.md

Lines changed: 133 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5,33 +5,19 @@
55
* [Specific File Configuration](#specific-file-configuration)
66
* [Source Configurations](#source-configurations)
77
* [Spotify](#spotify)
8-
* [ENV-Based](#env-based)
9-
* [File-Based](#file-based)
108
* [Plex](#plex)
11-
* [ENV-Based](#env-based-1)
12-
* [File-Based](#file-based-1)
139
* [Tautulli](#tautulli)
14-
* [ENV-Based](#env-based-2)
15-
* [File-Based](#file-based-2)
1610
* [Subsonic](#subsonic)
17-
* [ENV-Based](#env-based-3)
18-
* [File-Based](#file-based-3)
1911
* [Jellyfin](#jellyfin)
20-
* [ENV-Based](#env-based-4)
21-
* [File-Based](#file-based-4)
2212
* [Last.fm (Source)](#lastfm--source-)
23-
* [ENV-Based](#env-based-5)
24-
* [File-Based](#file-based-5)
2513
* [Deezer](#deezer)
26-
* [ENV-Based](#env-based-6)
27-
* [File-Based](#file-based-6)
14+
* [Youtube Music](#youtube-music)
2815
* [Client Configurations](#client-configurations)
2916
* [Maloja](#maloja)
30-
* [ENV-Based](#env-based-7)
31-
* [File-Based](#file-based-7)
3217
* [Last.fm](#lastfm)
33-
* [ENV-Based](#env-based-8)
34-
* [File-Based](#file-based-8)
18+
* [Monitoring](#monitoring)
19+
* [Webhooks](#webhook-configurations)
20+
* [Health Endpoint](#health-endpoint)
3521

3622
# Configuration Overview
3723

@@ -310,6 +296,33 @@ After starting multi-scrobbler with credentials in-place open the dashboard (`ht
310296

311297
See [`deezer.json.example`](/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%2Fdevelop%2Fsrc%2Fcommon%2Fschema%2Fsource.json)
312298

299+
## [Youtube Music](https://music.youtube.com)
300+
301+
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)
302+
303+
* Open a new tab
304+
* Open the developer tools (Ctrl-Shift-I) and select the “Network” tab
305+
* Go to https://music.youtube.com and ensure you are logged in
306+
307+
Then...
308+
309+
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.
310+
2. **Make sure **Headers** pane is selected and open
311+
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
312+
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
313+
314+
![Google Headers](/docs/google-header.jpg)
315+
316+
NOTES:
317+
318+
* 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.
319+
* 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.
320+
321+
### File-Based
322+
323+
See [`ytmusic.json.example`](/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%2Fdevelop%2Fsrc%2Fcommon%2Fschema%2Fsource.json)
324+
325+
313326
# Client Configurations
314327

315328
## [Maloja](https://github.com/krateng/maloja)
@@ -347,3 +360,105 @@ or replace `localhost:9078` with your own base URL
347360
### File-Based
348361

349362
See [`lastfm.json.example`](/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%2Fdevelop%2Fsrc%2Fcommon%2Fschema%2Fclient.json)
363+
364+
# Monitoring
365+
366+
multi-scrobbler supports some common webhooks and a healthcheck endpoint in order to monitor Sources and Clients for errors.
367+
368+
## Webhook Configurations
369+
370+
Webhooks will **push** a notification to your configured servers on these events:
371+
372+
* Source polling started
373+
* Source polling retry
374+
* Source polling stopped on error
375+
* Scrobble client scrobble failure
376+
377+
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:
378+
379+
```json
380+
{
381+
"sources": [
382+
...
383+
],
384+
"clients": [
385+
...
386+
],
387+
"webhooks": [
388+
{
389+
"name": "FirstGotifyServer",
390+
"type": "gotify",
391+
"url": "http://192.168.0.100:8070",
392+
"token": "abcd"
393+
},
394+
{
395+
"name": "SecondGotifyServer",
396+
"type": "gotify",
397+
...
398+
},
399+
{
400+
"name": "NtfyServerOne",
401+
"type": "ntfy",
402+
...
403+
},
404+
...
405+
]
406+
}
407+
```
408+
409+
### [Gotify](https://gotify.net/)
410+
411+
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%2Fdevelop%2Fsrc%2Fcommon%2Fschema%2Faio.json)
412+
413+
multi-scrobbler optionally supports setting message notification priority via `info` `warn` and `error` mappings.
414+
415+
EX
416+
417+
```json
418+
{
419+
"type": "gotify",
420+
"name": "MyGotifyFriendlyNameForLogs",
421+
"url": "http://192.168.0.100:8070",
422+
"token": "AQZI58fA.rfSZbm",
423+
"priorities": {
424+
"info": 5,
425+
"warn": 7,
426+
"error": 10
427+
}
428+
}
429+
```
430+
431+
### [Ntfy](https://ntfy.sh/)
432+
433+
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%2Fdevelop%2Fsrc%2Fcommon%2Fschema%2Faio.json)
434+
435+
multi-scrobbler optionally supports setting message notification priority via `info` `warn` and `error` mappings.
436+
437+
EX
438+
439+
```json
440+
{
441+
"type": "ntfy",
442+
"name": "MyNtfyFriendlyNameForLogs",
443+
"url": "http://192.168.0.100:9991",
444+
"topic": "RvOwKJ1XtIVMXGLR",
445+
"username": "Optional",
446+
"password": "Optional",
447+
"priorities": {
448+
"info": 3,
449+
"warn": 4,
450+
"error": 5
451+
}
452+
}
453+
```
454+
455+
## Health Endpoint
456+
457+
An endpoint for monitoring the health of sources/clients is available at GET `http://YourMultiScrobblerDomain/health`
458+
459+
* Returns `200 OK` when **everything** is working or `500 Internal Server Error` if **anything** is not
460+
* The plain url (`/health`) aggregates status of **all clients/sources** -- so any failing client/source will make status return 500
461+
* Use query params `type` or `name` to restrict client/sources aggregated IE `/health?type=spotify` or `/health?name=MyMaloja`
462+
* On 500 the response returns a JSON payload with `messages` array that describes any issues
463+
* For any clients/sources that require authentication `/health` will return 500 if they are **not authenticated**
464+
* For sources that poll (spotify, yt music, subsonic) `/health` will 500 if they are **not polling**

docs/google-header.jpg

226 KB
Loading

docs/kitchensink.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ Scenario:
66
* Each person has their own Maloja server
77
* Each person has their own Spotify account
88
* You have your own Airsonic (subsonic) server you to scrobble from
9+
* You have your own Youtube Music account you want to scrobble from
910
* Mary has her own Last.fm account she also wants to scrobble to
1011
* Fred has his own Spotify application and provides you with just his access and refresh token because he doesn't trust you (wtf Fred)
1112
* Fred has a Plex server and wants to scrobble everything he plays
@@ -101,6 +102,15 @@ Using just one config file located at `CONFIG_DIR/config.json`:
101102
"url": "https://airsonic.foxx.example"
102103
}
103104
},
105+
{
106+
"type": "ytmusic",
107+
"name": "foxxYoutube",
108+
"clients": ["foxxMaloja"],
109+
"data": {
110+
"cookie": "__Secure-3PAPISID=3AxsXpy0MKGu75Qb/AkISXGqOnSDn1jEKn; DEVICE_INFO=ChxOekU0Tmpjek5EWTBPRGd3TlRBMk16QXpNdz09EJbS8Z0GGJbS8Z0G; ...",
111+
"authUser": 1
112+
}
113+
},
104114
],
105115
"clients": [
106116
{
@@ -217,6 +227,22 @@ In `CONFIG_DIR/jellyfin.json`
217227
]
218228
```
219229

230+
In `CONFIG_DIR/ytmusic.json`
231+
232+
```json5
233+
[
234+
{
235+
"type": "ytmusic",
236+
"name": "foxxYoutube",
237+
"clients": ["foxxMaloja"],
238+
"data": {
239+
"cookie": "__Secure-3PAPISID=3AxsXpy0MKGu75Qb/AkISXGqOnSDn1jEKn; DEVICE_INFO=ChxOekU0Tmpjek5EWTBPRGd3TlRBMk16QXpNdz09EJbS8Z0GGJbS8Z0G; ...",
240+
"authUser": 1
241+
}
242+
}
243+
]
244+
```
245+
220246
In `CONFIG_DIR/maloja.json`:
221247

222248
```json5

0 commit comments

Comments
 (0)