Eluza133 commited on
Commit
2711c3e
·
verified ·
1 Parent(s): a30c72f

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +185 -123
app.py CHANGED
@@ -85,6 +85,25 @@ def periodic_backup():
85
  upload_db_to_hf()
86
  time.sleep(15)
87
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
88
  # Регистрация пользователя
89
  @app.route('/register', methods=['GET', 'POST'])
90
  def register():
@@ -103,6 +122,8 @@ def register():
103
  flash('Регистрация успешна! Войдите в систему.')
104
  return redirect(url_for('login'))
105
 
 
 
106
  html = '''
107
  <!DOCTYPE html>
108
  <html lang="ru">
@@ -112,18 +133,34 @@ def register():
112
  <title>Регистрация</title>
113
  <link href="https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;600&display=swap" rel="stylesheet">
114
  <style>
115
- body { font-family: 'Poppins', sans-serif; background: #f0f2f5; padding: 20px; margin: 0; }
116
- .container { max-width: 400px; margin: 0 auto; background: #fff; padding: 20px; border-radius: 10px; box-shadow: 0 4px 15px rgba(0,0,0,0.1); }
 
 
 
 
 
 
 
 
117
  input { width: 100%; padding: 10px; margin: 10px 0; border: 1px solid #e2e8f0; border-radius: 8px; box-sizing: border-box; }
118
- button { padding: 10px 20px; background: #3b82f6; color: white; border: none; border-radius: 8px; cursor: pointer; width: 100%; }
 
119
  .flash { color: red; margin-bottom: 10px; }
120
- @media (max-width: 600px) {
121
- .container { padding: 15px; max-width: 100%; }
 
 
 
 
 
 
122
  input, button { font-size: 14px; padding: 8px; }
123
  }
124
  </style>
125
  </head>
126
  <body>
 
127
  <div class="container">
128
  <h1>Регистрация</h1>
129
  {% with messages = get_flashed_messages() %}
@@ -140,10 +177,15 @@ def register():
140
  </form>
141
  <p>Уже есть аккаунт? <a href="{{ url_for('login') }}">Войти</a></p>
142
  </div>
 
 
 
 
 
143
  </body>
144
  </html>
145
  '''
146
- return render_template_string(html)
147
 
148
  # Авторизация пользователя
149
  @app.route('/login', methods=['GET', 'POST'])
@@ -161,6 +203,8 @@ def login():
161
  flash('Неверный логин или пароль!')
162
  return redirect(url_for('login'))
163
 
 
 
164
  html = '''
165
  <!DOCTYPE html>
166
  <html lang="ru">
@@ -170,18 +214,34 @@ def login():
170
  <title>Вход</title>
171
  <link href="https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;600&display=swap" rel="stylesheet">
172
  <style>
173
- body { font-family: 'Poppins', sans-serif; background: #f0f2f5; padding: 20px; margin: 0; }
174
- .container { max-width: 400px; margin: 0 auto; background: #fff; padding: 20px; border-radius: 10px; box-shadow: 0 4px 15px rgba(0,0,0,0.1); }
 
 
 
 
 
 
 
 
175
  input { width: 100%; padding: 10px; margin: 10px 0; border: 1px solid #e2e8f0; border-radius: 8px; box-sizing: border-box; }
176
- button { padding: 10px 20px; background: #3b82f6; color: white; border: none; border-radius: 8px; cursor: pointer; width: 100%; }
 
177
  .flash { color: red; margin-bottom: 10px; }
178
- @media (max-width: 600px) {
179
- .container { padding: 15px; max-width: 100%; }
 
 
 
 
 
 
180
  input, button { font-size: 14px; padding: 8px; }
181
  }
182
  </style>
183
  </head>
184
  <body>
 
185
  <div class="container">
186
  <h1>Вход</h1>
187
  {% with messages = get_flashed_messages() %}
@@ -198,10 +258,15 @@ def login():
198
  </form>
199
  <p>Нет аккаунта? <a href="{{ url_for('register') }}">Зарегистрироваться</a></p>
200
  </div>
 
 
 
 
 
201
  </body>
202
  </html>
203
  '''
204
- return render_template_string(html)
205
 
206
  # Выход из системы
207
  @app.route('/logout')
@@ -223,46 +288,41 @@ def feed():
223
  <head>
224
  <meta charset="UTF-8">
225
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
226
- <title>Хостинг контента</title>
227
  <link href="https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;600&display=swap" rel="stylesheet">
228
  <style>
229
- body { font-family: 'Poppins', sans-serif; background: #f0f2f5; padding: 20px; margin: 0; }
230
- .container { max-width: 1200px; margin: 0 auto; padding-left: 220px; transition: padding-left 0.3s; }
231
- .sidebar { position: fixed; left: -220px; top: 0; width: 200px; height: 100%; background: #fff; padding: 20px; box-shadow: 2px 0 5px rgba(0,0,0,0.1); transition: left 0.3s; z-index: 1000; }
232
- .sidebar.active { left: 0; }
 
 
 
 
 
 
233
  .post-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 20px; }
234
- .post-item { background: #fff; padding: 15px; border-radius: 10px; box-shadow: 0 4px 15px rgba(0,0,0,0.1); text-decoration: none; color: #2d3748; }
 
235
  .post-preview { width: 100%; border-radius: 8px; height: 200px; object-fit: cover; }
236
- .auth-links, .upload-btn, .logout-btn, .profile-link { display: block; margin: 10px 0; padding: 10px; background: #3b82f6; color: white; text-align: center; text-decoration: none; border-radius: 8px; }
237
- .logout-btn { background: #ef4444; }
238
- .profile-link { background: #10b981; }
239
- .menu-btn { display: none; font-size: 24px; background: none; border: none; cursor: pointer; position: fixed; top: 20px; left: 20px; z-index: 1001; }
240
- .stats { font-size: 0.9em; color: #666; }
241
  @media (max-width: 768px) {
242
- .container { padding-left: 20px; padding: 10px; }
243
- .sidebar { left: -220px; width: 150px; padding: 15px; }
244
- .sidebar.active { left: 0; }
245
  .menu-btn { display: block; }
 
 
 
 
246
  .post-grid { grid-template-columns: 1fr; gap: 15px; }
247
  .post-item { padding: 10px; }
248
  .post-preview { height: 150px; }
249
- .auth-links, .upload-btn, .logout-btn, .profile-link { font-size: 14px; padding: 8px; }
250
  }
251
  </style>
252
  </head>
253
  <body>
254
- <button class="menu-btn" onclick="toggleSidebar()">☰</button>
255
- <div class="sidebar" id="sidebar">
256
- {% if is_authenticated %}
257
- <a href="{{ url_for('profile') }}" class="profile-link">
258
- <span style="font-size: 1.2em;">👤</span> {{ username }}
259
- </a>
260
- <a href="{{ url_for('logout') }}" class="logout-btn">Выйти</a>
261
- {% else %}
262
- <a href="{{ url_for('login') }}" class="auth-links">Войти</a>
263
- <a href="{{ url_for('register') }}" class="auth-links">Зарегистрироваться</a>
264
- {% endif %}
265
- </div>
266
  <div class="container">
267
  <h1>Лента публикаций</h1>
268
  <div class="post-grid">
@@ -285,7 +345,7 @@ def feed():
285
  </div>
286
  <script>
287
  function toggleSidebar() {
288
- document.getElementById('sidebar').classList.toggle('active');
289
  }
290
  document.addEventListener('DOMContentLoaded', function() {
291
  const videos = document.querySelectorAll('.post-preview');
@@ -339,45 +399,43 @@ def post_page(post_id):
339
  <head>
340
  <meta charset="UTF-8">
341
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
342
- <title>{{ post['title'] }}</title>
343
  <link href="https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;600&display=swap" rel="stylesheet">
344
  <style>
345
- body { font-family: 'Poppins', sans-serif; background: #f0f2f5; padding: 20px; margin: 0; }
346
- .sidebar { position: fixed; left: -220px; top: 0; width: 200px; height: 100%; background: #fff; padding: 20px; box-shadow: 2px 0 5px rgba(0,0,0,0.1); transition: left 0.3s; z-index: 1000; }
347
- .sidebar.active { left: 0; }
348
- .container { max-width: 800px; margin: 0 auto; padding-left: 220px; background: #fff; padding: 20px; border-radius: 10px; box-shadow: 0 4px 15px rgba(0,0,0,0.1); transition: padding-left 0.3s; }
349
- video, img { width: 100%; border-radius: 8px; max-height: 400px; object-fit: cover; }
350
- .back-btn, .profile-link, .logout-btn, .like-btn { display: inline-block; margin: 10px 0; padding: 10px; background: #3b82f6; color: white; text-decoration: none; border-radius: 8px; border: none; cursor: pointer; }
351
- .profile-link { background: #10b981; }
352
  .logout-btn { background: #ef4444; }
 
 
 
 
 
 
353
  .like-btn.liked { background: #ef4444; }
354
- .menu-btn { display: none; font-size: 24px; background: none; border: none; cursor: pointer; position: fixed; top: 20px; left: 20px; z-index: 1001; }
355
- textarea { width: 100%; padding: 10px; margin: 10px 0; border: 1px solid #e2e8f0; border-radius: 8px; }
356
  .comment { border-top: 1px solid #e2e8f0; padding: 10px 0; }
357
  @media (max-width: 768px) {
358
- .container { padding-left: 20px; padding: 15px; max-width: 100%; }
359
- .sidebar { left: -220px; width: 150px; padding: 15px; }
360
- .sidebar.active { left: 0; }
361
  .menu-btn { display: block; }
 
 
 
 
362
  video, img { max-height: 250px; }
363
- .back-btn, .like-btn, textarea, button { width: 100%; font-size: 14px; padding: 8px; margin: 5px 0; }
364
- h1 { font-size: 1.2em; }
 
365
  }
366
  </style>
367
  </head>
368
  <body>
369
- <button class="menu-btn" onclick="toggleSidebar()">☰</button>
370
- <div class="sidebar" id="sidebar">
371
- {% if is_authenticated %}
372
- <a href="{{ url_for('profile') }}" class="profile-link">
373
- <span style="font-size: 1.2em;">👤</span> {{ username }}
374
- </a>
375
- <a href="{{ url_for('logout') }}" class="logout-btn">Выйти</a>
376
- {% else %}
377
- <a href="{{ url_for('login') }}" class="profile-link">Войти</a>
378
- <a href="{{ url_for('register') }}" class="profile-link">Зарегистрироваться</a>
379
- {% endif %}
380
- </div>
381
  <div class="container">
382
  <h1>{{ post['title'] }}</h1>
383
  {% if post['type'] == 'video' %}
@@ -391,14 +449,14 @@ def post_page(post_id):
391
  <p>Загрузил: {{ post['uploader'] }} | {{ post['upload_date'] }}</p>
392
  <p>Просмотров: {{ post['views'] }} | Лайков: {{ post['likes']|length }}</p>
393
  {% if is_authenticated %}
394
- <form method="POST">
395
- <button type="submit" name="like" class="like-btn {% if username in post['likes'] %}liked{% endif %}">
396
  {% if username in post['likes'] %}Убрать лайк{% else %}Лайк{% endif %}
397
  </button>
398
  </form>
399
  <form method="POST">
400
  <textarea name="comment" placeholder="Оставьте комментарий" rows="3"></textarea>
401
- <button type="submit">Отправить</button>
402
  </form>
403
  {% endif %}
404
  <h3>Комментарии</h3>
@@ -407,14 +465,14 @@ def post_page(post_id):
407
  <p><strong>{{ comment['user'] }}</strong> ({{ comment['date'] }}): {{ comment['text'] }}</p>
408
  </div>
409
  {% endfor %}
410
- <a href="{{ url_for('feed') }}" class="back-btn">Назад к ленте</a>
411
  {% if not is_authenticated %}
412
  <p><a href="{{ url_for('login') }}">Войдите</a>, чтобы ставить лайки и комментировать.</p>
413
  {% endif %}
414
  </div>
415
  <script>
416
  function toggleSidebar() {
417
- document.getElementById('sidebar').classList.toggle('active');
418
  }
419
  </script>
420
  </body>
@@ -447,46 +505,49 @@ def profile():
447
  <head>
448
  <meta charset="UTF-8">
449
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
450
- <title>Профиль - {{ username }}</title>
451
  <link href="https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;600&display=swap" rel="stylesheet">
452
  <style>
453
- body { font-family: 'Poppins', sans-serif; background: #f0f2f5; padding: 20px; margin: 0; }
454
- .sidebar { position: fixed; left: -220px; top: 0; width: 200px; height: 100%; background: #fff; padding: 20px; box-shadow: 2px 0 5px rgba(0,0,0,0.1); transition: left 0.3s; z-index: 1000; }
455
- .sidebar.active { left: 0; }
456
- .container { max-width: 800px; margin: 0 auto; padding-left: 220px; transition: padding-left 0.3s; }
 
 
 
 
 
 
457
  .post-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 20px; }
458
- .post-item { background: #fff; padding: 15px; border-radius: 10px; box-shadow: 0 4px 15px rgba(0,0,0,0.1); }
 
459
  .post-preview { width: 100%; border-radius: 8px; height: 200px; object-fit: cover; }
460
- .upload-btn, .delete-btn, .profile-link, .logout-btn { display: block; margin: 10px 0; padding: 10px; background: #3b82f6; color: white; text-decoration: none; border-radius: 8px; }
461
- .delete-btn { background: #ef4444; border: none; cursor: pointer; }
462
- .profile-link { background: #10b981; }
463
- .logout-btn { background: #ef4444; }
464
- .menu-btn { display: none; font-size: 24px; background: none; border: none; cursor: pointer; position: fixed; top: 20px; left: 20px; z-index: 1001; }
465
- .stats { font-size: 0.9em; color: #666; }
466
  @media (max-width: 768px) {
467
- .container { padding-left: 20px; padding: 15px; max-width: 100%; }
468
- .sidebar { left: -220px; width: 150px; padding: 15px; }
469
- .sidebar.active { left: 0; }
470
  .menu-btn { display: block; }
 
 
 
 
471
  .post-grid { grid-template-columns: 1fr; gap: 15px; }
472
  .post-item { padding: 10px; }
473
  .post-preview { height: 150px; }
474
- .upload-btn, .delete-btn, .profile-link, .logout-btn { font-size: 14px; padding: 8px; }
475
- h1, h2 { font-size: 1.2em; }
476
  }
477
  </style>
478
  </head>
479
  <body>
480
- <button class="menu-btn" onclick="toggleSidebar()">☰</button>
481
- <div class="sidebar" id="sidebar">
482
- <a href="{{ url_for('profile') }}" class="profile-link">
483
- <span style="font-size: 1.2em;">👤</span> {{ username }}
484
- </a>
485
- <a href="{{ url_for('logout') }}" class="logout-btn">Выйти</a>
486
- </div>
487
  <div class="container">
488
  <h1>Профиль: {{ username }}</h1>
489
- <a href="{{ url_for('upload') }}" class="upload-btn">Добавить публикацию</a>
490
  <h2>Ваши публикации</h2>
491
  <div class="post-grid">
492
  {% if user_posts %}
@@ -507,7 +568,7 @@ def profile():
507
  <p class="stats">Просмотров: {{ post['views'] }} | Лайков: {{ post['likes']|length }}</p>
508
  <form method="POST">
509
  <input type="hidden" name="post_id" value="{{ post['id'] }}">
510
- <button type="submit" class="delete-btn">Удалить</button>
511
  </form>
512
  </div>
513
  {% endfor %}
@@ -518,7 +579,7 @@ def profile():
518
  </div>
519
  <script>
520
  function toggleSidebar() {
521
- document.getElementById('sidebar').classList.toggle('active');
522
  }
523
  document.addEventListener('DOMContentLoaded', function() {
524
  const videos = document.querySelectorAll('.post-preview');
@@ -536,7 +597,7 @@ def profile():
536
  </body>
537
  </html>
538
  '''
539
- return render_template_string(html, username=username, user_posts=user_posts, repo_id=REPO_ID)
540
 
541
  # Страница загрузки контента
542
  @app.route('/upload', methods=['GET', 'POST'])
@@ -598,6 +659,7 @@ def upload():
598
 
599
  return redirect(url_for('profile'))
600
 
 
601
  username = session['username']
602
  html = '''
603
  <!DOCTYPE html>
@@ -605,41 +667,41 @@ def upload():
605
  <head>
606
  <meta charset="UTF-8">
607
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
608
- <title>Загрузка контента</title>
609
  <link href="https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;600&display=swap" rel="stylesheet">
610
  <style>
611
- body { font-family: 'Poppins', sans-serif; background: #f0f2f5; padding: 20px; margin: 0; }
612
- .sidebar { position: fixed; left: -220px; top: 0; width: 200px; height: 100%; background: #fff; padding: 20px; box-shadow: 2px 0 5px rgba(0,0,0,0.1); transition: left 0.3s; z-index: 1000; }
613
- .sidebar.active { left: 0; }
614
- .container { max-width: 600px; margin: 0 auto; padding-left: 220px; background: #fff; padding: 20px; border-radius: 10px; box-shadow: 0 4px 15px rgba(0,0,0,0.1); transition: padding-left 0.3s; }
 
 
 
 
 
 
615
  input, textarea { width: 100%; padding: 10px; margin: 10px 0; border: 1px solid #e2e8f0; border-radius: 8px; box-sizing: border-box; }
616
- button { padding: 10px 20px; background: #3b82f6; color: white; border: none; border-radius: 8px; cursor: pointer; width: 100%; }
 
617
  #progress-container { margin-top: 10px; }
618
  #progress-bar { width: 0%; height: 20px; background: #3b82f6; border-radius: 8px; transition: width 0.3s; }
619
- .profile-link, .logout-btn { display: block; margin: 10px 0; padding: 10px; background: #3b82f6; color: white; text-decoration: none; border-radius: 8px; }
620
- .profile-link { background: #10b981; }
621
- .logout-btn { background: #ef4444; }
622
- .menu-btn { display: none; font-size: 24px; background: none; border: none; cursor: pointer; position: fixed; top: 20px; left: 20px; z-index: 1001; }
623
  @media (max-width: 768px) {
624
- .container { padding-left: 20px; padding: 15px; max-width: 100%; }
625
- .sidebar { left: -220px; width: 150px; padding: 15px; }
626
- .sidebar.active { left: 0; }
627
  .menu-btn { display: block; }
 
 
 
 
628
  input, textarea, button { font-size: 14px; padding: 8px; margin: 5px 0; }
629
- h1 { font-size: 1.2em; }
630
  #progress-container { height: 15px; }
631
  #progress-bar { height: 15px; }
632
  }
633
  </style>
634
  </head>
635
  <body>
636
- <button class="menu-btn" onclick="toggleSidebar()">☰</button>
637
- <div class="sidebar" id="sidebar">
638
- <a href="{{ url_for('profile') }}" class="profile-link">
639
- <span style="font-size: 1.2em;">👤</span> {{ username }}
640
- </a>
641
- <a href="{{ url_for('logout') }}" class="logout-btn">Выйти</a>
642
- </div>
643
  <div class="container">
644
  <h1>Загрузить контент</h1>
645
  <form id="upload-form" enctype="multipart/form-data">
@@ -683,13 +745,13 @@ def upload():
683
  xhr.send(formData);
684
  };
685
  function toggleSidebar() {
686
- document.getElementById('sidebar').classList.toggle('active');
687
  }
688
  </script>
689
  </body>
690
  </html>
691
  '''
692
- return render_template_string(html, username=username)
693
 
694
  if __name__ == '__main__':
695
  backup_thread = threading.Thread(target=periodic_backup, daemon=True)
 
85
  upload_db_to_hf()
86
  time.sleep(15)
87
 
88
+ # Базовый шаблон навигации (будет включён во все страницы)
89
+ NAV_HTML = '''
90
+ <nav class="navbar">
91
+ <div class="nav-brand">Контент Хост</div>
92
+ <button class="menu-btn" onclick="toggleSidebar()">☰</button>
93
+ <div class="nav-links" id="nav-links">
94
+ <a href="{{ url_for('feed') }}" class="nav-link">Лента</a>
95
+ {% if is_authenticated %}
96
+ <a href="{{ url_for('profile') }}" class="nav-link">Профиль ({{ username }})</a>
97
+ <a href="{{ url_for('upload') }}" class="nav-link">Загрузить</a>
98
+ <a href="{{ url_for('logout') }}" class="nav-link logout-btn">Выйти</a>
99
+ {% else %}
100
+ <a href="{{ url_for('login') }}" class="nav-link">Войти</a>
101
+ <a href="{{ url_for('register') }}" class="nav-link">Регистрация</a>
102
+ {% endif %}
103
+ </div>
104
+ </nav>
105
+ '''
106
+
107
  # Регистрация пользователя
108
  @app.route('/register', methods=['GET', 'POST'])
109
  def register():
 
122
  flash('Регистрация успешна! Войдите в систему.')
123
  return redirect(url_for('login'))
124
 
125
+ is_authenticated = 'username' in session
126
+ username = session.get('username', None)
127
  html = '''
128
  <!DOCTYPE html>
129
  <html lang="ru">
 
133
  <title>Регистрация</title>
134
  <link href="https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;600&display=swap" rel="stylesheet">
135
  <style>
136
+ body { font-family: 'Poppins', sans-serif; background: #f0f2f5; margin: 0; padding: 0; }
137
+ .navbar { background: #fff; padding: 15px 20px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); position: fixed; top: 0; width: 100%; z-index: 1000; display: flex; justify-content: space-between; align-items: center; }
138
+ .nav-brand { font-size: 1.5em; font-weight: 600; color: #3b82f6; }
139
+ .nav-links { display: flex; gap: 15px; }
140
+ .nav-link { padding: 10px 15px; background: #3b82f6; color: white; text-decoration: none; border-radius: 8px; transition: background 0.3s; }
141
+ .nav-link:hover { background: #2563eb; }
142
+ .logout-btn { background: #ef4444; }
143
+ .logout-btn:hover { background: #dc2626; }
144
+ .menu-btn { display: none; font-size: 24px; background: none; border: none; cursor: pointer; }
145
+ .container { max-width: 400px; margin: 80px auto 20px; background: #fff; padding: 20px; border-radius: 10px; box-shadow: 0 4px 15px rgba(0,0,0,0.1); }
146
  input { width: 100%; padding: 10px; margin: 10px 0; border: 1px solid #e2e8f0; border-radius: 8px; box-sizing: border-box; }
147
+ button { padding: 10px 20px; background: #3b82f6; color: white; border: none; border-radius: 8px; cursor: pointer; width: 100%; transition: background 0.3s; }
148
+ button:hover { background: #2563eb; }
149
  .flash { color: red; margin-bottom: 10px; }
150
+ @media (max-width: 768px) {
151
+ .navbar { flex-wrap: wrap; padding: 10px; }
152
+ .nav-brand { font-size: 1.2em; }
153
+ .menu-btn { display: block; }
154
+ .nav-links { display: none; flex-direction: column; width: 100%; margin-top: 10px; }
155
+ .nav-links.active { display: flex; }
156
+ .nav-link { padding: 8px; font-size: 14px; }
157
+ .container { margin: 60px 10px 10px; padding: 15px; max-width: 100%; }
158
  input, button { font-size: 14px; padding: 8px; }
159
  }
160
  </style>
161
  </head>
162
  <body>
163
+ ''' + NAV_HTML + '''
164
  <div class="container">
165
  <h1>Регистрация</h1>
166
  {% with messages = get_flashed_messages() %}
 
177
  </form>
178
  <p>Уже есть аккаунт? <a href="{{ url_for('login') }}">Войти</a></p>
179
  </div>
180
+ <script>
181
+ function toggleSidebar() {
182
+ document.getElementById('nav-links').classList.toggle('active');
183
+ }
184
+ </script>
185
  </body>
186
  </html>
187
  '''
188
+ return render_template_string(html, is_authenticated=is_authenticated, username=username)
189
 
190
  # Авторизация пользователя
191
  @app.route('/login', methods=['GET', 'POST'])
 
203
  flash('Неверный логин или пароль!')
204
  return redirect(url_for('login'))
205
 
206
+ is_authenticated = 'username' in session
207
+ username = session.get('username', None)
208
  html = '''
209
  <!DOCTYPE html>
210
  <html lang="ru">
 
214
  <title>Вход</title>
215
  <link href="https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;600&display=swap" rel="stylesheet">
216
  <style>
217
+ body { font-family: 'Poppins', sans-serif; background: #f0f2f5; margin: 0; padding: 0; }
218
+ .navbar { background: #fff; padding: 15px 20px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); position: fixed; top: 0; width: 100%; z-index: 1000; display: flex; justify-content: space-between; align-items: center; }
219
+ .nav-brand { font-size: 1.5em; font-weight: 600; color: #3b82f6; }
220
+ .nav-links { display: flex; gap: 15px; }
221
+ .nav-link { padding: 10px 15px; background: #3b82f6; color: white; text-decoration: none; border-radius: 8px; transition: background 0.3s; }
222
+ .nav-link:hover { background: #2563eb; }
223
+ .logout-btn { background: #ef4444; }
224
+ .logout-btn:hover { background: #dc2626; }
225
+ .menu-btn { display: none; font-size: 24px; background: none; border: none; cursor: pointer; }
226
+ .container { max-width: 400px; margin: 80px auto 20px; background: #fff; padding: 20px; border-radius: 10px; box-shadow: 0 4px 15px rgba(0,0,0,0.1); }
227
  input { width: 100%; padding: 10px; margin: 10px 0; border: 1px solid #e2e8f0; border-radius: 8px; box-sizing: border-box; }
228
+ button { padding: 10px 20px; background: #3b82f6; color: white; border: none; border-radius: 8px; cursor: pointer; width: 100%; transition: background 0.3s; }
229
+ button:hover { background: #2563eb; }
230
  .flash { color: red; margin-bottom: 10px; }
231
+ @media (max-width: 768px) {
232
+ .navbar { flex-wrap: wrap; padding: 10px; }
233
+ .nav-brand { font-size: 1.2em; }
234
+ .menu-btn { display: block; }
235
+ .nav-links { display: none; flex-direction: column; width: 100%; margin-top: 10px; }
236
+ .nav-links.active { display: flex; }
237
+ .nav-link { padding: 8px; font-size: 14px; }
238
+ .container { margin: 60px 10px 10px; padding: 15px; max-width: 100%; }
239
  input, button { font-size: 14px; padding: 8px; }
240
  }
241
  </style>
242
  </head>
243
  <body>
244
+ ''' + NAV_HTML + '''
245
  <div class="container">
246
  <h1>Вход</h1>
247
  {% with messages = get_flashed_messages() %}
 
258
  </form>
259
  <p>Нет аккаунта? <a href="{{ url_for('register') }}">Зарегистрироваться</a></p>
260
  </div>
261
+ <script>
262
+ function toggleSidebar() {
263
+ document.getElementById('nav-links').classList.toggle('active');
264
+ }
265
+ </script>
266
  </body>
267
  </html>
268
  '''
269
+ return render_template_string(html, is_authenticated=is_authenticated, username=username)
270
 
271
  # Выход из системы
272
  @app.route('/logout')
 
288
  <head>
289
  <meta charset="UTF-8">
290
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
291
+ <title>Лента - Контент Хост</title>
292
  <link href="https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;600&display=swap" rel="stylesheet">
293
  <style>
294
+ body { font-family: 'Poppins', sans-serif; background: #f0f2f5; margin: 0; padding: 0; }
295
+ .navbar { background: #fff; padding: 15px 20px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); position: fixed; top: 0; width: 100%; z-index: 1000; display: flex; justify-content: space-between; align-items: center; }
296
+ .nav-brand { font-size: 1.5em; font-weight: 600; color: #3b82f6; }
297
+ .nav-links { display: flex; gap: 15px; }
298
+ .nav-link { padding: 10px 15px; background: #3b82f6; color: white; text-decoration: none; border-radius: 8px; transition: background 0.3s; }
299
+ .nav-link:hover { background: #2563eb; }
300
+ .logout-btn { background: #ef4444; }
301
+ .logout-btn:hover { background: #dc2626; }
302
+ .menu-btn { display: none; font-size: 24px; background: none; border: none; cursor: pointer; }
303
+ .container { max-width: 1200px; margin: 80px auto 20px; padding: 20px; }
304
  .post-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 20px; }
305
+ .post-item { background: #fff; padding: 15px; border-radius: 10px; box-shadow: 0 4px 15px rgba(0,0,0,0.1); text-decoration: none; color: #2d3748; transition: transform 0.2s; }
306
+ .post-item:hover { transform: translateY(-5px); }
307
  .post-preview { width: 100%; border-radius: 8px; height: 200px; object-fit: cover; }
308
+ .stats { font-size: 0.9em; color: #666; margin-top: 5px; }
 
 
 
 
309
  @media (max-width: 768px) {
310
+ .navbar { flex-wrap: wrap; padding: 10px; }
311
+ .nav-brand { font-size: 1.2em; }
 
312
  .menu-btn { display: block; }
313
+ .nav-links { display: none; flex-direction: column; width: 100%; margin-top: 10px; }
314
+ .nav-links.active { display: flex; }
315
+ .nav-link { padding: 8px; font-size: 14px; }
316
+ .container { margin: 60px 10px 10px; padding: 15px; }
317
  .post-grid { grid-template-columns: 1fr; gap: 15px; }
318
  .post-item { padding: 10px; }
319
  .post-preview { height: 150px; }
320
+ h1 { font-size: 1.5em; }
321
  }
322
  </style>
323
  </head>
324
  <body>
325
+ ''' + NAV_HTML + '''
 
 
 
 
 
 
 
 
 
 
 
326
  <div class="container">
327
  <h1>Лента публикаций</h1>
328
  <div class="post-grid">
 
345
  </div>
346
  <script>
347
  function toggleSidebar() {
348
+ document.getElementById('nav-links').classList.toggle('active');
349
  }
350
  document.addEventListener('DOMContentLoaded', function() {
351
  const videos = document.querySelectorAll('.post-preview');
 
399
  <head>
400
  <meta charset="UTF-8">
401
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
402
+ <title>{{ post['title'] }} - Контент Хост</title>
403
  <link href="https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;600&display=swap" rel="stylesheet">
404
  <style>
405
+ body { font-family: 'Poppins', sans-serif; background: #f0f2f5; margin: 0; padding: 0; }
406
+ .navbar { background: #fff; padding: 15px 20px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); position: fixed; top: 0; width: 100%; z-index: 1000; display: flex; justify-content: space-between; align-items: center; }
407
+ .nav-brand { font-size: 1.5em; font-weight: 600; color: #3b82f6; }
408
+ .nav-links { display: flex; gap: 15px; }
409
+ .nav-link { padding: 10px 15px; background: #3b82f6; color: white; text-decoration: none; border-radius: 8px; transition: background 0.3s; }
410
+ .nav-link:hover { background: #2563eb; }
 
411
  .logout-btn { background: #ef4444; }
412
+ .logout-btn:hover { background: #dc2626; }
413
+ .menu-btn { display: none; font-size: 24px; background: none; border: none; cursor: pointer; }
414
+ .container { max-width: 800px; margin: 80px auto 20px; background: #fff; padding: 20px; border-radius: 10px; box-shadow: 0 4px 15px rgba(0,0,0,0.1); }
415
+ video, img { width: 100%; border-radius: 8px; max-height: 400px; object-fit: cover; }
416
+ .btn { display: inline-block; margin: 10px 0; padding: 10px 20px; background: #3b82f6; color: white; text-decoration: none; border-radius: 8px; border: none; cursor: pointer; transition: background 0.3s; }
417
+ .btn:hover { background: #2563eb; }
418
  .like-btn.liked { background: #ef4444; }
419
+ .like-btn.liked:hover { background: #dc2626; }
420
+ textarea { width: 100%; padding: 10px; margin: 10px 0; border: 1px solid #e2e8f0; border-radius: 8px; resize: vertical; }
421
  .comment { border-top: 1px solid #e2e8f0; padding: 10px 0; }
422
  @media (max-width: 768px) {
423
+ .navbar { flex-wrap: wrap; padding: 10px; }
424
+ .nav-brand { font-size: 1.2em; }
 
425
  .menu-btn { display: block; }
426
+ .nav-links { display: none; flex-direction: column; width: 100%; margin-top: 10px; }
427
+ .nav-links.active { display: flex; }
428
+ .nav-link { padding: 8px; font-size: 14px; }
429
+ .container { margin: 60px 10px 10px; padding: 15px; }
430
  video, img { max-height: 250px; }
431
+ .btn, textarea { width: 100%; font-size: 14px; padding: 8px; margin: 5px 0; }
432
+ h1 { font-size: 1.5em; }
433
+ h3 { font-size: 1.2em; }
434
  }
435
  </style>
436
  </head>
437
  <body>
438
+ ''' + NAV_HTML + '''
 
 
 
 
 
 
 
 
 
 
 
439
  <div class="container">
440
  <h1>{{ post['title'] }}</h1>
441
  {% if post['type'] == 'video' %}
 
449
  <p>Загрузил: {{ post['uploader'] }} | {{ post['upload_date'] }}</p>
450
  <p>Просмотров: {{ post['views'] }} | Лайков: {{ post['likes']|length }}</p>
451
  {% if is_authenticated %}
452
+ <form method="POST" style="display: inline;">
453
+ <button type="submit" name="like" class="btn like-btn {% if username in post['likes'] %}liked{% endif %}">
454
  {% if username in post['likes'] %}Убрать лайк{% else %}Лайк{% endif %}
455
  </button>
456
  </form>
457
  <form method="POST">
458
  <textarea name="comment" placeholder="Оставьте комментарий" rows="3"></textarea>
459
+ <button type="submit" class="btn">Отправить</button>
460
  </form>
461
  {% endif %}
462
  <h3>Комментарии</h3>
 
465
  <p><strong>{{ comment['user'] }}</strong> ({{ comment['date'] }}): {{ comment['text'] }}</p>
466
  </div>
467
  {% endfor %}
468
+ <a href="{{ url_for('feed') }}" class="btn">Назад к ленте</a>
469
  {% if not is_authenticated %}
470
  <p><a href="{{ url_for('login') }}">Войдите</a>, чтобы ставить лайки и комментировать.</p>
471
  {% endif %}
472
  </div>
473
  <script>
474
  function toggleSidebar() {
475
+ document.getElementById('nav-links').classList.toggle('active');
476
  }
477
  </script>
478
  </body>
 
505
  <head>
506
  <meta charset="UTF-8">
507
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
508
+ <title>Профиль - {{ username }} - Контент Хост</title>
509
  <link href="https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;600&display=swap" rel="stylesheet">
510
  <style>
511
+ body { font-family: 'Poppins', sans-serif; background: #f0f2f5; margin: 0; padding: 0; }
512
+ .navbar { background: #fff; padding: 15px 20px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); position: fixed; top: 0; width: 100%; z-index: 1000; display: flex; justify-content: space-between; align-items: center; }
513
+ .nav-brand { font-size: 1.5em; font-weight: 600; color: #3b82f6; }
514
+ .nav-links { display: flex; gap: 15px; }
515
+ .nav-link { padding: 10px 15px; background: #3b82f6; color: white; text-decoration: none; border-radius: 8px; transition: background 0.3s; }
516
+ .nav-link:hover { background: #2563eb; }
517
+ .logout-btn { background: #ef4444; }
518
+ .logout-btn:hover { background: #dc2626; }
519
+ .menu-btn { display: none; font-size: 24px; background: none; border: none; cursor: pointer; }
520
+ .container { max-width: 800px; margin: 80px auto 20px; padding: 20px; }
521
  .post-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 20px; }
522
+ .post-item { background: #fff; padding: 15px; border-radius: 10px; box-shadow: 0 4px 15px rgba(0,0,0,0.1); transition: transform 0.2s; }
523
+ .post-item:hover { transform: translateY(-5px); }
524
  .post-preview { width: 100%; border-radius: 8px; height: 200px; object-fit: cover; }
525
+ .btn { display: block; margin: 10px 0; padding: 10px 20px; background: #3b82f6; color: white; text-decoration: none; border-radius: 8px; border: none; cursor: pointer; transition: background 0.3s; }
526
+ .btn:hover { background: #2563eb; }
527
+ .delete-btn { background: #ef4444; }
528
+ .delete-btn:hover { background: #dc2626; }
529
+ .stats { font-size: 0.9em; color: #666; margin-top: 5px; }
 
530
  @media (max-width: 768px) {
531
+ .navbar { flex-wrap: wrap; padding: 10px; }
532
+ .nav-brand { font-size: 1.2em; }
 
533
  .menu-btn { display: block; }
534
+ .nav-links { display: none; flex-direction: column; width: 100%; margin-top: 10px; }
535
+ .nav-links.active { display: flex; }
536
+ .nav-link { padding: 8px; font-size: 14px; }
537
+ .container { margin: 60px 10px 10px; padding: 15px; }
538
  .post-grid { grid-template-columns: 1fr; gap: 15px; }
539
  .post-item { padding: 10px; }
540
  .post-preview { height: 150px; }
541
+ .btn { font-size: 14px; padding: 8px; }
542
+ h1, h2 { font-size: 1.5em; }
543
  }
544
  </style>
545
  </head>
546
  <body>
547
+ ''' + NAV_HTML + '''
 
 
 
 
 
 
548
  <div class="container">
549
  <h1>Профиль: {{ username }}</h1>
550
+ <a href="{{ url_for('upload') }}" class="btn">Добавить публикацию</a>
551
  <h2>Ваши публикации</h2>
552
  <div class="post-grid">
553
  {% if user_posts %}
 
568
  <p class="stats">Просмотров: {{ post['views'] }} | Лайков: {{ post['likes']|length }}</p>
569
  <form method="POST">
570
  <input type="hidden" name="post_id" value="{{ post['id'] }}">
571
+ <button type="submit" class="btn delete-btn">Удалить</button>
572
  </form>
573
  </div>
574
  {% endfor %}
 
579
  </div>
580
  <script>
581
  function toggleSidebar() {
582
+ document.getElementById('nav-links').classList.toggle('active');
583
  }
584
  document.addEventListener('DOMContentLoaded', function() {
585
  const videos = document.querySelectorAll('.post-preview');
 
597
  </body>
598
  </html>
599
  '''
600
+ return render_template_string(html, username=username, user_posts=user_posts, repo_id=REPO_ID, is_authenticated=is_authenticated)
601
 
602
  # Страница загрузки контента
603
  @app.route('/upload', methods=['GET', 'POST'])
 
659
 
660
  return redirect(url_for('profile'))
661
 
662
+ is_authenticated = 'username' in session
663
  username = session['username']
664
  html = '''
665
  <!DOCTYPE html>
 
667
  <head>
668
  <meta charset="UTF-8">
669
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
670
+ <title>Загрузка контента - Контент Хост</title>
671
  <link href="https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;600&display=swap" rel="stylesheet">
672
  <style>
673
+ body { font-family: 'Poppins', sans-serif; background: #f0f2f5; margin: 0; padding: 0; }
674
+ .navbar { background: #fff; padding: 15px 20px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); position: fixed; top: 0; width: 100%; z-index: 1000; display: flex; justify-content: space-between; align-items: center; }
675
+ .nav-brand { font-size: 1.5em; font-weight: 600; color: #3b82f6; }
676
+ .nav-links { display: flex; gap: 15px; }
677
+ .nav-link { padding: 10px 15px; background: #3b82f6; color: white; text-decoration: none; border-radius: 8px; transition: background 0.3s; }
678
+ .nav-link:hover { background: #2563eb; }
679
+ .logout-btn { background: #ef4444; }
680
+ .logout-btn:hover { background: #dc2626; }
681
+ .menu-btn { display: none; font-size: 24px; background: none; border: none; cursor: pointer; }
682
+ .container { max-width: 600px; margin: 80px auto 20px; background: #fff; padding: 20px; border-radius: 10px; box-shadow: 0 4px 15px rgba(0,0,0,0.1); }
683
  input, textarea { width: 100%; padding: 10px; margin: 10px 0; border: 1px solid #e2e8f0; border-radius: 8px; box-sizing: border-box; }
684
+ button { padding: 10px 20px; background: #3b82f6; color: white; border: none; border-radius: 8px; cursor: pointer; width: 100%; transition: background 0.3s; }
685
+ button:hover { background: #2563eb; }
686
  #progress-container { margin-top: 10px; }
687
  #progress-bar { width: 0%; height: 20px; background: #3b82f6; border-radius: 8px; transition: width 0.3s; }
 
 
 
 
688
  @media (max-width: 768px) {
689
+ .navbar { flex-wrap: wrap; padding: 10px; }
690
+ .nav-brand { font-size: 1.2em; }
 
691
  .menu-btn { display: block; }
692
+ .nav-links { display: none; flex-direction: column; width: 100%; margin-top: 10px; }
693
+ .nav-links.active { display: flex; }
694
+ .nav-link { padding: 8px; font-size: 14px; }
695
+ .container { margin: 60px 10px 10px; padding: 15px; }
696
  input, textarea, button { font-size: 14px; padding: 8px; margin: 5px 0; }
697
+ h1 { font-size: 1.5em; }
698
  #progress-container { height: 15px; }
699
  #progress-bar { height: 15px; }
700
  }
701
  </style>
702
  </head>
703
  <body>
704
+ ''' + NAV_HTML + '''
 
 
 
 
 
 
705
  <div class="container">
706
  <h1>Загрузить контент</h1>
707
  <form id="upload-form" enctype="multipart/form-data">
 
745
  xhr.send(formData);
746
  };
747
  function toggleSidebar() {
748
+ document.getElementById('nav-links').classList.toggle('active');
749
  }
750
  </script>
751
  </body>
752
  </html>
753
  '''
754
+ return render_template_string(html, username=username, is_authenticated=is_authenticated)
755
 
756
  if __name__ == '__main__':
757
  backup_thread = threading.Thread(target=periodic_backup, daemon=True)