spotify-monitor 2.4__py3-none-any.whl → 2.5__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of spotify-monitor might be problematic. Click here for more details.

@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: spotify_monitor
3
- Version: 2.4
3
+ Version: 2.5
4
4
  Summary: Tool implementing real-time tracking of Spotify friends music activity
5
5
  Author-email: Michal Szymanski <misiektoja-pypi@rm-rf.ninja>
6
6
  License-Expression: GPL-3.0-or-later
@@ -80,7 +80,8 @@ Tool for real-time monitoring of **Spotify friends' music activity feed**.
80
80
  * [Access Token Retrieval via sp_dc Cookie and TOTP](#access-token-retrieval-via-sp_dc-cookie-and-totp)
81
81
  * [Secret Key Extraction from Spotify Web Player Bundles](#secret-key-extraction-from-spotify-web-player-bundles)
82
82
  7. [Change Log](#change-log)
83
- 8. [License](#license)
83
+ 8. [Maintainers](#maintainers)
84
+ 9. [License](#license)
84
85
 
85
86
  <a id="requirements"></a>
86
87
  ## Requirements
@@ -90,8 +91,8 @@ Tool for real-time monitoring of **Spotify friends' music activity feed**.
90
91
 
91
92
  Tested on:
92
93
 
93
- * **macOS**: Ventura, Sonoma, Sequoia
94
- * **Linux**: Raspberry Pi OS (Bullseye, Bookworm), Ubuntu 24, Rocky Linux 8.x/9.x, Kali Linux 2024/2025
94
+ * **macOS**: Ventura, Sonoma, Sequoia, Tahoe
95
+ * **Linux**: Raspberry Pi OS (Bullseye, Bookworm, Trixie), Ubuntu 24/25, Rocky Linux 8.x/9.x, Kali Linux 2024/2025
95
96
  * **Windows**: 10, 11
96
97
 
97
98
  It should work on other versions of macOS, Linux, Unix and Windows as well.
@@ -605,13 +606,15 @@ You should get a valid Spotify access token, example output:
605
606
  <img src="https://raw.githubusercontent.com/misiektoja/spotify_monitor/refs/heads/main/assets/spotify_monitor_totp_test.png" alt="spotify_monitor_totp_test" width="100%"/>
606
607
  </p>
607
608
 
608
- > **NOTE:** secrets used for TOTP generation (`SECRET_CIPHER_DICT`) expire every two days; you can either run the [spotify_monitor_secret_grabber](https://github.com/misiektoja/spotify_monitor/blob/dev/debug/spotify_monitor_secret_grabber.py) and extract it by yourself (see [here](#secret-key-extraction-from-spotify-web-player-bundles) for more info) or you can pass `--fetch-secrets` flag in [spotify_monitor_totp_test](https://github.com/misiektoja/spotify_monitor/blob/dev/debug/spotify_monitor_totp_test.py) (available since v1.6). There is also a [Thereallo1026/spotify-secrets](https://github.com/Thereallo1026/spotify-secrets) repo which offers JSON files that are automatically updated with current secrets.
609
+ > **NOTE:** secrets used for TOTP generation (`SECRET_CIPHER_DICT`) expire every two days; you can either run the [spotify_monitor_secret_grabber](https://github.com/misiektoja/spotify_monitor/blob/dev/debug/spotify_monitor_secret_grabber.py) and extract it by yourself (see [here](#secret-key-extraction-from-spotify-web-player-bundles) for more info) or you can pass `--fetch-secrets` flag in `spotify_monitor_totp_test` (available since v1.6). There is also a [xyloflake/spot-secrets-go/](https://github.com/xyloflake/spot-secrets-go/) repo which offers JSON files that are automatically updated with current secrets (you can pass `--download-secrets` flag in `spotify_monitor_totp_test` to get it automatically from remote URL, available since v1.8).
609
610
 
610
611
  <a id="secret-key-extraction-from-spotify-web-player-bundles"></a>
611
612
  ### Secret Key Extraction from Spotify Web Player Bundles
612
613
 
613
614
  The [spotify_monitor_secret_grabber](https://github.com/misiektoja/spotify_monitor/blob/dev/debug/spotify_monitor_secret_grabber.py) tool automatically extracts secret keys used for TOTP generation in Spotify Web Player JavaScript bundles.
614
615
 
616
+ > 💡 **Quick tip:** The easiest and recommended way to run this tool is via Docker. Jump directly to the [Docker usage section below](#-secret-key-extraction-via-docker-recommended-easiest-way).
617
+
615
618
  Download from [here](https://github.com/misiektoja/spotify_monitor/blob/dev/debug/spotify_monitor_secret_grabber.py) or:
616
619
 
617
620
  ```sh
@@ -625,7 +628,7 @@ pip install playwright
625
628
  playwright install
626
629
  ```
627
630
 
628
- Run:
631
+ Run interactively (default output mode):
629
632
 
630
633
  ```sh
631
634
  python3 spotify_monitor_secret_grabber.py
@@ -637,15 +640,100 @@ You should get output similar to below:
637
640
  <img src="https://raw.githubusercontent.com/misiektoja/spotify_monitor/refs/heads/main/assets/spotify_monitor_secret_grabber.png" alt="spotify_monitor_secret_grabber" width="100%"/>
638
641
  </p>
639
642
 
640
- You can now update the secrets used for TOTP generation (for example `SECRET_CIPHER_DICT` in `spotify_monitor_totp_test`, `spotify_monitor` and `spotify_profile_monitor`).
643
+ Show help:
644
+ ```sh
645
+ python3 spotify_monitor_secret_grabber.py -h
646
+ ```
647
+
648
+ ---
649
+
650
+ <a id="cli-output-modes"></a>
651
+ ### CLI Output Modes
652
+
653
+ The script supports several output modes for different use cases:
654
+
655
+ | Flag | Description | Output |
656
+ |------|--------------|--------|
657
+ | `--secret` | Prints plain JSON array of extracted secrets | `[{"version": X, "secret": "..."}, ...]` |
658
+ | `--secretbytes` | Prints JSON array with ASCII byte values | `[{"version": X, "secret": [..]}, ...]` |
659
+ | `--secretdict` | Prints JSON object/dict mapping version → byte list | `{"X": [..], "Y": [..]}` |
660
+ | `--all` | Extracts secrets and **writes all three outputs** to local files | `secrets.json`, `secretBytes.json`, `secretDict.json` |
661
+
662
+ Print extracted secrets in specific format, for example Python-friendly secret bytes (JSON object/dict) and save to indicated file:
663
+
664
+ ```sh
665
+ python3 spotify_monitor_secret_grabber.py --secretdict > secretDict.json
666
+ ```
667
+
668
+ Or, to generate and save all secret formats to files (`secrets.json`, `secretBytes.json`, `secretDict.json`) at once:
669
+
670
+ ```sh
671
+ python3 spotify_monitor_secret_grabber.py --all
672
+ ```
673
+
674
+ Default file paths and names can be configured directly in the `OUTPUT_FILES` dictionary at the top of the script.
675
+
676
+ ---
677
+
678
+ <a id="-secret-key-extraction-via-docker-recommended-easiest-way"></a>
679
+ ### 🐳 Secret Key Extraction via Docker (Recommended Easiest Way)
680
+
681
+ A prebuilt multi-architecture image is available on Docker Hub: [`misiektoja/spotify-secrets-grabber`](https://hub.docker.com/r/misiektoja/spotify-secrets-grabber)
682
+
683
+ This image works on:
684
+ - macOS (Intel & Apple Silicon)
685
+ - Linux (x86_64 and ARM64)
686
+ - Windows (Docker Desktop / WSL2)
687
+ - Raspberry Pi 4/5 (64-bit OS)
688
+
689
+ Run interactively (default output mode):
641
690
 
642
- > **NOTE:** you can also use [Thereallo1026/spotify-secrets](https://github.com/Thereallo1026/spotify-secrets) repo which offers JSON files that are automatically updated with current secrets (its secret extraction code is based on `spotify_monitor_secret_grabber`).
691
+ ```sh
692
+ docker run --rm misiektoja/spotify-secrets-grabber
693
+ ```
694
+
695
+ Show help:
696
+ ```sh
697
+ docker run --rm misiektoja/spotify-secrets-grabber -h
698
+ ```
699
+
700
+ Print extracted secrets in specific format, for example Python-friendly secret bytes (JSON object/dict) and save to indicated file:
701
+ ```sh
702
+ docker run --rm misiektoja/spotify-secrets-grabber --secretdict > secretDict.json
703
+ ```
704
+
705
+ Or, to generate and save all secret formats to files (`secrets.json`, `secretBytes.json`, `secretDict.json`) at once:
706
+
707
+ ```sh
708
+ docker run --rm -v .:/work -w /work misiektoja/spotify-secrets-grabber --all
709
+ ```
710
+
711
+ *For SELinux hosts (Fedora/RHEL), use `-v .:/work:Z`.*
712
+
713
+ <a id="optional-use-docker-compose-one-command-for-all-oss"></a>
714
+ Or optionally use Docker Compose (a preconfigured [compose.yaml](https://github.com/misiektoja/spotify_monitor/blob/dev/debug/spotify_monitor_secret_grabber_docker/compose.yaml) file is included in the repo):
715
+
716
+ ```sh
717
+ docker compose run --rm spotify-secrets-grabber --all
718
+ ```
719
+
720
+ This will save all files into your current directory on any system (macOS, Linux or Windows).
721
+
722
+ ---
723
+
724
+ You can now update the secrets used for TOTP generation (for example `SECRET_CIPHER_DICT` in `spotify_monitor_totp_test`, `spotify_monitor` and `spotify_profile_monitor`) either manually or by referencing an external `secretDict.json` file, which can be hosted in another repo or stored locally. See the description of `SECRET_CIPHER_DICT_URL` in those files for details.
643
725
 
644
726
  <a id="change-log"></a>
645
727
  ## Change Log
646
728
 
647
729
  See [RELEASE_NOTES.md](https://github.com/misiektoja/spotify_monitor/blob/main/RELEASE_NOTES.md) for details.
648
730
 
731
+ <a id="maintainers"></a>
732
+ ## Maintainers
733
+
734
+ [![Maintainer: misiektoja](https://img.shields.io/badge/maintainer-misiektoja-blue)](https://github.com/misiektoja)
735
+ [![Maintainer: tomballgithub](https://img.shields.io/badge/maintainer-tomballgithub-blue)](https://github.com/tomballgithub)
736
+
649
737
  <a id="license"></a>
650
738
  ## License
651
739
 
@@ -0,0 +1,7 @@
1
+ spotify_monitor.py,sha256=YGmW3_nq8NDJsM953_NO_W4c4GOianpZJp6RTk7u_Gs,162665
2
+ spotify_monitor-2.5.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
3
+ spotify_monitor-2.5.dist-info/METADATA,sha256=CtQagsvmirnZ1G1krTwfCnSgwrPRxQCQxxiQzumztqA,31063
4
+ spotify_monitor-2.5.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
5
+ spotify_monitor-2.5.dist-info/entry_points.txt,sha256=8HzePfUcCSXrYaXOwLbNNYO8GJcnhgCSl4wcDNECht8,57
6
+ spotify_monitor-2.5.dist-info/top_level.txt,sha256=EP6IPD4vHT12rLM5b_jo2i3nrfOuwk3ehhr2gWdQx9Y,16
7
+ spotify_monitor-2.5.dist-info/RECORD,,
spotify_monitor.py CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env python3
2
2
  """
3
3
  Author: Michal Szymanski <misiektoja-github@rm-rf.ninja>
4
- v2.4
4
+ v2.5
5
5
 
6
6
  Tool implementing real-time tracking of Spotify friends music activity:
7
7
  https://github.com/misiektoja/spotify_monitor/
@@ -16,7 +16,7 @@ python-dotenv (optional)
16
16
  wcwidth (optional, needed by TRUNCATE_CHARS feature)
17
17
  """
18
18
 
19
- VERSION = "2.4"
19
+ VERSION = "2.5"
20
20
 
21
21
  # ---------------------------
22
22
  # CONFIGURATION SECTION START
@@ -253,19 +253,17 @@ TOKEN_RETRY_TIMEOUT = 0.5 # 0.5 second
253
253
  # Newest secrets are downloaded automatically from SECRET_CIPHER_DICT_URL (see below)
254
254
  # Can also be fetched via spotify_monitor_secret_grabber.py utility - see debug dir
255
255
  SECRET_CIPHER_DICT = {
256
- "12": [107, 81, 49, 57, 67, 93, 87, 81, 69, 67, 40, 93, 48, 50, 46, 91, 94, 113, 41, 108, 77, 107, 34],
257
- "11": [111, 45, 40, 73, 95, 74, 35, 85, 105, 107, 60, 110, 55, 72, 69, 70, 114, 83, 63, 88, 91],
258
- "10": [61, 110, 58, 98, 35, 79, 117, 69, 102, 72, 92, 102, 69, 93, 41, 101, 42, 75],
259
- "9": [109, 101, 90, 99, 66, 92, 116, 108, 85, 70, 86, 49, 68, 54, 87, 50, 72, 121, 52, 64, 57, 43, 36, 81, 97, 72, 53, 41, 78, 56],
260
- "8": [37, 84, 32, 76, 87, 90, 87, 47, 13, 75, 48, 54, 44, 28, 19, 21, 22],
261
- "7": [59, 91, 66, 74, 30, 66, 74, 38, 46, 50, 72, 61, 44, 71, 86, 39, 89],
262
256
  "6": [21, 24, 85, 46, 48, 35, 33, 8, 11, 63, 76, 12, 55, 77, 14, 7, 54],
263
257
  "5": [12, 56, 76, 33, 88, 44, 88, 33, 78, 78, 11, 66, 22, 22, 55, 69, 54],
264
258
  }
265
259
 
266
- # Remote URL used to fetch updated secrets needed for TOTP generation
260
+ # Remote or local URL used to fetch updated secrets needed for TOTP generation
267
261
  # Set to empty string to disable
268
- SECRET_CIPHER_DICT_URL = "https://github.com/Thereallo1026/spotify-secrets/blob/main/secrets/secretDict.json?raw=true"
262
+ # If you used "spotify_monitor_secret_grabber.py --secretdict > secretDict.json" specify the file location below
263
+ # SECRET_CIPHER_DICT_URL = "https://github.com/Thereallo1026/spotify-secrets/blob/main/secrets/secretDict.json?raw=true"
264
+ SECRET_CIPHER_DICT_URL = "https://github.com/xyloflake/spot-secrets-go/blob/main/secrets/secretDict.json?raw=true"
265
+ # SECRET_CIPHER_DICT_URL = file:///C:/your_path/secretDict.json
266
+ # SECRET_CIPHER_DICT_URL = "file:///your_path/secretDict.json"
269
267
 
270
268
  # Identifier used to select the appropriate secret from SECRET_CIPHER_DICT when generating a TOTP token
271
269
  # Set to 0 to auto-select the highest available version
@@ -1282,7 +1280,8 @@ def fetch_server_time(session: req.Session, ua: str) -> int:
1282
1280
  def generate_totp():
1283
1281
  import pyotp
1284
1282
 
1285
- if str((ver := TOTP_VER or max(map(int, SECRET_CIPHER_DICT)))) not in SECRET_CIPHER_DICT:
1283
+ ver = TOTP_VER or max(map(int, SECRET_CIPHER_DICT))
1284
+ if str(ver) not in SECRET_CIPHER_DICT:
1286
1285
  raise Exception(f"generate_totp(): Defined TOTP_VER ({ver}) is missing in SECRET_CIPHER_DICT")
1287
1286
 
1288
1287
  secret_cipher_bytes = SECRET_CIPHER_DICT[str(ver)]
@@ -1302,12 +1301,43 @@ def fetch_and_update_secrets():
1302
1301
  return False
1303
1302
 
1304
1303
  try:
1305
- response = req.get(SECRET_CIPHER_DICT_URL, timeout=FUNCTION_TIMEOUT, verify=VERIFY_SSL)
1306
- response.raise_for_status()
1307
- secrets = response.json()
1304
+ if SECRET_CIPHER_DICT_URL.startswith("file:"):
1305
+ import os
1306
+ from urllib.parse import urlparse, unquote
1307
+
1308
+ parsed = urlparse(SECRET_CIPHER_DICT_URL)
1309
+
1310
+ if parsed.netloc:
1311
+ raw_path = f"/{parsed.netloc}{parsed.path or ''}"
1312
+ else:
1313
+ if SECRET_CIPHER_DICT_URL.startswith("file://"):
1314
+ raw_path = parsed.path or SECRET_CIPHER_DICT_URL[len("file://"):]
1315
+ else:
1316
+ raw_path = parsed.path or SECRET_CIPHER_DICT_URL[len("file:"):]
1317
+
1318
+ raw_path = unquote(raw_path)
1319
+
1320
+ if raw_path.startswith("/~"):
1321
+ raw_path = raw_path[1:]
1322
+
1323
+ if not raw_path.startswith("/") and not raw_path.startswith("~"):
1324
+ raw_path = "/" + raw_path
1325
+
1326
+ path = os.path.expanduser(os.path.expandvars(raw_path))
1327
+
1328
+ print(f"Loading Spotify web-player TOTP secrets from file: {path}")
1329
+ with open(path, "r", encoding="utf-8") as f:
1330
+ secrets = json.load(f)
1331
+ print("─" * HORIZONTAL_LINE)
1332
+ else:
1333
+ print(f"Fetching Spotify web-player TOTP secrets from URL: {SECRET_CIPHER_DICT_URL}")
1334
+ response = req.get(SECRET_CIPHER_DICT_URL, timeout=FUNCTION_TIMEOUT, verify=VERIFY_SSL)
1335
+ response.raise_for_status()
1336
+ secrets = response.json()
1337
+ print("─" * HORIZONTAL_LINE)
1308
1338
 
1309
1339
  if not isinstance(secrets, dict) or not secrets:
1310
- raise ValueError("fetch_and_update_secrets(): Fetched payload not a nonempty dict")
1340
+ raise ValueError("fetch_and_update_secrets(): Fetched payload not a non-empty dict")
1311
1341
 
1312
1342
  for key, value in secrets.items():
1313
1343
  if not isinstance(key, str) or not key.isdigit():
@@ -2045,7 +2075,7 @@ def spotify_convert_uri_to_url(uri):
2045
2075
  return url
2046
2076
 
2047
2077
 
2048
- # Prints the list of Spotify friends with the last listened track (-l flag)
2078
+ # Returns list of Spotify friends
2049
2079
  def spotify_list_friends(friend_activity):
2050
2080
 
2051
2081
  print(f"Number of friends:\t\t{len(friend_activity['friends'])}\n")
@@ -3374,6 +3404,7 @@ def main():
3374
3404
  else:
3375
3405
  if FLAG_FILE:
3376
3406
  FLAG_FILE = os.path.expanduser(FLAG_FILE)
3407
+ flag_file_delete()
3377
3408
 
3378
3409
  if args.send_test_email:
3379
3410
  print("* Sending test email notification ...\n")
@@ -1,7 +0,0 @@
1
- spotify_monitor.py,sha256=TtB0dWvl5Yn1ti4y8VFk61V8rqXEZfnLY2PJZ26hVsw,161638
2
- spotify_monitor-2.4.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
3
- spotify_monitor-2.4.dist-info/METADATA,sha256=rcnYf1XgMu4k55OO0m1yfP61TXRA_CkZLLDXUzDLHLM,27747
4
- spotify_monitor-2.4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
5
- spotify_monitor-2.4.dist-info/entry_points.txt,sha256=8HzePfUcCSXrYaXOwLbNNYO8GJcnhgCSl4wcDNECht8,57
6
- spotify_monitor-2.4.dist-info/top_level.txt,sha256=EP6IPD4vHT12rLM5b_jo2i3nrfOuwk3ehhr2gWdQx9Y,16
7
- spotify_monitor-2.4.dist-info/RECORD,,