simkl-mps 2.3.1__tar.gz → 2.3.3__tar.gz

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.
Files changed (63) hide show
  1. {simkl_mps-2.3.1 → simkl_mps-2.3.3}/PKG-INFO +1 -1
  2. {simkl_mps-2.3.1 → simkl_mps-2.3.3}/pyproject.toml +1 -1
  3. {simkl_mps-2.3.1 → simkl_mps-2.3.3}/simkl_mps/__init__.py +1 -1
  4. {simkl_mps-2.3.1 → simkl_mps-2.3.3}/simkl_mps/credentials.py +32 -24
  5. {simkl_mps-2.3.1 → simkl_mps-2.3.3}/simkl_mps/tray_linux.py +11 -3
  6. {simkl_mps-2.3.1 → simkl_mps-2.3.3}/LICENSE +0 -0
  7. {simkl_mps-2.3.1 → simkl_mps-2.3.3}/README.md +0 -0
  8. {simkl_mps-2.3.1 → simkl_mps-2.3.3}/simkl_mps/assets/simkl-mps (Custom).png +0 -0
  9. {simkl_mps-2.3.1 → simkl_mps-2.3.3}/simkl_mps/assets/simkl-mps-128.png +0 -0
  10. {simkl_mps-2.3.1 → simkl_mps-2.3.3}/simkl_mps/assets/simkl-mps-16.png +0 -0
  11. {simkl_mps-2.3.1 → simkl_mps-2.3.3}/simkl_mps/assets/simkl-mps-24.png +0 -0
  12. {simkl_mps-2.3.1 → simkl_mps-2.3.3}/simkl_mps/assets/simkl-mps-256.png +0 -0
  13. {simkl_mps-2.3.1 → simkl_mps-2.3.3}/simkl_mps/assets/simkl-mps-32.png +0 -0
  14. {simkl_mps-2.3.1 → simkl_mps-2.3.3}/simkl_mps/assets/simkl-mps-48.png +0 -0
  15. {simkl_mps-2.3.1 → simkl_mps-2.3.3}/simkl_mps/assets/simkl-mps-64.png +0 -0
  16. {simkl_mps-2.3.1 → simkl_mps-2.3.3}/simkl_mps/assets/simkl-mps-error.ico +0 -0
  17. {simkl_mps-2.3.1 → simkl_mps-2.3.3}/simkl_mps/assets/simkl-mps-error.png +0 -0
  18. {simkl_mps-2.3.1 → simkl_mps-2.3.3}/simkl_mps/assets/simkl-mps-paused.ico +0 -0
  19. {simkl_mps-2.3.1 → simkl_mps-2.3.3}/simkl_mps/assets/simkl-mps-paused.png +0 -0
  20. {simkl_mps-2.3.1 → simkl_mps-2.3.3}/simkl_mps/assets/simkl-mps-running.ico +0 -0
  21. {simkl_mps-2.3.1 → simkl_mps-2.3.3}/simkl_mps/assets/simkl-mps-running.png +0 -0
  22. {simkl_mps-2.3.1 → simkl_mps-2.3.3}/simkl_mps/assets/simkl-mps-stopped.ico +0 -0
  23. {simkl_mps-2.3.1 → simkl_mps-2.3.3}/simkl_mps/assets/simkl-mps-stopped.png +0 -0
  24. {simkl_mps-2.3.1 → simkl_mps-2.3.3}/simkl_mps/assets/simkl-mps.ico +0 -0
  25. {simkl_mps-2.3.1 → simkl_mps-2.3.3}/simkl_mps/assets/simkl-mps.png +0 -0
  26. {simkl_mps-2.3.1 → simkl_mps-2.3.3}/simkl_mps/backlog_cleaner.py +0 -0
  27. {simkl_mps-2.3.1 → simkl_mps-2.3.3}/simkl_mps/cli.py +0 -0
  28. {simkl_mps-2.3.1 → simkl_mps-2.3.3}/simkl_mps/compatibility_patches.py +0 -0
  29. {simkl_mps-2.3.1 → simkl_mps-2.3.3}/simkl_mps/config_manager.py +0 -0
  30. {simkl_mps-2.3.1 → simkl_mps-2.3.3}/simkl_mps/main.py +0 -0
  31. {simkl_mps-2.3.1 → simkl_mps-2.3.3}/simkl_mps/media_cache.py +0 -0
  32. {simkl_mps-2.3.1 → simkl_mps-2.3.3}/simkl_mps/media_scrobbler.py +0 -0
  33. {simkl_mps-2.3.1 → simkl_mps-2.3.3}/simkl_mps/media_tracker.py +0 -0
  34. {simkl_mps-2.3.1 → simkl_mps-2.3.3}/simkl_mps/migration.py +0 -0
  35. {simkl_mps-2.3.1 → simkl_mps-2.3.3}/simkl_mps/monitor.py +0 -0
  36. {simkl_mps-2.3.1 → simkl_mps-2.3.3}/simkl_mps/players/__init__.py +0 -0
  37. {simkl_mps-2.3.1 → simkl_mps-2.3.3}/simkl_mps/players/mpc.py +0 -0
  38. {simkl_mps-2.3.1 → simkl_mps-2.3.3}/simkl_mps/players/mpcqt.py +0 -0
  39. {simkl_mps-2.3.1 → simkl_mps-2.3.3}/simkl_mps/players/mpv.py +0 -0
  40. {simkl_mps-2.3.1 → simkl_mps-2.3.3}/simkl_mps/players/mpv_wrappers.py +0 -0
  41. {simkl_mps-2.3.1 → simkl_mps-2.3.3}/simkl_mps/players/potplayer.py +0 -0
  42. {simkl_mps-2.3.1 → simkl_mps-2.3.3}/simkl_mps/players/vlc.py +0 -0
  43. {simkl_mps-2.3.1 → simkl_mps-2.3.3}/simkl_mps/simkl_api.py +0 -0
  44. {simkl_mps-2.3.1 → simkl_mps-2.3.3}/simkl_mps/tray_app.py +0 -0
  45. {simkl_mps-2.3.1 → simkl_mps-2.3.3}/simkl_mps/tray_base.py +0 -0
  46. {simkl_mps-2.3.1 → simkl_mps-2.3.3}/simkl_mps/tray_mac.py +0 -0
  47. {simkl_mps-2.3.1 → simkl_mps-2.3.3}/simkl_mps/tray_win.py +0 -0
  48. {simkl_mps-2.3.1 → simkl_mps-2.3.3}/simkl_mps/utils/__init__.py +0 -0
  49. {simkl_mps-2.3.1 → simkl_mps-2.3.3}/simkl_mps/utils/constants.py +0 -0
  50. {simkl_mps-2.3.1 → simkl_mps-2.3.3}/simkl_mps/utils/linux_tray_diagnostics.py +0 -0
  51. {simkl_mps-2.3.1 → simkl_mps-2.3.3}/simkl_mps/utils/path_filter.py +0 -0
  52. {simkl_mps-2.3.1 → simkl_mps-2.3.3}/simkl_mps/utils/updater.ps1 +0 -0
  53. {simkl_mps-2.3.1 → simkl_mps-2.3.3}/simkl_mps/utils/updater.sh +0 -0
  54. {simkl_mps-2.3.1 → simkl_mps-2.3.3}/simkl_mps/watch-history-viewer/fonts/Inter-Bold.woff2 +0 -0
  55. {simkl_mps-2.3.1 → simkl_mps-2.3.3}/simkl_mps/watch-history-viewer/fonts/Inter-Medium.woff2 +0 -0
  56. {simkl_mps-2.3.1 → simkl_mps-2.3.3}/simkl_mps/watch-history-viewer/fonts/Inter-Regular.woff2 +0 -0
  57. {simkl_mps-2.3.1 → simkl_mps-2.3.3}/simkl_mps/watch-history-viewer/fonts/Inter-SemiBold.woff2 +0 -0
  58. {simkl_mps-2.3.1 → simkl_mps-2.3.3}/simkl_mps/watch-history-viewer/fonts.css +0 -0
  59. {simkl_mps-2.3.1 → simkl_mps-2.3.3}/simkl_mps/watch-history-viewer/index.html +0 -0
  60. {simkl_mps-2.3.1 → simkl_mps-2.3.3}/simkl_mps/watch-history-viewer/script.js +0 -0
  61. {simkl_mps-2.3.1 → simkl_mps-2.3.3}/simkl_mps/watch-history-viewer/style.css +0 -0
  62. {simkl_mps-2.3.1 → simkl_mps-2.3.3}/simkl_mps/watch_history_manager.py +0 -0
  63. {simkl_mps-2.3.1 → simkl_mps-2.3.3}/simkl_mps/window_detection.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: simkl-mps
3
- Version: 2.3.1
3
+ Version: 2.3.3
4
4
  Summary: Automatic Media Scrobbler for Simkl
5
5
  License: GPL-3.0
6
6
  License-File: LICENSE
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "simkl-mps"
3
- version = "2.3.1"
3
+ version = "2.3.3"
4
4
  description = "Automatic Media Scrobbler for Simkl"
5
5
  authors = [
6
6
  "kavin <kavinthangavel.dev@gmail.com>",
@@ -2,7 +2,7 @@
2
2
  Media Player Scrobbler for SIMKL package.
3
3
  """
4
4
 
5
- __version__ = "2.2.2"
5
+ __version__ = "2.3.3"
6
6
  __author__ = "kavin"
7
7
 
8
8
  # Apply compatibility patches first, before any other imports
@@ -7,7 +7,7 @@ Access Token is loaded from a .env file in the user's application data directory
7
7
  import pathlib
8
8
  import logging
9
9
  import os
10
- from dotenv import dotenv_values, load_dotenv
10
+ from dotenv import dotenv_values
11
11
  from .migration import get_app_data_dir, perform_full_migration
12
12
 
13
13
  logger = logging.getLogger(__name__)
@@ -20,13 +20,13 @@ except Exception as e:
20
20
 
21
21
 
22
22
  # --- Injected by build process ---
23
- # These placeholders are replaced by the build workflow using secrets.
24
- CLIENT_ID_PLACEHOLDER = "063e363a1596eb693066cf3b9848be8d2c4a6d9ef300666c9f19ef5980312b27"
25
- CLIENT_SECRET_PLACEHOLDER = "1e2781d773564774c6788bf64b871374b2cee2b31eaed361488821ffc7c5bba9"
23
+ # These placeholders are replaced by the build workflow.
24
+ CLIENT_ID_PLACEHOLDER = "SIMKL_CLIENT_ID_PLACEHOLDER"
25
+ CLIENT_SECRET_PLACEHOLDER = "SIMKL_CLIENT_SECRET_PLACEHOLDER"
26
26
  # --- End of injected values ---
27
27
 
28
- SIMKL_CLIENT_ID = CLIENT_ID_PLACEHOLDER
29
- SIMKL_CLIENT_SECRET = CLIENT_SECRET_PLACEHOLDER
28
+ SIMKL_CLIENT_ID = "063e363a1596eb693066cf3b9848be8d2c4a6d9ef300666c9f19ef5980312b27"
29
+ SIMKL_CLIENT_SECRET = "1e2781d773564774c6788bf64b871374b2cee2b31eaed361488821ffc7c5bba9"
30
30
 
31
31
 
32
32
  def _is_placeholder_credential(value: str, placeholder: str = None) -> bool:
@@ -46,17 +46,22 @@ def _is_placeholder_credential(value: str, placeholder: str = None) -> bool:
46
46
  if placeholder and normalized == placeholder:
47
47
  return True
48
48
 
49
- # Check for common placeholder patterns from env/config
50
- placeholder_patterns = [
49
+ # Check common placeholder literals from env/config.
50
+ # Keep checks strict to avoid false positives for real secret values.
51
+ placeholder_literals = {
51
52
  "placeholder",
52
- "id",
53
- "change_me",
54
- ]
55
-
53
+ "simkl_client_id",
54
+ "simkl_client_secret",
55
+ "simkl_client_id_placeholder",
56
+ "simkl_client_secret_placeholder",
57
+ }
58
+
56
59
  normalized_lower = normalized.lower()
57
- for pattern in placeholder_patterns:
58
- if pattern in normalized_lower:
59
- return True
60
+ if normalized_lower in placeholder_literals:
61
+ return True
62
+
63
+ if normalized_lower.startswith("simkl_client_") and normalized_lower.endswith("_placeholder"):
64
+ return True
60
65
 
61
66
  return False
62
67
 
@@ -153,36 +158,39 @@ def get_credentials():
153
158
  if dev_client_secret and not _is_placeholder_credential(dev_client_secret):
154
159
  client_secret = client_secret or dev_client_secret
155
160
 
156
-
157
161
  access_token = None
158
162
  user_id = None
159
- env_file_path = get_env_file_path()
163
+ env_file_path = get_env_file_path()
160
164
  if env_file_path.exists():
161
165
  logger.debug(f"Reading credentials from {env_file_path} inside get_credentials()")
162
166
  config = dotenv_values(env_file_path)
163
-
167
+
164
168
  # Validate access token against placeholders
165
169
  raw_access_token = config.get("SIMKL_ACCESS_TOKEN")
166
170
  if raw_access_token and not _is_placeholder_credential(raw_access_token):
167
171
  access_token = raw_access_token
168
-
172
+
169
173
  # Validate user ID against placeholders
170
174
  raw_user_id = config.get("SIMKL_USER_ID")
171
175
  if raw_user_id and not _is_placeholder_credential(raw_user_id):
172
176
  user_id = raw_user_id
173
-
177
+
174
178
  if user_id:
175
179
  logger.debug(f"Found user ID in env file: {user_id}")
176
180
  else:
177
181
  logger.debug("User ID not found in env file or value is a placeholder")
178
-
182
+
179
183
  if not access_token:
180
- logger.warning(f"Found env file at {env_file_path}, but SIMKL_ACCESS_TOKEN key is missing, empty, or contains a placeholder value.")
184
+ logger.warning(
185
+ f"Found env file at {env_file_path}, but SIMKL_ACCESS_TOKEN key is missing, empty, or contains a placeholder value."
186
+ )
181
187
  else:
182
- logger.debug(f"Env file not found at {env_file_path} inside get_credentials()")
188
+ logger.debug(f"Env file not found at {env_file_path} inside get_credentials()")
183
189
 
184
190
  if not client_id or not client_secret:
185
- logger.warning("Client ID or Secret not found. For local development, create a dev_credentials.env file with SIMKL_CLIENT_ID and SIMKL_CLIENT_SECRET.")
191
+ logger.warning(
192
+ "Client ID or Secret not found. For local development, create a .env file with SIMKL_CLIENT_ID and SIMKL_CLIENT_SECRET."
193
+ )
186
194
 
187
195
  return {
188
196
  "client_id": client_id,
@@ -185,13 +185,21 @@ class AppIndicatorTray:
185
185
  # --- Threshold Submenu (nested under Scrobbling) ---
186
186
  threshold_item = gtk_module.MenuItem(label="Completion Threshold")
187
187
  threshold_submenu = gtk_module.Menu()
188
- threshold_group = [] # For radio buttons
188
+ threshold_group = None # Will hold the first RadioMenuItem for grouping
189
189
 
190
190
  current_threshold = get_setting('watch_completion_threshold', DEFAULT_THRESHOLD)
191
191
 
192
192
  def create_preset_item(value, label):
193
- item = gtk_module.CheckMenuItem(label=label, group=threshold_group)
194
- threshold_group.append(item) # Add to group for radio behavior
193
+ nonlocal threshold_group
194
+ # Use RadioMenuItem instead of CheckMenuItem for proper radio behavior
195
+ if threshold_group is None:
196
+ # First item in the group
197
+ item = gtk_module.RadioMenuItem(label=label)
198
+ threshold_group = item
199
+ else:
200
+ # Subsequent items join the group
201
+ item = gtk_module.RadioMenuItem(group=threshold_group, label=label)
202
+
195
203
  item.set_active(current_threshold == value)
196
204
  item.connect("activate", lambda w, v=value: self._wrap_callback(lambda: self.app._set_preset_threshold(v))())
197
205
  return item
File without changes
File without changes
File without changes
File without changes