MyanmarSwe commited on
Commit
63fa4d7
Β·
verified Β·
1 Parent(s): fef82ba

Update main.py

Browse files
Files changed (1) hide show
  1. main.py +24 -12
main.py CHANGED
@@ -5,6 +5,7 @@ import base64
5
  import httpx
6
  import random
7
  import asyncio
 
8
  from bs4 import BeautifulSoup
9
  from fastapi import FastAPI, HTTPException, Request
10
  from fastapi.responses import StreamingResponse
@@ -22,16 +23,16 @@ ACCESS_KEY = os.getenv("ACCESS_KEY", "0000")
22
  SERVICE_ACCOUNT_JSON_STR = os.getenv("GOOGLE_SERVICE_ACCOUNT_JSON")
23
  ua = UserAgent(fallback='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36')
24
 
25
- # Global Async Client: Video α€€α€»α€±α€¬α€Ία€€α€Όα€Šα€·α€Ία€α€²α€·α€‘α€α€« Connection α€‘α€žα€…α€Ία€α€½α€± မြန်မြန်ဆောက်နိုင်ဖို့
26
  client = httpx.AsyncClient(
27
- timeout=httpx.Timeout(20.0, read=None),
28
  follow_redirects=True,
29
  limits=httpx.Limits(max_connections=100, max_keepalive_connections=20)
30
  )
31
 
32
  @app.get("/")
33
  async def index():
34
- return {"Online"}
35
 
36
  def get_all_service_accounts():
37
  if not SERVICE_ACCOUNT_JSON_STR: return []
@@ -44,7 +45,7 @@ async def get_token_for_account(cred_dict):
44
  try:
45
  scopes = ['https://www.googleapis.com/auth/drive.readonly']
46
  creds = service_account.Credentials.from_service_account_info(cred_dict, scopes=scopes)
47
- # Token refresh α€€α€­α€― thread ထဲမှာ run α€•α€«α€α€šα€Ί (Google library α€€ sync α€–α€Όα€…α€Ία€œα€­α€―α€·)
48
  loop = asyncio.get_event_loop()
49
  auth_req = google.auth.transport.requests.Request()
50
  await loop.run_in_executor(None, creds.refresh, auth_req)
@@ -60,6 +61,9 @@ async def download_proxy(request: Request, url: str, key: str = None):
60
  if key != ACCESS_KEY:
61
  raise HTTPException(status_code=403, detail="Access Denied")
62
 
 
 
 
63
  range_header = request.headers.get('range')
64
 
65
  # --- MediaFire & Others ---
@@ -71,8 +75,9 @@ async def download_proxy(request: Request, url: str, key: str = None):
71
  try:
72
  headers['Referer'] = 'https://www.mediafire.com/'
73
  r = await client.get(url, headers=headers)
74
- # Regex ဖြင့် Direct Link α€€α€­α€― ထမြန်ဆုဢး ရှာဖွေခြင်း
75
- match = re.search(r'href="(https?://download[^"]+)"', r.text)
 
76
  if match:
77
  target_link = match.group(1)
78
  else:
@@ -111,7 +116,6 @@ async def download_proxy(request: Request, url: str, key: str = None):
111
  if range_header: headers['Range'] = range_header
112
 
113
  try:
114
- # Stream mode ဖြင့် ချိတ်ဆက်ခြင်း
115
  req = client.build_request("GET", api_link, headers=headers)
116
  r = await client.send(req, stream=True)
117
  if r.status_code in [200, 206]:
@@ -132,10 +136,11 @@ async def stream_file(target_url, range_header):
132
  r = await client.send(req, stream=True)
133
  return await process_response(r)
134
  except Exception as e:
 
135
  raise HTTPException(status_code=500, detail=str(e))
136
 
137
  async def process_response(r):
138
- # α€™α€°α€œα€œα€¬α€α€²α€· content-disposition α€€α€­α€― α€–α€šα€Ία€‘α€―α€α€Ία€–α€­α€―α€· excluded ထဲ α€‘α€Šα€·α€Ία€œα€­α€―α€€α€Ία€•α€«α€™α€šα€Ί
139
  excluded = ['content-encoding', 'content-length', 'transfer-encoding', 'connection', 'content-disposition']
140
  response_headers = {n: v for n, v in r.headers.items() if n.lower() not in excluded}
141
 
@@ -146,15 +151,22 @@ async def process_response(r):
146
  if 'Content-Range' in r.headers:
147
  response_headers['Content-Range'] = r.headers['Content-Range']
148
 
149
- # --- Direct Download α€–α€Όα€…α€Ία€…α€±α€›α€”α€Ί ပြင်ဆင်ချက် ---
150
- # content-disposition α€€α€­α€― attachment α€œα€­α€―α€· α€žα€α€Ία€™α€Ύα€α€Ία€•α€±α€Έα€œα€­α€―α€€α€Ία€›α€„α€Ί browser α€€ တန်း download α€œα€―α€•α€Ία€•α€«α€œα€­α€™α€·α€Ία€™α€šα€Ί
151
  response_headers['Content-Disposition'] = 'attachment'
152
 
 
 
 
 
 
 
 
 
153
  return StreamingResponse(
154
- r.aiter_bytes(chunk_size=131072), # 128KB chunks for perfect buffering
155
  status_code=r.status_code,
156
  headers=response_headers,
157
- media_type='application/octet-stream' # stream ထနေနဲ့ တန်းဆွဲဖို့ application/octet-stream α€•α€Όα€±α€¬α€„α€Ία€Έα€œα€­α€―α€€α€Ία€•α€«α€α€šα€Ί
158
  )
159
 
160
  if __name__ == "__main__":
 
5
  import httpx
6
  import random
7
  import asyncio
8
+ import urllib.parse
9
  from bs4 import BeautifulSoup
10
  from fastapi import FastAPI, HTTPException, Request
11
  from fastapi.responses import StreamingResponse
 
23
  SERVICE_ACCOUNT_JSON_STR = os.getenv("GOOGLE_SERVICE_ACCOUNT_JSON")
24
  ua = UserAgent(fallback='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36')
25
 
26
+ # Global Async Client
27
  client = httpx.AsyncClient(
28
+ timeout=httpx.Timeout(30.0, read=None), # Timeout α€€α€­α€― 30 စက္ကန့်ထထိ α€α€­α€―α€Έα€•α€±α€Έα€‘α€¬α€Έα€•α€«α€α€šα€Ί
29
  follow_redirects=True,
30
  limits=httpx.Limits(max_connections=100, max_keepalive_connections=20)
31
  )
32
 
33
  @app.get("/")
34
  async def index():
35
+ return {"status": "Online"}
36
 
37
  def get_all_service_accounts():
38
  if not SERVICE_ACCOUNT_JSON_STR: return []
 
45
  try:
46
  scopes = ['https://www.googleapis.com/auth/drive.readonly']
47
  creds = service_account.Credentials.from_service_account_info(cred_dict, scopes=scopes)
48
+ # Token refresh α€€α€­α€― thread ထဲမှာ run α€•α€«α€α€šα€Ί
49
  loop = asyncio.get_event_loop()
50
  auth_req = google.auth.transport.requests.Request()
51
  await loop.run_in_executor(None, creds.refresh, auth_req)
 
61
  if key != ACCESS_KEY:
62
  raise HTTPException(status_code=403, detail="Access Denied")
63
 
64
+ # Double encoded α€–α€Όα€…α€Ία€”α€±α€žα€±α€¬ URL များကို α€›α€Ύα€„α€Ία€Έα€œα€„α€Ία€Έα€›α€”α€Ί
65
+ url = urllib.parse.unquote(url)
66
+
67
  range_header = request.headers.get('range')
68
 
69
  # --- MediaFire & Others ---
 
75
  try:
76
  headers['Referer'] = 'https://www.mediafire.com/'
77
  r = await client.get(url, headers=headers)
78
+
79
+ # Regex ဖြင့် Direct Link α€€α€­α€― ရှာဖွေခြင်း (ပိုမိုတိကျစေရန် α€•α€Όα€„α€Ία€‘α€¬α€Έα€žα€Šα€Ί)
80
+ match = re.search(r'href="(https?://[a-zA-Z0-9-]+\.mediafire\.com/download/[^"]+)"', r.text)
81
  if match:
82
  target_link = match.group(1)
83
  else:
 
116
  if range_header: headers['Range'] = range_header
117
 
118
  try:
 
119
  req = client.build_request("GET", api_link, headers=headers)
120
  r = await client.send(req, stream=True)
121
  if r.status_code in [200, 206]:
 
136
  r = await client.send(req, stream=True)
137
  return await process_response(r)
138
  except Exception as e:
139
+ print(f"Stream Error for {target_url}: {e}")
140
  raise HTTPException(status_code=500, detail=str(e))
141
 
142
  async def process_response(r):
143
+ # α€™α€°α€œα€œα€¬α€α€²α€· content-disposition α€€α€­α€― α€–α€šα€Ία€‘α€―α€α€Ία€–α€­α€―α€· excluded ထဲ α€‘α€Šα€·α€Ία€•α€«α€™α€šα€Ί
144
  excluded = ['content-encoding', 'content-length', 'transfer-encoding', 'connection', 'content-disposition']
145
  response_headers = {n: v for n, v in r.headers.items() if n.lower() not in excluded}
146
 
 
151
  if 'Content-Range' in r.headers:
152
  response_headers['Content-Range'] = r.headers['Content-Range']
153
 
154
+ # Direct Download α€–α€Όα€…α€Ία€…α€±α€›α€”α€Ί
 
155
  response_headers['Content-Disposition'] = 'attachment'
156
 
157
+ # Connection များကို Memory Leak α€™α€–α€Όα€…α€Ία€…α€±α€˜α€² α€žα€±α€α€»α€¬α€•α€­α€α€Ία€•α€±α€Έα€™α€Šα€·α€Ί Generator
158
+ async def stream_generator():
159
+ try:
160
+ async for chunk in r.aiter_bytes(chunk_size=131072): # 128KB chunks
161
+ yield chunk
162
+ finally:
163
+ await r.aclose()
164
+
165
  return StreamingResponse(
166
+ stream_generator(),
167
  status_code=r.status_code,
168
  headers=response_headers,
169
+ media_type='application/octet-stream'
170
  )
171
 
172
  if __name__ == "__main__":