MyanmarSwe commited on
Commit
214fcc2
·
verified ·
1 Parent(s): c60549e

Update main.py

Browse files
Files changed (1) hide show
  1. main.py +50 -32
main.py CHANGED
@@ -28,10 +28,11 @@ ua = UserAgent(fallback='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/5
28
  MEDIAFIRE_CACHE = {}
29
  CACHE_TTL = 1800
30
 
 
31
  client = httpx.AsyncClient(
32
  timeout=httpx.Timeout(60.0, read=None),
33
  follow_redirects=True,
34
- limits=httpx.Limits(max_connections=300, max_keepalive_connections=100)
35
  )
36
 
37
  @app.get("/")
@@ -65,25 +66,32 @@ def get_clean_filename(url):
65
  return name if (name and '.' in name) else "video.mp4"
66
 
67
  async def scrape_mediafire(url):
68
- """MediaFire Direct Link ကို ပိုမိုကျစွာ ရှာဖွေပေးခြင်း"""
69
  try:
70
  headers = {
71
  'User-Agent': ua.random,
72
  'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8',
73
  'Referer': 'https://www.mediafire.com/'
74
  }
75
- async with httpx.AsyncClient(headers=headers, follow_redirects=True, timeout=20.0) as temp_client:
76
  r = await temp_client.get(url)
77
- if r.status_code == 200:
78
- # Regex ရှာဖွေခြင်း
79
- match = re.search(r'https?://download[^\s"\']+mediafire\.com/[^\s"\']+', r.text)
80
- if match: return match.group(0).strip()
81
-
82
- # BS4 နဲ့ ထပ်ရှာခြင်း
83
- soup = BeautifulSoup(r.text, 'html.parser')
84
- btn = soup.find('a', {'id': 'downloadButton'}) or soup.find('a', {'aria-label': re.compile(r'Download', re.I)})
85
- if btn: return btn.get('href')
86
- except: pass
 
 
 
 
 
 
 
87
  return None
88
 
89
  @app.get("/download")
@@ -107,19 +115,22 @@ async def download_proxy(request: Request, url: str, key: str = None):
107
  if target_link.startswith("//"): target_link = f"https:{target_link}"
108
  MEDIAFIRE_CACHE[clean_url] = {'link': target_link, 'time': current_time}
109
 
110
- if target_link:
111
- # Retry Logic: Block ခံရရင် တစ်ကြိမ်ထပ်ကြိုးစားမည်
112
- try:
113
- return await stream_file(target_link, range_header, filename, referer=clean_url)
114
- except HTTPException as e:
115
- if e.status_code == 415: # HTML Blocked ဖြစ်ခဲ့ရင် Cache ဖျက်ပြီး အသစ်တခါပြန်ရှာ
116
- del MEDIAFIRE_CACHE[clean_url]
117
- new_link = await scrape_mediafire(clean_url)
118
- if new_link:
119
- return await stream_file(new_link, range_header, filename, referer=clean_url)
120
- raise e
121
- else:
122
- raise HTTPException(status_code=404, detail="Direct link failure")
 
 
 
123
 
124
  # --- Google Drive Section ---
125
  elif "drive.google.com" in clean_url:
@@ -158,10 +169,11 @@ async def stream_file(target_url, range_header, filename, referer=None):
158
  req = client.build_request("GET", target_url, headers=headers)
159
  r = await client.send(req, stream=True)
160
 
161
- # HTML Blocked Detection
162
- if "text/html" in r.headers.get("Content-Type", "").lower() and r.status_code == 200:
 
163
  await r.aclose()
164
- raise HTTPException(status_code=415, detail="MediaFire detection triggered.")
165
 
166
  return await process_response(r, filename)
167
  except HTTPException: raise
@@ -177,19 +189,25 @@ async def process_response(r, filename):
177
  'Content-Type': mime_type,
178
  'Accept-Ranges': 'bytes',
179
  'Content-Disposition': f'inline; filename="{urllib.parse.quote(filename)}"',
180
- 'Cache-Control': 'no-cache'
 
181
  }
182
  if 'content-length' in r.headers: res_headers['Content-Length'] = r.headers['content-length']
183
  if 'content-range' in r.headers: res_headers['Content-Range'] = r.headers['content-range']
184
 
185
  async def stream_generator():
186
  try:
187
- async for chunk in r.aiter_bytes(chunk_size=131072):
188
  yield chunk
189
  finally:
190
  await r.aclose()
191
 
192
- return StreamingResponse(stream_generator(), status_code=r.status_code, headers=res_headers, media_type=mime_type)
 
 
 
 
 
193
 
194
  if __name__ == "__main__":
195
  uvicorn.run(app, host="0.0.0.0", port=7860)
 
28
  MEDIAFIRE_CACHE = {}
29
  CACHE_TTL = 1800
30
 
31
+ # Global Client
32
  client = httpx.AsyncClient(
33
  timeout=httpx.Timeout(60.0, read=None),
34
  follow_redirects=True,
35
+ limits=httpx.Limits(max_connections=500, max_keepalive_connections=100)
36
  )
37
 
38
  @app.get("/")
 
66
  return name if (name and '.' in name) else "video.mp4"
67
 
68
  async def scrape_mediafire(url):
69
+ """MediaFire direct link ကို ပိုမိုုင်မာစွာ ရှာဖွေခြင်း"""
70
  try:
71
  headers = {
72
  'User-Agent': ua.random,
73
  'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8',
74
  'Referer': 'https://www.mediafire.com/'
75
  }
76
+ async with httpx.AsyncClient(headers=headers, follow_redirects=True, timeout=25.0) as temp_client:
77
  r = await temp_client.get(url)
78
+ if r.status_code != 200: return None
79
+
80
+ # Pattern 1: Direct Regex
81
+ match = re.search(r'https?://download[^\s"\']+mediafire\.com/[^\s"\']+', r.text)
82
+ if match: return match.group(0).strip().replace("'", "").replace('"', '')
83
+
84
+ # Pattern 2: BeautifulSoup
85
+ soup = BeautifulSoup(r.text, 'html.parser')
86
+ btn = soup.find('a', {'id': 'downloadButton'}) or soup.find('a', {'aria-label': re.compile(r'Download', re.I)})
87
+ if btn and btn.get('href'): return btn.get('href')
88
+
89
+ # Pattern 3: Javascript Variable
90
+ js_match = re.search(r"khtmlurl\s*=\s*['\"](https?://download.*?)['\"]", r.text)
91
+ if js_match: return js_match.group(1)
92
+
93
+ except Exception as e:
94
+ print(f"Scraper internal error: {e}")
95
  return None
96
 
97
  @app.get("/download")
 
115
  if target_link.startswith("//"): target_link = f"https:{target_link}"
116
  MEDIAFIRE_CACHE[clean_url] = {'link': target_link, 'time': current_time}
117
 
118
+ if not target_link:
119
+ raise HTTPException(status_code=404, detail="MediaFire direct link could not be found.")
120
+
121
+ # Stream with Retry on Block
122
+ try:
123
+ return await stream_file(target_link, range_header, filename, referer=clean_url)
124
+ except HTTPException as e:
125
+ if e.status_code == 415: # Detection Triggered
126
+ if clean_url in MEDIAFIRE_CACHE: del MEDIAFIRE_CACHE[clean_url]
127
+ new_link = await scrape_mediafire(clean_url)
128
+ if new_link:
129
+ return await stream_file(new_link, range_header, filename, referer=clean_url)
130
+ raise e
131
+ except Exception as e:
132
+ print(f"MediaFire Stream Error: {e}")
133
+ raise HTTPException(status_code=500, detail="Streaming failed.")
134
 
135
  # --- Google Drive Section ---
136
  elif "drive.google.com" in clean_url:
 
169
  req = client.build_request("GET", target_url, headers=headers)
170
  r = await client.send(req, stream=True)
171
 
172
+ # HTML Content detected (MediaFire error page or bot challenge)
173
+ ctype = r.headers.get("Content-Type", "").lower()
174
+ if "text/html" in ctype and r.status_code == 200:
175
  await r.aclose()
176
+ raise HTTPException(status_code=415, detail="MediaFire blocked request.")
177
 
178
  return await process_response(r, filename)
179
  except HTTPException: raise
 
189
  'Content-Type': mime_type,
190
  'Accept-Ranges': 'bytes',
191
  'Content-Disposition': f'inline; filename="{urllib.parse.quote(filename)}"',
192
+ 'Cache-Control': 'no-cache',
193
+ 'Connection': 'keep-alive'
194
  }
195
  if 'content-length' in r.headers: res_headers['Content-Length'] = r.headers['content-length']
196
  if 'content-range' in r.headers: res_headers['Content-Range'] = r.headers['content-range']
197
 
198
  async def stream_generator():
199
  try:
200
+ async for chunk in r.aiter_bytes(chunk_size=131072): # 128KB
201
  yield chunk
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)