weeb-cli 2.16.0__tar.gz → 2.16.1__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 (129) hide show
  1. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/PKG-INFO +4 -1
  2. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/pyproject.toml +2 -1
  3. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli/__init__.py +1 -1
  4. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli/main.py +11 -0
  5. weeb_cli-2.16.1/weeb_cli/utils/shortcuts.py +269 -0
  6. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli.egg-info/PKG-INFO +4 -1
  7. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli.egg-info/SOURCES.txt +2 -1
  8. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli.egg-info/requires.txt +6 -0
  9. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/LICENSE +0 -0
  10. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/README.md +0 -0
  11. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/setup.cfg +0 -0
  12. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/tests/test_anilist_tracker.py +0 -0
  13. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/tests/test_aniworld_provider.py +0 -0
  14. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/tests/test_api.py +0 -0
  15. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/tests/test_cache.py +0 -0
  16. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/tests/test_exceptions.py +0 -0
  17. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/tests/test_kitsu_tracker.py +0 -0
  18. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/tests/test_mal_tracker.py +0 -0
  19. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/tests/test_providers.py +0 -0
  20. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/tests/test_restful_api.py +0 -0
  21. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/tests/test_sanitizer.py +0 -0
  22. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/tests/test_sanitizer_security.py +0 -0
  23. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/tests/test_sdk.py +0 -0
  24. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli/__main__.py +0 -0
  25. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli/commands/__init__.py +0 -0
  26. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli/commands/api.py +0 -0
  27. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli/commands/downloads.py +0 -0
  28. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli/commands/library.py +0 -0
  29. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli/commands/search/__init__.py +0 -0
  30. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli/commands/search/anime_details.py +0 -0
  31. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli/commands/search/download_flow.py +0 -0
  32. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli/commands/search/episode_utils.py +0 -0
  33. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli/commands/search/search_handlers.py +0 -0
  34. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli/commands/search/stream_utils.py +0 -0
  35. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli/commands/search/watch_flow.py +0 -0
  36. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli/commands/search.py +0 -0
  37. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli/commands/serve.py +0 -0
  38. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli/commands/serve_restful.py +0 -0
  39. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli/commands/settings/__init__.py +0 -0
  40. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli/commands/settings/settings_backup.py +0 -0
  41. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli/commands/settings/settings_cache.py +0 -0
  42. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli/commands/settings/settings_config.py +0 -0
  43. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli/commands/settings/settings_download.py +0 -0
  44. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli/commands/settings/settings_drives.py +0 -0
  45. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli/commands/settings/settings_menu.py +0 -0
  46. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli/commands/settings/settings_shortcuts.py +0 -0
  47. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli/commands/settings/settings_trackers.py +0 -0
  48. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli/commands/settings.py +0 -0
  49. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli/commands/setup.py +0 -0
  50. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli/commands/watchlist.py +0 -0
  51. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli/config.py +0 -0
  52. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli/constants.py +0 -0
  53. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli/exceptions.py +0 -0
  54. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli/i18n.py +0 -0
  55. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli/locales/de.json +0 -0
  56. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli/locales/en.json +0 -0
  57. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli/locales/pl.json +0 -0
  58. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli/locales/tr.json +0 -0
  59. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli/providers/__init__.py +0 -0
  60. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli/providers/base.py +0 -0
  61. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli/providers/de/__init__.py +0 -0
  62. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli/providers/de/aniworld.py +0 -0
  63. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli/providers/en/__init__.py +0 -0
  64. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli/providers/en/allanime.py +0 -0
  65. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli/providers/en/hianime.py +0 -0
  66. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli/providers/extractors/__init__.py +0 -0
  67. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli/providers/extractors/doodstream.py +0 -0
  68. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli/providers/extractors/filemoon.py +0 -0
  69. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli/providers/extractors/megacloud.py +0 -0
  70. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli/providers/extractors/streamtape.py +0 -0
  71. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli/providers/extractors/vidoza.py +0 -0
  72. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli/providers/extractors/voe.py +0 -0
  73. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli/providers/pl/__init__.py +0 -0
  74. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli/providers/pl/docchi.py +0 -0
  75. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli/providers/registry.py +0 -0
  76. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli/providers/tr/__init__.py +0 -0
  77. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli/providers/tr/animecix.py +0 -0
  78. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli/providers/tr/anizle.py +0 -0
  79. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli/providers/tr/turkanime.py +0 -0
  80. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli/providers/tr/weeb.py +0 -0
  81. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli/sdk.py +0 -0
  82. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli/services/__init__.py +0 -0
  83. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli/services/_base.py +0 -0
  84. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli/services/_tracker_base.py +0 -0
  85. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli/services/aniskip.py +0 -0
  86. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli/services/cache.py +0 -0
  87. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli/services/database.py +0 -0
  88. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli/services/dependency_manager.py +0 -0
  89. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli/services/details.py +0 -0
  90. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli/services/discord_rpc.py +0 -0
  91. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli/services/download/__init__.py +0 -0
  92. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli/services/download/context.py +0 -0
  93. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli/services/download/manager.py +0 -0
  94. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli/services/download/queue.py +0 -0
  95. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli/services/download/strategies/__init__.py +0 -0
  96. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli/services/download/strategies/aria2.py +0 -0
  97. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli/services/download/strategies/base.py +0 -0
  98. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli/services/download/strategies/ffmpeg.py +0 -0
  99. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli/services/download/strategies/generic.py +0 -0
  100. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli/services/download/strategies/ytdlp.py +0 -0
  101. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli/services/downloader.py +0 -0
  102. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli/services/error_handler.py +0 -0
  103. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli/services/headless_downloader.py +0 -0
  104. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli/services/local_library.py +0 -0
  105. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli/services/logger.py +0 -0
  106. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli/services/notifier.py +0 -0
  107. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli/services/player.py +0 -0
  108. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli/services/progress.py +0 -0
  109. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli/services/scraper.py +0 -0
  110. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli/services/search.py +0 -0
  111. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli/services/shortcuts.py +0 -0
  112. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli/services/stream_validator.py +0 -0
  113. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli/services/tracker.py +0 -0
  114. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli/services/updater.py +0 -0
  115. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli/services/watch.py +0 -0
  116. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli/templates/anilist_error.html +0 -0
  117. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli/templates/anilist_success.html +0 -0
  118. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli/templates/mal_error.html +0 -0
  119. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli/templates/mal_success.html +0 -0
  120. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli/ui/__init__.py +0 -0
  121. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli/ui/header.py +0 -0
  122. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli/ui/menu.py +0 -0
  123. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli/ui/prompt.py +0 -0
  124. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli/utils/__init__.py +0 -0
  125. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli/utils/decorators.py +0 -0
  126. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli/utils/sanitizer.py +0 -0
  127. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli.egg-info/dependency_links.txt +0 -0
  128. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli.egg-info/entry_points.txt +0 -0
  129. {weeb_cli-2.16.0 → weeb_cli-2.16.1}/weeb_cli.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: weeb-cli
3
- Version: 2.16.0
3
+ Version: 2.16.1
4
4
  Summary: No browser, no ads, no distractions. Just you and an unparalleled anime viewing experience.
5
5
  Author-email: ewgsta <ewgst@proton.me>
6
6
  License-Expression: GPL-3.0-only
@@ -35,6 +35,9 @@ Requires-Dist: pyyaml>=6.0; extra == "serve"
35
35
  Provides-Extra: serve-restful
36
36
  Requires-Dist: flask>=3.0; extra == "serve-restful"
37
37
  Requires-Dist: flask-cors>=4.0; extra == "serve-restful"
38
+ Provides-Extra: shortcuts
39
+ Requires-Dist: pywin32; sys_platform == "win32" and extra == "shortcuts"
40
+ Requires-Dist: winshell; sys_platform == "win32" and extra == "shortcuts"
38
41
  Provides-Extra: dev
39
42
  Requires-Dist: build; extra == "dev"
40
43
  Requires-Dist: pyinstaller; extra == "dev"
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "weeb-cli"
7
- version = "2.16.0"
7
+ version = "2.16.1"
8
8
  description = "No browser, no ads, no distractions. Just you and an unparalleled anime viewing experience."
9
9
  readme = "README.md"
10
10
  authors = [{ name = "ewgsta", email = "ewgst@proton.me" }]
@@ -37,6 +37,7 @@ dependencies = [
37
37
  [project.optional-dependencies]
38
38
  serve = ["flask>=3.0", "pyyaml>=6.0"]
39
39
  serve-restful = ["flask>=3.0", "flask-cors>=4.0"]
40
+ shortcuts = ["pywin32; sys_platform == 'win32'", "winshell; sys_platform == 'win32'"]
40
41
  dev = ["build", "pyinstaller", "pytest>=7.0.0", "pytest-cov", "pytest-asyncio", "pytest-mock"]
41
42
 
42
43
  [tool.setuptools.packages.find]
@@ -31,7 +31,7 @@ Attributes:
31
31
  __version__ (str): Current version of Weeb CLI.
32
32
  """
33
33
 
34
- __version__ = "2.16.0"
34
+ __version__ = "2.16.1"
35
35
 
36
36
  # SDK exports for easy import
37
37
  from weeb_cli.sdk import WeebSDK, list_providers, get_provider_info
@@ -65,6 +65,17 @@ def start():
65
65
  if not config.get("language"):
66
66
  run_setup()
67
67
 
68
+ # Create desktop shortcuts in background (non-blocking)
69
+ import threading
70
+ def _create_shortcuts_background():
71
+ try:
72
+ from weeb_cli.utils.shortcuts import create_shortcuts
73
+ create_shortcuts()
74
+ except Exception:
75
+ pass # Silently fail, shortcuts are optional
76
+
77
+ threading.Thread(target=_create_shortcuts_background, daemon=True).start()
78
+
68
79
  # Initialize AniSkip service with config
69
80
  from weeb_cli.services.aniskip import aniskip_service
70
81
  aniskip_enabled = config.get("aniskip_enabled", False)
@@ -0,0 +1,269 @@
1
+ """Desktop shortcut creation utilities.
2
+
3
+ Creates platform-specific shortcuts for easy application access:
4
+ - Linux: .desktop file in ~/.local/share/applications/
5
+ - macOS: .app alias in /Applications/
6
+ - Windows: Start Menu shortcut
7
+ """
8
+
9
+ import os
10
+ import sys
11
+ import shutil
12
+ from pathlib import Path
13
+ from typing import Optional
14
+
15
+
16
+ def get_executable_path() -> str:
17
+ """Get the path to the weeb-cli executable.
18
+
19
+ Returns:
20
+ Path to the executable or python script.
21
+ """
22
+ if getattr(sys, 'frozen', False):
23
+ # Running as compiled executable
24
+ return sys.executable
25
+ else:
26
+ # Running as Python script
27
+ return shutil.which('weeb-cli') or sys.executable
28
+
29
+
30
+ def get_icon_path() -> Optional[str]:
31
+ """Get the path to the application icon if available.
32
+
33
+ Returns:
34
+ Path to icon file or None.
35
+ """
36
+ # Try to find icon in package
37
+ try:
38
+ import weeb_cli
39
+ package_dir = Path(weeb_cli.__file__).parent
40
+ icon_path = package_dir / 'assets' / 'icon.png'
41
+ if icon_path.exists():
42
+ return str(icon_path)
43
+ except Exception:
44
+ pass
45
+ return None
46
+
47
+
48
+ def create_linux_desktop_file() -> bool:
49
+ """Create .desktop file for Linux.
50
+
51
+ Creates a desktop entry in ~/.local/share/applications/
52
+ following the freedesktop.org specification.
53
+
54
+ Returns:
55
+ True if successful, False otherwise.
56
+ """
57
+ try:
58
+ apps_dir = Path.home() / '.local' / 'share' / 'applications'
59
+ apps_dir.mkdir(parents=True, exist_ok=True)
60
+
61
+ desktop_file = apps_dir / 'weeb-cli.desktop'
62
+
63
+ # Don't recreate if it already exists
64
+ if desktop_file.exists():
65
+ return True
66
+
67
+ executable = get_executable_path()
68
+ icon = get_icon_path() or 'utilities-terminal'
69
+
70
+ content = f"""[Desktop Entry]
71
+ Version=1.0
72
+ Type=Application
73
+ Name=Weeb CLI
74
+ Comment=Terminal-based anime streaming application
75
+ Exec={executable}
76
+ Icon={icon}
77
+ Terminal=true
78
+ Categories=AudioVideo;Video;Player;
79
+ Keywords=anime;streaming;video;
80
+ StartupNotify=false
81
+ """
82
+
83
+ desktop_file.write_text(content)
84
+ desktop_file.chmod(0o755)
85
+
86
+ return True
87
+ except Exception:
88
+ return False
89
+
90
+
91
+ def create_macos_alias() -> bool:
92
+ """Create application alias for macOS.
93
+
94
+ Creates a symbolic link in /Applications/ if user has permissions,
95
+ otherwise creates in ~/Applications/.
96
+
97
+ Returns:
98
+ True if successful, False otherwise.
99
+ """
100
+ try:
101
+ executable = get_executable_path()
102
+
103
+ # Try system Applications first, fallback to user Applications
104
+ for apps_dir in [Path('/Applications'), Path.home() / 'Applications']:
105
+ apps_dir.mkdir(parents=True, exist_ok=True)
106
+
107
+ link_path = apps_dir / 'Weeb CLI'
108
+
109
+ # Don't recreate if it already exists
110
+ if link_path.exists():
111
+ return True
112
+
113
+ try:
114
+ # Create symbolic link
115
+ link_path.symlink_to(executable)
116
+ return True
117
+ except PermissionError:
118
+ # Try next location
119
+ continue
120
+
121
+ return False
122
+ except Exception:
123
+ return False
124
+
125
+
126
+ def create_windows_shortcut() -> bool:
127
+ """Create Start Menu shortcut for Windows.
128
+
129
+ Creates a shortcut in the Start Menu using Windows COM API.
130
+
131
+ Returns:
132
+ True if successful, False otherwise.
133
+ """
134
+ try:
135
+ import winshell
136
+ from win32com.client import Dispatch
137
+
138
+ start_menu = Path(winshell.start_menu())
139
+ programs = start_menu / 'Programs'
140
+ programs.mkdir(parents=True, exist_ok=True)
141
+
142
+ shortcut_path = programs / 'Weeb CLI.lnk'
143
+
144
+ # Don't recreate if it already exists
145
+ if shortcut_path.exists():
146
+ return True
147
+
148
+ executable = get_executable_path()
149
+
150
+ shell = Dispatch('WScript.Shell')
151
+ shortcut = shell.CreateShortCut(str(shortcut_path))
152
+ shortcut.TargetPath = executable
153
+ shortcut.WorkingDirectory = str(Path.home())
154
+ shortcut.Description = 'Terminal-based anime streaming application'
155
+
156
+ icon = get_icon_path()
157
+ if icon:
158
+ shortcut.IconLocation = icon
159
+
160
+ shortcut.save()
161
+
162
+ return True
163
+ except ImportError:
164
+ # winshell or pywin32 not available
165
+ return False
166
+ except Exception:
167
+ return False
168
+
169
+
170
+ def should_create_shortcuts() -> bool:
171
+ """Check if shortcuts should be created.
172
+
173
+ Returns:
174
+ True if this is first run or shortcuts are missing.
175
+ """
176
+ from weeb_cli.config import CONFIG_DIR
177
+
178
+ marker_file = CONFIG_DIR / '.shortcuts_created'
179
+
180
+ # If marker exists, check if shortcuts still exist
181
+ if marker_file.exists():
182
+ if sys.platform == 'linux':
183
+ desktop_file = Path.home() / '.local' / 'share' / 'applications' / 'weeb-cli.desktop'
184
+ return not desktop_file.exists()
185
+ elif sys.platform == 'darwin':
186
+ for apps_dir in [Path('/Applications'), Path.home() / 'Applications']:
187
+ if (apps_dir / 'Weeb CLI').exists():
188
+ return False
189
+ return True
190
+ elif sys.platform == 'win32':
191
+ try:
192
+ import winshell
193
+ start_menu = Path(winshell.start_menu())
194
+ shortcut = start_menu / 'Programs' / 'Weeb CLI.lnk'
195
+ return not shortcut.exists()
196
+ except ImportError:
197
+ return False
198
+
199
+ return True
200
+
201
+
202
+ def create_shortcuts() -> bool:
203
+ """Create platform-specific shortcuts.
204
+
205
+ Automatically detects the platform and creates appropriate shortcuts.
206
+ Only runs on first launch or if shortcuts are missing.
207
+
208
+ Returns:
209
+ True if shortcuts were created successfully.
210
+ """
211
+ if not should_create_shortcuts():
212
+ return True
213
+
214
+ success = False
215
+
216
+ if sys.platform == 'linux':
217
+ success = create_linux_desktop_file()
218
+ elif sys.platform == 'darwin':
219
+ success = create_macos_alias()
220
+ elif sys.platform == 'win32':
221
+ success = create_windows_shortcut()
222
+
223
+ # Mark as created even if failed to avoid repeated attempts
224
+ if success:
225
+ from weeb_cli.config import CONFIG_DIR
226
+ marker_file = CONFIG_DIR / '.shortcuts_created'
227
+ CONFIG_DIR.mkdir(parents=True, exist_ok=True)
228
+ marker_file.touch()
229
+
230
+ return success
231
+
232
+
233
+ def remove_shortcuts() -> bool:
234
+ """Remove all platform-specific shortcuts.
235
+
236
+ Returns:
237
+ True if shortcuts were removed successfully.
238
+ """
239
+ try:
240
+ if sys.platform == 'linux':
241
+ desktop_file = Path.home() / '.local' / 'share' / 'applications' / 'weeb-cli.desktop'
242
+ if desktop_file.exists():
243
+ desktop_file.unlink()
244
+
245
+ elif sys.platform == 'darwin':
246
+ for apps_dir in [Path('/Applications'), Path.home() / 'Applications']:
247
+ link_path = apps_dir / 'Weeb CLI'
248
+ if link_path.exists():
249
+ link_path.unlink()
250
+
251
+ elif sys.platform == 'win32':
252
+ try:
253
+ import winshell
254
+ start_menu = Path(winshell.start_menu())
255
+ shortcut = start_menu / 'Programs' / 'Weeb CLI.lnk'
256
+ if shortcut.exists():
257
+ shortcut.unlink()
258
+ except ImportError:
259
+ pass
260
+
261
+ # Remove marker
262
+ from weeb_cli.config import CONFIG_DIR
263
+ marker_file = CONFIG_DIR / '.shortcuts_created'
264
+ if marker_file.exists():
265
+ marker_file.unlink()
266
+
267
+ return True
268
+ except Exception:
269
+ return False
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: weeb-cli
3
- Version: 2.16.0
3
+ Version: 2.16.1
4
4
  Summary: No browser, no ads, no distractions. Just you and an unparalleled anime viewing experience.
5
5
  Author-email: ewgsta <ewgst@proton.me>
6
6
  License-Expression: GPL-3.0-only
@@ -35,6 +35,9 @@ Requires-Dist: pyyaml>=6.0; extra == "serve"
35
35
  Provides-Extra: serve-restful
36
36
  Requires-Dist: flask>=3.0; extra == "serve-restful"
37
37
  Requires-Dist: flask-cors>=4.0; extra == "serve-restful"
38
+ Provides-Extra: shortcuts
39
+ Requires-Dist: pywin32; sys_platform == "win32" and extra == "shortcuts"
40
+ Requires-Dist: winshell; sys_platform == "win32" and extra == "shortcuts"
38
41
  Provides-Extra: dev
39
42
  Requires-Dist: build; extra == "dev"
40
43
  Requires-Dist: pyinstaller; extra == "dev"
@@ -123,4 +123,5 @@ weeb_cli/ui/menu.py
123
123
  weeb_cli/ui/prompt.py
124
124
  weeb_cli/utils/__init__.py
125
125
  weeb_cli/utils/decorators.py
126
- weeb_cli/utils/sanitizer.py
126
+ weeb_cli/utils/sanitizer.py
127
+ weeb_cli/utils/shortcuts.py
@@ -31,3 +31,9 @@ pyyaml>=6.0
31
31
  [serve-restful]
32
32
  flask>=3.0
33
33
  flask-cors>=4.0
34
+
35
+ [shortcuts]
36
+
37
+ [shortcuts:sys_platform == "win32"]
38
+ pywin32
39
+ winshell
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