torrent-downloader-react 1.0.19__py3-none-any.whl → 1.0.21__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- torrent_downloader/server.py +24 -50
- torrent_downloader/static/assets/index-BAUKkMK0.js +49 -0
- torrent_downloader/static/assets/{index-CdUAChFP.css → index-DpeprjRI.css} +1 -1
- torrent_downloader/static/index.html +2 -2
- {torrent_downloader_react-1.0.19.dist-info → torrent_downloader_react-1.0.21.dist-info}/METADATA +1 -1
- torrent_downloader_react-1.0.21.dist-info/RECORD +11 -0
- torrent_downloader/static/assets/index-COG6Byoc.js +0 -49
- torrent_downloader_react-1.0.19.dist-info/RECORD +0 -11
- {torrent_downloader_react-1.0.19.dist-info → torrent_downloader_react-1.0.21.dist-info}/WHEEL +0 -0
- {torrent_downloader_react-1.0.19.dist-info → torrent_downloader_react-1.0.21.dist-info}/entry_points.txt +0 -0
- {torrent_downloader_react-1.0.19.dist-info → torrent_downloader_react-1.0.21.dist-info}/top_level.txt +0 -0
torrent_downloader/server.py
CHANGED
@@ -75,17 +75,6 @@ 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['active_downloads'] = -1 # No limit
|
79
|
-
settings['active_seeds'] = -1 # No limit
|
80
|
-
settings['active_limit'] = -1 # No limit
|
81
|
-
settings['auto_manage_interval'] = 1 # Check every second
|
82
|
-
settings['active_tracker_limit'] = -1 # No limit
|
83
|
-
settings['enable_outgoing_utp'] = True
|
84
|
-
settings['enable_incoming_utp'] = True
|
85
|
-
settings['announce_to_all_tiers'] = True
|
86
|
-
settings['announce_to_all_trackers'] = True
|
87
|
-
settings['aio_threads'] = 8 # Number of async I/O threads
|
88
|
-
settings['checking_mem_usage'] = 128 # Memory usage for checking (in MB)
|
89
78
|
session.apply_settings(settings)
|
90
79
|
|
91
80
|
# Store active torrents
|
@@ -103,6 +92,7 @@ class TorrentInfo(BaseModel):
|
|
103
92
|
state: str
|
104
93
|
total_size: int
|
105
94
|
downloaded: int
|
95
|
+
eta_seconds: Optional[int] = None
|
106
96
|
|
107
97
|
@app.post("/api/torrent/add")
|
108
98
|
async def add_torrent(request: TorrentRequest):
|
@@ -143,8 +133,27 @@ async def list_torrents() -> List[TorrentInfo]:
|
|
143
133
|
state_str = "finished"
|
144
134
|
elif status.state == lt.torrent_status.checking_files:
|
145
135
|
state_str = "checking"
|
146
|
-
|
147
|
-
|
136
|
+
|
137
|
+
logging.debug(f"Torrent {torrent_id} state: {state_str} (raw state: {status.state})")
|
138
|
+
|
139
|
+
# Calculate ETA
|
140
|
+
eta = None
|
141
|
+
try:
|
142
|
+
if state_str == "downloading":
|
143
|
+
remaining_bytes = status.total_wanted - status.total_wanted_done
|
144
|
+
if remaining_bytes <= 0:
|
145
|
+
eta = 0 # Download complete
|
146
|
+
elif status.download_rate > 0:
|
147
|
+
eta = int(remaining_bytes / status.download_rate)
|
148
|
+
else:
|
149
|
+
eta = None # Can't calculate ETA with zero download rate
|
150
|
+
elif state_str in ["finished", "seeding"]:
|
151
|
+
eta = 0 # Already complete
|
152
|
+
elif state_str == "checking":
|
153
|
+
eta = None # Can't estimate during checking
|
154
|
+
except Exception as e:
|
155
|
+
logging.error(f"Error calculating ETA for torrent {torrent_id}: {e}")
|
156
|
+
eta = None
|
148
157
|
|
149
158
|
info = TorrentInfo(
|
150
159
|
id=torrent_id,
|
@@ -154,7 +163,8 @@ async def list_torrents() -> List[TorrentInfo]:
|
|
154
163
|
upload_speed=status.upload_rate / 1024, # Convert to KB/s
|
155
164
|
state=state_str,
|
156
165
|
total_size=status.total_wanted,
|
157
|
-
downloaded=status.total_wanted_done
|
166
|
+
downloaded=status.total_wanted_done,
|
167
|
+
eta_seconds=eta
|
158
168
|
)
|
159
169
|
result.append(info)
|
160
170
|
|
@@ -182,42 +192,6 @@ async def open_downloads():
|
|
182
192
|
raise HTTPException(status_code=500, detail="Failed to open downloads folder")
|
183
193
|
return {"message": "Downloads folder opened successfully"}
|
184
194
|
|
185
|
-
@app.post("/api/torrent/{torrent_id}/pause")
|
186
|
-
async def pause_torrent(torrent_id: str):
|
187
|
-
"""Pause a specific torrent."""
|
188
|
-
if torrent_id not in active_torrents:
|
189
|
-
raise HTTPException(status_code=404, detail="Torrent not found")
|
190
|
-
|
191
|
-
handle = active_torrents[torrent_id]
|
192
|
-
handle.pause()
|
193
|
-
# Force an immediate pause
|
194
|
-
handle.flush_cache()
|
195
|
-
return {"message": "Torrent paused successfully"}
|
196
|
-
|
197
|
-
@app.post("/api/torrent/{torrent_id}/resume")
|
198
|
-
async def resume_torrent(torrent_id: str):
|
199
|
-
"""Resume a specific torrent."""
|
200
|
-
if torrent_id not in active_torrents:
|
201
|
-
raise HTTPException(status_code=404, detail="Torrent not found")
|
202
|
-
|
203
|
-
handle = active_torrents[torrent_id]
|
204
|
-
handle.resume()
|
205
|
-
return {"message": "Torrent resumed successfully"}
|
206
|
-
|
207
|
-
@app.post("/api/torrent/pause-all")
|
208
|
-
async def pause_all_torrents():
|
209
|
-
"""Pause all active torrents."""
|
210
|
-
for handle in active_torrents.values():
|
211
|
-
handle.pause()
|
212
|
-
return {"message": "All torrents paused successfully"}
|
213
|
-
|
214
|
-
@app.post("/api/torrent/resume-all")
|
215
|
-
async def resume_all_torrents():
|
216
|
-
"""Resume all active torrents."""
|
217
|
-
for handle in active_torrents.values():
|
218
|
-
handle.resume()
|
219
|
-
return {"message": "All torrents resumed successfully"}
|
220
|
-
|
221
195
|
def main():
|
222
196
|
"""Entry point for the application."""
|
223
197
|
import uvicorn
|