torrent-downloader-react 1.0.19__py3-none-any.whl → 1.0.21__py3-none-any.whl
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.
- 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
|