MyanmarSwe commited on
Commit
2a0a05e
Β·
verified Β·
1 Parent(s): c844414

Update main.py

Browse files
Files changed (1) hide show
  1. main.py +56 -55
main.py CHANGED
@@ -2,8 +2,9 @@ import os
2
  import re
3
  import json
4
  import base64
5
- import requests
6
  import random
 
7
  from bs4 import BeautifulSoup
8
  from fastapi import FastAPI, HTTPException, Request
9
  from fastapi.responses import StreamingResponse
@@ -19,55 +20,65 @@ app = FastAPI()
19
  # --- Configurations ---
20
  ACCESS_KEY = os.getenv("ACCESS_KEY", "0000")
21
  SERVICE_ACCOUNT_JSON_STR = os.getenv("GOOGLE_SERVICE_ACCOUNT_JSON")
22
-
23
- # User-Agent Generator with fallback
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
  @app.get("/")
27
- def index():
28
- return {"message": "Proxy is Online!", "usage": "/download?url=[LINK]&key=[YOUR_KEY]"}
29
 
30
  def get_all_service_accounts():
31
- if not SERVICE_ACCOUNT_JSON_STR:
32
- return []
33
  try:
34
  data = json.loads(SERVICE_ACCOUNT_JSON_STR)
35
  return data if isinstance(data, list) else [data]
36
- except Exception as e:
37
- print(f"JSON Parsing Error: {e}")
38
- return []
39
 
40
- def get_token_for_account(cred_dict):
41
  try:
42
  scopes = ['https://www.googleapis.com/auth/drive.readonly']
43
  creds = service_account.Credentials.from_service_account_info(cred_dict, scopes=scopes)
 
 
44
  auth_req = google.auth.transport.requests.Request()
45
- creds.refresh(auth_req)
46
  return creds.token
47
- except Exception as e:
48
- print(f"Auth Error for {cred_dict.get('client_email')}: {e}")
49
- return None
50
 
51
  def get_google_file_id(url):
52
  fid = re.search(r'/(?:d|file/d|open\?id=)/([a-zA-Z0-9_-]+)', url)
53
  return fid.group(1) if fid else None
54
 
55
  @app.get("/download")
56
- def download_proxy(request: Request, url: str, key: str = None):
57
  if key != ACCESS_KEY:
58
  raise HTTPException(status_code=403, detail="Access Denied")
59
 
 
 
 
60
  if "drive.google.com" not in url:
61
  target_link = None
62
- current_headers = {'User-Agent': ua.random, 'Accept-Language': 'en-US,en;q=0.9'}
63
 
64
  if "mediafire.com" in url:
65
  try:
66
- current_headers['Referer'] = 'https://www.mediafire.com/'
67
- r = requests.get(url, headers=current_headers, timeout=15)
68
- soup = BeautifulSoup(r.text, 'html.parser')
69
- btn = soup.find('a', {'id': 'downloadButton'})
70
- target_link = btn.get('href') if btn else None
 
 
 
 
 
71
  except Exception as e:
72
  print(f"MediaFire Error: {e}")
73
 
@@ -81,8 +92,9 @@ def download_proxy(request: Request, url: str, key: str = None):
81
  if not target_link:
82
  raise HTTPException(status_code=400, detail="Could not resolve direct link")
83
 
84
- return stream_file(target_link, request.headers.get('range'))
85
 
 
86
  file_id = get_google_file_id(url)
87
  if not file_id:
88
  raise HTTPException(status_code=400, detail="Invalid Google Drive Link")
@@ -91,61 +103,50 @@ def download_proxy(request: Request, url: str, key: str = None):
91
  random.shuffle(accounts)
92
 
93
  for account in accounts:
94
- token = get_token_for_account(account)
95
  if not token: continue
96
 
97
  api_link = f"https://www.googleapis.com/drive/v3/files/{file_id}?alt=media"
98
  headers = {"Authorization": f"Bearer {token}"}
99
- if request.headers.get('range'):
100
- headers['Range'] = request.headers.get('range')
101
 
102
  try:
103
- r = requests.get(api_link, headers=headers, stream=True, allow_redirects=True, timeout=15)
 
 
104
  if r.status_code in [200, 206]:
105
- return process_response(r)
106
- except Exception as e:
107
- print(f"Account Request Error: {e}")
108
 
109
  # Public Fallback
110
- try:
111
- public_url = f"https://drive.google.com/uc?export=download&id={file_id}"
112
- headers = {'User-Agent': ua.random}
113
- if request.headers.get('range'):
114
- headers['Range'] = request.headers.get('range')
115
- r = requests.get(public_url, headers=headers, stream=True, allow_redirects=True, timeout=15)
116
- return process_response(r)
117
- except:
118
- raise HTTPException(status_code=500, detail="Download failed.")
119
-
120
- def stream_file(target_url, range_header):
121
  headers = {'User-Agent': ua.random}
122
- if range_header:
123
- headers['Range'] = range_header
124
  try:
125
- r = requests.get(target_url, headers=headers, stream=True, allow_redirects=True, timeout=15)
126
- return process_response(r)
 
127
  except Exception as e:
128
  raise HTTPException(status_code=500, detail=str(e))
129
 
130
- def process_response(r):
131
  excluded = ['content-encoding', 'content-length', 'transfer-encoding', 'connection']
132
  response_headers = {n: v for n, v in r.headers.items() if n.lower() not in excluded}
 
 
133
  response_headers['Accept-Ranges'] = 'bytes'
134
  if 'Content-Length' in r.headers:
135
  response_headers['Content-Length'] = r.headers['Content-Length']
136
  if 'Content-Range' in r.headers:
137
  response_headers['Content-Range'] = r.headers['Content-Range']
138
 
139
- def iterfile():
140
- try:
141
- # Chunk size α€€α€­α€― 5MB α€α€­α€―α€Έα€™α€Όα€Ύα€„α€·α€Ία€‘α€¬α€Έα€•α€«α€α€šα€Ί (Speed ပိုကောင်းစေရန်)
142
- for chunk in r.iter_content(chunk_size=1024*1024):
143
- if chunk: yield chunk
144
- finally:
145
- r.close()
146
-
147
  return StreamingResponse(
148
- iterfile(),
149
  status_code=r.status_code,
150
  headers=response_headers,
151
  media_type=r.headers.get('Content-Type', 'application/octet-stream')
 
2
  import re
3
  import json
4
  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
 
20
  # --- Configurations ---
21
  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 {"message": "High-Speed Async Proxy Online!", "usage": "/download?url=[LINK]&key=[YOUR_KEY]"}
35
 
36
  def get_all_service_accounts():
37
+ if not SERVICE_ACCOUNT_JSON_STR: return []
 
38
  try:
39
  data = json.loads(SERVICE_ACCOUNT_JSON_STR)
40
  return data if isinstance(data, list) else [data]
41
+ except: return []
 
 
42
 
43
+ 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)
51
  return creds.token
52
+ except: return None
 
 
53
 
54
  def get_google_file_id(url):
55
  fid = re.search(r'/(?:d|file/d|open\?id=)/([a-zA-Z0-9_-]+)', url)
56
  return fid.group(1) if fid else None
57
 
58
  @app.get("/download")
59
+ 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 ---
66
  if "drive.google.com" not in url:
67
  target_link = None
68
+ headers = {'User-Agent': ua.random, 'Accept-Language': 'en-US,en;q=0.9'}
69
 
70
  if "mediafire.com" in url:
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:
79
+ soup = BeautifulSoup(r.text, 'html.parser')
80
+ btn = soup.find('a', {'id': 'downloadButton'})
81
+ target_link = btn.get('href') if btn else None
82
  except Exception as e:
83
  print(f"MediaFire Error: {e}")
84
 
 
92
  if not target_link:
93
  raise HTTPException(status_code=400, detail="Could not resolve direct link")
94
 
95
+ return await stream_file(target_link, range_header)
96
 
97
+ # --- Google Drive ---
98
  file_id = get_google_file_id(url)
99
  if not file_id:
100
  raise HTTPException(status_code=400, detail="Invalid Google Drive Link")
 
103
  random.shuffle(accounts)
104
 
105
  for account in accounts:
106
+ token = await get_token_for_account(account)
107
  if not token: continue
108
 
109
  api_link = f"https://www.googleapis.com/drive/v3/files/{file_id}?alt=media"
110
  headers = {"Authorization": f"Bearer {token}"}
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]:
118
+ return await process_response(r)
119
+ await r.aclose()
120
+ except: continue
121
 
122
  # Public Fallback
123
+ public_url = f"https://drive.google.com/uc?export=download&id={file_id}"
124
+ return await stream_file(public_url, range_header)
125
+
126
+ async def stream_file(target_url, range_header):
 
 
 
 
 
 
 
127
  headers = {'User-Agent': ua.random}
128
+ if range_header: headers['Range'] = range_header
129
+
130
  try:
131
+ req = client.build_request("GET", target_url, headers=headers)
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
  excluded = ['content-encoding', 'content-length', 'transfer-encoding', 'connection']
139
  response_headers = {n: v for n, v in r.headers.items() if n.lower() not in excluded}
140
+
141
+ # Video Seeking ထတွက် α€™α€›α€Ύα€­α€™α€–α€Όα€…α€Ία€œα€­α€―α€‘α€•α€Ία€žα€±α€¬ Headers များ
142
  response_headers['Accept-Ranges'] = 'bytes'
143
  if 'Content-Length' in r.headers:
144
  response_headers['Content-Length'] = r.headers['Content-Length']
145
  if 'Content-Range' in r.headers:
146
  response_headers['Content-Range'] = r.headers['Content-Range']
147
 
 
 
 
 
 
 
 
 
148
  return StreamingResponse(
149
+ r.aiter_bytes(chunk_size=131072), # 128KB chunks for perfect buffering
150
  status_code=r.status_code,
151
  headers=response_headers,
152
  media_type=r.headers.get('Content-Type', 'application/octet-stream')