Eluza133 commited on
Commit
ee5bf70
·
verified ·
1 Parent(s): d654aca

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +102 -16
app.py CHANGED
@@ -14,7 +14,7 @@ import string
14
  app = Flask(__name__)
15
  app.secret_key = os.getenv("FLASK_SECRET_KEY", "supersecretkey")
16
  DATA_FILE = 'cloud_data.json'
17
- REPO_ID = "Eluza133/Z1e1u" # Используем тот же репозиторий
18
  HF_TOKEN_WRITE = os.getenv("HF_TOKEN")
19
  HF_TOKEN_READ = os.getenv("HF_TOKEN_READ") or HF_TOKEN_WRITE
20
  ADMIN_PASSWORD = "87132morflot"
@@ -22,7 +22,7 @@ ADMIN_PASSWORD = "87132morflot"
22
  cache = Cache(app, config={'CACHE_TYPE': 'simple'})
23
  logging.basicConfig(level=logging.INFO)
24
 
25
- # Функции из вашего кода для работы с базой данных и Hugging Face
26
  @cache.memoize(timeout=300)
27
  def load_data():
28
  try:
@@ -92,6 +92,16 @@ def periodic_backup():
92
  def generate_token():
93
  return ''.join(random.choices(string.ascii_letters + string.digits, k=13))
94
 
 
 
 
 
 
 
 
 
 
 
95
  # Базовый стиль CSS
96
  BASE_STYLE = '''
97
  :root {
@@ -121,7 +131,7 @@ body.dark {
121
  }
122
  .container {
123
  margin: 20px auto;
124
- max-width: 900px;
125
  padding: 25px;
126
  background: var(--card-bg);
127
  border-radius: 20px;
@@ -139,7 +149,7 @@ h1 {
139
  -webkit-background-clip: text;
140
  color: transparent;
141
  }
142
- input {
143
  width: 100%;
144
  padding: 14px;
145
  margin: 12px 0;
@@ -150,10 +160,10 @@ input {
150
  font-size: 1.1em;
151
  box-shadow: inset 0 3px 10px rgba(0, 0, 0, 0.1);
152
  }
153
- body.dark input {
154
  color: var(--text-dark);
155
  }
156
- input:focus {
157
  outline: none;
158
  box-shadow: 0 0 0 4px var(--primary);
159
  }
@@ -168,11 +178,20 @@ input:focus {
168
  font-weight: 600;
169
  transition: var(--transition);
170
  box-shadow: var(--shadow);
 
 
171
  }
172
  .btn:hover {
173
  transform: scale(1.05);
174
  background: #e6415f;
175
  }
 
 
 
 
 
 
 
176
  .flash {
177
  color: var(--secondary);
178
  text-align: center;
@@ -180,7 +199,7 @@ input:focus {
180
  }
181
  .file-grid {
182
  display: grid;
183
- grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
184
  gap: 20px;
185
  margin-top: 20px;
186
  }
@@ -190,10 +209,26 @@ input:focus {
190
  border-radius: 16px;
191
  box-shadow: var(--shadow);
192
  text-align: center;
 
193
  }
194
  body.dark .file-item {
195
  background: var(--card-bg-dark);
196
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
197
  .file-item a {
198
  color: var(--primary);
199
  text-decoration: none;
@@ -201,6 +236,25 @@ body.dark .file-item {
201
  .file-item a:hover {
202
  color: var(--accent);
203
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
204
  '''
205
 
206
  # Регистрация через /admhosto
@@ -227,13 +281,13 @@ def register():
227
  <head>
228
  <meta charset="UTF-8">
229
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
230
- <title>Регистрация</title>
231
  <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600;800&display=swap" rel="stylesheet">
232
  <style>''' + BASE_STYLE + '''</style>
233
  </head>
234
  <body>
235
  <div class="container">
236
- <h1>Регистрация</h1>
237
  {% with messages = get_flashed_messages() %}
238
  {% if messages %}
239
  {% for message in messages %}
@@ -257,11 +311,11 @@ def login():
257
  if request.method == 'POST':
258
  token = request.form.get('token')
259
  data = load_data()
260
- if token in data['users']:
261
  session['token'] = token
262
  return redirect(url_for('dashboard'))
263
  else:
264
- flash('Неверный токен!')
265
 
266
  html = '''
267
  <!DOCTYPE html>
@@ -269,13 +323,13 @@ def login():
269
  <head>
270
  <meta charset="UTF-8">
271
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
272
- <title>Вход</title>
273
  <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600;800&display=swap" rel="stylesheet">
274
  <style>''' + BASE_STYLE + '''</style>
275
  </head>
276
  <body>
277
  <div class="container">
278
- <h1>Вход в облако</h1>
279
  {% with messages = get_flashed_messages() %}
280
  {% if messages %}
281
  {% for message in messages %}
@@ -332,6 +386,7 @@ def dashboard():
332
  file_info = {
333
  'filename': filename,
334
  'path': file_path,
 
335
  'upload_date': datetime.now().strftime('%Y-%m-%d %H:%M:%S')
336
  }
337
  data['users'][token]['files'].append(file_info)
@@ -348,13 +403,13 @@ def dashboard():
348
  <head>
349
  <meta charset="UTF-8">
350
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
351
- <title>Dashboard</title>
352
  <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600;800&display=swap" rel="stylesheet">
353
  <style>''' + BASE_STYLE + '''</style>
354
  </head>
355
  <body>
356
  <div class="container">
357
- <h1>Ваш Dashboard</h1>
358
  <p>Токен: {{ token }}</p>
359
  <form method="POST" enctype="multipart/form-data">
360
  <input type="file" name="file" required>
@@ -364,8 +419,17 @@ def dashboard():
364
  <div class="file-grid">
365
  {% for file in user_files %}
366
  <div class="file-item">
367
- <a href="https://huggingface.co/datasets/{{ repo_id }}/resolve/main/{{ file['path'] }}" target="_blank">{{ file['filename'] }}</a>
 
 
 
 
 
 
 
 
368
  <p>{{ file['upload_date'] }}</p>
 
369
  </div>
370
  {% endfor %}
371
  {% if not user_files %}
@@ -374,6 +438,28 @@ def dashboard():
374
  </div>
375
  <a href="{{ url_for('logout') }}" class="btn" style="margin-top: 20px;">Выйти</a>
376
  </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
377
  </body>
378
  </html>
379
  '''
 
14
  app = Flask(__name__)
15
  app.secret_key = os.getenv("FLASK_SECRET_KEY", "supersecretkey")
16
  DATA_FILE = 'cloud_data.json'
17
+ REPO_ID = "Eluza133/Z1e1u" # Новый репозиторий
18
  HF_TOKEN_WRITE = os.getenv("HF_TOKEN")
19
  HF_TOKEN_READ = os.getenv("HF_TOKEN_READ") or HF_TOKEN_WRITE
20
  ADMIN_PASSWORD = "87132morflot"
 
22
  cache = Cache(app, config={'CACHE_TYPE': 'simple'})
23
  logging.basicConfig(level=logging.INFO)
24
 
25
+ # Функции для работы с базой данных и Hugging Face
26
  @cache.memoize(timeout=300)
27
  def load_data():
28
  try:
 
92
  def generate_token():
93
  return ''.join(random.choices(string.ascii_letters + string.digits, k=13))
94
 
95
+ # Определение типа файла для предпросмотра
96
+ def get_file_type(filename):
97
+ video_extensions = ('.mp4', '.mov', '.avi')
98
+ image_extensions = ('.jpg', '.jpeg', '.png', '.gif')
99
+ if filename.lower().endswith(video_extensions):
100
+ return 'video'
101
+ elif filename.lower().endswith(image_extensions):
102
+ return 'image'
103
+ return 'other'
104
+
105
  # Базовый стиль CSS
106
  BASE_STYLE = '''
107
  :root {
 
131
  }
132
  .container {
133
  margin: 20px auto;
134
+ max-width: 1200px;
135
  padding: 25px;
136
  background: var(--card-bg);
137
  border-radius: 20px;
 
149
  -webkit-background-clip: text;
150
  color: transparent;
151
  }
152
+ input, textarea {
153
  width: 100%;
154
  padding: 14px;
155
  margin: 12px 0;
 
160
  font-size: 1.1em;
161
  box-shadow: inset 0 3px 10px rgba(0, 0, 0, 0.1);
162
  }
163
+ body.dark input, body.dark textarea {
164
  color: var(--text-dark);
165
  }
166
+ input:focus, textarea:focus {
167
  outline: none;
168
  box-shadow: 0 0 0 4px var(--primary);
169
  }
 
178
  font-weight: 600;
179
  transition: var(--transition);
180
  box-shadow: var(--shadow);
181
+ display: inline-block;
182
+ text-decoration: none;
183
  }
184
  .btn:hover {
185
  transform: scale(1.05);
186
  background: #e6415f;
187
  }
188
+ .download-btn {
189
+ background: var(--secondary);
190
+ margin-top: 10px;
191
+ }
192
+ .download-btn:hover {
193
+ background: #00b8c5;
194
+ }
195
  .flash {
196
  color: var(--secondary);
197
  text-align: center;
 
199
  }
200
  .file-grid {
201
  display: grid;
202
+ grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
203
  gap: 20px;
204
  margin-top: 20px;
205
  }
 
209
  border-radius: 16px;
210
  box-shadow: var(--shadow);
211
  text-align: center;
212
+ transition: var(--transition);
213
  }
214
  body.dark .file-item {
215
  background: var(--card-bg-dark);
216
  }
217
+ .file-item:hover {
218
+ transform: translateY(-5px);
219
+ }
220
+ .file-preview {
221
+ max-width: 100%;
222
+ max-height: 200px;
223
+ object-fit: cover;
224
+ border-radius: 10px;
225
+ margin-bottom: 10px;
226
+ loading: lazy;
227
+ }
228
+ .file-item p {
229
+ font-size: 0.9em;
230
+ margin: 5px 0;
231
+ }
232
  .file-item a {
233
  color: var(--primary);
234
  text-decoration: none;
 
236
  .file-item a:hover {
237
  color: var(--accent);
238
  }
239
+ .modal {
240
+ display: none;
241
+ position: fixed;
242
+ top: 0;
243
+ left: 0;
244
+ width: 100%;
245
+ height: 100%;
246
+ background: rgba(0, 0, 0, 0.85);
247
+ z-index: 2000;
248
+ justify-content: center;
249
+ align-items: center;
250
+ }
251
+ .modal img, .modal video {
252
+ max-width: 95%;
253
+ max-height: 95%;
254
+ object-fit: contain;
255
+ border-radius: 20px;
256
+ box-shadow: var(--shadow);
257
+ }
258
  '''
259
 
260
  # Регистрация через /admhosto
 
281
  <head>
282
  <meta charset="UTF-8">
283
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
284
+ <title>Регистрация - Zues Cloud</title>
285
  <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600;800&display=swap" rel="stylesheet">
286
  <style>''' + BASE_STYLE + '''</style>
287
  </head>
288
  <body>
289
  <div class="container">
290
+ <h1>Регистрация в Zues Cloud</h1>
291
  {% with messages = get_flashed_messages() %}
292
  {% if messages %}
293
  {% for message in messages %}
 
311
  if request.method == 'POST':
312
  token = request.form.get('token')
313
  data = load_data()
314
+ if token in data['users'] and len(token) == 13:
315
  session['token'] = token
316
  return redirect(url_for('dashboard'))
317
  else:
318
+ flash('Неверный токен! Токен должен быть 13 символов.')
319
 
320
  html = '''
321
  <!DOCTYPE html>
 
323
  <head>
324
  <meta charset="UTF-8">
325
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
326
+ <title>Zues Cloud</title>
327
  <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600;800&display=swap" rel="stylesheet">
328
  <style>''' + BASE_STYLE + '''</style>
329
  </head>
330
  <body>
331
  <div class="container">
332
+ <h1>Zues Cloud</h1>
333
  {% with messages = get_flashed_messages() %}
334
  {% if messages %}
335
  {% for message in messages %}
 
386
  file_info = {
387
  'filename': filename,
388
  'path': file_path,
389
+ 'type': get_file_type(filename),
390
  'upload_date': datetime.now().strftime('%Y-%m-%d %H:%M:%S')
391
  }
392
  data['users'][token]['files'].append(file_info)
 
403
  <head>
404
  <meta charset="UTF-8">
405
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
406
+ <title>Dashboard - Zues Cloud</title>
407
  <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600;800&display=swap" rel="stylesheet">
408
  <style>''' + BASE_STYLE + '''</style>
409
  </head>
410
  <body>
411
  <div class="container">
412
+ <h1>Zues Cloud Dashboard</h1>
413
  <p>Токен: {{ token }}</p>
414
  <form method="POST" enctype="multipart/form-data">
415
  <input type="file" name="file" required>
 
419
  <div class="file-grid">
420
  {% for file in user_files %}
421
  <div class="file-item">
422
+ {% if file['type'] == 'video' %}
423
+ <video class="file-preview" preload="metadata" muted loading="lazy" onclick="openModal('https://huggingface.co/datasets/{{ repo_id }}/resolve/main/{{ file['path'] }}', true)">
424
+ <source src="https://huggingface.co/datasets/{{ repo_id }}/resolve/main/{{ file['path'] }}" type="video/mp4">
425
+ </video>
426
+ {% elif file['type'] == 'image' %}
427
+ <img class="file-preview" src="https://huggingface.co/datasets/{{ repo_id }}/resolve/main/{{ file['path'] }}" alt="{{ file['filename'] }}" loading="lazy" onclick="openModal(this.src, false)">
428
+ {% else %}
429
+ <p><a href="https://huggingface.co/datasets/{{ repo_id }}/resolve/main/{{ file['path'] }}" target="_blank">{{ file['filename'] }}</a></p>
430
+ {% endif %}
431
  <p>{{ file['upload_date'] }}</p>
432
+ <a href="https://huggingface.co/datasets/{{ repo_id }}/resolve/main/{{ file['path'] }}" class="btn download-btn" download="{{ file['filename'] }}">Скачать</a>
433
  </div>
434
  {% endfor %}
435
  {% if not user_files %}
 
438
  </div>
439
  <a href="{{ url_for('logout') }}" class="btn" style="margin-top: 20px;">Выйти</a>
440
  </div>
441
+ <div class="modal" id="mediaModal" onclick="closeModal(event)">
442
+ <div id="modalContent"></div>
443
+ </div>
444
+ <script>
445
+ function openModal(src, isVideo) {
446
+ const modal = document.getElementById('mediaModal');
447
+ const modalContent = document.getElementById('modalContent');
448
+ if (isVideo) {
449
+ modalContent.innerHTML = `<video controls><source src="${src}" type="video/mp4"></video>`;
450
+ } else {
451
+ modalContent.innerHTML = `<img src="${src}">`;
452
+ }
453
+ modal.style.display = 'flex';
454
+ }
455
+ function closeModal(event) {
456
+ if (event.target.tagName !== 'IMG' && event.target.tagName !== 'VIDEO') {
457
+ const modal = document.getElementById('mediaModal');
458
+ modal.style.display = 'none';
459
+ modal.innerHTML = '<div id="modalContent"></div>';
460
+ }
461
+ }
462
+ </script>
463
  </body>
464
  </html>
465
  '''