torrent-downloader-react 1.0.20__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.
@@ -92,6 +92,7 @@ class TorrentInfo(BaseModel):
92
92
  state: str
93
93
  total_size: int
94
94
  downloaded: int
95
+ eta_seconds: Optional[int] = None
95
96
 
96
97
  @app.post("/api/torrent/add")
97
98
  async def add_torrent(request: TorrentRequest):
@@ -132,11 +133,28 @@ async def list_torrents() -> List[TorrentInfo]:
132
133
  state_str = "finished"
133
134
  elif status.state == lt.torrent_status.checking_files:
134
135
  state_str = "checking"
135
- elif status.state == lt.torrent_status.paused:
136
- state_str = "paused"
137
136
 
138
137
  logging.debug(f"Torrent {torrent_id} state: {state_str} (raw state: {status.state})")
139
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
157
+
140
158
  info = TorrentInfo(
141
159
  id=torrent_id,
142
160
  name=handle.name(),
@@ -145,7 +163,8 @@ async def list_torrents() -> List[TorrentInfo]:
145
163
  upload_speed=status.upload_rate / 1024, # Convert to KB/s
146
164
  state=state_str,
147
165
  total_size=status.total_wanted,
148
- downloaded=status.total_wanted_done
166
+ downloaded=status.total_wanted_done,
167
+ eta_seconds=eta
149
168
  )
150
169
  result.append(info)
151
170
 
@@ -173,46 +192,6 @@ async def open_downloads():
173
192
  raise HTTPException(status_code=500, detail="Failed to open downloads folder")
174
193
  return {"message": "Downloads folder opened successfully"}
175
194
 
176
- @app.post("/api/torrent/{torrent_id}/pause")
177
- async def pause_torrent(torrent_id: str):
178
- """Pause a specific torrent."""
179
- if torrent_id not in active_torrents:
180
- raise HTTPException(status_code=404, detail="Torrent not found")
181
-
182
- handle = active_torrents[torrent_id]
183
- logging.info(f"Pausing torrent {torrent_id}, current state: {handle.status().state}")
184
- handle.pause()
185
- # Force an immediate pause
186
- handle.flush_cache()
187
- logging.info(f"Torrent {torrent_id} paused, new state: {handle.status().state}")
188
- return {"message": "Torrent paused successfully"}
189
-
190
- @app.post("/api/torrent/{torrent_id}/resume")
191
- async def resume_torrent(torrent_id: str):
192
- """Resume a specific torrent."""
193
- if torrent_id not in active_torrents:
194
- raise HTTPException(status_code=404, detail="Torrent not found")
195
-
196
- handle = active_torrents[torrent_id]
197
- logging.info(f"Resuming torrent {torrent_id}, current state: {handle.status().state}")
198
- handle.resume()
199
- logging.info(f"Torrent {torrent_id} resumed, new state: {handle.status().state}")
200
- return {"message": "Torrent resumed successfully"}
201
-
202
- @app.post("/api/torrent/pause-all")
203
- async def pause_all_torrents():
204
- """Pause all active torrents."""
205
- for handle in active_torrents.values():
206
- handle.pause()
207
- return {"message": "All torrents paused successfully"}
208
-
209
- @app.post("/api/torrent/resume-all")
210
- async def resume_all_torrents():
211
- """Resume all active torrents."""
212
- for handle in active_torrents.values():
213
- handle.resume()
214
- return {"message": "All torrents resumed successfully"}
215
-
216
195
  def main():
217
196
  """Entry point for the application."""
218
197
  import uvicorn