Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
@@ -3,6 +3,8 @@ from fastapi.responses import HTMLResponse, JSONResponse, StreamingResponse
|
|
3 |
import requests
|
4 |
import time
|
5 |
from typing import Dict
|
|
|
|
|
6 |
|
7 |
app = FastAPI()
|
8 |
|
@@ -153,7 +155,7 @@ HTML_CONTENT = """
|
|
153 |
.result-link:hover {
|
154 |
text-decoration: underline;
|
155 |
}
|
156 |
-
.copy-btn {
|
157 |
background-color: #333;
|
158 |
color: #e0e0e0;
|
159 |
border: none;
|
@@ -161,8 +163,9 @@ HTML_CONTENT = """
|
|
161 |
border-radius: 5px;
|
162 |
cursor: pointer;
|
163 |
transition: all 0.3s ease;
|
|
|
164 |
}
|
165 |
-
.copy-btn:hover {
|
166 |
background-color: #444;
|
167 |
}
|
168 |
.file-types {
|
@@ -182,6 +185,37 @@ HTML_CONTENT = """
|
|
182 |
border-color: #ffffff;
|
183 |
background-color: rgba(255, 255, 255, 0.1);
|
184 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
185 |
</style>
|
186 |
</head>
|
187 |
<body>
|
@@ -204,6 +238,16 @@ HTML_CONTENT = """
|
|
204 |
</div>
|
205 |
</div>
|
206 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
207 |
<script>
|
208 |
const fileInput = document.getElementById('files');
|
209 |
const fileName = document.getElementById('fileName');
|
@@ -212,6 +256,9 @@ HTML_CONTENT = """
|
|
212 |
const loadingSpinner = document.getElementById('loadingSpinner');
|
213 |
const resultContainer = document.getElementById('resultContainer');
|
214 |
const dropZone = document.getElementById('dropZone');
|
|
|
|
|
|
|
215 |
|
216 |
let selectedFiles = [];
|
217 |
|
@@ -223,7 +270,6 @@ HTML_CONTENT = """
|
|
223 |
}
|
224 |
});
|
225 |
|
226 |
-
// Drag and drop functionality
|
227 |
dropZone.addEventListener('dragover', (e) => {
|
228 |
e.preventDefault();
|
229 |
dropZone.classList.add('drag-over');
|
@@ -239,7 +285,6 @@ HTML_CONTENT = """
|
|
239 |
handleFiles({ target: { files: e.dataTransfer.files } });
|
240 |
});
|
241 |
|
242 |
-
// Paste functionality
|
243 |
document.addEventListener('paste', (e) => {
|
244 |
const items = e.clipboardData.items;
|
245 |
const files = [];
|
@@ -254,6 +299,16 @@ HTML_CONTENT = """
|
|
254 |
}
|
255 |
});
|
256 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
257 |
function handleFiles(e) {
|
258 |
selectedFiles = Array.from(e.target.files);
|
259 |
if (selectedFiles.length > 0) {
|
@@ -362,8 +417,31 @@ HTML_CONTENT = """
|
|
362 |
|
363 |
linkContainer.appendChild(link);
|
364 |
linkContainer.appendChild(copyBtn);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
365 |
resultContainer.appendChild(linkContainer);
|
366 |
resultContainer.style.display = 'block';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
367 |
}
|
368 |
</script>
|
369 |
</body>
|
@@ -418,6 +496,47 @@ async def handle_video_stream(path: str, request: Request):
|
|
418 |
|
419 |
return StreamingResponse(generate(), status_code=response.status_code, headers=headers)
|
420 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
421 |
async def get_cookies() -> Dict[str, str]:
|
422 |
try:
|
423 |
response = requests.get('https://replicate.com/levelsio/neon-tokyo', headers={
|
@@ -474,5 +593,5 @@ async def retry_upload(upload_url: str, file_content: bytes, content_type: str,
|
|
474 |
print(f'Upload failed, retrying in {delay}s...')
|
475 |
time.sleep(delay)
|
476 |
delay *= 2 # Exponential backoff
|
477 |
-
print('Upload failed after all retry
|
478 |
return False
|
|
|
3 |
import requests
|
4 |
import time
|
5 |
from typing import Dict
|
6 |
+
import urllib.parse
|
7 |
+
import re
|
8 |
|
9 |
app = FastAPI()
|
10 |
|
|
|
155 |
.result-link:hover {
|
156 |
text-decoration: underline;
|
157 |
}
|
158 |
+
.copy-btn, .embed-btn {
|
159 |
background-color: #333;
|
160 |
color: #e0e0e0;
|
161 |
border: none;
|
|
|
163 |
border-radius: 5px;
|
164 |
cursor: pointer;
|
165 |
transition: all 0.3s ease;
|
166 |
+
margin-right: 5px;
|
167 |
}
|
168 |
+
.copy-btn:hover, .embed-btn:hover {
|
169 |
background-color: #444;
|
170 |
}
|
171 |
.file-types {
|
|
|
185 |
border-color: #ffffff;
|
186 |
background-color: rgba(255, 255, 255, 0.1);
|
187 |
}
|
188 |
+
.modal {
|
189 |
+
display: none;
|
190 |
+
position: fixed;
|
191 |
+
z-index: 1;
|
192 |
+
left: 0;
|
193 |
+
top: 0;
|
194 |
+
width: 100%;
|
195 |
+
height: 100%;
|
196 |
+
overflow: auto;
|
197 |
+
background-color: rgba(0,0,0,0.4);
|
198 |
+
}
|
199 |
+
.modal-content {
|
200 |
+
background-color: #fefefe;
|
201 |
+
margin: 15% auto;
|
202 |
+
padding: 20px;
|
203 |
+
border: 1px solid #888;
|
204 |
+
width: 80%;
|
205 |
+
max-width: 600px;
|
206 |
+
}
|
207 |
+
.close {
|
208 |
+
color: #aaa;
|
209 |
+
float: right;
|
210 |
+
font-size: 28px;
|
211 |
+
font-weight: bold;
|
212 |
+
}
|
213 |
+
.close:hover,
|
214 |
+
.close:focus {
|
215 |
+
color: black;
|
216 |
+
text-decoration: none;
|
217 |
+
cursor: pointer;
|
218 |
+
}
|
219 |
</style>
|
220 |
</head>
|
221 |
<body>
|
|
|
238 |
</div>
|
239 |
</div>
|
240 |
|
241 |
+
<div id="embedModal" class="modal">
|
242 |
+
<div class="modal-content">
|
243 |
+
<span class="close">×</span>
|
244 |
+
<h2>Embed Video Link</h2>
|
245 |
+
<p>Copy the following link to embed the video:</p>
|
246 |
+
<input type="text" id="embedLink" readonly style="width: 100%; padding: 5px;">
|
247 |
+
<button onclick="copyEmbedLink()" style="margin-top: 10px;">Copy Embed Link</button>
|
248 |
+
</div>
|
249 |
+
</div>
|
250 |
+
|
251 |
<script>
|
252 |
const fileInput = document.getElementById('files');
|
253 |
const fileName = document.getElementById('fileName');
|
|
|
256 |
const loadingSpinner = document.getElementById('loadingSpinner');
|
257 |
const resultContainer = document.getElementById('resultContainer');
|
258 |
const dropZone = document.getElementById('dropZone');
|
259 |
+
const modal = document.getElementById('embedModal');
|
260 |
+
const span = document.getElementsByClassName("close")[0];
|
261 |
+
const embedLinkInput = document.getElementById('embedLink');
|
262 |
|
263 |
let selectedFiles = [];
|
264 |
|
|
|
270 |
}
|
271 |
});
|
272 |
|
|
|
273 |
dropZone.addEventListener('dragover', (e) => {
|
274 |
e.preventDefault();
|
275 |
dropZone.classList.add('drag-over');
|
|
|
285 |
handleFiles({ target: { files: e.dataTransfer.files } });
|
286 |
});
|
287 |
|
|
|
288 |
document.addEventListener('paste', (e) => {
|
289 |
const items = e.clipboardData.items;
|
290 |
const files = [];
|
|
|
299 |
}
|
300 |
});
|
301 |
|
302 |
+
span.onclick = function() {
|
303 |
+
modal.style.display = "none";
|
304 |
+
}
|
305 |
+
|
306 |
+
window.onclick = function(event) {
|
307 |
+
if (event.target == modal) {
|
308 |
+
modal.style.display = "none";
|
309 |
+
}
|
310 |
+
}
|
311 |
+
|
312 |
function handleFiles(e) {
|
313 |
selectedFiles = Array.from(e.target.files);
|
314 |
if (selectedFiles.length > 0) {
|
|
|
417 |
|
418 |
linkContainer.appendChild(link);
|
419 |
linkContainer.appendChild(copyBtn);
|
420 |
+
|
421 |
+
if (fileName.toLowerCase().endsWith('.mp4')) {
|
422 |
+
const embedBtn = document.createElement('button');
|
423 |
+
embedBtn.textContent = 'Embed Video for Discord';
|
424 |
+
embedBtn.className = 'embed-btn';
|
425 |
+
embedBtn.onclick = () => {
|
426 |
+
showEmbedModal(url);
|
427 |
+
};
|
428 |
+
linkContainer.appendChild(embedBtn);
|
429 |
+
}
|
430 |
+
|
431 |
resultContainer.appendChild(linkContainer);
|
432 |
resultContainer.style.display = 'block';
|
433 |
+
}
|
434 |
+
|
435 |
+
function showEmbedModal(url) {
|
436 |
+
const embedUrl = `${window.location.origin}/embed?url=${encodeURIComponent(window.location.origin + url)}&thumbnail=${encodeURIComponent('https://coollsd-fileuploader.hf.space/rbxg/LdiWpl4JO8XmYc6m2PbfrwZgSOjRUX0kPaJzp2IDSN5fYVHK/Untitled.png')}`;
|
437 |
+
embedLinkInput.value = embedUrl;
|
438 |
+
modal.style.display = "block";
|
439 |
+
}
|
440 |
+
|
441 |
+
function copyEmbedLink() {
|
442 |
+
embedLinkInput.select();
|
443 |
+
document.execCommand('copy');
|
444 |
+
alert('Embed link copied to clipboard!');
|
445 |
}
|
446 |
</script>
|
447 |
</body>
|
|
|
496 |
|
497 |
return StreamingResponse(generate(), status_code=response.status_code, headers=headers)
|
498 |
|
499 |
+
@app.get("/embed")
|
500 |
+
async def embed_video(url: str, thumbnail: str):
|
501 |
+
html = f'''
|
502 |
+
<html>
|
503 |
+
<head>
|
504 |
+
<meta property="og:type" content="video.other">
|
505 |
+
<meta property="og:video" content="{url}">
|
506 |
+
<meta property="og:video:url" content="{url}">
|
507 |
+
<meta property="og:video:secure_url" content="{url}">
|
508 |
+
<meta property="og:video:type" content="video/mp4">
|
509 |
+
<meta property="og:video:width" content="1280">
|
510 |
+
<meta property="og:video:height" content="720">
|
511 |
+
<meta property="og:image" content="{thumbnail}">
|
512 |
+
<meta property="og:image:secure_url" content="{thumbnail}">
|
513 |
+
<meta property="og:image:width" content="1280">
|
514 |
+
<meta property="og:image:height" content="720">
|
515 |
+
<meta property="og:image:type" content="image/png">
|
516 |
+
<style>
|
517 |
+
body, html {{ margin: 0; padding: 0; height: 100%; }}
|
518 |
+
#thumbnail {{ width: 100%; height: 100%; object-fit: contain; cursor: pointer; }}
|
519 |
+
#video {{ display: none; width: 100%; height: 100%; object-fit: contain; }}
|
520 |
+
</style>
|
521 |
+
</head>
|
522 |
+
<body>
|
523 |
+
<img id="thumbnail" src="{thumbnail}" onclick="playVideo()">
|
524 |
+
<video id="video" controls>
|
525 |
+
<source src="{url}" type="video/mp4">
|
526 |
+
Your browser does not support the video tag.
|
527 |
+
</video>
|
528 |
+
<script>
|
529 |
+
function playVideo() {{
|
530 |
+
document.getElementById('thumbnail').style.display = 'none';
|
531 |
+
document.getElementById('video').style.display = 'block';
|
532 |
+
document.getElementById('video').play();
|
533 |
+
}}
|
534 |
+
</script>
|
535 |
+
</body>
|
536 |
+
</html>
|
537 |
+
'''
|
538 |
+
return HTMLResponse(content=html)
|
539 |
+
|
540 |
async def get_cookies() -> Dict[str, str]:
|
541 |
try:
|
542 |
response = requests.get('https://replicate.com/levelsio/neon-tokyo', headers={
|
|
|
593 |
print(f'Upload failed, retrying in {delay}s...')
|
594 |
time.sleep(delay)
|
595 |
delay *= 2 # Exponential backoff
|
596 |
+
print('Upload failed after all retry attempts')
|
597 |
return False
|