torrent-downloader-react 1.0.20__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.
@@ -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