riplex 0.2.4__tar.gz → 0.2.6__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 (112) hide show
  1. {riplex-0.2.4/src/riplex.egg-info → riplex-0.2.6}/PKG-INFO +2 -2
  2. {riplex-0.2.4 → riplex-0.2.6}/README.md +1 -1
  3. {riplex-0.2.4 → riplex-0.2.6/src/riplex.egg-info}/PKG-INFO +2 -2
  4. {riplex-0.2.4 → riplex-0.2.6}/src/riplex_app/screens/welcome.py +97 -13
  5. {riplex-0.2.4 → riplex-0.2.6}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
  6. {riplex-0.2.4 → riplex-0.2.6}/.github/agents/riplex.agent.md +0 -0
  7. {riplex-0.2.4 → riplex-0.2.6}/.github/copilot-instructions.md +0 -0
  8. {riplex-0.2.4 → riplex-0.2.6}/.github/workflows/publish.yml +0 -0
  9. {riplex-0.2.4 → riplex-0.2.6}/.github/workflows/release.yml +0 -0
  10. {riplex-0.2.4 → riplex-0.2.6}/.gitignore +0 -0
  11. {riplex-0.2.4 → riplex-0.2.6}/MONOREPO_PLAN.md +0 -0
  12. {riplex-0.2.4 → riplex-0.2.6}/PLANNED_FEATURES.md +0 -0
  13. {riplex-0.2.4 → riplex-0.2.6}/REFACTOR_PLAN.md +0 -0
  14. {riplex-0.2.4 → riplex-0.2.6}/docs/architecture.md +0 -0
  15. {riplex-0.2.4 → riplex-0.2.6}/docs/changelog.md +0 -0
  16. {riplex-0.2.4 → riplex-0.2.6}/docs/getting-started/configuration.md +0 -0
  17. {riplex-0.2.4 → riplex-0.2.6}/docs/getting-started/installation.md +0 -0
  18. {riplex-0.2.4 → riplex-0.2.6}/docs/guide/lookup.md +0 -0
  19. {riplex-0.2.4 → riplex-0.2.6}/docs/guide/orchestrate.md +0 -0
  20. {riplex-0.2.4 → riplex-0.2.6}/docs/guide/organize.md +0 -0
  21. {riplex-0.2.4 → riplex-0.2.6}/docs/guide/workflow.md +0 -0
  22. {riplex-0.2.4 → riplex-0.2.6}/docs/index.md +0 -0
  23. {riplex-0.2.4 → riplex-0.2.6}/docs/naming-rules.md +0 -0
  24. {riplex-0.2.4 → riplex-0.2.6}/docs/reference/cli.md +0 -0
  25. {riplex-0.2.4 → riplex-0.2.6}/issues/cross-disc-dvdcompare-matching.md +0 -0
  26. {riplex-0.2.4 → riplex-0.2.6}/mkdocs.yml +0 -0
  27. {riplex-0.2.4 → riplex-0.2.6}/plex_naming_rules.md +0 -0
  28. {riplex-0.2.4 → riplex-0.2.6}/pyproject.toml +0 -0
  29. {riplex-0.2.4 → riplex-0.2.6}/setup.cfg +0 -0
  30. {riplex-0.2.4 → riplex-0.2.6}/src/riplex/__init__.py +0 -0
  31. {riplex-0.2.4 → riplex-0.2.6}/src/riplex/cache.py +0 -0
  32. {riplex-0.2.4 → riplex-0.2.6}/src/riplex/config.py +0 -0
  33. {riplex-0.2.4 → riplex-0.2.6}/src/riplex/dedup.py +0 -0
  34. {riplex-0.2.4 → riplex-0.2.6}/src/riplex/detect.py +0 -0
  35. {riplex-0.2.4 → riplex-0.2.6}/src/riplex/disc/__init__.py +0 -0
  36. {riplex-0.2.4 → riplex-0.2.6}/src/riplex/disc/analysis.py +0 -0
  37. {riplex-0.2.4 → riplex-0.2.6}/src/riplex/disc/makemkv.py +0 -0
  38. {riplex-0.2.4 → riplex-0.2.6}/src/riplex/disc/provider.py +0 -0
  39. {riplex-0.2.4 → riplex-0.2.6}/src/riplex/formatter.py +0 -0
  40. {riplex-0.2.4 → riplex-0.2.6}/src/riplex/lookup.py +0 -0
  41. {riplex-0.2.4 → riplex-0.2.6}/src/riplex/manifest.py +0 -0
  42. {riplex-0.2.4 → riplex-0.2.6}/src/riplex/matcher.py +0 -0
  43. {riplex-0.2.4 → riplex-0.2.6}/src/riplex/metadata/__init__.py +0 -0
  44. {riplex-0.2.4 → riplex-0.2.6}/src/riplex/metadata/planner.py +0 -0
  45. {riplex-0.2.4 → riplex-0.2.6}/src/riplex/metadata/provider.py +0 -0
  46. {riplex-0.2.4 → riplex-0.2.6}/src/riplex/metadata/sources/__init__.py +0 -0
  47. {riplex-0.2.4 → riplex-0.2.6}/src/riplex/metadata/sources/tmdb.py +0 -0
  48. {riplex-0.2.4 → riplex-0.2.6}/src/riplex/models.py +0 -0
  49. {riplex-0.2.4 → riplex-0.2.6}/src/riplex/normalize.py +0 -0
  50. {riplex-0.2.4 → riplex-0.2.6}/src/riplex/organizer.py +0 -0
  51. {riplex-0.2.4 → riplex-0.2.6}/src/riplex/scanner.py +0 -0
  52. {riplex-0.2.4 → riplex-0.2.6}/src/riplex/snapshot.py +0 -0
  53. {riplex-0.2.4 → riplex-0.2.6}/src/riplex/splitter.py +0 -0
  54. {riplex-0.2.4 → riplex-0.2.6}/src/riplex/tagger.py +0 -0
  55. {riplex-0.2.4 → riplex-0.2.6}/src/riplex/title.py +0 -0
  56. {riplex-0.2.4 → riplex-0.2.6}/src/riplex/ui.py +0 -0
  57. {riplex-0.2.4 → riplex-0.2.6}/src/riplex.egg-info/SOURCES.txt +0 -0
  58. {riplex-0.2.4 → riplex-0.2.6}/src/riplex.egg-info/dependency_links.txt +0 -0
  59. {riplex-0.2.4 → riplex-0.2.6}/src/riplex.egg-info/entry_points.txt +0 -0
  60. {riplex-0.2.4 → riplex-0.2.6}/src/riplex.egg-info/requires.txt +0 -0
  61. {riplex-0.2.4 → riplex-0.2.6}/src/riplex.egg-info/top_level.txt +0 -0
  62. {riplex-0.2.4 → riplex-0.2.6}/src/riplex_app/__init__.py +0 -0
  63. {riplex-0.2.4 → riplex-0.2.6}/src/riplex_app/main.py +0 -0
  64. {riplex-0.2.4 → riplex-0.2.6}/src/riplex_app/screens/__init__.py +0 -0
  65. {riplex-0.2.4 → riplex-0.2.6}/src/riplex_app/screens/disc_detection.py +0 -0
  66. {riplex-0.2.4 → riplex-0.2.6}/src/riplex_app/screens/done.py +0 -0
  67. {riplex-0.2.4 → riplex-0.2.6}/src/riplex_app/screens/folder_picker.py +0 -0
  68. {riplex-0.2.4 → riplex-0.2.6}/src/riplex_app/screens/metadata.py +0 -0
  69. {riplex-0.2.4 → riplex-0.2.6}/src/riplex_app/screens/organize_done.py +0 -0
  70. {riplex-0.2.4 → riplex-0.2.6}/src/riplex_app/screens/organize_preview.py +0 -0
  71. {riplex-0.2.4 → riplex-0.2.6}/src/riplex_app/screens/progress.py +0 -0
  72. {riplex-0.2.4 → riplex-0.2.6}/src/riplex_app/screens/release.py +0 -0
  73. {riplex-0.2.4 → riplex-0.2.6}/src/riplex_app/screens/selection.py +0 -0
  74. {riplex-0.2.4 → riplex-0.2.6}/src/riplex_app/updater.py +0 -0
  75. {riplex-0.2.4 → riplex-0.2.6}/src/riplex_cli/__init__.py +0 -0
  76. {riplex-0.2.4 → riplex-0.2.6}/src/riplex_cli/commands/__init__.py +0 -0
  77. {riplex-0.2.4 → riplex-0.2.6}/src/riplex_cli/commands/lookup.py +0 -0
  78. {riplex-0.2.4 → riplex-0.2.6}/src/riplex_cli/commands/orchestrate.py +0 -0
  79. {riplex-0.2.4 → riplex-0.2.6}/src/riplex_cli/commands/organize.py +0 -0
  80. {riplex-0.2.4 → riplex-0.2.6}/src/riplex_cli/commands/rip.py +0 -0
  81. {riplex-0.2.4 → riplex-0.2.6}/src/riplex_cli/commands/setup.py +0 -0
  82. {riplex-0.2.4 → riplex-0.2.6}/src/riplex_cli/formatting.py +0 -0
  83. {riplex-0.2.4 → riplex-0.2.6}/src/riplex_cli/main.py +0 -0
  84. {riplex-0.2.4 → riplex-0.2.6}/tests/__init__.py +0 -0
  85. {riplex-0.2.4 → riplex-0.2.6}/tests/fixtures/makemkvcon_frozen_planet_ii_d2.txt +0 -0
  86. {riplex-0.2.4 → riplex-0.2.6}/tests/fixtures/makemkvcon_list.txt +0 -0
  87. {riplex-0.2.4 → riplex-0.2.6}/tests/snapshots/Batman Begins.snapshot.json +0 -0
  88. {riplex-0.2.4 → riplex-0.2.6}/tests/snapshots/Blade Runner (Blu-ray 4k).snapshot.json +0 -0
  89. {riplex-0.2.4 → riplex-0.2.6}/tests/snapshots/Blade Runner The Final Cut.snapshot.json +0 -0
  90. {riplex-0.2.4 → riplex-0.2.6}/tests/snapshots/Seven Worlds One Planet.snapshot.json +0 -0
  91. {riplex-0.2.4 → riplex-0.2.6}/tests/snapshots/The Dark Knight Rises.snapshot.json +0 -0
  92. {riplex-0.2.4 → riplex-0.2.6}/tests/snapshots/The Dark Knight.snapshot.json +0 -0
  93. {riplex-0.2.4 → riplex-0.2.6}/tests/snapshots/Waterworld.snapshot.json +0 -0
  94. {riplex-0.2.4 → riplex-0.2.6}/tests/test_cache.py +0 -0
  95. {riplex-0.2.4 → riplex-0.2.6}/tests/test_cli_utils.py +0 -0
  96. {riplex-0.2.4 → riplex-0.2.6}/tests/test_config.py +0 -0
  97. {riplex-0.2.4 → riplex-0.2.6}/tests/test_dedup.py +0 -0
  98. {riplex-0.2.4 → riplex-0.2.6}/tests/test_detect.py +0 -0
  99. {riplex-0.2.4 → riplex-0.2.6}/tests/test_disc_analysis.py +0 -0
  100. {riplex-0.2.4 → riplex-0.2.6}/tests/test_disc_provider.py +0 -0
  101. {riplex-0.2.4 → riplex-0.2.6}/tests/test_formatter.py +0 -0
  102. {riplex-0.2.4 → riplex-0.2.6}/tests/test_makemkv.py +0 -0
  103. {riplex-0.2.4 → riplex-0.2.6}/tests/test_matcher.py +0 -0
  104. {riplex-0.2.4 → riplex-0.2.6}/tests/test_normalize.py +0 -0
  105. {riplex-0.2.4 → riplex-0.2.6}/tests/test_organizer.py +0 -0
  106. {riplex-0.2.4 → riplex-0.2.6}/tests/test_planner.py +0 -0
  107. {riplex-0.2.4 → riplex-0.2.6}/tests/test_rip_guide.py +0 -0
  108. {riplex-0.2.4 → riplex-0.2.6}/tests/test_scanner.py +0 -0
  109. {riplex-0.2.4 → riplex-0.2.6}/tests/test_snapshot.py +0 -0
  110. {riplex-0.2.4 → riplex-0.2.6}/tests/test_splitter.py +0 -0
  111. {riplex-0.2.4 → riplex-0.2.6}/tests/test_tagger.py +0 -0
  112. {riplex-0.2.4 → riplex-0.2.6}/tests/test_ui.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: riplex
3
- Version: 0.2.4
3
+ Version: 0.2.6
4
4
  Summary: Automates the tedious manual work around MakeMKV: figuring out what to rip, which MKV files are actually what, and organizing everything into Plex-compatible folder structures.
5
5
  License: MIT
6
6
  Requires-Python: >=3.11
@@ -19,7 +19,7 @@ Requires-Dist: flet>=0.84; extra == "gui"
19
19
 
20
20
  Automates the tedious manual work around MakeMKV: figuring out what to rip, which MKV files are actually what, and organizing everything into Plex-compatible folder structures.
21
21
 
22
- ## Desktop App (recommended for most users)
22
+ ## Desktop App
23
23
 
24
24
  If you'd rather use a simple graphical interface instead of the command line, download the pre-built app from the [Releases page](https://github.com/AnyCredit5518/riplex/releases/latest):
25
25
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  Automates the tedious manual work around MakeMKV: figuring out what to rip, which MKV files are actually what, and organizing everything into Plex-compatible folder structures.
4
4
 
5
- ## Desktop App (recommended for most users)
5
+ ## Desktop App
6
6
 
7
7
  If you'd rather use a simple graphical interface instead of the command line, download the pre-built app from the [Releases page](https://github.com/AnyCredit5518/riplex/releases/latest):
8
8
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: riplex
3
- Version: 0.2.4
3
+ Version: 0.2.6
4
4
  Summary: Automates the tedious manual work around MakeMKV: figuring out what to rip, which MKV files are actually what, and organizing everything into Plex-compatible folder structures.
5
5
  License: MIT
6
6
  Requires-Python: >=3.11
@@ -19,7 +19,7 @@ Requires-Dist: flet>=0.84; extra == "gui"
19
19
 
20
20
  Automates the tedious manual work around MakeMKV: figuring out what to rip, which MKV files are actually what, and organizing everything into Plex-compatible folder structures.
21
21
 
22
- ## Desktop App (recommended for most users)
22
+ ## Desktop App
23
23
 
24
24
  If you'd rather use a simple graphical interface instead of the command line, download the pre-built app from the [Releases page](https://github.com/AnyCredit5518/riplex/releases/latest):
25
25
 
@@ -31,6 +31,14 @@ class WelcomeScreen:
31
31
  ("mkvmerge", has_mkvmerge),
32
32
  ]
33
33
 
34
+ missing_tools = []
35
+ if not has_makemkv:
36
+ missing_tools.append("makemkvcon")
37
+ if not has_ffprobe:
38
+ missing_tools.append("ffprobe")
39
+ if not has_mkvmerge:
40
+ missing_tools.append("mkvmerge")
41
+
34
42
  status_rows = []
35
43
  for label, ok in checks:
36
44
  icon = ft.Icon(ft.Icons.CHECK_CIRCLE, color=ft.Colors.GREEN) if ok else ft.Icon(ft.Icons.ERROR, color=ft.Colors.RED)
@@ -38,6 +46,41 @@ class WelcomeScreen:
38
46
  ft.Row([icon, ft.Text(label, size=14)], spacing=8)
39
47
  )
40
48
 
49
+ # Install tools section (shown when tools are missing)
50
+ self._install_status = ft.Text("", size=12, color=ft.Colors.GREY_400)
51
+ install_section = ft.Container(
52
+ ft.Column([
53
+ ft.Text(
54
+ "Some tools are missing. Click below to install them automatically, "
55
+ "or use the links to download manually.",
56
+ size=13,
57
+ color=ft.Colors.ORANGE,
58
+ ),
59
+ ft.Container(height=4),
60
+ ft.Row([
61
+ ft.ElevatedButton(
62
+ "Install Missing Tools",
63
+ icon=ft.Icons.DOWNLOAD,
64
+ on_click=lambda _: self._install_tools(missing_tools),
65
+ ),
66
+ ft.TextButton(
67
+ "MakeMKV ↗",
68
+ url="https://www.makemkv.com/download/",
69
+ ),
70
+ ft.TextButton(
71
+ "FFmpeg ↗",
72
+ url="https://ffmpeg.org/download.html",
73
+ ),
74
+ ft.TextButton(
75
+ "MKVToolNix ↗",
76
+ url="https://mkvtoolnix.download/downloads.html",
77
+ ),
78
+ ], spacing=8, wrap=True),
79
+ self._install_status,
80
+ ], spacing=4),
81
+ visible=bool(missing_tools),
82
+ )
83
+
41
84
  # Rip requires all tools; organize only needs ffprobe + config
42
85
  can_rip = all(ok for _, ok in checks)
43
86
  can_organize = has_config and has_ffprobe
@@ -123,15 +166,6 @@ class WelcomeScreen:
123
166
  visible=not has_config,
124
167
  )
125
168
 
126
- # Tool warning
127
- tool_warning = ft.Container(
128
- ft.Text(
129
- "Some required tools are missing. Install them and restart the app.",
130
- color=ft.Colors.ORANGE,
131
- ),
132
- visible=not can_rip and has_config,
133
- )
134
-
135
169
  # Workflow buttons
136
170
  rip_button = ft.ElevatedButton(
137
171
  "Rip Disc",
@@ -154,8 +188,8 @@ class WelcomeScreen:
154
188
  self.update_banner = ft.Container(
155
189
  ft.Row(
156
190
  [
157
- ft.Icon(ft.Icons.SYSTEM_UPDATE, color=ft.Colors.BLUE),
158
- ft.Text("", size=13, ref=None),
191
+ ft.Icon(ft.Icons.SYSTEM_UPDATE, color=ft.Colors.BLUE_700),
192
+ ft.Text("", size=13, color=ft.Colors.BLUE_900),
159
193
  ft.TextButton("Download", on_click=self._open_update),
160
194
  ],
161
195
  spacing=8,
@@ -191,9 +225,9 @@ class WelcomeScreen:
191
225
  ft.Container(height=5),
192
226
  ft.Text("Status", size=18, weight=ft.FontWeight.BOLD),
193
227
  ft.Column(status_rows, spacing=4),
228
+ install_section,
194
229
  ft.Container(height=10),
195
230
  setup_section,
196
- tool_warning,
197
231
  ft.Container(expand=True),
198
232
  ft.Text("What would you like to do?", size=16, weight=ft.FontWeight.BOLD),
199
233
  ft.Row([rip_button, organize_button], spacing=20),
@@ -235,7 +269,9 @@ class WelcomeScreen:
235
269
  async def _show():
236
270
  banner_row = self.update_banner.content
237
271
  banner_row.controls[1] = ft.Text(
238
- f"Update available: {info['tag']}", size=13
272
+ f"Update available: {info['tag']}",
273
+ size=13,
274
+ color=ft.Colors.BLUE_900,
239
275
  )
240
276
  self.update_banner.visible = True
241
277
  self.app.page.update()
@@ -250,6 +286,54 @@ class WelcomeScreen:
250
286
  url = get_download_url(self._update_info)
251
287
  webbrowser.open(url)
252
288
 
289
+ def _install_tools(self, missing: list[str]):
290
+ """Install missing tools via system package manager in background."""
291
+ import platform
292
+ import subprocess
293
+ import sys
294
+
295
+ system = platform.system()
296
+ packages = {
297
+ "Windows": {"makemkvcon": "MakeMKV.MakeMKV", "ffprobe": "Gyan.FFmpeg", "mkvmerge": "MKVToolNix.MKVToolNix"},
298
+ "Darwin": {"makemkvcon": "makemkv", "ffprobe": "ffmpeg", "mkvmerge": "mkvtoolnix"},
299
+ }
300
+
301
+ pkg_map = packages.get(system, {})
302
+ to_install = sorted(set(pkg_map[t] for t in missing if pkg_map.get(t)))
303
+ if not to_install:
304
+ self._install_status.value = "Auto-install not supported on this platform. Use the links above."
305
+ self.app.page.update()
306
+ return
307
+
308
+ def _do_install():
309
+ async def _update_status(msg):
310
+ self._install_status.value = msg
311
+ self.app.page.update()
312
+
313
+ try:
314
+ if system == "Windows":
315
+ for pkg in to_install:
316
+ self.app.page.run_task(lambda p=pkg: _update_status(f"Installing {p}..."))
317
+ subprocess.run(
318
+ ["winget", "install", "--accept-source-agreements",
319
+ "--accept-package-agreements", pkg],
320
+ check=True,
321
+ creationflags=subprocess.CREATE_NO_WINDOW if sys.platform == "win32" else 0,
322
+ )
323
+ elif system == "Darwin":
324
+ self.app.page.run_task(lambda: _update_status("Installing via brew..."))
325
+ subprocess.run(["brew", "install"] + to_install, check=True)
326
+
327
+ self.app.page.run_task(
328
+ lambda: _update_status("Done! Restart the app for changes to take effect.")
329
+ )
330
+ except (subprocess.CalledProcessError, FileNotFoundError) as exc:
331
+ self.app.page.run_task(
332
+ lambda: _update_status(f"Install failed: {exc}. Try the manual links above.")
333
+ )
334
+
335
+ threading.Thread(target=_do_install, daemon=True).start()
336
+
253
337
  def _save_config(self, e):
254
338
  """Write config from the setup fields."""
255
339
  from riplex.config import save_config
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes