r3hab commited on
Commit
c918e99
·
verified ·
1 Parent(s): abd6fd6

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +96 -47
app.py CHANGED
@@ -1,57 +1,106 @@
1
- from fastapi import FastAPI, File, UploadFile, HTTPException
 
 
 
 
 
 
2
  from fastapi.responses import StreamingResponse
3
- from PIL import Image
4
- import io
5
 
6
- app = FastAPI(title="Advanced Image Converter")
 
7
 
8
- ALLOWED_OUTPUT_FORMATS = ["jpeg", "png", "gif", "bmp", "tiff", "webp"]
 
 
 
 
 
9
 
10
- @app.post("/convert_image/")
11
- async def convert_image(
12
- file: UploadFile = File(...),
13
- output_format: str = "jpeg",
14
- quality: int = 95 # For JPEG/WebP, adjust compression quality (0-100)
15
- ):
16
- """
17
- Converts an uploaded image to the specified format.
18
 
19
- - Supports common image formats as input.
20
- - Output formats: JPEG, PNG, GIF, BMP, TIFF, WebP.
21
- - For JPEG and WebP, you can adjust the `quality` (0-100).
22
- """
23
- if output_format.lower() not in ALLOWED_OUTPUT_FORMATS:
24
- raise HTTPException(
25
- status_code=400,
26
- detail=f"Invalid output format. Allowed formats: {', '.join(ALLOWED_OUTPUT_FORMATS)}",
27
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
28
 
29
- if output_format.lower() in ["jpeg", "webp"] and not (0 <= quality <= 100):
30
- raise HTTPException(
31
- status_code=400, detail="Quality must be between 0 and 100 for JPEG and WebP."
32
- )
33
-
34
- try:
35
- image = Image.open(io.BytesIO(await file.read()))
36
- except Exception as e:
37
- raise HTTPException(status_code=400, detail="Invalid image file.") from e
38
-
39
- output_io = io.BytesIO()
40
  try:
41
- save_kwargs = {}
42
- if output_format.lower() in ["jpeg", "webp"]:
43
- save_kwargs["quality"] = quality
44
- image.save(output_io, format=output_format.upper(), **save_kwargs)
45
- except KeyError:
46
- raise HTTPException(
47
- status_code=400, detail=f"Conversion to {output_format} failed."
48
- )
49
  except Exception as e:
50
- raise HTTPException(status_code=500, detail=f"Image processing error: {e}")
 
 
 
51
 
52
- output_io.seek(0)
53
- media_type = f"image/{output_format.lower()}"
54
- if output_format.lower() == "tiff":
55
- media_type = "image/tiff" # Special case for TIFF
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
56
 
57
- return StreamingResponse(output_io, media_type=media_type)
 
 
 
1
+ # app.py
2
+ import os
3
+ import time
4
+ import uuid
5
+ import asyncio
6
+ import libtorrent as lt
7
+ from fastapi import FastAPI, HTTPException
8
  from fastapi.responses import StreamingResponse
9
+ import magic
 
10
 
11
+ app = FastAPI()
12
+ active_sessions = {}
13
 
14
+ def get_largest_file(torrent_info):
15
+ files = torrent_info.files()
16
+ file_sizes = [(i, files.file_size(i)) for i in range(files.num_files())]
17
+ if not file_sizes:
18
+ return None
19
+ return max(file_sizes, key=lambda x: x[1])
20
 
21
+ async def add_torrent(magnet_link: str, save_path: str):
22
+ ses = lt.session()
23
+ params = {
24
+ 'save_path': save_path,
25
+ 'storage_mode': lt.storage_mode_t(2),
26
+ }
 
 
27
 
28
+ handle = lt.add_magnet_uri(ses, magnet_link, params)
29
+
30
+ # Wait for metadata
31
+ while not handle.has_metadata():
32
+ await asyncio.sleep(1)
33
+
34
+ torrent_info = handle.get_torrent_info()
35
+ file_info = get_largest_file(torrent_info)
36
+ if not file_info:
37
+ raise Exception("No files found in torrent")
38
+
39
+ file_index, _ = file_info
40
+ file_path = os.path.join(save_path, torrent_info.files().file_path(file_index))
41
+
42
+ # Prioritize largest file
43
+ for i in range(torrent_info.num_files()):
44
+ handle.file_priority(i, 7 if i == file_index else 0)
45
+
46
+ handle.set_sequential_download(True)
47
+ ses.resume()
48
+
49
+ return {
50
+ "session": ses,
51
+ "handle": handle,
52
+ "file_path": file_path,
53
+ "downloading": True
54
+ }
55
 
56
+ @app.post("/start_stream")
57
+ async def start_stream(magnet_link: str):
58
+ torrent_id = str(uuid.uuid4())
59
+ save_path = f"./downloads/{torrent_id}"
60
+ os.makedirs(save_path, exist_ok=True)
61
+
 
 
 
 
 
62
  try:
63
+ session_info = await add_torrent(magnet_link, save_path)
 
 
 
 
 
 
 
64
  except Exception as e:
65
+ raise HTTPException(status_code=500, detail=str(e))
66
+
67
+ active_sessions[torrent_id] = session_info
68
+ return {"stream_url": f"/stream/{torrent_id}"}
69
 
70
+ @app.get("/stream/{torrent_id}")
71
+ async def stream_torrent(torrent_id: str):
72
+ if torrent_id not in active_sessions:
73
+ raise HTTPException(status_code=404, detail="Torrent session not found")
74
+
75
+ session_info = active_sessions[torrent_id]
76
+ file_path = session_info["file_path"]
77
+
78
+ if not os.path.exists(file_path):
79
+ raise HTTPException(status_code=404, detail="File not found")
80
+
81
+ mime = magic.Magic(mime=True)
82
+ mime_type = mime.from_file(file_path)
83
+
84
+ def file_generator():
85
+ last_position = 0
86
+ while True:
87
+ if not os.path.exists(file_path):
88
+ time.sleep(1)
89
+ continue
90
+
91
+ with open(file_path, "rb") as f:
92
+ f.seek(last_position)
93
+ data = f.read(1024 * 1024) # 1MB chunks
94
+ if not data:
95
+ if session_info["handle"].is_seed():
96
+ break
97
+ time.sleep(1)
98
+ continue
99
+ last_position = f.tell()
100
+ yield data
101
+
102
+ return StreamingResponse(file_generator(), media_type=mime_type)
103
 
104
+ if __name__ == "__main__":
105
+ import uvicorn
106
+ uvicorn.run(app, host="0.0.0.0", port=8000)