riplex 0.2.3__tar.gz → 0.2.5__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.3/src/riplex.egg-info → riplex-0.2.5}/PKG-INFO +12 -1
  2. {riplex-0.2.3 → riplex-0.2.5}/README.md +11 -0
  3. {riplex-0.2.3 → riplex-0.2.5/src/riplex.egg-info}/PKG-INFO +12 -1
  4. {riplex-0.2.3 → riplex-0.2.5}/src/riplex_app/screens/welcome.py +92 -10
  5. {riplex-0.2.3 → riplex-0.2.5}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
  6. {riplex-0.2.3 → riplex-0.2.5}/.github/agents/riplex.agent.md +0 -0
  7. {riplex-0.2.3 → riplex-0.2.5}/.github/copilot-instructions.md +0 -0
  8. {riplex-0.2.3 → riplex-0.2.5}/.github/workflows/publish.yml +0 -0
  9. {riplex-0.2.3 → riplex-0.2.5}/.github/workflows/release.yml +0 -0
  10. {riplex-0.2.3 → riplex-0.2.5}/.gitignore +0 -0
  11. {riplex-0.2.3 → riplex-0.2.5}/MONOREPO_PLAN.md +0 -0
  12. {riplex-0.2.3 → riplex-0.2.5}/PLANNED_FEATURES.md +0 -0
  13. {riplex-0.2.3 → riplex-0.2.5}/REFACTOR_PLAN.md +0 -0
  14. {riplex-0.2.3 → riplex-0.2.5}/docs/architecture.md +0 -0
  15. {riplex-0.2.3 → riplex-0.2.5}/docs/changelog.md +0 -0
  16. {riplex-0.2.3 → riplex-0.2.5}/docs/getting-started/configuration.md +0 -0
  17. {riplex-0.2.3 → riplex-0.2.5}/docs/getting-started/installation.md +0 -0
  18. {riplex-0.2.3 → riplex-0.2.5}/docs/guide/lookup.md +0 -0
  19. {riplex-0.2.3 → riplex-0.2.5}/docs/guide/orchestrate.md +0 -0
  20. {riplex-0.2.3 → riplex-0.2.5}/docs/guide/organize.md +0 -0
  21. {riplex-0.2.3 → riplex-0.2.5}/docs/guide/workflow.md +0 -0
  22. {riplex-0.2.3 → riplex-0.2.5}/docs/index.md +0 -0
  23. {riplex-0.2.3 → riplex-0.2.5}/docs/naming-rules.md +0 -0
  24. {riplex-0.2.3 → riplex-0.2.5}/docs/reference/cli.md +0 -0
  25. {riplex-0.2.3 → riplex-0.2.5}/issues/cross-disc-dvdcompare-matching.md +0 -0
  26. {riplex-0.2.3 → riplex-0.2.5}/mkdocs.yml +0 -0
  27. {riplex-0.2.3 → riplex-0.2.5}/plex_naming_rules.md +0 -0
  28. {riplex-0.2.3 → riplex-0.2.5}/pyproject.toml +0 -0
  29. {riplex-0.2.3 → riplex-0.2.5}/setup.cfg +0 -0
  30. {riplex-0.2.3 → riplex-0.2.5}/src/riplex/__init__.py +0 -0
  31. {riplex-0.2.3 → riplex-0.2.5}/src/riplex/cache.py +0 -0
  32. {riplex-0.2.3 → riplex-0.2.5}/src/riplex/config.py +0 -0
  33. {riplex-0.2.3 → riplex-0.2.5}/src/riplex/dedup.py +0 -0
  34. {riplex-0.2.3 → riplex-0.2.5}/src/riplex/detect.py +0 -0
  35. {riplex-0.2.3 → riplex-0.2.5}/src/riplex/disc/__init__.py +0 -0
  36. {riplex-0.2.3 → riplex-0.2.5}/src/riplex/disc/analysis.py +0 -0
  37. {riplex-0.2.3 → riplex-0.2.5}/src/riplex/disc/makemkv.py +0 -0
  38. {riplex-0.2.3 → riplex-0.2.5}/src/riplex/disc/provider.py +0 -0
  39. {riplex-0.2.3 → riplex-0.2.5}/src/riplex/formatter.py +0 -0
  40. {riplex-0.2.3 → riplex-0.2.5}/src/riplex/lookup.py +0 -0
  41. {riplex-0.2.3 → riplex-0.2.5}/src/riplex/manifest.py +0 -0
  42. {riplex-0.2.3 → riplex-0.2.5}/src/riplex/matcher.py +0 -0
  43. {riplex-0.2.3 → riplex-0.2.5}/src/riplex/metadata/__init__.py +0 -0
  44. {riplex-0.2.3 → riplex-0.2.5}/src/riplex/metadata/planner.py +0 -0
  45. {riplex-0.2.3 → riplex-0.2.5}/src/riplex/metadata/provider.py +0 -0
  46. {riplex-0.2.3 → riplex-0.2.5}/src/riplex/metadata/sources/__init__.py +0 -0
  47. {riplex-0.2.3 → riplex-0.2.5}/src/riplex/metadata/sources/tmdb.py +0 -0
  48. {riplex-0.2.3 → riplex-0.2.5}/src/riplex/models.py +0 -0
  49. {riplex-0.2.3 → riplex-0.2.5}/src/riplex/normalize.py +0 -0
  50. {riplex-0.2.3 → riplex-0.2.5}/src/riplex/organizer.py +0 -0
  51. {riplex-0.2.3 → riplex-0.2.5}/src/riplex/scanner.py +0 -0
  52. {riplex-0.2.3 → riplex-0.2.5}/src/riplex/snapshot.py +0 -0
  53. {riplex-0.2.3 → riplex-0.2.5}/src/riplex/splitter.py +0 -0
  54. {riplex-0.2.3 → riplex-0.2.5}/src/riplex/tagger.py +0 -0
  55. {riplex-0.2.3 → riplex-0.2.5}/src/riplex/title.py +0 -0
  56. {riplex-0.2.3 → riplex-0.2.5}/src/riplex/ui.py +0 -0
  57. {riplex-0.2.3 → riplex-0.2.5}/src/riplex.egg-info/SOURCES.txt +0 -0
  58. {riplex-0.2.3 → riplex-0.2.5}/src/riplex.egg-info/dependency_links.txt +0 -0
  59. {riplex-0.2.3 → riplex-0.2.5}/src/riplex.egg-info/entry_points.txt +0 -0
  60. {riplex-0.2.3 → riplex-0.2.5}/src/riplex.egg-info/requires.txt +0 -0
  61. {riplex-0.2.3 → riplex-0.2.5}/src/riplex.egg-info/top_level.txt +0 -0
  62. {riplex-0.2.3 → riplex-0.2.5}/src/riplex_app/__init__.py +0 -0
  63. {riplex-0.2.3 → riplex-0.2.5}/src/riplex_app/main.py +0 -0
  64. {riplex-0.2.3 → riplex-0.2.5}/src/riplex_app/screens/__init__.py +0 -0
  65. {riplex-0.2.3 → riplex-0.2.5}/src/riplex_app/screens/disc_detection.py +0 -0
  66. {riplex-0.2.3 → riplex-0.2.5}/src/riplex_app/screens/done.py +0 -0
  67. {riplex-0.2.3 → riplex-0.2.5}/src/riplex_app/screens/folder_picker.py +0 -0
  68. {riplex-0.2.3 → riplex-0.2.5}/src/riplex_app/screens/metadata.py +0 -0
  69. {riplex-0.2.3 → riplex-0.2.5}/src/riplex_app/screens/organize_done.py +0 -0
  70. {riplex-0.2.3 → riplex-0.2.5}/src/riplex_app/screens/organize_preview.py +0 -0
  71. {riplex-0.2.3 → riplex-0.2.5}/src/riplex_app/screens/progress.py +0 -0
  72. {riplex-0.2.3 → riplex-0.2.5}/src/riplex_app/screens/release.py +0 -0
  73. {riplex-0.2.3 → riplex-0.2.5}/src/riplex_app/screens/selection.py +0 -0
  74. {riplex-0.2.3 → riplex-0.2.5}/src/riplex_app/updater.py +0 -0
  75. {riplex-0.2.3 → riplex-0.2.5}/src/riplex_cli/__init__.py +0 -0
  76. {riplex-0.2.3 → riplex-0.2.5}/src/riplex_cli/commands/__init__.py +0 -0
  77. {riplex-0.2.3 → riplex-0.2.5}/src/riplex_cli/commands/lookup.py +0 -0
  78. {riplex-0.2.3 → riplex-0.2.5}/src/riplex_cli/commands/orchestrate.py +0 -0
  79. {riplex-0.2.3 → riplex-0.2.5}/src/riplex_cli/commands/organize.py +0 -0
  80. {riplex-0.2.3 → riplex-0.2.5}/src/riplex_cli/commands/rip.py +0 -0
  81. {riplex-0.2.3 → riplex-0.2.5}/src/riplex_cli/commands/setup.py +0 -0
  82. {riplex-0.2.3 → riplex-0.2.5}/src/riplex_cli/formatting.py +0 -0
  83. {riplex-0.2.3 → riplex-0.2.5}/src/riplex_cli/main.py +0 -0
  84. {riplex-0.2.3 → riplex-0.2.5}/tests/__init__.py +0 -0
  85. {riplex-0.2.3 → riplex-0.2.5}/tests/fixtures/makemkvcon_frozen_planet_ii_d2.txt +0 -0
  86. {riplex-0.2.3 → riplex-0.2.5}/tests/fixtures/makemkvcon_list.txt +0 -0
  87. {riplex-0.2.3 → riplex-0.2.5}/tests/snapshots/Batman Begins.snapshot.json +0 -0
  88. {riplex-0.2.3 → riplex-0.2.5}/tests/snapshots/Blade Runner (Blu-ray 4k).snapshot.json +0 -0
  89. {riplex-0.2.3 → riplex-0.2.5}/tests/snapshots/Blade Runner The Final Cut.snapshot.json +0 -0
  90. {riplex-0.2.3 → riplex-0.2.5}/tests/snapshots/Seven Worlds One Planet.snapshot.json +0 -0
  91. {riplex-0.2.3 → riplex-0.2.5}/tests/snapshots/The Dark Knight Rises.snapshot.json +0 -0
  92. {riplex-0.2.3 → riplex-0.2.5}/tests/snapshots/The Dark Knight.snapshot.json +0 -0
  93. {riplex-0.2.3 → riplex-0.2.5}/tests/snapshots/Waterworld.snapshot.json +0 -0
  94. {riplex-0.2.3 → riplex-0.2.5}/tests/test_cache.py +0 -0
  95. {riplex-0.2.3 → riplex-0.2.5}/tests/test_cli_utils.py +0 -0
  96. {riplex-0.2.3 → riplex-0.2.5}/tests/test_config.py +0 -0
  97. {riplex-0.2.3 → riplex-0.2.5}/tests/test_dedup.py +0 -0
  98. {riplex-0.2.3 → riplex-0.2.5}/tests/test_detect.py +0 -0
  99. {riplex-0.2.3 → riplex-0.2.5}/tests/test_disc_analysis.py +0 -0
  100. {riplex-0.2.3 → riplex-0.2.5}/tests/test_disc_provider.py +0 -0
  101. {riplex-0.2.3 → riplex-0.2.5}/tests/test_formatter.py +0 -0
  102. {riplex-0.2.3 → riplex-0.2.5}/tests/test_makemkv.py +0 -0
  103. {riplex-0.2.3 → riplex-0.2.5}/tests/test_matcher.py +0 -0
  104. {riplex-0.2.3 → riplex-0.2.5}/tests/test_normalize.py +0 -0
  105. {riplex-0.2.3 → riplex-0.2.5}/tests/test_organizer.py +0 -0
  106. {riplex-0.2.3 → riplex-0.2.5}/tests/test_planner.py +0 -0
  107. {riplex-0.2.3 → riplex-0.2.5}/tests/test_rip_guide.py +0 -0
  108. {riplex-0.2.3 → riplex-0.2.5}/tests/test_scanner.py +0 -0
  109. {riplex-0.2.3 → riplex-0.2.5}/tests/test_snapshot.py +0 -0
  110. {riplex-0.2.3 → riplex-0.2.5}/tests/test_splitter.py +0 -0
  111. {riplex-0.2.3 → riplex-0.2.5}/tests/test_tagger.py +0 -0
  112. {riplex-0.2.3 → riplex-0.2.5}/tests/test_ui.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: riplex
3
- Version: 0.2.3
3
+ Version: 0.2.5
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,6 +19,17 @@ 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
23
+
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
+
26
+ - **Windows**: Download `riplex-ui-windows.exe` and double-click to run
27
+ - **macOS**: Download `riplex-ui-macos.zip`, unzip, and open `riplex-ui.app`
28
+
29
+ No Python install required. The app walks you through setup and provides buttons for all workflows.
30
+
31
+ ---
32
+
22
33
  ## Why?
23
34
 
24
35
  MakeMKV is great at one thing: reading a disc and dumping raw MKV files. But that's where its job ends and yours begins.
@@ -2,6 +2,17 @@
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
6
+
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
+
9
+ - **Windows**: Download `riplex-ui-windows.exe` and double-click to run
10
+ - **macOS**: Download `riplex-ui-macos.zip`, unzip, and open `riplex-ui.app`
11
+
12
+ No Python install required. The app walks you through setup and provides buttons for all workflows.
13
+
14
+ ---
15
+
5
16
  ## Why?
6
17
 
7
18
  MakeMKV is great at one thing: reading a disc and dumping raw MKV files. But that's where its job ends and yours begins.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: riplex
3
- Version: 0.2.3
3
+ Version: 0.2.5
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,6 +19,17 @@ 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
23
+
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
+
26
+ - **Windows**: Download `riplex-ui-windows.exe` and double-click to run
27
+ - **macOS**: Download `riplex-ui-macos.zip`, unzip, and open `riplex-ui.app`
28
+
29
+ No Python install required. The app walks you through setup and provides buttons for all workflows.
30
+
31
+ ---
32
+
22
33
  ## Why?
23
34
 
24
35
  MakeMKV is great at one thing: reading a disc and dumping raw MKV files. But that's where its job ends and yours begins.
@@ -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",
@@ -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),
@@ -250,6 +284,54 @@ class WelcomeScreen:
250
284
  url = get_download_url(self._update_info)
251
285
  webbrowser.open(url)
252
286
 
287
+ def _install_tools(self, missing: list[str]):
288
+ """Install missing tools via system package manager in background."""
289
+ import platform
290
+ import subprocess
291
+ import sys
292
+
293
+ system = platform.system()
294
+ packages = {
295
+ "Windows": {"makemkvcon": "MakeMKV.MakeMKV", "ffprobe": "Gyan.FFmpeg", "mkvmerge": "MKVToolNix.MKVToolNix"},
296
+ "Darwin": {"makemkvcon": "makemkv", "ffprobe": "ffmpeg", "mkvmerge": "mkvtoolnix"},
297
+ }
298
+
299
+ pkg_map = packages.get(system, {})
300
+ to_install = sorted(set(pkg_map[t] for t in missing if pkg_map.get(t)))
301
+ if not to_install:
302
+ self._install_status.value = "Auto-install not supported on this platform. Use the links above."
303
+ self.app.page.update()
304
+ return
305
+
306
+ def _do_install():
307
+ async def _update_status(msg):
308
+ self._install_status.value = msg
309
+ self.app.page.update()
310
+
311
+ try:
312
+ if system == "Windows":
313
+ for pkg in to_install:
314
+ self.app.page.run_task(lambda p=pkg: _update_status(f"Installing {p}..."))
315
+ subprocess.run(
316
+ ["winget", "install", "--accept-source-agreements",
317
+ "--accept-package-agreements", pkg],
318
+ check=True,
319
+ creationflags=subprocess.CREATE_NO_WINDOW if sys.platform == "win32" else 0,
320
+ )
321
+ elif system == "Darwin":
322
+ self.app.page.run_task(lambda: _update_status("Installing via brew..."))
323
+ subprocess.run(["brew", "install"] + to_install, check=True)
324
+
325
+ self.app.page.run_task(
326
+ lambda: _update_status("Done! Restart the app for changes to take effect.")
327
+ )
328
+ except (subprocess.CalledProcessError, FileNotFoundError) as exc:
329
+ self.app.page.run_task(
330
+ lambda: _update_status(f"Install failed: {exc}. Try the manual links above.")
331
+ )
332
+
333
+ threading.Thread(target=_do_install, daemon=True).start()
334
+
253
335
  def _save_config(self, e):
254
336
  """Write config from the setup fields."""
255
337
  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