albumup commited on
Commit
2f3eee0
·
verified ·
1 Parent(s): 0f7a742

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +86 -81
app.py CHANGED
@@ -14,14 +14,13 @@ app = FastAPI()
14
 
15
  DENO_API_URL = "https://dataerrr99.deno.dev"
16
 
17
- async def save_album_to_db(album_name: str, album_id: str, files: list):
18
  async with httpx.AsyncClient() as client:
19
  try:
20
  response = await client.post(DENO_API_URL, json={
21
  "albumName": album_name,
22
  "albumLink": album_id,
23
- "files": files,
24
- "createdAt": datetime.now().isoformat()
25
  })
26
  return response.json()
27
  except Exception as e:
@@ -37,6 +36,15 @@ async def get_albums_from_db():
37
  print(f"Error fetching from DB: {str(e)}")
38
  return {"data": []}
39
 
 
 
 
 
 
 
 
 
 
40
  HTML_CONTENT = """
41
  <!DOCTYPE html>
42
  <html lang="en">
@@ -45,41 +53,42 @@ HTML_CONTENT = """
45
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
46
  <title>File Upload</title>
47
  <style>
48
- .container {
49
  max-width: 800px;
50
  margin: 0 auto;
51
  padding: 20px;
52
- }
53
- .upload-form {
54
  margin-bottom: 20px;
55
  padding: 20px;
56
  border: 1px solid #ddd;
57
  border-radius: 5px;
58
- }
59
- .preview {
60
  margin-top: 20px;
61
- }
62
- .search-form {
63
  margin: 20px 0;
64
  padding: 20px;
65
  border: 1px solid #ddd;
66
  border-radius: 5px;
67
- }
68
- .album-list {
69
  margin-top: 20px;
70
- }
71
- .album-item {
72
  padding: 10px;
73
  border: 1px solid #ddd;
74
  margin-bottom: 10px;
75
  border-radius: 5px;
76
- }
77
  </style>
78
  </head>
79
  <body>
80
  <div class="container">
81
  <h1>File Upload & Album Management</h1>
82
 
 
83
  <div class="search-form">
84
  <h2>Search Albums</h2>
85
  <form action="/search" method="get">
@@ -88,6 +97,7 @@ HTML_CONTENT = """
88
  </form>
89
  </div>
90
 
 
91
  <div class="upload-form">
92
  <h2>Single File Upload</h2>
93
  <form action="/upload" method="post" enctype="multipart/form-data">
@@ -96,6 +106,7 @@ HTML_CONTENT = """
96
  </form>
97
  </div>
98
 
 
99
  <div class="upload-form">
100
  <h2>Create Album</h2>
101
  <form action="/album/create" method="post" enctype="multipart/form-data">
@@ -117,30 +128,30 @@ ALBUM_VIEW_HTML = """
117
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
118
  <title>Album View - {album_name}</title>
119
  <style>
120
- .container {
121
  max-width: 800px;
122
  margin: 0 auto;
123
  padding: 20px;
124
- }
125
- .file-grid {
126
  display: grid;
127
  grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
128
  gap: 20px;
129
- }
130
- .file-item {
131
  border: 1px solid #ddd;
132
  padding: 10px;
133
  text-align: center;
134
  border-radius: 5px;
135
- }
136
- .download-all {
137
  margin: 20px 0;
138
- }
139
- .back-link {
140
  margin-bottom: 20px;
141
  display: block;
142
- }
143
- .button {
144
  display: inline-block;
145
  padding: 8px 16px;
146
  background-color: #007bff;
@@ -148,11 +159,11 @@ ALBUM_VIEW_HTML = """
148
  text-decoration: none;
149
  border-radius: 4px;
150
  margin: 5px;
151
- }
152
- .button:hover {
153
  background-color: #0056b3;
154
- }
155
- .preview-container {
156
  margin-bottom: 10px;
157
  max-width: 100%;
158
  height: 200px;
@@ -162,18 +173,18 @@ ALBUM_VIEW_HTML = """
162
  justify-content: center;
163
  background-color: #f8f9fa;
164
  border-radius: 4px;
165
- }
166
- .preview-container img {
167
  max-width: 100%;
168
  max-height: 100%;
169
  object-fit: contain;
170
- }
171
- .preview-container video {
172
  max-width: 100%;
173
  max-height: 100%;
174
  object-fit: contain;
175
- }
176
- .modal {
177
  display: none;
178
  position: fixed;
179
  z-index: 1000;
@@ -183,15 +194,15 @@ ALBUM_VIEW_HTML = """
183
  height: 100%;
184
  background-color: rgba(0,0,0,0.9);
185
  overflow: auto;
186
- }
187
- .modal-content {
188
  margin: auto;
189
  display: block;
190
  max-width: 90%;
191
  max-height: 90vh;
192
  margin-top: 50px;
193
- }
194
- .close {
195
  position: absolute;
196
  right: 35px;
197
  top: 15px;
@@ -199,39 +210,39 @@ ALBUM_VIEW_HTML = """
199
  font-size: 40px;
200
  font-weight: bold;
201
  cursor: pointer;
202
- }
203
  </style>
204
  <script>
205
- function openModal(url) {
206
  const modal = document.getElementById('previewModal');
207
  const modalContent = document.getElementById('modalContent');
208
  const contentType = getContentType(url);
209
 
210
- if (contentType === 'image') {
211
- modalContent.innerHTML = `<img src="${url}" style="max-width:100%;max-height:90vh;">`;
212
- } else if (contentType === 'video') {
213
  modalContent.innerHTML = `<video controls style="max-width:100%;max-height:90vh;">
214
- <source src="${url}" type="video/mp4">
215
  Your browser does not support the video tag.
216
  </video>`;
217
- }
218
 
219
  modal.style.display = 'block';
220
- }
221
 
222
- function closeModal() {
223
  const modal = document.getElementById('previewModal');
224
  modal.style.display = 'none';
225
  const modalContent = document.getElementById('modalContent');
226
  modalContent.innerHTML = '';
227
- }
228
 
229
- function getContentType(url) {
230
  const ext = url.split('.').pop().toLowerCase();
231
  if (['jpg', 'jpeg', 'png', 'gif', 'webp'].includes(ext)) return 'image';
232
  if (['mp4', 'webm', 'ogg'].includes(ext)) return 'video';
233
  return 'other';
234
- }
235
  </script>
236
  </head>
237
  <body>
@@ -246,6 +257,7 @@ ALBUM_VIEW_HTML = """
246
  </div>
247
  </div>
248
 
 
249
  <div id="previewModal" class="modal" onclick="closeModal()">
250
  <span class="close">&times;</span>
251
  <div id="modalContent" class="modal-content">
@@ -263,22 +275,22 @@ SEARCH_RESULTS_HTML = """
263
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
264
  <title>Search Results</title>
265
  <style>
266
- .container {
267
  max-width: 800px;
268
  margin: 0 auto;
269
  padding: 20px;
270
- }
271
- .album-item {
272
  border: 1px solid #ddd;
273
  padding: 15px;
274
  margin-bottom: 15px;
275
  border-radius: 5px;
276
- }
277
- .back-link {
278
  margin-bottom: 20px;
279
  display: block;
280
- }
281
- .button {
282
  display: inline-block;
283
  padding: 8px 16px;
284
  background-color: #007bff;
@@ -286,10 +298,10 @@ SEARCH_RESULTS_HTML = """
286
  text-decoration: none;
287
  border-radius: 4px;
288
  margin: 5px;
289
- }
290
- .button:hover {
291
  background-color: #0056b3;
292
- }
293
  </style>
294
  </head>
295
  <body>
@@ -320,10 +332,12 @@ async def index():
320
 
321
  @app.get("/search", response_class=HTMLResponse)
322
  async def search_albums(query: str = ""):
323
- db_data = await get_albums_from_db()
 
 
324
  matching_albums = [
325
- album for album in db_data['data']
326
- if query.lower() in album['name'].lower()
327
  ]
328
 
329
  results_html = ""
@@ -332,6 +346,7 @@ async def search_albums(query: str = ""):
332
  <div class="album-item">
333
  <h3>{album['name']}</h3>
334
  <p>Created: {album['createdAt']}</p>
 
335
  <a href="/album/{album['albumLink']}" class="button">View Album</a>
336
  </div>
337
  """
@@ -368,25 +383,21 @@ async def create_album(
368
  'uploaded_at': datetime.now().isoformat()
369
  })
370
 
 
371
  await save_album_to_db(album_name, album_id, album_files)
372
-
373
  base_url = str(request.base_url).rstrip('/')
374
  return RedirectResponse(url=f"{base_url}/album/{album_id}", status_code=303)
375
 
376
  @app.get("/album/{album_id}", response_class=HTMLResponse)
377
  async def view_album(album_id: str):
378
- db_data = await get_albums_from_db()
379
- album = None
380
- for a in db_data['data']:
381
- if a['albumLink'] == album_id:
382
- album = a
383
- break
384
-
385
  if not album:
386
  return "Album not found", 404
387
 
388
  file_list_html = ""
389
- for file in album.get('files', []):
 
390
  file_url = f"/upload/{file['path']}"
391
  file_type = get_file_type(file['filename'])
392
 
@@ -430,13 +441,7 @@ async def view_album(album_id: str):
430
 
431
  @app.get("/album/{album_id}/download")
432
  async def download_album(album_id: str):
433
- db_data = await get_albums_from_db()
434
- album = None
435
- for a in db_data['data']:
436
- if a['albumLink'] == album_id:
437
- album = a
438
- break
439
-
440
  if not album:
441
  return {"error": "Album not found"}, 404
442
 
 
14
 
15
  DENO_API_URL = "https://dataerrr99.deno.dev"
16
 
17
+ async def save_album_to_db(album_name: str, album_id: str, files: List[dict]):
18
  async with httpx.AsyncClient() as client:
19
  try:
20
  response = await client.post(DENO_API_URL, json={
21
  "albumName": album_name,
22
  "albumLink": album_id,
23
+ "files": files
 
24
  })
25
  return response.json()
26
  except Exception as e:
 
36
  print(f"Error fetching from DB: {str(e)}")
37
  return {"data": []}
38
 
39
+ async def get_album_from_db(album_id: str):
40
+ async with httpx.AsyncClient() as client:
41
+ try:
42
+ response = await client.get(f"{DENO_API_URL}/{album_id}")
43
+ return response.json()
44
+ except Exception as e:
45
+ print(f"Error fetching album from DB: {str(e)}")
46
+ return None
47
+
48
  HTML_CONTENT = """
49
  <!DOCTYPE html>
50
  <html lang="en">
 
53
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
54
  <title>File Upload</title>
55
  <style>
56
+ .container {{
57
  max-width: 800px;
58
  margin: 0 auto;
59
  padding: 20px;
60
+ }}
61
+ .upload-form {{
62
  margin-bottom: 20px;
63
  padding: 20px;
64
  border: 1px solid #ddd;
65
  border-radius: 5px;
66
+ }}
67
+ .preview {{
68
  margin-top: 20px;
69
+ }}
70
+ .search-form {{
71
  margin: 20px 0;
72
  padding: 20px;
73
  border: 1px solid #ddd;
74
  border-radius: 5px;
75
+ }}
76
+ .album-list {{
77
  margin-top: 20px;
78
+ }}
79
+ .album-item {{
80
  padding: 10px;
81
  border: 1px solid #ddd;
82
  margin-bottom: 10px;
83
  border-radius: 5px;
84
+ }}
85
  </style>
86
  </head>
87
  <body>
88
  <div class="container">
89
  <h1>File Upload & Album Management</h1>
90
 
91
+ <!-- Search Albums -->
92
  <div class="search-form">
93
  <h2>Search Albums</h2>
94
  <form action="/search" method="get">
 
97
  </form>
98
  </div>
99
 
100
+ <!-- Single File Upload -->
101
  <div class="upload-form">
102
  <h2>Single File Upload</h2>
103
  <form action="/upload" method="post" enctype="multipart/form-data">
 
106
  </form>
107
  </div>
108
 
109
+ <!-- Album Upload -->
110
  <div class="upload-form">
111
  <h2>Create Album</h2>
112
  <form action="/album/create" method="post" enctype="multipart/form-data">
 
128
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
129
  <title>Album View - {album_name}</title>
130
  <style>
131
+ .container {{
132
  max-width: 800px;
133
  margin: 0 auto;
134
  padding: 20px;
135
+ }}
136
+ .file-grid {{
137
  display: grid;
138
  grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
139
  gap: 20px;
140
+ }}
141
+ .file-item {{
142
  border: 1px solid #ddd;
143
  padding: 10px;
144
  text-align: center;
145
  border-radius: 5px;
146
+ }}
147
+ .download-all {{
148
  margin: 20px 0;
149
+ }}
150
+ .back-link {{
151
  margin-bottom: 20px;
152
  display: block;
153
+ }}
154
+ .button {{
155
  display: inline-block;
156
  padding: 8px 16px;
157
  background-color: #007bff;
 
159
  text-decoration: none;
160
  border-radius: 4px;
161
  margin: 5px;
162
+ }}
163
+ .button:hover {{
164
  background-color: #0056b3;
165
+ }}
166
+ .preview-container {{
167
  margin-bottom: 10px;
168
  max-width: 100%;
169
  height: 200px;
 
173
  justify-content: center;
174
  background-color: #f8f9fa;
175
  border-radius: 4px;
176
+ }}
177
+ .preview-container img {{
178
  max-width: 100%;
179
  max-height: 100%;
180
  object-fit: contain;
181
+ }}
182
+ .preview-container video {{
183
  max-width: 100%;
184
  max-height: 100%;
185
  object-fit: contain;
186
+ }}
187
+ .modal {{
188
  display: none;
189
  position: fixed;
190
  z-index: 1000;
 
194
  height: 100%;
195
  background-color: rgba(0,0,0,0.9);
196
  overflow: auto;
197
+ }}
198
+ .modal-content {{
199
  margin: auto;
200
  display: block;
201
  max-width: 90%;
202
  max-height: 90vh;
203
  margin-top: 50px;
204
+ }}
205
+ .close {{
206
  position: absolute;
207
  right: 35px;
208
  top: 15px;
 
210
  font-size: 40px;
211
  font-weight: bold;
212
  cursor: pointer;
213
+ }}
214
  </style>
215
  <script>
216
+ function openModal(url) {{
217
  const modal = document.getElementById('previewModal');
218
  const modalContent = document.getElementById('modalContent');
219
  const contentType = getContentType(url);
220
 
221
+ if (contentType === 'image') {{
222
+ modalContent.innerHTML = `<img src="${{url}}" style="max-width:100%;max-height:90vh;">`;
223
+ }} else if (contentType === 'video') {{
224
  modalContent.innerHTML = `<video controls style="max-width:100%;max-height:90vh;">
225
+ <source src="${{url}}" type="video/mp4">
226
  Your browser does not support the video tag.
227
  </video>`;
228
+ }}
229
 
230
  modal.style.display = 'block';
231
+ }}
232
 
233
+ function closeModal() {{
234
  const modal = document.getElementById('previewModal');
235
  modal.style.display = 'none';
236
  const modalContent = document.getElementById('modalContent');
237
  modalContent.innerHTML = '';
238
+ }}
239
 
240
+ function getContentType(url) {{
241
  const ext = url.split('.').pop().toLowerCase();
242
  if (['jpg', 'jpeg', 'png', 'gif', 'webp'].includes(ext)) return 'image';
243
  if (['mp4', 'webm', 'ogg'].includes(ext)) return 'video';
244
  return 'other';
245
+ }}
246
  </script>
247
  </head>
248
  <body>
 
257
  </div>
258
  </div>
259
 
260
+ <!-- Modal for previews -->
261
  <div id="previewModal" class="modal" onclick="closeModal()">
262
  <span class="close">&times;</span>
263
  <div id="modalContent" class="modal-content">
 
275
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
276
  <title>Search Results</title>
277
  <style>
278
+ .container {{
279
  max-width: 800px;
280
  margin: 0 auto;
281
  padding: 20px;
282
+ }}
283
+ .album-item {{
284
  border: 1px solid #ddd;
285
  padding: 15px;
286
  margin-bottom: 15px;
287
  border-radius: 5px;
288
+ }}
289
+ .back-link {{
290
  margin-bottom: 20px;
291
  display: block;
292
+ }}
293
+ .button {{
294
  display: inline-block;
295
  padding: 8px 16px;
296
  background-color: #007bff;
 
298
  text-decoration: none;
299
  border-radius: 4px;
300
  margin: 5px;
301
+ }}
302
+ .button:hover {{
303
  background-color: #0056b3;
304
+ }}
305
  </style>
306
  </head>
307
  <body>
 
332
 
333
  @app.get("/search", response_class=HTMLResponse)
334
  async def search_albums(query: str = ""):
335
+ query = query.lower()
336
+ db_albums = await get_albums_from_db()
337
+
338
  matching_albums = [
339
+ album for album in db_albums['data']
340
+ if query in album['name'].lower()
341
  ]
342
 
343
  results_html = ""
 
346
  <div class="album-item">
347
  <h3>{album['name']}</h3>
348
  <p>Created: {album['createdAt']}</p>
349
+ <p>Files: {len(album['files'])}</p>
350
  <a href="/album/{album['albumLink']}" class="button">View Album</a>
351
  </div>
352
  """
 
383
  'uploaded_at': datetime.now().isoformat()
384
  })
385
 
386
+ # Save to Deno KV database
387
  await save_album_to_db(album_name, album_id, album_files)
388
+
389
  base_url = str(request.base_url).rstrip('/')
390
  return RedirectResponse(url=f"{base_url}/album/{album_id}", status_code=303)
391
 
392
  @app.get("/album/{album_id}", response_class=HTMLResponse)
393
  async def view_album(album_id: str):
394
+ album = await get_album_from_db(album_id)
 
 
 
 
 
 
395
  if not album:
396
  return "Album not found", 404
397
 
398
  file_list_html = ""
399
+
400
+ for file in album['files']:
401
  file_url = f"/upload/{file['path']}"
402
  file_type = get_file_type(file['filename'])
403
 
 
441
 
442
  @app.get("/album/{album_id}/download")
443
  async def download_album(album_id: str):
444
+ album = await get_album_from_db(album_id)
 
 
 
 
 
 
445
  if not album:
446
  return {"error": "Album not found"}, 404
447