coollsd commited on
Commit
aa79c07
1 Parent(s): 2c943e0

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +238 -138
app.py CHANGED
@@ -3,8 +3,6 @@ from fastapi.responses import HTMLResponse, JSONResponse, StreamingResponse
3
  import requests
4
  import time
5
  from typing import Dict
6
- import urllib.parse
7
- import re
8
 
9
  app = FastAPI()
10
 
@@ -13,106 +11,158 @@ HTML_CONTENT = """
13
  <html lang="en">
14
  <head>
15
  <meta charset="UTF-8">
16
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
17
  <title>Radd PRO Uploader</title>
18
  <link href="https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;600&display=swap" rel="stylesheet">
19
  <style>
 
20
  body {
21
  font-family: 'Poppins', sans-serif;
22
- background: #121212;
23
- height: 100vh;
24
- margin: 0;
25
- display: flex;
26
- justify-content: center;
27
- align-items: center;
28
  color: #e0e0e0;
 
 
 
29
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
30
  .container {
31
- background: rgba(255, 255, 255, 0.1);
32
- padding: 2.5rem;
 
 
 
 
33
  border-radius: 15px;
34
- box-shadow: 0 0 20px rgba(255, 255, 255, 0.2);
35
- backdrop-filter: blur(4px);
36
- border: 1px solid rgba(255, 255, 255, 0.18);
37
  text-align: center;
38
- max-width: 450px;
39
- width: 100%;
40
- transition: all 0.3s ease;
41
- }
42
- .container:hover {
43
- background: rgba(255, 255, 255, 0.2);
44
- transform: translateY(-5px);
45
- box-shadow: 0 0 30px rgba(255, 255, 255, 0.3);
46
  }
47
- h1, h2 {
 
 
 
48
  color: #ffffff;
49
- margin-bottom: 1.5rem;
50
- font-weight: 600;
51
- }
52
- .file-input {
53
- display: none;
54
  }
 
 
55
  .btn {
56
- background-color: #ffffff;
57
- color: #121212;
58
- padding: 12px 24px;
59
- border-radius: 5px;
60
- cursor: pointer;
61
- transition: all 0.3s ease;
62
  display: inline-block;
 
 
 
 
63
  font-weight: 600;
 
 
64
  border: none;
65
- font-size: 1rem;
66
- margin: 0.5rem;
67
- position: relative;
68
  overflow: hidden;
 
 
 
 
 
 
69
  }
70
- .btn::after {
 
71
  content: '';
72
  position: absolute;
73
- top: 50%;
74
- left: 50%;
75
- width: 5px;
76
- height: 5px;
77
- background: rgba(0, 0, 0, 0.3);
78
- opacity: 0;
79
- border-radius: 100%;
80
- transform: scale(1, 1) translate(-50%);
81
- transform-origin: 50% 50%;
82
- }
83
- @keyframes ripple {
 
 
84
  0% {
85
- transform: scale(0, 0);
86
- opacity: 1;
87
  }
88
- 20% {
89
- transform: scale(25, 25);
90
- opacity: 1;
91
  }
92
  100% {
93
- opacity: 0;
94
- transform: scale(40, 40);
95
  }
96
  }
97
- .btn:focus:not(:active)::after {
98
- animation: ripple 1s ease-out;
99
- }
100
- .btn:hover {
101
- background-color: #f0f0f0;
102
  }
 
103
  .btn:disabled {
104
- background-color: #555;
105
  cursor: not-allowed;
106
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
107
  .file-name {
108
  margin-top: 1rem;
109
  font-size: 0.9rem;
110
  color: #aaa;
111
  }
 
 
112
  .progress-container {
113
- margin-top: 1.5rem;
114
  display: none;
 
115
  }
 
116
  .progress-bar {
117
  width: 100%;
118
  height: 10px;
@@ -121,12 +171,20 @@ HTML_CONTENT = """
121
  overflow: hidden;
122
  margin-bottom: 10px;
123
  }
 
124
  .progress {
125
  width: 0%;
126
  height: 100%;
127
- background-color: #ffffff;
128
- transition: width 0.3s ease;
129
  }
 
 
 
 
 
 
 
130
  .loading-spinner {
131
  display: none;
132
  width: 40px;
@@ -137,14 +195,18 @@ HTML_CONTENT = """
137
  animation: spin 1s linear infinite;
138
  margin: 20px auto;
139
  }
 
140
  @keyframes spin {
141
  0% { transform: rotate(0deg); }
142
  100% { transform: rotate(360deg); }
143
  }
 
 
144
  .result-container {
145
  display: none;
146
  margin-top: 1.5rem;
147
  }
 
148
  .result-link {
149
  color: #ffffff;
150
  text-decoration: none;
@@ -152,43 +214,64 @@ HTML_CONTENT = """
152
  transition: all 0.3s ease;
153
  margin-right: 10px;
154
  }
 
155
  .result-link:hover {
156
  text-decoration: underline;
157
  }
 
158
  .copy-btn, .embed-btn {
159
- background-color: #333;
160
- color: #e0e0e0;
 
 
 
 
 
161
  border: none;
162
- padding: 5px 10px;
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 {
172
  margin-top: 2rem;
173
  font-size: 0.8rem;
174
  color: #aaa;
175
  }
176
- .drop-zone {
177
- border: 2px dashed #aaa;
178
- border-radius: 10px;
179
- padding: 20px;
180
- text-align: center;
181
- cursor: pointer;
182
- transition: all 0.3s ease;
183
- }
184
- .drop-zone:hover, .drop-zone.drag-over {
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%;
@@ -196,6 +279,7 @@ HTML_CONTENT = """
196
  overflow: auto;
197
  background-color: rgba(0,0,0,0.8);
198
  }
 
199
  .modal-content {
200
  background-color: #1e1e1e;
201
  margin: 15% auto;
@@ -206,78 +290,103 @@ HTML_CONTENT = """
206
  border-radius: 10px;
207
  color: #e0e0e0;
208
  animation: modalFadeIn 0.3s;
 
209
  }
 
210
  @keyframes modalFadeIn {
211
  from {opacity: 0; transform: scale(0.8);}
212
  to {opacity: 1; transform: scale(1);}
213
  }
 
214
  .close {
215
  color: #aaa;
216
- float: right;
 
 
217
  font-size: 28px;
218
  font-weight: bold;
219
  transition: color 0.3s ease;
220
  }
 
221
  .close:hover,
222
  .close:focus {
223
  color: #fff;
224
  text-decoration: none;
225
  cursor: pointer;
226
  }
 
 
 
 
 
 
 
227
  #embedLink {
228
- width: 100%;
229
  padding: 10px;
230
- margin-top: 10px;
231
  background-color: #333;
232
  border: 1px solid #555;
233
  color: #e0e0e0;
234
  border-radius: 5px;
235
- text-align: center;
236
  }
237
- .embed-btn {
 
238
  position: relative;
 
 
 
 
 
 
 
 
239
  overflow: hidden;
 
 
240
  }
241
- .embed-btn::before {
 
242
  content: '';
243
  position: absolute;
244
- top: -50%;
245
- left: -50%;
246
- width: 200%;
247
- height: 200%;
248
- background: radial-gradient(circle, rgba(255,255,255,0.3) 0%, rgba(255,255,255,0) 70%);
249
- transform: scale(0);
250
- transition: transform 0.3s ease-out;
251
- }
252
- .embed-btn:hover::before {
253
- transform: scale(1);
254
- }
255
- .copy-embed-btn {
256
- background-color: #333;
257
- color: white;
258
- border: none;
259
- padding: 10px 20px;
260
- text-align: center;
261
- text-decoration: none;
262
- display: inline-block;
263
- font-size: 16px;
264
- margin: 4px 2px;
265
- transition-duration: 0.4s;
266
- cursor: pointer;
267
  border-radius: 5px;
 
 
 
 
 
 
 
 
268
  }
 
269
  .copy-embed-btn:hover {
270
- background-color: #444;
271
  }
272
- .embed-container {
273
- display: flex;
274
- align-items: center;
275
- justify-content: space-between;
276
- margin-top: 15px;
277
  }
278
- #embedLink {
279
- flex-grow: 1;
280
- margin-right: 10px;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
281
  }
282
  </style>
283
  </head>
@@ -438,7 +547,7 @@ HTML_CONTENT = """
438
  }
439
  }
440
 
441
- function resetUploadState() {
442
  fileInput.value = '';
443
  fileName.textContent = '';
444
  document.getElementById('uploadBtn').style.display = 'none';
@@ -449,13 +558,13 @@ HTML_CONTENT = """
449
  function addResultLink(url, fileName) {
450
  const linkContainer = document.createElement('div');
451
  linkContainer.style.marginBottom = '10px';
452
-
453
  const link = document.createElement('a');
454
  link.href = url;
455
  link.textContent = `View ${fileName}`;
456
  link.className = 'result-link';
457
  link.target = '_blank';
458
-
459
  const copyBtn = document.createElement('button');
460
  copyBtn.textContent = 'Copy Link';
461
  copyBtn.className = 'copy-btn';
@@ -464,7 +573,7 @@ HTML_CONTENT = """
464
  alert('Link copied to clipboard!');
465
  });
466
  };
467
-
468
  linkContainer.appendChild(link);
469
  linkContainer.appendChild(copyBtn);
470
 
@@ -483,7 +592,7 @@ HTML_CONTENT = """
483
  }
484
 
485
  function showEmbedModal(url) {
486
- const embedUrl = `${window.location.origin}/embed?url=${encodeURIComponent(window.location.origin + url)}&thumbnail=${encodeURIComponent('https://coollsd-fileuploader.hf.space/rbxg/LdiWpl4JO8XmYc6m2PbfrwZgSOjRUX0kPaJzp2IDSN5fYVHK/Untitled.png')}`;
487
  embedLinkInput.value = embedUrl;
488
  modal.style.display = "block";
489
  }
@@ -564,7 +673,7 @@ async def embed_video(url: str, thumbnail: str):
564
  <meta property="og:image:height" content="720">
565
  <meta property="og:image:type" content="image/png">
566
  <style>
567
- body, html {{ margin: 0; padding: 0; height: 100%; }}
568
  #thumbnail {{ width: 100%; height: 100%; object-fit: contain; cursor: pointer; }}
569
  #video {{ display: none; width: 100%; height: 100%; object-fit: contain; }}
570
  </style>
@@ -614,9 +723,6 @@ async def initiate_upload(cookies: Dict[str, str], filename: str, content_type:
614
  'Sec-GPC': '1',
615
  'Priority': 'u=1, i'
616
  })
617
- print(f'Initiate upload response status: {response.status_code}')
618
- print(f'Initiate upload response headers: {response.headers}')
619
- print(f'Response body: {response.text}')
620
  return response.json()
621
  except Exception as e:
622
  print(f'Error initiating upload: {e}')
@@ -625,8 +731,6 @@ async def initiate_upload(cookies: Dict[str, str], filename: str, content_type:
625
  async def upload_file(upload_url: str, file_content: bytes, content_type: str) -> bool:
626
  try:
627
  response = requests.put(upload_url, data=file_content, headers={'Content-Type': content_type})
628
- print(f'File upload response status: {response.status_code}')
629
- print(f'File upload response headers: {response.headers}')
630
  return response.status_code == 200
631
  except Exception as e:
632
  print(f'Error uploading file: {e}')
@@ -634,14 +738,10 @@ async def upload_file(upload_url: str, file_content: bytes, content_type: str) -
634
 
635
  async def retry_upload(upload_url: str, file_content: bytes, content_type: str, max_retries: int = 5, delay: int = 1) -> bool:
636
  for attempt in range(1, max_retries + 1):
637
- print(f'Upload attempt {attempt} of {max_retries}')
638
  success = await upload_file(upload_url, file_content, content_type)
639
  if success:
640
- print('Upload successful')
641
  return True
642
  if attempt < max_retries:
643
- print(f'Upload failed, retrying in {delay}s...')
644
  time.sleep(delay)
645
  delay *= 2 # Exponential backoff
646
- print('Upload failed after all retry attempts')
647
  return False
 
3
  import requests
4
  import time
5
  from typing import Dict
 
 
6
 
7
  app = FastAPI()
8
 
 
11
  <html lang="en">
12
  <head>
13
  <meta charset="UTF-8">
 
14
  <title>Radd PRO Uploader</title>
15
  <link href="https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;600&display=swap" rel="stylesheet">
16
  <style>
17
+ /* Global Styles */
18
  body {
19
  font-family: 'Poppins', sans-serif;
20
+ background-color: #121212;
 
 
 
 
 
21
  color: #e0e0e0;
22
+ margin: 0;
23
+ height: 100vh;
24
+ overflow: hidden;
25
  }
26
+
27
+ /* Moving Grainy Background */
28
+ body::before {
29
+ content: "";
30
+ position: fixed;
31
+ top: 0;
32
+ left: 0;
33
+ width: 100%;
34
+ height: 100%;
35
+ background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADwAAAA8CAQAAACM/9unAAAACXBIWXMAAAsTAAALEwEAmpwYAAABF0lEQVR4nO3YMRLCQBRE0clsYgxZwwq7oLGxAgp2AtbsqQZsYgEG0wEWc/LSZnb9HcMjR8fHvEKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgsK8tJOq9fzs7vlkNlWvf5ELi+20t5k2VSL7p/iHJ5Rz5ynOhU7rQ4pUi+6b4hyeUc+cpzoVO60OkV7rQ4pUi+6b4hxenu+en4rQAOkaks/eJegGaUfOHI+nRvQCND1w2J9yf8C2KZwNjkeUsAKRa7Nz50tQAokVbO/U6AaiWjl5wd6kQAOke8Xpx3JgTQKVq7Heh0ADpFvF6cd0kE0Claux3odAA6RfxenHc+BNCpWrsd6HQAOkX8Xpx3PgTQqVq7Heh0ADpF/F6cdz4E0KlarjdI/cR1FBQUGBgYGBgYGBgYG/AT4AIHph6aQGU7oAAAAASUVORK5CYII=') repeat;
36
+ animation: grain 8s steps(10) infinite;
37
+ opacity: 0.2;
38
+ pointer-events: none;
39
+ }
40
+
41
+ @keyframes grain {
42
+ 0% { transform: translate(0, 0); }
43
+ 10% { transform: translate(-5%, -5%); }
44
+ 20% { transform: translate(-10%, 5%); }
45
+ 30% { transform: translate(5%, -10%); }
46
+ 40% { transform: translate(-5%, 15%); }
47
+ 50% { transform: translate(-10%, 5%); }
48
+ 60% { transform: translate(15%, 0); }
49
+ 70% { transform: translate(0, 10%); }
50
+ 80% { transform: translate(-15%, 0); }
51
+ 90% { transform: translate(10%, 5%); }
52
+ 100% { transform: translate(5%, 0); }
53
+ }
54
+
55
  .container {
56
+ position: relative;
57
+ max-width: 450px;
58
+ margin: 0 auto;
59
+ padding: 3rem 2rem;
60
+ background: rgba(18, 18, 18, 0.9);
61
+ backdrop-filter: blur(10px);
62
  border-radius: 15px;
63
+ z-index: 1;
 
 
64
  text-align: center;
65
+ box-shadow: 0 0 20px rgba(0, 0, 0, 0.8);
 
 
 
 
 
 
 
66
  }
67
+
68
+ h1 {
69
+ margin-bottom: 2rem;
70
+ font-size: 2rem;
71
  color: #ffffff;
72
+ text-shadow: 0 0 5px rgba(255, 255, 255, 0.2);
 
 
 
 
73
  }
74
+
75
+ /* Buttons */
76
  .btn {
 
 
 
 
 
 
77
  display: inline-block;
78
+ position: relative;
79
+ padding: 12px 24px;
80
+ margin: 0.5rem;
81
+ font-size: 1rem;
82
  font-weight: 600;
83
+ color: #ffffff;
84
+ background-color: transparent;
85
  border: none;
86
+ border-radius: 5px;
87
+ cursor: pointer;
 
88
  overflow: hidden;
89
+ z-index: 1;
90
+ transition: color 0.3s ease;
91
+ }
92
+
93
+ .btn:hover {
94
+ color: #e0e0e0;
95
  }
96
+
97
+ .btn::before {
98
  content: '';
99
  position: absolute;
100
+ inset: 0;
101
+ border-radius: 5px;
102
+ padding: 3px;
103
+ background: linear-gradient(45deg, #0000ff, #ffffff, #000000);
104
+ -webkit-mask:
105
+ linear-gradient(#fff 0 0) content-box,
106
+ linear-gradient(#fff 0 0);
107
+ -webkit-mask-composite: destination-out;
108
+ mask-composite: exclude;
109
+ animation: borderAnimation 5s infinite;
110
+ }
111
+
112
+ @keyframes borderAnimation {
113
  0% {
114
+ background-position: 0% 50%;
 
115
  }
116
+ 50% {
117
+ background-position: 100% 50%;
 
118
  }
119
  100% {
120
+ background-position: 0% 50%;
 
121
  }
122
  }
123
+
124
+ .btn:active {
125
+ transform: scale(0.98);
 
 
126
  }
127
+
128
  .btn:disabled {
129
+ color: #555;
130
  cursor: not-allowed;
131
  }
132
+
133
+ /* Drop Zone */
134
+ .drop-zone {
135
+ position: relative;
136
+ padding: 20px;
137
+ margin-bottom: 1rem;
138
+ border: 2px dashed #aaa;
139
+ border-radius: 10px;
140
+ cursor: pointer;
141
+ transition: all 0.3s ease;
142
+ background: rgba(255, 255, 255, 0.05);
143
+ }
144
+
145
+ .drop-zone:hover, .drop-zone.drag-over {
146
+ border-color: #ffffff;
147
+ background: rgba(255, 255, 255, 0.1);
148
+ }
149
+
150
+ .file-input {
151
+ display: none;
152
+ }
153
+
154
  .file-name {
155
  margin-top: 1rem;
156
  font-size: 0.9rem;
157
  color: #aaa;
158
  }
159
+
160
+ /* Progress Bar */
161
  .progress-container {
 
162
  display: none;
163
+ margin-top: 1.5rem;
164
  }
165
+
166
  .progress-bar {
167
  width: 100%;
168
  height: 10px;
 
171
  overflow: hidden;
172
  margin-bottom: 10px;
173
  }
174
+
175
  .progress {
176
  width: 0%;
177
  height: 100%;
178
+ background: linear-gradient(90deg, #0000ff, #ffffff, #000000);
179
+ animation: progressAnimation 2s infinite;
180
  }
181
+
182
+ @keyframes progressAnimation {
183
+ 0% { background-position: 0% 50%; }
184
+ 100% { background-position: 100% 50%; }
185
+ }
186
+
187
+ /* Loading Spinner */
188
  .loading-spinner {
189
  display: none;
190
  width: 40px;
 
195
  animation: spin 1s linear infinite;
196
  margin: 20px auto;
197
  }
198
+
199
  @keyframes spin {
200
  0% { transform: rotate(0deg); }
201
  100% { transform: rotate(360deg); }
202
  }
203
+
204
+ /* Result Container */
205
  .result-container {
206
  display: none;
207
  margin-top: 1.5rem;
208
  }
209
+
210
  .result-link {
211
  color: #ffffff;
212
  text-decoration: none;
 
214
  transition: all 0.3s ease;
215
  margin-right: 10px;
216
  }
217
+
218
  .result-link:hover {
219
  text-decoration: underline;
220
  }
221
+
222
  .copy-btn, .embed-btn {
223
+ position: relative;
224
+ padding: 10px 20px;
225
+ margin: 0.5rem;
226
+ font-size: 0.9rem;
227
+ font-weight: 600;
228
+ color: #ffffff;
229
+ background-color: transparent;
230
  border: none;
 
231
  border-radius: 5px;
232
  cursor: pointer;
233
+ overflow: hidden;
234
+ z-index: 1;
235
+ transition: color 0.3s ease;
236
  }
237
+
238
+ .copy-btn::before,
239
+ .embed-btn::before {
240
+ content: '';
241
+ position: absolute;
242
+ inset: 0;
243
+ border-radius: 5px;
244
+ padding: 3px;
245
+ background: linear-gradient(45deg, #0000ff, #ffffff, #000000);
246
+ -webkit-mask:
247
+ linear-gradient(#fff 0 0) content-box,
248
+ linear-gradient(#fff 0 0);
249
+ -webkit-mask-composite: destination-out;
250
+ mask-composite: exclude;
251
+ animation: borderAnimation 5s infinite;
252
+ }
253
+
254
+ .copy-btn:hover,
255
+ .embed-btn:hover {
256
+ color: #e0e0e0;
257
  }
258
+
259
+ .copy-btn:active,
260
+ .embed-btn:active {
261
+ transform: scale(0.98);
262
+ }
263
+
264
  .file-types {
265
  margin-top: 2rem;
266
  font-size: 0.8rem;
267
  color: #aaa;
268
  }
269
+
270
+ /* Modal Styles */
 
 
 
 
 
 
 
 
 
 
271
  .modal {
272
  display: none;
273
  position: fixed;
274
+ z-index: 2;
275
  left: 0;
276
  top: 0;
277
  width: 100%;
 
279
  overflow: auto;
280
  background-color: rgba(0,0,0,0.8);
281
  }
282
+
283
  .modal-content {
284
  background-color: #1e1e1e;
285
  margin: 15% auto;
 
290
  border-radius: 10px;
291
  color: #e0e0e0;
292
  animation: modalFadeIn 0.3s;
293
+ position: relative;
294
  }
295
+
296
  @keyframes modalFadeIn {
297
  from {opacity: 0; transform: scale(0.8);}
298
  to {opacity: 1; transform: scale(1);}
299
  }
300
+
301
  .close {
302
  color: #aaa;
303
+ position: absolute;
304
+ top: 10px;
305
+ right: 15px;
306
  font-size: 28px;
307
  font-weight: bold;
308
  transition: color 0.3s ease;
309
  }
310
+
311
  .close:hover,
312
  .close:focus {
313
  color: #fff;
314
  text-decoration: none;
315
  cursor: pointer;
316
  }
317
+
318
+ .embed-container {
319
+ display: flex;
320
+ align-items: center;
321
+ margin-top: 15px;
322
+ }
323
+
324
  #embedLink {
325
+ flex-grow: 1;
326
  padding: 10px;
 
327
  background-color: #333;
328
  border: 1px solid #555;
329
  color: #e0e0e0;
330
  border-radius: 5px;
331
+ margin-right: 10px;
332
  }
333
+
334
+ .copy-embed-btn {
335
  position: relative;
336
+ padding: 10px 20px;
337
+ font-size: 0.9rem;
338
+ font-weight: 600;
339
+ color: #ffffff;
340
+ background-color: transparent;
341
+ border: none;
342
+ border-radius: 5px;
343
+ cursor: pointer;
344
  overflow: hidden;
345
+ z-index: 1;
346
+ transition: color 0.3s ease;
347
  }
348
+
349
+ .copy-embed-btn::before {
350
  content: '';
351
  position: absolute;
352
+ inset: 0;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
353
  border-radius: 5px;
354
+ padding: 3px;
355
+ background: linear-gradient(45deg, #0000ff, #ffffff, #000000);
356
+ -webkit-mask:
357
+ linear-gradient(#fff 0 0) content-box,
358
+ linear-gradient(#fff 0 0);
359
+ -webkit-mask-composite: destination-out;
360
+ mask-composite: exclude;
361
+ animation: borderAnimation 5s infinite;
362
  }
363
+
364
  .copy-embed-btn:hover {
365
+ color: #e0e0e0;
366
  }
367
+
368
+ .copy-embed-btn:active {
369
+ transform: scale(0.98);
 
 
370
  }
371
+
372
+ /* Media Queries */
373
+ @media (max-width: 480px) {
374
+ .container {
375
+ padding: 2rem 1rem;
376
+ }
377
+
378
+ h1 {
379
+ font-size: 1.5rem;
380
+ }
381
+
382
+ .embed-container {
383
+ flex-direction: column;
384
+ }
385
+
386
+ #embedLink {
387
+ margin-bottom: 10px;
388
+ margin-right: 0;
389
+ }
390
  }
391
  </style>
392
  </head>
 
547
  }
548
  }
549
 
550
+ function resetUploadState() {
551
  fileInput.value = '';
552
  fileName.textContent = '';
553
  document.getElementById('uploadBtn').style.display = 'none';
 
558
  function addResultLink(url, fileName) {
559
  const linkContainer = document.createElement('div');
560
  linkContainer.style.marginBottom = '10px';
561
+
562
  const link = document.createElement('a');
563
  link.href = url;
564
  link.textContent = `View ${fileName}`;
565
  link.className = 'result-link';
566
  link.target = '_blank';
567
+
568
  const copyBtn = document.createElement('button');
569
  copyBtn.textContent = 'Copy Link';
570
  copyBtn.className = 'copy-btn';
 
573
  alert('Link copied to clipboard!');
574
  });
575
  };
576
+
577
  linkContainer.appendChild(link);
578
  linkContainer.appendChild(copyBtn);
579
 
 
592
  }
593
 
594
  function showEmbedModal(url) {
595
+ const embedUrl = `${window.location.origin}/embed?url=${encodeURIComponent(window.location.origin + url)}&thumbnail=${encodeURIComponent('https://example.com/thumbnail.png')}`;
596
  embedLinkInput.value = embedUrl;
597
  modal.style.display = "block";
598
  }
 
673
  <meta property="og:image:height" content="720">
674
  <meta property="og:image:type" content="image/png">
675
  <style>
676
+ body, html {{ margin: 0; padding: 0; height: 100%; background: #000; }}
677
  #thumbnail {{ width: 100%; height: 100%; object-fit: contain; cursor: pointer; }}
678
  #video {{ display: none; width: 100%; height: 100%; object-fit: contain; }}
679
  </style>
 
723
  'Sec-GPC': '1',
724
  'Priority': 'u=1, i'
725
  })
 
 
 
726
  return response.json()
727
  except Exception as e:
728
  print(f'Error initiating upload: {e}')
 
731
  async def upload_file(upload_url: str, file_content: bytes, content_type: str) -> bool:
732
  try:
733
  response = requests.put(upload_url, data=file_content, headers={'Content-Type': content_type})
 
 
734
  return response.status_code == 200
735
  except Exception as e:
736
  print(f'Error uploading file: {e}')
 
738
 
739
  async def retry_upload(upload_url: str, file_content: bytes, content_type: str, max_retries: int = 5, delay: int = 1) -> bool:
740
  for attempt in range(1, max_retries + 1):
 
741
  success = await upload_file(upload_url, file_content, content_type)
742
  if success:
 
743
  return True
744
  if attempt < max_retries:
 
745
  time.sleep(delay)
746
  delay *= 2 # Exponential backoff
 
747
  return False