Spaces:
Paused
Paused
| from fastapi import FastAPI, File, UploadFile, Request | |
| from fastapi.responses import HTMLResponse, JSONResponse, StreamingResponse, FileResponse | |
| import requests | |
| import time | |
| import asyncio | |
| from typing import Dict | |
| import os | |
| import mimetypes | |
| app = FastAPI() | |
| HTML_CONTENT = """ | |
| <!DOCTYPE html> | |
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>PRO Uploader</title> | |
| <link href="https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;600&display=swap" rel="stylesheet"> | |
| <style> | |
| body { | |
| font-family: 'Poppins', sans-serif; | |
| background-color: #121212; | |
| color: #e0e0e0; | |
| margin: 0; | |
| min-height: 100vh; | |
| display: flex; | |
| justify-content: center; | |
| align-items: center; | |
| padding: 20px; | |
| box-sizing: border-box; | |
| } | |
| body::before { | |
| content: ""; | |
| position: fixed; | |
| top: 0; | |
| left: 0; | |
| width: 100%; | |
| height: 100%; | |
| background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADwAAAA8CAQAAACM/9unAAAACXBIWXMAAAsTAAALEwEAmpwYAAABF0lEQVR4nO3YMRLCQBRE0clsYgxZwwq7oLGxAgp2AtbsqQZsYgEG0wEWc/LSZnb9HcMjR8fHvEKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgsK8tJOq9fzs7vlkNlWvf5ELi+20t5k2VSL7p/iHJ5Rz5ynOhU7rQ4pUi+6b4hyeUc+cpzoVO60OkV7rQ4pUi+6b4hxenu+en4rQAOkaks/eJegGaUfOHI+nRvQCND1w2J9yf8C2KZwNjkeUsAKRa7Nz50tQAokVbO/U6AaiWjl5wd6kQAOke8Xpx3JgTQKVq7Heh0ADpFvF6cd0kE0Claux3odAA6RfxenHc+BNCpWrsd6HQAOkX8Xpx3PgTQqVq7Heh0ADpF/F6cdz4E0KlarjdI/cR1FBQUGBgYGBgYGBgYG/AT4AIHph6aQGU7oAAAAASUVORK5CYII=') repeat; | |
| animation: grain 8s steps(10) infinite; | |
| opacity: 0.2; | |
| pointer-events: none; | |
| } | |
| @keyframes grain { | |
| 0% { transform: translate(0, 0); } | |
| 10% { transform: translate(-5%, -5%); } | |
| 20% { transform: translate(-10%, 5%); } | |
| 30% { transform: translate(5%, -10%); } | |
| 40% { transform: translate(-5%, 15%); } | |
| 50% { transform: translate(-10%, 5%); } | |
| 60% { transform: translate(15%, 0); } | |
| 70% { transform: translate(0, 10%); } | |
| 80% { transform: translate(-15%, 0); } | |
| 90% { transform: translate(10%, 5%); } | |
| 100% { transform: translate(5%, 0); } | |
| } | |
| .container { | |
| position: relative; | |
| width: 100%; | |
| max-width: 450px; | |
| margin: 0 auto; | |
| padding: 2rem; | |
| background: rgba(18, 18, 18, 0.9); | |
| backdrop-filter: blur(10px); | |
| border-radius: 15px; | |
| z-index: 1; | |
| text-align: center; | |
| box-shadow: 0 0 20px rgba(0, 0, 0, 0.8); | |
| } | |
| h1 { | |
| margin-bottom: 1.5rem; | |
| font-size: 1.8rem; | |
| color: #ffffff; | |
| text-shadow: 0 0 5px rgba(255, 255, 255, 0.2); | |
| } | |
| .btn { | |
| display: inline-block; | |
| position: relative; | |
| padding: 12px 24px; | |
| margin: 0.5rem; | |
| font-size: 1rem; | |
| font-weight: 600; | |
| color: #ffffff; | |
| background-color: #2a2a2a; | |
| border: none; | |
| border-radius: 5px; | |
| cursor: pointer; | |
| overflow: hidden; | |
| z-index: 1; | |
| transition: color 0.3s ease, box-shadow 0.3s ease; | |
| } | |
| .btn:hover { | |
| color: #ffffff; | |
| box-shadow: 0 0 15px rgba(200, 200, 200, 0.5); | |
| } | |
| .btn:hover::before { | |
| content: ''; | |
| position: absolute; | |
| inset: -10px; | |
| background: radial-gradient(circle at center, rgba(200,200,200,0.2), transparent); | |
| filter: blur(20px); | |
| animation: glowAnimation 2s infinite; | |
| z-index: -1; | |
| pointer-events: none; | |
| } | |
| @keyframes glowAnimation { | |
| 0% { transform: scale(0.8); } | |
| 50% { transform: scale(1.2); } | |
| 100% { transform: scale(0.8); } | |
| } | |
| .btn:active { | |
| transform: scale(0.98); | |
| } | |
| .small-btn { | |
| padding: 6px 12px; | |
| font-size: 0.8rem; | |
| font-weight: 500; | |
| background-color: #2a2a2a; | |
| color: #ffffff; | |
| border: none; | |
| border-radius: 5px; | |
| cursor: pointer; | |
| transition: color 0.3s ease, box-shadow 0.3s ease; | |
| position: relative; | |
| overflow: hidden; | |
| z-index: 1; | |
| margin: 0.25rem; | |
| } | |
| .small-btn:hover { | |
| color: #ffffff; | |
| box-shadow: 0 0 10px rgba(200, 200, 200, 0.5); | |
| } | |
| .small-btn:hover::before { | |
| content: ''; | |
| position: absolute; | |
| inset: -10px; | |
| background: radial-gradient(circle at center, rgba(200,200,200,0.2), transparent); | |
| filter: blur(15px); | |
| animation: glowAnimation 2s infinite; | |
| z-index: -1; | |
| pointer-events: none; | |
| } | |
| .small-btn:active { | |
| transform: scale(0.98); | |
| } | |
| .drop-zone { | |
| position: relative; | |
| padding: 20px; | |
| margin-bottom: 1rem; | |
| border: 2px dashed #aaa; | |
| border-radius: 10px; | |
| cursor: pointer; | |
| transition: all 0.3s ease; | |
| background: rgba(255, 255, 255, 0.05); | |
| overflow: hidden; | |
| } | |
| .drop-zone:hover, .drop-zone.drag-over { | |
| border-color: #ffffff; | |
| background: rgba(255, 255, 255, 0.1); | |
| position: relative; | |
| } | |
| .drop-zone:hover::before, .drop-zone.drag-over::before { | |
| content: ''; | |
| position: absolute; | |
| inset: -10px; | |
| background: radial-gradient(circle at center, rgba(200,200,200,0.2), transparent); | |
| filter: blur(30px); | |
| animation: grainGlow 5s infinite; | |
| z-index: -1; | |
| pointer-events: none; | |
| } | |
| @keyframes grainGlow { | |
| 0% { opacity: 0.2; } | |
| 50% { opacity: 0.5; } | |
| 100% { opacity: 0.2; } | |
| } | |
| .file-input { | |
| display: none; | |
| } | |
| .file-name { | |
| margin-top: 1rem; | |
| font-size: 0.9rem; | |
| color: #aaa; | |
| word-break: break-all; | |
| } | |
| .progress-container { | |
| display: none; | |
| margin-top: 1.5rem; | |
| } | |
| .progress-bar { | |
| width: 100%; | |
| height: 10px; | |
| background-color: #333; | |
| border-radius: 5px; | |
| overflow: hidden; | |
| margin-bottom: 10px; | |
| } | |
| .progress { | |
| width: 0%; | |
| height: 100%; | |
| background-color: #ffffff; | |
| transition: width 0.3s ease; | |
| } | |
| .loading-spinner { | |
| display: none; | |
| width: 40px; | |
| height: 40px; | |
| border: 4px solid #333; | |
| border-top: 4px solid #ffffff; | |
| border-radius: 50%; | |
| animation: spin 1s linear infinite; | |
| margin: 20px auto; | |
| } | |
| @keyframes spin { | |
| 0% { transform: rotate(0deg); } | |
| 100% { transform: rotate(360deg); } | |
| } | |
| .result-container { | |
| display: none; | |
| margin-top: 1.5rem; | |
| } | |
| .result-link { | |
| color: #ffffff; | |
| text-decoration: none; | |
| font-weight: 600; | |
| transition: all 0.3s ease; | |
| margin-right: 10px; | |
| word-break: break-all; | |
| } | |
| .result-link:hover { | |
| text-decoration: underline; | |
| } | |
| .link-buttons { | |
| display: flex; | |
| justify-content: center; | |
| flex-wrap: wrap; | |
| margin-top: 10px; | |
| } | |
| .file-types { | |
| margin-top: 2rem; | |
| font-size: 0.8rem; | |
| color: #aaa; | |
| } | |
| .modal { | |
| display: none; | |
| position: fixed; | |
| z-index: 2; | |
| left: 0; | |
| top: 0; | |
| width: 100%; | |
| height: 100%; | |
| overflow: auto; | |
| background-color: rgba(0,0,0,0.8); | |
| } | |
| .modal-content { | |
| background-color: #1e1e1e; | |
| margin: 15% auto; | |
| padding: 20px; | |
| border: 1px solid #333; | |
| width: 90%; | |
| max-width: 600px; | |
| border-radius: 10px; | |
| color: #e0e0e0; | |
| animation: modalFadeIn 0.3s; | |
| position: relative; | |
| } | |
| @keyframes modalFadeIn { | |
| from {opacity: 0; transform: scale(0.8);} | |
| to {opacity: 1; transform: scale(1);} | |
| } | |
| .close { | |
| color: #aaa; | |
| position: absolute; | |
| top: 10px; | |
| right: 15px; | |
| font-size: 28px; | |
| font-weight: bold; | |
| transition: color 0.3s ease; | |
| } | |
| .close:hover, | |
| .close:focus { | |
| color: #fff; | |
| text-decoration: none; | |
| cursor: pointer; | |
| } | |
| .embed-container { | |
| display: flex; | |
| flex-direction: column; | |
| align-items: stretch; | |
| margin-top: 15px; | |
| } | |
| #embedLink { | |
| width: 100%; | |
| padding: 10px; | |
| background-color: #333; | |
| border: 1px solid #555; | |
| color: #e0e0e0; | |
| border-radius: 5px; | |
| margin-bottom: 10px; | |
| font-size: 0.9rem; | |
| } | |
| .history-btn-container { | |
| display: flex; | |
| justify-content: center; | |
| gap: 10px; | |
| margin-top: 1rem; | |
| } | |
| .history-btn, .clear-history-btn { | |
| display: inline-block; | |
| padding: 8px 16px; | |
| font-size: 0.9rem; | |
| font-weight: 500; | |
| color: #ffffff; | |
| border: none; | |
| border-radius: 3px; | |
| cursor: pointer; | |
| transition: background-color 0.3s ease, box-shadow 0.3s ease; | |
| } | |
| .history-btn { | |
| background-color: #2a2a2a; | |
| } | |
| .history-btn:hover { | |
| background-color: #3a3a3a; | |
| box-shadow: 0 0 10px rgba(200, 200, 200, 0.3); | |
| } | |
| .clear-history-btn { | |
| background-color: #1a0505; | |
| } | |
| .clear-history-btn:hover { | |
| background-color: #2a0a0a; | |
| box-shadow: 0 0 10px rgba(255, 0, 0, 0.3); | |
| } | |
| .history-modal { | |
| display: none; | |
| position: fixed; | |
| z-index: 3; | |
| left: 0; | |
| top: 0; | |
| width: 100%; | |
| height: 100%; | |
| overflow: auto; | |
| background-color: rgba(0,0,0,0.8); | |
| } | |
| .history-modal-content { | |
| background-color: #1e1e1e; | |
| margin: 10% auto; | |
| padding: 20px; | |
| border: 1px solid #333; | |
| width: 90%; | |
| max-width: 600px; | |
| border-radius: 10px; | |
| color: #e0e0e0; | |
| animation: modalFadeIn 0.3s; | |
| position: relative; | |
| max-height: 80vh; | |
| overflow-y: auto; | |
| } | |
| .history-item { | |
| display: flex; | |
| justify-content: space-between; | |
| align-items: center; | |
| padding: 10px; | |
| border-bottom: 1px solid #333; | |
| transition: background-color 0.3s ease; | |
| } | |
| .history-item:hover { | |
| background-color: #2a2a2a; | |
| } | |
| .history-item-name { | |
| flex-grow: 1; | |
| margin-right: 10px; | |
| word-break: break-all; | |
| } | |
| .history-item-actions { | |
| display: flex; | |
| gap: 5px; | |
| } | |
| .quick-open-modal { | |
| display: none; | |
| position: fixed; | |
| z-index: 4; | |
| left: 0; | |
| top: 0; | |
| width: 100%; | |
| height: 100%; | |
| background-color: rgba(0,0,0,0.9); | |
| overflow: auto; | |
| } | |
| .quick-open-content { | |
| margin: 5% auto; | |
| padding: 20px; | |
| width: 90%; | |
| max-width: 800px; | |
| text-align: center; | |
| } | |
| .quick-open-content img, | |
| .quick-open-content video, | |
| .quick-open-content audio { | |
| max-width: 100%; | |
| max-height: 70vh; | |
| margin-bottom: 20px; | |
| } | |
| .quick-open-content iframe { | |
| width: 100%; | |
| height: 70vh; | |
| border: none; | |
| } | |
| @media (max-width: 480px) { | |
| .container { | |
| padding: 1.5rem; | |
| } | |
| h1 { | |
| font-size: 1.5rem; | |
| } | |
| .btn, .small-btn { | |
| font-size: 0.9rem; | |
| padding: 10px 20px; | |
| margin: 0.25rem; | |
| } | |
| .file-types { | |
| font-size: 0.7rem; | |
| } | |
| .modal-content, .history-modal-content { | |
| width: 95%; | |
| margin: 5% auto; | |
| padding: 15px; | |
| } | |
| .history-item { | |
| flex-direction: column; | |
| align-items: flex-start; | |
| } | |
| .history-item-actions { | |
| margin-top: 10px; | |
| flex-wrap: wrap; | |
| } | |
| .history-item-name { | |
| font-size: 0.9rem; | |
| } | |
| .drop-zone { | |
| padding: 15px; | |
| } | |
| .drop-zone p { | |
| font-size: 0.9rem; | |
| } | |
| .result-link { | |
| font-size: 0.9rem; | |
| } | |
| .link-buttons { | |
| flex-direction: column; | |
| align-items: stretch; | |
| } | |
| .link-buttons .small-btn { | |
| margin: 0.25rem 0; | |
| } | |
| .close { | |
| top: 5px; | |
| right: 10px; | |
| font-size: 24px; | |
| } | |
| .quick-open-content { | |
| margin: 10% auto; | |
| padding: 10px; | |
| } | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="container"> | |
| <h1>PRO Uploader</h1> | |
| <form id="uploadForm"> | |
| <div id="dropZone" class="drop-zone"> | |
| <input type="file" name="file" id="file" class="file-input" accept="*" required> | |
| <label for="file" class="btn">Choose File</label> | |
| <p>or drag and drop file here/paste image</p> | |
| </div> | |
| <div class="file-name" id="fileName"></div> | |
| <button type="submit" id="uploadBtn" class="btn" style="display: none; margin-top: 1rem;">Upload File</button> | |
| <div class="progress-container" id="progressContainer"></div> | |
| <div class="loading-spinner" id="loadingSpinner"></div> | |
| </form> | |
| <div class="result-container" id="resultContainer"></div> | |
| <div class="file-types"> | |
| All file types are supported | |
| </div> | |
| <div class="history-btn-container"> | |
| <button id="historyBtn" class="history-btn">View Upload History</button> | |
| <button id="clearHistoryBtn" class="clear-history-btn">Clear History</button> | |
| </div> | |
| </div> | |
| <div id="embedModal" class="modal"> | |
| <div class="modal-content"> | |
| <span class="close">×</span> | |
| <h2>Embed Video Link</h2> | |
| <p>copy the link to embed it on discord:</p> | |
| <div class="embed-container"> | |
| <input type="text" id="embedLink" readonly> | |
| <button onclick="copyEmbedLink()" class="small-btn copy-embed-btn">Copy</button> | |
| </div> | |
| </div> | |
| </div> | |
| <div id="historyModal" class="history-modal"> | |
| <div class="history-modal-content"> | |
| <span class="close">×</span> | |
| <h2>Upload History</h2> | |
| <div id="historyList"></div> | |
| </div> | |
| </div> | |
| <div id="quickOpenModal" class="quick-open-modal"> | |
| <div class="quick-open-content"> | |
| <span class="close">×</span> | |
| <div id="quickOpenContent"></div> | |
| </div> | |
| </div> | |
| <script> | |
| const fileInput = document.getElementById('file'); | |
| const fileName = document.getElementById('fileName'); | |
| const uploadForm = document.getElementById('uploadForm'); | |
| const progressContainer = document.getElementById('progressContainer'); | |
| const loadingSpinner = document.getElementById('loadingSpinner'); | |
| const resultContainer = document.getElementById('resultContainer'); | |
| const dropZone = document.getElementById('dropZone'); | |
| const modal = document.getElementById('embedModal'); | |
| const historyModal = document.getElementById('historyModal'); | |
| const quickOpenModal = document.getElementById('quickOpenModal'); | |
| const span = document.getElementsByClassName("close"); | |
| const embedLinkInput = document.getElementById('embedLink'); | |
| const uploadBtn = document.getElementById('uploadBtn'); | |
| const historyBtn = document.getElementById('historyBtn'); | |
| const clearHistoryBtn = document.getElementById('clearHistoryBtn'); | |
| const historyList = document.getElementById('historyList'); | |
| const quickOpenContent = document.getElementById('quickOpenContent'); | |
| fileInput.addEventListener('change', handleFileSelect); | |
| uploadForm.addEventListener('submit', (e) => { | |
| e.preventDefault(); | |
| if (fileInput.files.length > 0) { | |
| uploadFile(fileInput.files[0]); | |
| } | |
| }); | |
| dropZone.addEventListener('dragover', (e) => { | |
| e.preventDefault(); | |
| dropZone.classList.add('drag-over'); | |
| }); | |
| dropZone.addEventListener('dragleave', () => { | |
| dropZone.classList.remove('drag-over'); | |
| }); | |
| dropZone.addEventListener('drop', (e) => { | |
| e.preventDefault(); | |
| dropZone.classList.remove('drag-over'); | |
| handleFileSelect({ target: { files: e.dataTransfer.files } }); | |
| }); | |
| document.addEventListener('paste', (e) => { | |
| const items = e.clipboardData.items; | |
| for (let i = 0; i < items.length; i++) { | |
| if (items[i].kind === 'file') { | |
| const file = items[i].getAsFile(); | |
| handleFileSelect({ target: { files: [file] } }); | |
| break; | |
| } | |
| } | |
| }); | |
| span[0].onclick = function() { | |
| modal.style.display = "none"; | |
| } | |
| span[1].onclick = function() { | |
| historyModal.style.display = "none"; | |
| } | |
| span[2].onclick = function() { | |
| quickOpenModal.style.display = "none"; | |
| } | |
| window.onclick = function(event) { | |
| if (event.target == modal) { | |
| modal.style.display = "none"; | |
| } | |
| if (event.target == historyModal) { | |
| historyModal.style.display = "none"; | |
| } | |
| if (event.target == quickOpenModal) { | |
| quickOpenModal.style.display = "none"; | |
| } | |
| } | |
| historyBtn.onclick = function() { | |
| showHistory(); | |
| } | |
| clearHistoryBtn.onclick = function() { | |
| if (confirm('Are you sure you want to clear your upload history?')) { | |
| localStorage.removeItem('uploadHistory'); | |
| alert('Upload history has been cleared.'); | |
| } | |
| } | |
| function handleFileSelect(e) { | |
| if (e.target.files && e.target.files.length > 0) { | |
| const file = e.target.files[0]; | |
| fileName.textContent = file.name; | |
| uploadBtn.style.display = 'inline-block'; | |
| const dataTransfer = new DataTransfer(); | |
| dataTransfer.items.add(file); | |
| fileInput.files = dataTransfer.files; | |
| } | |
| } | |
| async function uploadFile(file) { | |
| progressContainer.innerHTML = ''; | |
| progressContainer.style.display = 'block'; | |
| loadingSpinner.style.display = 'block'; | |
| uploadBtn.disabled = true; | |
| resultContainer.innerHTML = ''; | |
| resultContainer.style.display = 'none'; | |
| const progressBar = createProgressBar(file.name); | |
| progressContainer.appendChild(progressBar); | |
| const formData = new FormData(); | |
| formData.append('file', file); | |
| while (true) { | |
| try { | |
| const xhr = new XMLHttpRequest(); | |
| xhr.open('POST', '/upload', true); | |
| xhr.upload.onprogress = (event) => updateProgress(event, progressBar.querySelector('.progress')); | |
| xhr.onload = function() { | |
| if (xhr.status === 200) { | |
| const response = JSON.parse(xhr.responseText); | |
| if (response.url) { | |
| addResultLink(response.url, file.name, response.originalExtension); | |
| saveToHistory(file.name, response.url, response.originalExtension); | |
| resetUploadState(); | |
| return; | |
| } else { | |
| throw new Error('Upload failed: ' + response.error); | |
| } | |
| } else { | |
| throw new Error(`HTTP error! status: ${xhr.status}`); | |
| } | |
| }; | |
| xhr.onerror = function() { | |
| throw new Error('Network error occurred'); | |
| }; | |
| xhr.send(formData); | |
| await new Promise((resolve, reject) => { | |
| xhr.onloadend = resolve; | |
| xhr.onerror = reject; | |
| }); | |
| break; | |
| } catch (error) { | |
| console.error('Upload error:', error); | |
| await new Promise(resolve => setTimeout(resolve, 1000)); | |
| } | |
| } | |
| } | |
| function createProgressBar(fileName) { | |
| const progressBarContainer = document.createElement('div'); | |
| progressBarContainer.className = 'progress-bar'; | |
| const progress = document.createElement('div'); | |
| progress.className = 'progress'; | |
| progressBarContainer.appendChild(progress); | |
| const label = document.createElement('div'); | |
| label.textContent = fileName; | |
| label.style.fontSize = '0.8rem'; | |
| label.style.marginBottom = '5px'; | |
| const container = document.createElement('div'); | |
| container.appendChild(label); | |
| container.appendChild(progressBarContainer); | |
| return container; | |
| } | |
| function updateProgress(event, progressBar) { | |
| if (event.lengthComputable) { | |
| const percentComplete = (event.loaded / event.total) * 100; | |
| progressBar.style.width = percentComplete + '%'; | |
| } | |
| } | |
| function resetUploadState() { | |
| fileInput.value = ''; | |
| fileName.textContent = ''; | |
| uploadBtn.style.display = 'none'; | |
| uploadBtn.disabled = false; | |
| loadingSpinner.style.display = 'none'; | |
| } | |
| function addResultLink(url, fileName, originalExtension) { | |
| const linkContainer = document.createElement('div'); | |
| linkContainer.style.marginBottom = '10px'; | |
| const link = document.createElement('a'); | |
| link.href = url; | |
| link.textContent = `View ${fileName}`; | |
| link.className = 'result-link'; | |
| link.target = '_blank'; | |
| link.download = fileName; | |
| linkContainer.appendChild(link); | |
| const buttonsContainer = document.createElement('div'); | |
| buttonsContainer.className = 'link-buttons'; | |
| const copyBtn = document.createElement('button'); | |
| copyBtn.textContent = 'Copy Link'; | |
| copyBtn.className = 'small-btn copy-btn'; | |
| copyBtn.onclick = () => { | |
| navigator.clipboard.writeText(window.location.origin + url).then(() => { | |
| alert('Link copied to clipboard!'); | |
| }); | |
| }; | |
| buttonsContainer.appendChild(copyBtn); | |
| const openBtn = document.createElement('button'); | |
| openBtn.textContent = 'Open'; | |
| openBtn.className = 'small-btn'; | |
| openBtn.onclick = () => { | |
| quickOpen(url, fileName, originalExtension); | |
| }; | |
| buttonsContainer.appendChild(openBtn); | |
| if (originalExtension.toLowerCase() === 'mp4') { | |
| const embedBtn = document.createElement('button'); | |
| embedBtn.textContent = 'Embed Video for Discord'; | |
| embedBtn.className = 'small-btn embed-btn'; | |
| embedBtn.onclick = () => { | |
| showEmbedModal(url); | |
| }; | |
| buttonsContainer.appendChild(embedBtn); | |
| } | |
| linkContainer.appendChild(buttonsContainer); | |
| resultContainer.appendChild(linkContainer); | |
| resultContainer.style.display = 'block'; | |
| } | |
| function showEmbedModal(url) { | |
| const embedUrl = `https://x266.mov/e/${encodeURIComponent(window.location.origin + url)}`; | |
| embedLinkInput.value = embedUrl; | |
| modal.style.display = "block"; | |
| } | |
| function copyEmbedLink() { | |
| embedLinkInput.select(); | |
| document.execCommand('copy'); | |
| alert('Embed link copied to clipboard!'); | |
| } | |
| function saveToHistory(fileName, url, originalExtension) { | |
| let history = JSON.parse(localStorage.getItem('uploadHistory')) || []; | |
| history.unshift({ fileName, url, originalExtension, timestamp: new Date().toISOString() }); | |
| if (history.length > 500) history = history.slice(0, 500); | |
| localStorage.setItem('uploadHistory', JSON.stringify(history)); | |
| } | |
| function showHistory() { | |
| const history = JSON.parse(localStorage.getItem('uploadHistory')) || []; | |
| historyList.innerHTML = ''; | |
| history.forEach(item => { | |
| const historyItem = document.createElement('div'); | |
| historyItem.className = 'history-item'; | |
| const itemName = document.createElement('span'); | |
| itemName.className = 'history-item-name'; | |
| itemName.textContent = item.fileName; | |
| historyItem.appendChild(itemName); | |
| const actionsContainer = document.createElement('div'); | |
| actionsContainer.className = 'history-item-actions'; | |
| const copyBtn = document.createElement('button'); | |
| copyBtn.textContent = 'Copy Link'; | |
| copyBtn.className = 'small-btn'; | |
| copyBtn.onclick = () => { | |
| navigator.clipboard.writeText(window.location.origin + item.url).then(() => { | |
| alert('Link copied to clipboard!'); | |
| }); | |
| }; | |
| actionsContainer.appendChild(copyBtn); | |
| const openBtn = document.createElement('button'); | |
| openBtn.textContent = 'Open'; | |
| openBtn.className = 'small-btn'; | |
| openBtn.onclick = () => { | |
| quickOpen(item.url, item.fileName, item.originalExtension); | |
| }; | |
| actionsContainer.appendChild(openBtn); | |
| if (item.originalExtension.toLowerCase() === 'mp4') { | |
| const embedBtn = document.createElement('button'); | |
| embedBtn.textContent = 'Embed'; | |
| embedBtn.className = 'small-btn'; | |
| embedBtn.onclick = () => { | |
| showEmbedModal(item.url); | |
| historyModal.style.display = "none"; | |
| }; | |
| actionsContainer.appendChild(embedBtn); | |
| } | |
| historyItem.appendChild(actionsContainer); | |
| historyList.appendChild(historyItem); | |
| }); | |
| historyModal.style.display = "block"; | |
| } | |
| function quickOpen(url, fileName, originalExtension) { | |
| quickOpenContent.innerHTML = ''; | |
| const fullUrl = window.location.origin + url; | |
| if (['jpeg', 'jpg', 'gif', 'png'].includes(originalExtension.toLowerCase())) { | |
| const img = document.createElement('img'); | |
| img.src = fullUrl; | |
| img.alt = fileName; | |
| quickOpenContent.appendChild(img); | |
| } else if (originalExtension.toLowerCase() === 'mp4') { | |
| const video = document.createElement('video'); | |
| video.src = fullUrl; | |
| video.controls = true; | |
| quickOpenContent.appendChild(video); | |
| } else if (originalExtension.toLowerCase() === 'mp3') { | |
| const audio = document.createElement('audio'); | |
| audio.src = fullUrl; | |
| audio.controls = true; | |
| quickOpenContent.appendChild(audio); | |
| } else if (originalExtension.toLowerCase() === 'pdf') { | |
| const iframe = document.createElement('iframe'); | |
| iframe.src = fullUrl; | |
| quickOpenContent.appendChild(iframe); | |
| } else if (originalExtension.toLowerCase() === 'txt') { | |
| fetch(fullUrl) | |
| .then(response => response.text()) | |
| .then(text => { | |
| const pre = document.createElement('pre'); | |
| pre.textContent = text; | |
| quickOpenContent.appendChild(pre); | |
| }); | |
| } else { | |
| const link = document.createElement('a'); | |
| link.href = fullUrl; | |
| link.textContent = 'Download ' + fileName; | |
| link.target = '_blank'; | |
| link.download = fileName; | |
| quickOpenContent.appendChild(link); | |
| } | |
| quickOpenModal.style.display = "block"; | |
| } | |
| </script> | |
| </body> | |
| </html> | |
| """ | |
| async def index(): | |
| return HTML_CONTENT | |
| async def handle_upload(file: UploadFile = File(...)): | |
| if not file.filename: | |
| return JSONResponse(content={"error": "No file selected."}, status_code=400) | |
| cookies = await get_cookies() | |
| if 'csrftoken' not in cookies or 'sessionid' not in cookies: | |
| return JSONResponse(content={"error": "Failed"}, status_code=500) | |
| original_extension = os.path.splitext(file.filename)[1][1:] | |
| supported_types = ['mp4', 'png', 'jpg', 'jpeg', 'gif', 'mp3', 'pdf', 'txt'] | |
| if original_extension.lower() in supported_types: | |
| temp_filename = file.filename | |
| content_type = file.content_type | |
| else: | |
| temp_filename = f"{file.filename}.png" | |
| content_type = "image/png" | |
| upload_result = await initiate_upload(cookies, temp_filename, content_type) | |
| if not upload_result or 'upload_url' not in upload_result: | |
| return JSONResponse(content={"error": "Failed to upload"}, status_code=500) | |
| file_content = await file.read() | |
| upload_success = await retry_upload(upload_result['upload_url'], file_content, content_type) | |
| if not upload_success: | |
| return JSONResponse(content={"error": "FAILED GOD MAN AFTER alot of attempts"}, status_code=500) | |
| original_url = upload_result['serving_url'] | |
| mirrored_url = f"/upload/{original_url.split('/pbxt/')[1]}" | |
| if original_extension.lower() not in supported_types: | |
| mirrored_url = mirrored_url.replace('.png', '') | |
| return JSONResponse(content={"url": mirrored_url, "originalExtension": original_extension}) | |
| async def handle_file_stream(path: str, request: Request): | |
| original_url = f'https://replicate.delivery/pbxt/{path}' | |
| if not path.lower().endswith(('.png', '.jpg', '.jpeg', '.gif', '.mp4', '.mp3', '.pdf', '.txt')): | |
| original_url += '.png' | |
| range_header = request.headers.get('Range') | |
| headers = {'Range': range_header} if range_header else {} | |
| response = requests.get(original_url, headers=headers, stream=True) | |
| def generate(): | |
| for chunk in response.iter_content(chunk_size=8192): | |
| yield chunk | |
| headers = dict(response.headers) | |
| headers['Access-Control-Allow-Origin'] = '*' | |
| headers['Content-Disposition'] = 'inline' | |
| if response.status_code == 206: | |
| headers['Content-Range'] = response.headers.get('Content-Range') | |
| original_extension = os.path.splitext(path)[1][1:] | |
| content_type, _ = mimetypes.guess_type(f"file.{original_extension}") | |
| if content_type: | |
| headers['Content-Type'] = content_type | |
| return StreamingResponse(generate(), status_code=response.status_code, headers=headers) | |
| async def embed_video(url: str, thumbnail: str): | |
| html = f''' | |
| <html> | |
| <head> | |
| <meta property="og:type" content="video.other"> | |
| <meta property="og:video" content="{url}"> | |
| <meta property="og:video:url" content="{url}"> | |
| <meta property="og:video:secure_url" content="{url}"> | |
| <meta property="og:video:type" content="video/mp4"> | |
| <meta property="og:video:width" content="1280"> | |
| <meta property="og:video:height" content="720"> | |
| <meta property="og:image" content="{thumbnail}"> | |
| <meta property="og:image:secure_url" content="{thumbnail}"> | |
| <meta property="og:image:width" content="1280"> | |
| <meta property="og:image:height" content="720"> | |
| <meta property="og:image:type" content="image/png"> | |
| <style> | |
| body, html {{ margin: 0; padding: 0; height: 100%; background: #000; }} | |
| #thumbnail {{ width: 100%; height: 100%; object-fit: contain; cursor: pointer; }} | |
| #video {{ display: none; width: 100%; height: 100%; object-fit: contain; }} | |
| </style> | |
| </head> | |
| <body> | |
| <img id="thumbnail" src="{thumbnail}" onclick="playVideo()"> | |
| <video id="video" controls autoplay> | |
| <source src="{url}" type="video/mp4"> | |
| Your browser does not support the video tag. | |
| </video> | |
| <script> | |
| function playVideo() {{ | |
| document.getElementById('thumbnail').style.display = 'none'; | |
| document.getElementById('video').style.display = 'block'; | |
| document.getElementById('video').play(); | |
| }} | |
| </script> | |
| </body> | |
| </html> | |
| ''' | |
| return HTMLResponse(content=html) | |
| async def get_cookies() -> Dict[str, str]: | |
| try: | |
| response = requests.get('https://replicate.com/levelsio/neon-tokyo', headers={ | |
| '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' | |
| }) | |
| return dict(response.cookies) | |
| except Exception as e: | |
| print(f'Error fetching the page: {e}') | |
| return {} | |
| async def initiate_upload(cookies: Dict[str, str], filename: str, content_type: str) -> Dict: | |
| url = f'https://replicate.com/api/upload/{filename}?content_type={content_type}' | |
| try: | |
| response = requests.post(url, cookies=cookies, headers={ | |
| 'X-CSRFToken': cookies.get('csrftoken'), | |
| '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', | |
| 'Referer': 'https://replicate.com/levelsio/neon-tokyo', | |
| 'Origin': 'https://replicate.com', | |
| 'Accept': '*/*', | |
| 'Accept-Language': 'en-US,en;q=0.5', | |
| 'Accept-Encoding': 'identity', | |
| 'Sec-Fetch-Dest': 'empty', | |
| 'Sec-Fetch-Mode': 'cors', | |
| 'Sec-Fetch-Site': 'same-origin', | |
| 'Sec-GPC': '1', | |
| 'Priority': 'u=1, i' | |
| }) | |
| return response.json() | |
| except Exception as e: | |
| print(f'Error initiating upload: {e}') | |
| raise | |
| async def upload_file(upload_url: str, file_content: bytes, content_type: str) -> bool: | |
| try: | |
| response = requests.put(upload_url, data=file_content, headers={'Content-Type': content_type}) | |
| return response.status_code == 200 | |
| except Exception as e: | |
| print(f'Error uploading file: {e}') | |
| return False | |
| async def retry_upload(upload_url: str, file_content: bytes, content_type: str, max_retries: int = 5, delay: int = 1) -> bool: | |
| while True: | |
| try: | |
| success = await upload_file(upload_url, file_content, content_type) | |
| if success: | |
| return True | |
| print("Upload failed. Retrying...") | |
| except Exception as e: | |
| print(f"Error during upload: {e}") | |
| await asyncio.sleep(delay) | |
| delay = min(delay * 2, 60) | |
| return False | |