MyanmarSwe commited on
Commit
50e694b
·
verified ·
1 Parent(s): 3816526

Update main.py

Browse files
Files changed (1) hide show
  1. main.py +21 -53
main.py CHANGED
@@ -9,7 +9,7 @@ import urllib.parse
9
  import mimetypes
10
  from bs4 import BeautifulSoup
11
  from fastapi import FastAPI, HTTPException, Request
12
- from fastapi.responses import StreamingResponse
13
  from fake_useragent import UserAgent
14
  import uvicorn
15
 
@@ -28,7 +28,6 @@ ua = UserAgent(fallback='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/5
28
  MEDIAFIRE_CACHE = {}
29
  CACHE_TTL = 3600
30
 
31
- # Global Client
32
  client = httpx.AsyncClient(
33
  timeout=httpx.Timeout(60.0, read=None),
34
  follow_redirects=True,
@@ -77,7 +76,7 @@ async def download_proxy(request: Request, url: str, key: str = None):
77
  range_header = request.headers.get('range')
78
  current_time = time.time()
79
 
80
- # --- MediaFire Section ---
81
  if "mediafire.com" in clean_url:
82
  target_link = None
83
  cached = MEDIAFIRE_CACHE.get(clean_url)
@@ -87,8 +86,8 @@ async def download_proxy(request: Request, url: str, key: str = None):
87
 
88
  if not target_link:
89
  try:
90
- headers = {'User-Agent': ua.random}
91
- async with httpx.AsyncClient(headers=headers, follow_redirects=True, timeout=30.0) as temp_client:
92
  r = await temp_client.get(clean_url)
93
  if r.status_code == 200:
94
  match = re.search(r"https?://download[0-9]+\.mediafire\.com/[a-zA-Z0-9_-]+/[a-zA-Z0-9_-]+/[^\s'\"]+", r.text)
@@ -105,11 +104,19 @@ async def download_proxy(request: Request, url: str, key: str = None):
105
  except: pass
106
 
107
  if target_link:
108
- return await stream_file(target_link, range_header, filename)
 
 
 
 
 
 
 
 
109
  else:
110
  raise HTTPException(status_code=404, detail="MediaFire direct link not found.")
111
 
112
- # --- Google Drive Section ---
113
  elif "drive.google.com" in clean_url:
114
  file_id = get_google_file_id(clean_url)
115
  if not file_id: raise HTTPException(status_code=400, detail="Invalid GD Link")
@@ -123,10 +130,12 @@ async def download_proxy(request: Request, url: str, key: str = None):
123
  api_link = f"https://www.googleapis.com/drive/v3/files/{file_id}?alt=media"
124
  headers = {"Authorization": f"Bearer {token}"}
125
  if range_header: headers['Range'] = range_header
126
-
127
- # Google Drive API Stream
128
  try:
129
- return await stream_file(api_link, range_header, filename, extra_headers=headers)
 
 
 
 
130
  except: continue
131
 
132
  public_url = f"https://drive.google.com/uc?export=download&id={file_id}"
@@ -135,50 +144,14 @@ async def download_proxy(request: Request, url: str, key: str = None):
135
  else:
136
  return await stream_file(clean_url, range_header, filename)
137
 
138
- async def stream_file(target_url, range_header, filename, extra_headers=None):
139
  headers = {'User-Agent': ua.random}
140
  if range_header: headers['Range'] = range_header
141
- if extra_headers: headers.update(extra_headers)
142
-
143
- # Correct Way to Stream with HTTPX
144
  try:
145
- # We use a context manager to ensure the request is properly handled
146
- async def response_streamer():
147
- async with client.stream("GET", target_url, headers=headers) as r:
148
- if r.status_code >= 400:
149
- yield b"Error accessing file"
150
- return
151
-
152
- mime_type, _ = mimetypes.guess_type(filename)
153
- if not mime_type or 'application' in mime_type:
154
- mime_type = 'video/mp4' if filename.lower().endswith('.mp4') else 'video/x-matroska'
155
-
156
- # Headers for Resume/Seek
157
- res_headers = {
158
- 'Content-Type': mime_type,
159
- 'Accept-Ranges': 'bytes',
160
- 'Content-Disposition': f'inline; filename="{urllib.parse.quote(filename)}"',
161
- 'Cache-Control': 'no-cache'
162
- }
163
- if 'content-length' in r.headers: res_headers['Content-Length'] = r.headers['content-length']
164
- if 'content-range' in r.headers: res_headers['Content-Range'] = r.headers['content-range']
165
-
166
- # Note: StreamingResponse requires the generator to be passed,
167
- # but we need to send headers first. So we use a nested approach.
168
- # Since FastAPI's StreamingResponse needs an async iterator:
169
-
170
- # ပြန်လည်ပြင်ဆင်ထားသော Stream Logic
171
  req = client.build_request("GET", target_url, headers=headers)
172
  r = await client.send(req, stream=True)
173
-
174
- if "text/html" in r.headers.get("Content-Type", "").lower() and r.status_code == 200:
175
- await r.aclose()
176
- raise HTTPException(status_code=415, detail="MediaFire Blocked (HTML received)")
177
-
178
  return await process_response(r, filename)
179
-
180
  except Exception as e:
181
- print(f"Stream Error: {e}")
182
  raise HTTPException(status_code=500, detail=str(e))
183
 
184
  async def process_response(r, filename):
@@ -202,12 +175,7 @@ async def process_response(r, filename):
202
  finally:
203
  await r.aclose()
204
 
205
- return StreamingResponse(
206
- stream_generator(),
207
- status_code=r.status_code,
208
- headers=res_headers,
209
- media_type=mime_type
210
- )
211
 
212
  if __name__ == "__main__":
213
  uvicorn.run(app, host="0.0.0.0", port=7860)
 
9
  import mimetypes
10
  from bs4 import BeautifulSoup
11
  from fastapi import FastAPI, HTTPException, Request
12
+ from fastapi.responses import StreamingResponse, RedirectResponse
13
  from fake_useragent import UserAgent
14
  import uvicorn
15
 
 
28
  MEDIAFIRE_CACHE = {}
29
  CACHE_TTL = 3600
30
 
 
31
  client = httpx.AsyncClient(
32
  timeout=httpx.Timeout(60.0, read=None),
33
  follow_redirects=True,
 
76
  range_header = request.headers.get('range')
77
  current_time = time.time()
78
 
79
+ # --- MediaFire Section (Redirect with Path Trick) ---
80
  if "mediafire.com" in clean_url:
81
  target_link = None
82
  cached = MEDIAFIRE_CACHE.get(clean_url)
 
86
 
87
  if not target_link:
88
  try:
89
+ # Scrape Direct Link
90
+ async with httpx.AsyncClient(headers={'User-Agent': ua.random}, follow_redirects=True) as temp_client:
91
  r = await temp_client.get(clean_url)
92
  if r.status_code == 200:
93
  match = re.search(r"https?://download[0-9]+\.mediafire\.com/[a-zA-Z0-9_-]+/[a-zA-Z0-9_-]+/[^\s'\"]+", r.text)
 
104
  except: pass
105
 
106
  if target_link:
107
+ # Player က Video လို့သိအောင် Link ကို ပုံစံပြောင်းပြီး Redirect လုပ်ခြင်း
108
+ # MediaFire link ထဲမှာ filename ကို Path အနေနဲ့ ကပ်ပေးလိုက်တာပါ (ဒါကို Player က ပိုကြိုက်ပါတယ်)
109
+ if "?" in target_link:
110
+ redirect_url = f"{target_link}&file={urllib.parse.quote(filename)}"
111
+ else:
112
+ # Link ရဲ့ အဆုံးမှာ /filename.mp4 ကပ်ပေးခြင်း (MediaFire server က ဒါကို ignore လုပ်လေ့ရှိပါတယ်)
113
+ redirect_url = f"{target_link}/{urllib.parse.quote(filename)}"
114
+
115
+ return RedirectResponse(url=redirect_url)
116
  else:
117
  raise HTTPException(status_code=404, detail="MediaFire direct link not found.")
118
 
119
+ # --- Google Drive Section (Proxy as usual) ---
120
  elif "drive.google.com" in clean_url:
121
  file_id = get_google_file_id(clean_url)
122
  if not file_id: raise HTTPException(status_code=400, detail="Invalid GD Link")
 
130
  api_link = f"https://www.googleapis.com/drive/v3/files/{file_id}?alt=media"
131
  headers = {"Authorization": f"Bearer {token}"}
132
  if range_header: headers['Range'] = range_header
 
 
133
  try:
134
+ req = client.build_request("GET", api_link, headers=headers)
135
+ r = await client.send(req, stream=True)
136
+ if r.status_code in [200, 206]:
137
+ return await process_response(r, filename)
138
+ await r.aclose()
139
  except: continue
140
 
141
  public_url = f"https://drive.google.com/uc?export=download&id={file_id}"
 
144
  else:
145
  return await stream_file(clean_url, range_header, filename)
146
 
147
+ async def stream_file(target_url, range_header, filename):
148
  headers = {'User-Agent': ua.random}
149
  if range_header: headers['Range'] = range_header
 
 
 
150
  try:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
151
  req = client.build_request("GET", target_url, headers=headers)
152
  r = await client.send(req, stream=True)
 
 
 
 
 
153
  return await process_response(r, filename)
 
154
  except Exception as e:
 
155
  raise HTTPException(status_code=500, detail=str(e))
156
 
157
  async def process_response(r, filename):
 
175
  finally:
176
  await r.aclose()
177
 
178
+ return StreamingResponse(stream_generator(), status_code=r.status_code, headers=res_headers, media_type=mime_type)
 
 
 
 
 
179
 
180
  if __name__ == "__main__":
181
  uvicorn.run(app, host="0.0.0.0", port=7860)