coollsd commited on
Commit
5d1fa44
1 Parent(s): 5e36128

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +124 -130
app.py CHANGED
@@ -1,17 +1,12 @@
1
- from fastapi import FastAPI, File, UploadFile, Request, HTTPException
2
  from fastapi.responses import HTMLResponse, JSONResponse, StreamingResponse
3
- import aiohttp
 
4
  import asyncio
5
  from typing import Dict
6
- import io
7
- import logging
8
 
9
  app = FastAPI()
10
 
11
- # Set up logging
12
- logging.basicConfig(level=logging.INFO)
13
- logger = logging.getLogger(__name__)
14
-
15
  HTML_CONTENT = """
16
  <!DOCTYPE html>
17
  <html lang="en">
@@ -428,7 +423,7 @@ HTML_CONTENT = """
428
  gap: 5px;
429
  }
430
 
431
- .quick-open-modal {
432
  display: none;
433
  position: fixed;
434
  z-index: 4;
@@ -440,7 +435,7 @@ HTML_CONTENT = """
440
  overflow: auto;
441
  }
442
 
443
- .quick-open-content {
444
  margin: 5% auto;
445
  padding: 20px;
446
  width: 90%;
@@ -701,28 +696,44 @@ HTML_CONTENT = """
701
  const formData = new FormData();
702
  formData.append('file', file);
703
 
704
- try {
705
- const response = await fetch('/upload', {
706
- method: 'POST',
707
- body: formData
708
- });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
709
 
710
- if (!response.ok) {
711
- throw new Error(`HTTP error! status: ${response.status}`);
712
- }
 
 
713
 
714
- const result = await response.json();
715
- if (result.url) {
716
- addResultLink(result.url, file.name);
717
- saveToHistory(file.name, result.url);
718
- } else {
719
- throw new Error('Upload failed: ' + result.error);
 
 
 
720
  }
721
- } catch (error) {
722
- console.error('Upload error:', error);
723
- alert('Upload failed. Please try again.');
724
- } finally {
725
- resetUploadState();
726
  }
727
  }
728
 
@@ -742,13 +753,19 @@ HTML_CONTENT = """
742
  return container;
743
  }
744
 
 
 
 
 
 
 
 
745
  function resetUploadState() {
746
  fileInput.value = '';
747
  fileName.textContent = '';
748
  uploadBtn.style.display = 'none';
749
  uploadBtn.disabled = false;
750
  loadingSpinner.style.display = 'none';
751
- progressContainer.style.display = 'none';
752
  }
753
 
754
  function addResultLink(url, fileName) {
@@ -836,7 +853,7 @@ HTML_CONTENT = """
836
  };
837
  actionsContainer.appendChild(copyBtn);
838
 
839
- const openBtn = document.createElement('button');
840
  openBtn.textContent = 'Open';
841
  openBtn.className = 'small-btn';
842
  openBtn.onclick = () => {
@@ -869,7 +886,7 @@ HTML_CONTENT = """
869
  historyModal.style.display = "block";
870
  }
871
 
872
- function quickOpen(url, fileName) {
873
  quickOpenContent.innerHTML = '';
874
  const fullUrl = window.location.origin + url;
875
 
@@ -914,6 +931,7 @@ HTML_CONTENT = """
914
  </body>
915
  </html>
916
  """
 
917
  @app.get("/", response_class=HTMLResponse)
918
  async def index():
919
  return HTML_CONTENT
@@ -921,28 +939,25 @@ async def index():
921
  @app.post("/upload")
922
  async def handle_upload(file: UploadFile = File(...)):
923
  if not file.filename:
924
- raise HTTPException(status_code=400, detail="No file selected.")
925
 
926
- try:
927
- cookies = await get_cookies()
928
- if 'csrftoken' not in cookies or 'sessionid' not in cookies:
929
- raise HTTPException(status_code=500, detail="Failed to get cookies")
930
 
931
- upload_result = await initiate_upload(cookies, file.filename, file.content_type)
932
- if not upload_result or 'upload_url' not in upload_result:
933
- raise HTTPException(status_code=500, detail="Failed to initiate upload")
934
 
935
- upload_success = await chunked_upload(upload_result['upload_url'], file, file.content_type)
936
- if not upload_success:
937
- raise HTTPException(status_code=500, detail="Failed to upload file after multiple attempts")
 
938
 
939
- original_url = upload_result['serving_url']
940
- mirrored_url = f"/rbxg/{original_url.split('/pbxt/')[1]}"
941
 
942
- return JSONResponse(content={"url": mirrored_url})
943
- except Exception as e:
944
- logger.error(f"Upload error: {str(e)}")
945
- raise HTTPException(status_code=500, detail=str(e))
946
 
947
  @app.get("/rbxg/{path:path}")
948
  async def handle_video_stream(path: str, request: Request):
@@ -950,17 +965,20 @@ async def handle_video_stream(path: str, request: Request):
950
  range_header = request.headers.get('Range')
951
 
952
  headers = {'Range': range_header} if range_header else {}
953
- async with aiohttp.ClientSession() as session:
954
- async with session.get(original_url, headers=headers) as response:
955
- content = await response.read()
956
- headers = dict(response.headers)
957
- headers['Access-Control-Allow-Origin'] = '*'
958
- headers['Content-Disposition'] = 'inline'
959
 
960
- if response.status == 206:
961
- headers['Content-Range'] = response.headers.get('Content-Range')
 
962
 
963
- return StreamingResponse(io.BytesIO(content), status_code=response.status, headers=headers)
 
 
 
 
 
 
 
964
 
965
  @app.get("/embed")
966
  async def embed_video(url: str, thumbnail: str):
@@ -1004,80 +1022,56 @@ async def embed_video(url: str, thumbnail: str):
1004
  return HTMLResponse(content=html)
1005
 
1006
  async def get_cookies() -> Dict[str, str]:
1007
- async with aiohttp.ClientSession() as session:
1008
- async with session.get('https://replicate.com/levelsio/neon-tokyo', headers={
1009
  'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36'
1010
- }) as response:
1011
- return {k: v.value for k, v in response.cookies.items()}
 
 
 
1012
 
1013
  async def initiate_upload(cookies: Dict[str, str], filename: str, content_type: str) -> Dict:
1014
  url = f'https://replicate.com/api/upload/{filename}?content_type={content_type}'
1015
- headers = {
1016
- 'X-CSRFToken': cookies.get('csrftoken', ''),
1017
- 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36',
1018
- 'Referer': 'https://replicate.com/levelsio/neon-tokyo',
1019
- 'Origin': 'https://replicate.com',
1020
- 'Accept': '*/*',
1021
- 'Accept-Language': 'en-US,en;q=0.5',
1022
- 'Accept-Encoding': 'identity',
1023
- 'Sec-Fetch-Dest': 'empty',
1024
- 'Sec-Fetch-Mode': 'cors',
1025
- 'Sec-Fetch-Site': 'same-origin',
1026
- 'Sec-GPC': '1',
1027
- 'Priority': 'u=1, i'
1028
- }
1029
- async with aiohttp.ClientSession() as session:
1030
- async with session.post(url, cookies=cookies, headers=headers) as response:
1031
- if response.status != 200:
1032
- raise HTTPException(status_code=response.status, detail=f"Failed to initiate upload: {await response.text()}")
1033
- return await response.json()
1034
-
1035
- async def chunked_upload(upload_url: str, file: UploadFile, content_type: str, chunk_size: int = 1024 * 1024) -> bool:
1036
- async with aiohttp.ClientSession() as session:
1037
- file_size = await get_file_size(file)
1038
- await file.seek(0)
1039
-
1040
- for start in range(0, file_size, chunk_size):
1041
- end = min(start + chunk_size, file_size)
1042
- chunk = await file.read(end - start)
1043
-
1044
- headers = {
1045
- 'Content-Type': content_type,
1046
- 'Content-Range': f'bytes {start}-{end-1}/{file_size}'
1047
- }
1048
 
1049
- for attempt in range(5): # 5 retries
1050
- try:
1051
- async with session.put(upload_url, data=chunk, headers=headers) as response:
1052
- if response.status in [200, 201, 204]:
1053
- break
1054
- elif response.status == 308: # Resume Incomplete
1055
- continue
1056
- else:
1057
- raise aiohttp.ClientError(f"Unexpected status code: {response.status}")
1058
- except aiohttp.ClientError as e:
1059
- if attempt == 4: # Last attempt
1060
- logger.error(f"Upload failed: {str(e)}")
1061
- return False
1062
- await asyncio.sleep(2 ** attempt) # Exponential backoff
1063
- else:
1064
- return False
1065
-
1066
- # Verify the upload
1067
- async with session.put(upload_url, headers={'Content-Range': f'bytes */{file_size}'}) as response:
1068
- if response.status not in [200, 201, 204]:
1069
- logger.error(f"Upload verification failed: {response.status}")
1070
- return False
1071
-
1072
- return True
1073
-
1074
- async def get_file_size(file: UploadFile) -> int:
1075
- size = 0
1076
- while chunk := await file.read(8192):
1077
- size += len(chunk)
1078
- await file.seek(0)
1079
- return size
1080
-
1081
- if __name__ == "__main__":
1082
- import uvicorn
1083
- uvicorn.run(app, host="0.0.0.0", port=7860)
 
1
+ from fastapi import FastAPI, File, UploadFile, Request
2
  from fastapi.responses import HTMLResponse, JSONResponse, StreamingResponse
3
+ import requests
4
+ import time
5
  import asyncio
6
  from typing import Dict
 
 
7
 
8
  app = FastAPI()
9
 
 
 
 
 
10
  HTML_CONTENT = """
11
  <!DOCTYPE html>
12
  <html lang="en">
 
423
  gap: 5px;
424
  }
425
 
426
+ .quick-open-modal {
427
  display: none;
428
  position: fixed;
429
  z-index: 4;
 
435
  overflow: auto;
436
  }
437
 
438
+ .quick-open-content {
439
  margin: 5% auto;
440
  padding: 20px;
441
  width: 90%;
 
696
  const formData = new FormData();
697
  formData.append('file', file);
698
 
699
+ while (true) {
700
+ try {
701
+ const xhr = new XMLHttpRequest();
702
+ xhr.open('POST', '/upload', true);
703
+ xhr.upload.onprogress = (event) => updateProgress(event, progressBar.querySelector('.progress'));
704
+
705
+ xhr.onload = function() {
706
+ if (xhr.status === 200) {
707
+ const response = JSON.parse(xhr.responseText);
708
+ if (response.url) {
709
+ addResultLink(response.url, file.name);
710
+ saveToHistory(file.name, response.url);
711
+ resetUploadState();
712
+ return;
713
+ } else {
714
+ throw new Error('Upload failed: ' + response.error);
715
+ }
716
+ } else {
717
+ throw new Error(`HTTP error! status: ${xhr.status}`);
718
+ }
719
+ };
720
 
721
+ xhr.onerror = function() {
722
+ throw new Error('Network error occurred');
723
+ };
724
+
725
+ xhr.send(formData);
726
 
727
+ await new Promise((resolve, reject) => {
728
+ xhr.onloadend = resolve;
729
+ xhr.onerror = reject;
730
+ });
731
+
732
+ break;
733
+ } catch (error) {
734
+ console.error('Upload error:', error);
735
+ await new Promise(resolve => setTimeout(resolve, 1000));
736
  }
 
 
 
 
 
737
  }
738
  }
739
 
 
753
  return container;
754
  }
755
 
756
+ function updateProgress(event, progressBar) {
757
+ if (event.lengthComputable) {
758
+ const percentComplete = (event.loaded / event.total) * 100;
759
+ progressBar.style.width = percentComplete + '%';
760
+ }
761
+ }
762
+
763
  function resetUploadState() {
764
  fileInput.value = '';
765
  fileName.textContent = '';
766
  uploadBtn.style.display = 'none';
767
  uploadBtn.disabled = false;
768
  loadingSpinner.style.display = 'none';
 
769
  }
770
 
771
  function addResultLink(url, fileName) {
 
853
  };
854
  actionsContainer.appendChild(copyBtn);
855
 
856
+ const openBtn = document.createElement('button');
857
  openBtn.textContent = 'Open';
858
  openBtn.className = 'small-btn';
859
  openBtn.onclick = () => {
 
886
  historyModal.style.display = "block";
887
  }
888
 
889
+ function quickOpen(url, fileName) {
890
  quickOpenContent.innerHTML = '';
891
  const fullUrl = window.location.origin + url;
892
 
 
931
  </body>
932
  </html>
933
  """
934
+
935
  @app.get("/", response_class=HTMLResponse)
936
  async def index():
937
  return HTML_CONTENT
 
939
  @app.post("/upload")
940
  async def handle_upload(file: UploadFile = File(...)):
941
  if not file.filename:
942
+ return JSONResponse(content={"error": "No file selected."}, status_code=400)
943
 
944
+ cookies = await get_cookies()
945
+ if 'csrftoken' not in cookies or 'sessionid' not in cookies:
946
+ return JSONResponse(content={"error": "Failed"}, status_code=500)
 
947
 
948
+ upload_result = await initiate_upload(cookies, file.filename, file.content_type)
949
+ if not upload_result or 'upload_url' not in upload_result:
950
+ return JSONResponse(content={"error": "Failed to upload"}, status_code=500)
951
 
952
+ file_content = await file.read()
953
+ upload_success = await retry_upload(upload_result['upload_url'], file_content, file.content_type)
954
+ if not upload_success:
955
+ return JSONResponse(content={"error": "FAILED GOD MAN AFTER alot of attempts"}, status_code=500)
956
 
957
+ original_url = upload_result['serving_url']
958
+ mirrored_url = f"/rbxg/{original_url.split('/pbxt/')[1]}"
959
 
960
+ return JSONResponse(content={"url": mirrored_url})
 
 
 
961
 
962
  @app.get("/rbxg/{path:path}")
963
  async def handle_video_stream(path: str, request: Request):
 
965
  range_header = request.headers.get('Range')
966
 
967
  headers = {'Range': range_header} if range_header else {}
968
+ response = requests.get(original_url, headers=headers, stream=True)
 
 
 
 
 
969
 
970
+ def generate():
971
+ for chunk in response.iter_content(chunk_size=8192):
972
+ yield chunk
973
 
974
+ headers = dict(response.headers)
975
+ headers['Access-Control-Allow-Origin'] = '*'
976
+ headers['Content-Disposition'] = 'inline'
977
+
978
+ if response.status_code == 206:
979
+ headers['Content-Range'] = response.headers.get('Content-Range')
980
+
981
+ return StreamingResponse(generate(), status_code=response.status_code, headers=headers)
982
 
983
  @app.get("/embed")
984
  async def embed_video(url: str, thumbnail: str):
 
1022
  return HTMLResponse(content=html)
1023
 
1024
  async def get_cookies() -> Dict[str, str]:
1025
+ try:
1026
+ response = requests.get('https://replicate.com/levelsio/neon-tokyo', headers={
1027
  'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36'
1028
+ })
1029
+ return dict(response.cookies)
1030
+ except Exception as e:
1031
+ print(f'Error fetching the page: {e}')
1032
+ return {}
1033
 
1034
  async def initiate_upload(cookies: Dict[str, str], filename: str, content_type: str) -> Dict:
1035
  url = f'https://replicate.com/api/upload/{filename}?content_type={content_type}'
1036
+ try:
1037
+ response = requests.post(url, cookies=cookies, headers={
1038
+ 'X-CSRFToken': cookies.get('csrftoken'),
1039
+ 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36',
1040
+ 'Referer': 'https://replicate.com/levelsio/neon-tokyo',
1041
+ 'Origin': 'https://replicate.com',
1042
+ 'Accept': '*/*',
1043
+ 'Accept-Language': 'en-US,en;q=0.5',
1044
+ 'Accept-Encoding': 'identity',
1045
+ 'Sec-Fetch-Dest': 'empty',
1046
+ 'Sec-Fetch-Mode': 'cors',
1047
+ 'Sec-Fetch-Site': 'same-origin',
1048
+ 'Sec-GPC': '1',
1049
+ 'Priority': 'u=1, i'
1050
+ })
1051
+ return response.json()
1052
+ except Exception as e:
1053
+ print(f'Error initiating upload: {e}')
1054
+ raise
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1055
 
1056
+ async def upload_file(upload_url: str, file_content: bytes, content_type: str) -> bool:
1057
+ try:
1058
+ response = requests.put(upload_url, data=file_content, headers={'Content-Type': content_type})
1059
+ return response.status_code == 200
1060
+ except Exception as e:
1061
+ print(f'Error uploading file: {e}')
1062
+ return False
1063
+
1064
+ async def retry_upload(upload_url: str, file_content: bytes, content_type: str, max_retries: int = 5, delay: int = 1) -> bool:
1065
+ while True:
1066
+ try:
1067
+ success = await upload_file(upload_url, file_content, content_type)
1068
+ if success:
1069
+ return True
1070
+ print("Upload failed. Retrying...")
1071
+ except Exception as e:
1072
+ print(f"Error during upload: {e}")
1073
+
1074
+ await asyncio.sleep(delay)
1075
+ delay = min(delay * 2, 60)
1076
+
1077
+ return False