torrent-downloader-react 1.1.11__tar.gz → 1.2.0__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 (17) hide show
  1. {torrent-downloader-react-1.1.11 → torrent-downloader-react-1.2.0}/PKG-INFO +7 -7
  2. {torrent-downloader-react-1.1.11 → torrent-downloader-react-1.2.0}/setup.py +5 -5
  3. {torrent-downloader-react-1.1.11 → torrent-downloader-react-1.2.0}/torrent_downloader/server.py +34 -2
  4. torrent-downloader-react-1.2.0/torrent_downloader/static/assets/index-1tlJV8lw.css +1 -0
  5. torrent-downloader-react-1.2.0/torrent_downloader/static/assets/index-DNc3M5gl.js +325 -0
  6. {torrent-downloader-react-1.1.11 → torrent-downloader-react-1.2.0}/torrent_downloader/static/index.html +2 -2
  7. {torrent-downloader-react-1.1.11 → torrent-downloader-react-1.2.0}/torrent_downloader_react.egg-info/PKG-INFO +7 -7
  8. {torrent-downloader-react-1.1.11 → torrent-downloader-react-1.2.0}/torrent_downloader_react.egg-info/SOURCES.txt +2 -2
  9. torrent-downloader-react-1.1.11/torrent_downloader/static/assets/index-BKZnulWN.css +0 -1
  10. torrent-downloader-react-1.1.11/torrent_downloader/static/assets/index-lPeprbEH.js +0 -49
  11. {torrent-downloader-react-1.1.11 → torrent-downloader-react-1.2.0}/setup.cfg +0 -0
  12. {torrent-downloader-react-1.1.11 → torrent-downloader-react-1.2.0}/torrent_downloader/__init__.py +0 -0
  13. {torrent-downloader-react-1.1.11 → torrent-downloader-react-1.2.0}/torrent_downloader/static/vite.svg +0 -0
  14. {torrent-downloader-react-1.1.11 → torrent-downloader-react-1.2.0}/torrent_downloader_react.egg-info/dependency_links.txt +0 -0
  15. {torrent-downloader-react-1.1.11 → torrent-downloader-react-1.2.0}/torrent_downloader_react.egg-info/entry_points.txt +0 -0
  16. {torrent-downloader-react-1.1.11 → torrent-downloader-react-1.2.0}/torrent_downloader_react.egg-info/requires.txt +0 -0
  17. {torrent-downloader-react-1.1.11 → torrent-downloader-react-1.2.0}/torrent_downloader_react.egg-info/top_level.txt +0 -0
@@ -1,13 +1,13 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: torrent-downloader-react
3
- Version: 1.1.11
3
+ Version: 1.2.0
4
4
  Summary: A high-performance, React-based BitTorrent client with an intuitive interface for seamless file downloading
5
- Home-page: https://github.com/stevenbtc/torrent-downloader
5
+ Home-page: https://github.com/stevenyyan/torrent-downloader
6
6
  Author: Steven Yan
7
7
  Author-email: yulong.yan@uqconnect.edu.au
8
- Project-URL: Bug Tracker, https://github.com/stevenbtc/torrent-downloader/issues
9
- Project-URL: Documentation, https://github.com/stevenbtc/torrent-downloader#readme
10
- Project-URL: Source Code, https://github.com/stevenbtc/torrent-downloader
8
+ Project-URL: Bug Tracker, https://github.com/stevenyyan/torrent-downloader/issues
9
+ Project-URL: Documentation, https://github.com/stevenyyan/torrent-downloader#readme
10
+ Project-URL: Source Code, https://github.com/stevenyyan/torrent-downloader
11
11
  Keywords: torrent,downloader,p2p,bittorrent,libtorrent
12
12
  Classifier: Development Status :: 4 - Beta
13
13
  Classifier: Environment :: Web Environment
@@ -29,7 +29,7 @@ Description-Content-Type: text/markdown
29
29
 
30
30
  A modern, full-featured torrent downloader with a clean React interface and FastAPI backend.
31
31
 
32
- ![Torrent Downloader Web UI](https://github.com/stevenbtc/torrent-downloader/raw/main/torrent-downloader-react/screenshots/webapp_screenshot.png)
32
+ ![Torrent Downloader Web UI](https://github.com/stevenyyan/torrent-downloader/raw/main/torrent-downloader-react/screenshots/webapp_screenshot.png)
33
33
 
34
34
  ## Features
35
35
 
@@ -60,7 +60,7 @@ pip install torrent-downloader-react
60
60
  ### From Source
61
61
 
62
62
  ```bash
63
- git clone https://github.com/stevenbtc/torrent-downloader.git
63
+ git clone https://github.com/stevenyyan/torrent-downloader.git
64
64
  cd torrent-downloader/torrent-downloader-react/backend
65
65
  pip install -e .
66
66
  ```
@@ -7,7 +7,7 @@ with open(os.path.join(os.path.dirname(os.path.dirname(__file__)), "README.md"),
7
7
 
8
8
  setup(
9
9
  name="torrent-downloader-react",
10
- version="1.1.11",
10
+ version="1.2.0",
11
11
  packages=find_packages(),
12
12
  install_requires=[
13
13
  "fastapi>=0.109.0",
@@ -28,11 +28,11 @@ setup(
28
28
  long_description=long_description,
29
29
  long_description_content_type="text/markdown",
30
30
  keywords="torrent, downloader, p2p, bittorrent, libtorrent",
31
- url="https://github.com/stevenbtc/torrent-downloader",
31
+ url="https://github.com/stevenyyan/torrent-downloader",
32
32
  project_urls={
33
- "Bug Tracker": "https://github.com/stevenbtc/torrent-downloader/issues",
34
- "Documentation": "https://github.com/stevenbtc/torrent-downloader#readme",
35
- "Source Code": "https://github.com/stevenbtc/torrent-downloader",
33
+ "Bug Tracker": "https://github.com/stevenyyan/torrent-downloader/issues",
34
+ "Documentation": "https://github.com/stevenyyan/torrent-downloader#readme",
35
+ "Source Code": "https://github.com/stevenyyan/torrent-downloader",
36
36
  },
37
37
  classifiers=[
38
38
  "Development Status :: 4 - Beta",
@@ -75,10 +75,13 @@ DOWNLOAD_PATH = get_downloads_dir()
75
75
  session = lt.session()
76
76
  settings = session.get_settings()
77
77
  settings['listen_interfaces'] = '0.0.0.0:6881'
78
+ settings['auto_manage_interval'] = 30 # Reduce auto-management frequency
79
+ settings['auto_manage_startup'] = 60 # Delay auto-management on startup
78
80
  session.apply_settings(settings)
79
81
 
80
- # Store active torrents
82
+ # Store active torrents and their pause state
81
83
  active_torrents: Dict[str, lt.torrent_handle] = {}
84
+ paused_torrents: set = set() # Track manually paused torrents
82
85
 
83
86
  class TorrentRequest(BaseModel):
84
87
  magnet_link: str
@@ -139,9 +142,15 @@ async def list_torrents() -> List[TorrentInfo]:
139
142
  for torrent_id, handle in active_torrents.items():
140
143
  status = handle.status()
141
144
 
145
+ # Enforce pause state for manually paused torrents
146
+ if torrent_id in paused_torrents and not status.paused:
147
+ handle.pause() # Re-pause if libtorrent auto-resumed it
148
+
142
149
  # Get the state string
143
150
  state_str = "unknown"
144
- if status.state == lt.torrent_status.downloading:
151
+ if torrent_id in paused_torrents or status.paused:
152
+ state_str = "paused"
153
+ elif status.state == lt.torrent_status.downloading:
145
154
  state_str = "downloading"
146
155
  elif status.state == lt.torrent_status.seeding:
147
156
  state_str = "seeding"
@@ -194,9 +203,32 @@ async def remove_torrent(torrent_id: str, delete_files: bool = False):
194
203
  handle = active_torrents[torrent_id]
195
204
  session.remove_torrent(handle, 1 if delete_files else 0)
196
205
  del active_torrents[torrent_id]
206
+ paused_torrents.discard(torrent_id) # Clean up pause state
197
207
 
198
208
  return {"message": "Torrent removed successfully"}
199
209
 
210
+ @app.post("/api/torrent/{torrent_id}/pause")
211
+ async def pause_torrent(torrent_id: str):
212
+ if torrent_id not in active_torrents:
213
+ raise HTTPException(status_code=404, detail="Torrent not found")
214
+
215
+ handle = active_torrents[torrent_id]
216
+ handle.pause()
217
+ paused_torrents.add(torrent_id) # Track that this torrent was manually paused
218
+
219
+ return {"message": "Torrent paused successfully"}
220
+
221
+ @app.post("/api/torrent/{torrent_id}/resume")
222
+ async def resume_torrent(torrent_id: str):
223
+ if torrent_id not in active_torrents:
224
+ raise HTTPException(status_code=404, detail="Torrent not found")
225
+
226
+ handle = active_torrents[torrent_id]
227
+ handle.resume()
228
+ paused_torrents.discard(torrent_id) # Remove from manually paused set
229
+
230
+ return {"message": "Torrent resumed successfully"}
231
+
200
232
  @app.get("/api/downloads/path")
201
233
  async def get_downloads_path():
202
234
  return {"path": str(DOWNLOAD_PATH)}
@@ -0,0 +1 @@
1
+ :root{font-family:Inter,system-ui,Avenir,Helvetica,Arial,sans-serif;line-height:1.5;font-weight:400;color-scheme:light dark;color:#213547;background-color:#fff;font-synthesis:none;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}*{box-sizing:border-box;margin:0;padding:0}body{margin:0;min-width:320px;min-height:100vh}h1{font-size:3.2em;line-height:1.1}button{border-radius:8px;border:1px solid transparent;padding:.6em 1.2em;font-size:1em;font-weight:500;font-family:inherit;background-color:#1a1a1a;cursor:pointer;transition:border-color .25s}button:hover{border-color:#646cff}button:focus,button:focus-visible{outline:4px auto -webkit-focus-ring-color}@media (prefers-color-scheme: dark){:root{color:#ffffffde;background-color:#242424}.torrent-item{background-color:#2a2a2a!important;border-color:#404040!important}.torrent-info h3{color:#e2e8f0!important}.torrent-info p{color:#94a3b8!important}.progress-bar{background-color:#404040!important}input{background-color:#2a2a2a;color:#fff;border-color:#404040!important}input::placeholder{color:#94a3b8}}:root{--text-primary: #1e293b;--text-secondary: #64748b;--text-muted: #94a3b8;--border-color: #e2e8f0;--background-primary: #ffffff;--background-secondary: #f8fafc;--background-tertiary: #f1f5f9;--accent-color: #2563eb;--accent-hover: #1d4ed8;--success-color: #16a34a;--error-color: #dc2626;--warning-color: #ea580c;--spacing-xs: .25rem;--spacing-sm: .5rem;--spacing-md: 1rem;--spacing-lg: 1.5rem;--spacing-xl: 2rem;--spacing-2xl: 3rem;--radius-sm: .25rem;--radius-md: .5rem;--radius-lg: .75rem;--radius-xl: 1rem;--shadow-sm: 0 1px 2px 0 rgb(0 0 0 / .05);--shadow-md: 0 4px 6px -1px rgb(0 0 0 / .1), 0 2px 4px -2px rgb(0 0 0 / .1);--shadow-lg: 0 10px 15px -3px rgb(0 0 0 / .1), 0 4px 6px -4px rgb(0 0 0 / .1)}@media (prefers-color-scheme: dark){:root{--text-primary: #e2e8f0;--text-secondary: #94a3b8;--text-muted: #64748b;--border-color: #334155;--background-primary: #0f172a;--background-secondary: #1e293b;--background-tertiary: #334155;--accent-color: #3b82f6;--accent-hover: #2563eb}}*{box-sizing:border-box}body{font-family:system-ui,-apple-system,Segoe UI,Roboto,sans-serif;line-height:1.6;color:var(--text-primary);background-color:var(--background-primary);margin:0;padding:0}.app{min-height:100vh;display:flex;flex-direction:column}.app-header{background-color:var(--background-secondary);border-bottom:1px solid var(--border-color);padding:var(--spacing-lg) var(--spacing-xl);position:sticky;top:0;z-index:100;-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px)}.header-main{max-width:1200px;margin:0 auto;display:flex;align-items:center;justify-content:space-between;gap:var(--spacing-xl)}.header-brand{display:flex;align-items:center;gap:var(--spacing-lg)}.header-brand h1{margin:0;font-size:1.75rem;font-weight:700;color:var(--text-primary)}.connection-status{display:flex;align-items:center;gap:var(--spacing-xs);font-size:.875rem;color:var(--text-secondary)}.status-icon.online{color:var(--success-color)}.header-stats{display:flex;gap:var(--spacing-xl)}.stat-group{display:flex;gap:var(--spacing-lg)}.stat-item-header{display:flex;align-items:center;gap:var(--spacing-xs);font-size:.875rem}.stat-icon.download{color:var(--accent-color)}.stat-icon.upload{color:var(--success-color)}.stat-label{color:var(--text-secondary)}.stat-value{font-weight:600;color:var(--text-primary)}.stat-count{font-weight:700;font-size:1.25rem;color:var(--text-primary)}.header-actions{display:flex;gap:var(--spacing-md)}.main-content{flex:1;max-width:1200px;margin:0 auto;padding:var(--spacing-xl);width:100%}.error-banner{background-color:#fee2e2;border:1px solid #fecaca;color:var(--error-color);padding:var(--spacing-md);border-radius:var(--radius-md);margin-bottom:var(--spacing-lg)}@media (prefers-color-scheme: dark){.error-banner{background-color:#450a0a;border-color:#7f1d1d;color:#fecaca}}.add-torrent-container{background-color:var(--background-secondary);border:1px solid var(--border-color);border-radius:var(--radius-lg);padding:var(--spacing-lg);margin-bottom:var(--spacing-xl);box-shadow:var(--shadow-sm)}.tab-selector{display:flex;gap:var(--spacing-xs);margin-bottom:var(--spacing-lg);background-color:var(--background-tertiary);border-radius:var(--radius-md);padding:var(--spacing-xs)}.tab-button{flex:1;display:flex;align-items:center;justify-content:center;gap:var(--spacing-xs);padding:var(--spacing-sm) var(--spacing-md);border:none;background:transparent;color:var(--text-secondary);border-radius:var(--radius-sm);cursor:pointer;transition:all .2s ease;font-size:.875rem;font-weight:500}.tab-button.active{background-color:var(--background-primary);color:var(--text-primary);box-shadow:var(--shadow-sm)}.add-torrent-form{width:100%}.input-group{display:flex;gap:var(--spacing-md);align-items:flex-start}.torrent-input{flex:1;padding:var(--spacing-md);border:1px solid var(--border-color);border-radius:var(--radius-md);font-size:1rem;background-color:var(--background-primary);color:var(--text-primary);transition:border-color .2s ease}.torrent-input:focus{outline:none;border-color:var(--accent-color);box-shadow:0 0 0 3px #2563eb1a}.torrent-input.invalid{border-color:var(--error-color)}.torrent-input.invalid:focus{box-shadow:0 0 0 3px #dc26261a}.input-error{margin-top:var(--spacing-sm);color:var(--error-color);font-size:.875rem}.add-button{display:flex;align-items:center;gap:var(--spacing-xs);padding:var(--spacing-md) var(--spacing-lg);background-color:var(--accent-color);color:#fff;border:none;border-radius:var(--radius-md);cursor:pointer;font-size:1rem;font-weight:500;transition:background-color .2s ease;white-space:nowrap}.add-button:hover:not(:disabled){background-color:var(--accent-hover)}.add-button:disabled{background-color:var(--text-muted);cursor:not-allowed}.file-upload-section{text-align:center}.file-input{display:none}.file-upload-label{display:flex;flex-direction:column;align-items:center;gap:var(--spacing-md);padding:var(--spacing-xl);border:2px dashed var(--border-color);border-radius:var(--radius-lg);cursor:pointer;transition:all .2s ease;color:var(--text-secondary)}.file-upload-label:hover{border-color:var(--accent-color);color:var(--accent-color)}.file-upload-notice{margin-top:var(--spacing-md);color:var(--text-muted);font-size:.875rem}.status-message{padding:var(--spacing-md);border-radius:var(--radius-md);margin-bottom:var(--spacing-lg);animation:slideIn .3s ease}.status-loading{background-color:#dbeafe;border:1px solid #bfdbfe;color:#1e40af}.status-success{background-color:#dcfce7;border:1px solid #bbf7d0;color:#166534}.status-error{background-color:#fee2e2;border:1px solid #fecaca;color:#dc2626}@media (prefers-color-scheme: dark){.status-loading{background-color:#1e3a8a;border-color:#1d4ed8;color:#bfdbfe}.status-success{background-color:#14532d;border-color:#16a34a;color:#bbf7d0}.status-error{background-color:#7f1d1d;border-color:#dc2626;color:#fecaca}}.status-content{display:flex;align-items:center;gap:var(--spacing-md)}.status-text{margin:0;font-weight:500}.torrents-section{flex:1}.empty-state{display:flex;align-items:center;justify-content:center;min-height:300px;text-align:center}.empty-state-content h3{margin:0 0 var(--spacing-md) 0;color:var(--text-primary);font-size:1.5rem}.empty-state-content p{margin:0;color:var(--text-secondary)}.torrents-grid{display:grid;gap:var(--spacing-lg);grid-template-columns:repeat(auto-fill,minmax(400px,1fr))}.torrent-card{background-color:var(--background-secondary);border:1px solid var(--border-color);border-radius:var(--radius-lg);padding:var(--spacing-lg);box-shadow:var(--shadow-sm);transition:all .2s ease;position:relative}.torrent-card:hover{box-shadow:var(--shadow-md);transform:translateY(-1px)}.torrent-card-header{display:flex;justify-content:space-between;align-items:flex-start;margin-bottom:var(--spacing-lg);gap:var(--spacing-md)}.torrent-title-section{flex:1;min-width:0}.torrent-title{margin:0 0 var(--spacing-sm) 0;font-size:1.125rem;font-weight:600;color:var(--text-primary);line-height:1.4;overflow:hidden;text-overflow:ellipsis;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical}.torrent-actions{position:relative}.torrent-progress-section{margin-bottom:var(--spacing-lg)}.progress-bar-container{display:flex;align-items:center;gap:var(--spacing-md)}.progress-bar{flex:1;height:8px;background-color:var(--background-tertiary);border-radius:var(--radius-sm);overflow:hidden}.progress-fill{height:100%;transition:width .3s ease;border-radius:var(--radius-sm)}.progress-text{font-size:.875rem;font-weight:600;color:var(--text-primary);min-width:48px;text-align:right}.torrent-stats{display:grid;grid-template-columns:repeat(2,1fr);gap:var(--spacing-md)}.stat-item{display:flex;align-items:center;gap:var(--spacing-xs);font-size:.875rem}.stat-icon{color:var(--text-secondary);flex-shrink:0}.stat-value{color:var(--text-primary);font-weight:500;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.action-button{display:flex;align-items:center;gap:var(--spacing-xs);padding:var(--spacing-sm) var(--spacing-md);border:1px solid var(--border-color);border-radius:var(--radius-md);background-color:var(--background-primary);color:var(--text-primary);cursor:pointer;font-size:.875rem;font-weight:500;transition:all .2s ease}.action-button:hover:not(:disabled){background-color:var(--background-secondary);border-color:var(--accent-color)}.action-button.secondary{background-color:var(--background-secondary)}.action-button:disabled{opacity:.5;cursor:not-allowed}.action-menu{position:absolute;top:100%;right:0;margin-top:var(--spacing-xs);background-color:var(--background-primary);border:1px solid var(--border-color);border-radius:var(--radius-md);box-shadow:var(--shadow-lg);z-index:10;min-width:140px;overflow:hidden}.menu-item{display:flex;align-items:center;gap:var(--spacing-xs);width:100%;padding:var(--spacing-sm) var(--spacing-md);border:none;background:transparent;color:var(--text-primary);text-align:left;cursor:pointer;font-size:.875rem;transition:background-color .2s ease}.menu-item:hover:not(:disabled){background-color:var(--background-secondary)}.menu-item.danger{color:var(--error-color)}.menu-item.danger:hover:not(:disabled){background-color:#fee2e2}@media (prefers-color-scheme: dark){.menu-item.danger:hover:not(:disabled){background-color:#450a0a}}.loading-spinner{width:20px;height:20px;border:2px solid var(--border-color);border-top:2px solid var(--accent-color);border-radius:50%;animation:spin 1s linear infinite}.loading-spinner.small{width:16px;height:16px}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}@keyframes slideIn{0%{opacity:0;transform:translateY(-10px)}to{opacity:1;transform:translateY(0)}}.animate-spin{animation:spin 1s linear infinite}@media (max-width: 768px){.header-main{flex-direction:column;gap:var(--spacing-md);text-align:center}.header-stats{flex-direction:column;gap:var(--spacing-md)}.main-content{padding:var(--spacing-md)}.input-group{flex-direction:column}.torrents-grid,.torrent-stats{grid-template-columns:1fr}.stat-group{justify-content:center}}@media (max-width: 480px){.torrent-card-header{flex-direction:column;align-items:stretch}.torrent-actions{align-self:flex-end}.progress-bar-container{flex-direction:column;gap:var(--spacing-sm)}.progress-text{text-align:center}}