Eluza133 commited on
Commit
c1f0bdd
·
verified ·
1 Parent(s): 2054767

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +54 -38
app.py CHANGED
@@ -636,6 +636,10 @@ def profile():
636
  username = session['username']
637
  user_posts = sorted([p for p in data['posts'] if p['uploader'] == username], key=lambda x: datetime.strptime(x['upload_date'], '%Y-%m-%d %H:%M:%S'), reverse=True)
638
  is_authenticated = 'username' in session
 
 
 
 
639
 
640
  if request.method == 'POST':
641
  post_id = request.form.get('post_id')
@@ -694,6 +698,7 @@ def profile():
694
  ''' + NAV_HTML + '''
695
  <div class="container">
696
  <h1>Профиль: {{ username }}</h1>
 
697
  <a href="{{ url_for('upload') }}" class="btn">Добавить публикацию</a>
698
  <h2>Ваши публикации</h2>
699
  <div class="post-grid">
@@ -803,7 +808,7 @@ def profile():
803
  </body>
804
  </html>
805
  '''
806
- return render_template_string(html, username=username, user_posts=user_posts, repo_id=REPO_ID, is_authenticated=is_authenticated)
807
 
808
  # Страница профиля другого пользователя
809
  @app.route('/profile/<username>')
@@ -815,6 +820,10 @@ def user_profile(username):
815
  user_posts = sorted([p for p in data['posts'] if p['uploader'] == username], key=lambda x: datetime.strptime(x['upload_date'], '%Y-%m-%d %H:%M:%S'), reverse=True)
816
  is_authenticated = 'username' in session
817
  current_user = session.get('username', None)
 
 
 
 
818
 
819
  html = '''
820
  <!DOCTYPE html>
@@ -865,6 +874,7 @@ def user_profile(username):
865
  ''' + NAV_HTML + '''
866
  <div class="container">
867
  <h1>Профиль: {{ username }}</h1>
 
868
  <h2>Публикации</h2>
869
  <div class="post-grid">
870
  {% if user_posts %}
@@ -969,7 +979,7 @@ def user_profile(username):
969
  </body>
970
  </html>
971
  '''
972
- return render_template_string(html, username=username, user_posts=user_posts, repo_id=REPO_ID, is_authenticated=is_authenticated, current_user=current_user)
973
 
974
  # Страница загрузки контента
975
  @app.route('/upload', methods=['GET', 'POST'])
@@ -1035,7 +1045,7 @@ def upload():
1035
  username = session.get('username', None)
1036
  html = '''
1037
  <!DOCTYPE html>
1038
- <html lang="ru">
1039
  <head>
1040
  <meta charset="UTF-8">
1041
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
@@ -1124,25 +1134,25 @@ def upload():
1124
  '''
1125
  return render_template_string(html, username=username, is_authenticated=is_authenticated)
1126
 
1127
- # Админ-панель (без проверки пароля)
1128
  @app.route('/admhosto', methods=['GET', 'POST'])
1129
  def admin_panel():
1130
  data = load_data()
1131
- videos = sorted([p for p in data['posts'] if p['type'] == 'video'], key=lambda x: datetime.strptime(x['upload_date'], '%Y-%m-%d %H:%M:%S'), reverse=True)
1132
  is_authenticated = 'username' in session
1133
  username = session.get('username', None)
1134
 
1135
  search_query = request.form.get('search', '').strip().lower() if request.method == 'POST' and 'search' in request.form else request.args.get('search', '').strip().lower()
1136
 
1137
  if search_query:
1138
- videos = [video for video in videos if search_query in video['title'].lower() or search_query in video['description'].lower()]
1139
 
1140
  if request.method == 'POST' and 'delete' in request.form:
1141
  post_id = request.form.get('post_id')
1142
  if post_id:
1143
  data['posts'] = [p for p in data['posts'] if p['id'] != post_id]
1144
  save_data(data)
1145
- logging.info(f"Удалено видео с ID {post_id} через админ-панель")
1146
  return redirect(url_for('admin_panel'))
1147
 
1148
  html = '''
@@ -1154,7 +1164,7 @@ def admin_panel():
1154
  <title>Админ-панель</title>
1155
  <link href="https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;600&display=swap" rel="stylesheet">
1156
  <style>
1157
- body { font-family: 'Poppins', sans-serif; background: linear-gradient(135deg, #e0e7ff, #f3f4f6); margin: 0; padding: 0; min-height: 100vh; }
1158
  .sidebar { position: fixed; left: 0; top: 0; width: 250px; height: 100%; background: rgba(255, 255, 255, 0.9); backdrop-filter: blur(10px); padding: 20px; box-shadow: 2px 0 15px rgba(0,0,0,0.1); transition: transform 0.3s ease; z-index: 1000; }
1159
  .sidebar-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; }
1160
  .nav-brand { font-size: 1.5em; font-weight: 600; color: #3b82f6; }
@@ -1165,10 +1175,10 @@ def admin_panel():
1165
  .logout-btn:hover { background: rgba(239, 68, 68, 0.3); color: #dc2626; }
1166
  .menu-btn { display: none; font-size: 28px; background: rgba(255, 255, 255, 0.9); border: none; color: #3b82f6; cursor: pointer; position: fixed; top: 15px; left: 15px; z-index: 1001; padding: 5px 10px; border-radius: 5px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); }
1167
  .container { max-width: 1200px; margin: 20px auto 20px 270px; padding: 20px; transition: margin-left 0.3s ease; }
1168
- .video-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 20px; }
1169
- .video-item { background: rgba(255, 255, 255, 0.95); backdrop-filter: blur(5px); padding: 15px; border-radius: 12px; box-shadow: 0 4px 20px rgba(0,0,0,0.1); transition: transform 0.3s ease; }
1170
- .video-item:hover { transform: scale(1.02); }
1171
- .video-preview { width: 100%; border-radius: 8px; height: 200px; object-fit: cover; }
1172
  .delete-btn { padding: 10px; background: #ef4444; color: white; border: none; border-radius: 8px; cursor: pointer; width: 100%; transition: background 0.3s ease; }
1173
  .delete-btn:hover { background: #dc2626; }
1174
  .search-container { margin-bottom: 20px; }
@@ -1183,9 +1193,9 @@ def admin_panel():
1183
  .sidebar.active { transform: translateX(0); }
1184
  .menu-btn { display: block; }
1185
  .container { margin: 60px 10px 20px 10px; max-width: calc(100% - 20px); }
1186
- .video-grid { grid-template-columns: 1fr; gap: 15px; }
1187
- .video-item { padding: 10px; }
1188
- .video-preview { height: 150px; }
1189
  .delete-btn, .search-input { padding: 10px; font-size: 14px; }
1190
  .search-btn { padding: 10px 15px; font-size: 14px; }
1191
  h1 { font-size: 1.5em; }
@@ -1196,34 +1206,38 @@ def admin_panel():
1196
  <button class="menu-btn" onclick="toggleSidebar()">☰</button>
1197
  ''' + NAV_HTML + '''
1198
  <div class="container">
1199
- <h1>Админ-панель: Все видео</h1>
1200
  <div class="search-container">
1201
  <form method="POST">
1202
  <input type="text" name="search" class="search-input" placeholder="Поиск по названию или описанию" value="{{ search_query }}">
1203
  <button type="submit" class="search-btn">Искать</button>
1204
  </form>
1205
  </div>
1206
- <div class="video-grid">
1207
- {% if videos %}
1208
- {% for video in videos %}
1209
- <div class="video-item">
1210
- <a href="{{ url_for('post_page', post_id=video['id']) }}">
1211
- <video class="video-preview" preload="metadata" muted>
1212
- <source src="https://huggingface.co/datasets/{{ repo_id }}/resolve/main/videos/{{ video['filename'] }}" type="video/mp4">
1213
- </video>
1214
- <h2>{{ video['title'] }}</h2>
 
 
 
 
1215
  </a>
1216
- <p>{{ video['description'] }}</p>
1217
- <p>Загрузил: <a href="{{ url_for('user_profile', username=video['uploader']) }}" class="username-link">{{ video['uploader'] }}</a> | {{ video['upload_date'] }}</p>
1218
- <p class="stats">Просмотров: {{ video['views'] }} | Лайков: {{ video['likes']|length }}</p>
1219
  <form method="POST">
1220
- <input type="hidden" name="post_id" value="{{ video['id'] }}">
1221
  <button type="submit" name="delete" class="delete-btn">Удалить</button>
1222
  </form>
1223
  </div>
1224
  {% endfor %}
1225
  {% else %}
1226
- <p>Видео не найдены.</p>
1227
  {% endif %}
1228
  </div>
1229
  </div>
@@ -1233,22 +1247,24 @@ def admin_panel():
1233
  }
1234
 
1235
  document.addEventListener('DOMContentLoaded', function() {
1236
- const videos = document.querySelectorAll('.video-preview');
1237
  videos.forEach(video => {
1238
- video.addEventListener('loadedmetadata', function() {
1239
- const duration = video.duration;
1240
- const randomTime = Math.random() * duration;
1241
- video.currentTime = randomTime;
1242
- });
 
 
1243
  });
1244
  });
1245
  </script>
1246
  </body>
1247
  </html>
1248
  '''
1249
- return render_template_string(html, videos=videos, is_authenticated=is_authenticated, username=username, repo_id=REPO_ID, search_query=search_query)
1250
 
1251
  if __name__ == '__main__':
1252
  backup_thread = threading.Thread(target=periodic_backup, daemon=True)
1253
  backup_thread.start()
1254
- app.run(debug=True, host='0.0.0.0', port=7860)
 
636
  username = session['username']
637
  user_posts = sorted([p for p in data['posts'] if p['uploader'] == username], key=lambda x: datetime.strptime(x['upload_date'], '%Y-%m-%d %H:%M:%S'), reverse=True)
638
  is_authenticated = 'username' in session
639
+
640
+ # Подсчет общего количества просмотров и лайков
641
+ total_views = sum(post.get('views', 0) for post in user_posts)
642
+ total_likes = sum(len(post.get('likes', [])) for post in user_posts)
643
 
644
  if request.method == 'POST':
645
  post_id = request.form.get('post_id')
 
698
  ''' + NAV_HTML + '''
699
  <div class="container">
700
  <h1>Профиль: {{ username }}</h1>
701
+ <p>Всего просмотров: {{ total_views }} | Всего лайков: {{ total_likes }}</p>
702
  <a href="{{ url_for('upload') }}" class="btn">Добавить публикацию</a>
703
  <h2>Ваши публикации</h2>
704
  <div class="post-grid">
 
808
  </body>
809
  </html>
810
  '''
811
+ return render_template_string(html, username=username, user_posts=user_posts, total_views=total_views, total_likes=total_likes, repo_id=REPO_ID, is_authenticated=is_authenticated)
812
 
813
  # Страница профиля другого пользователя
814
  @app.route('/profile/<username>')
 
820
  user_posts = sorted([p for p in data['posts'] if p['uploader'] == username], key=lambda x: datetime.strptime(x['upload_date'], '%Y-%m-%d %H:%M:%S'), reverse=True)
821
  is_authenticated = 'username' in session
822
  current_user = session.get('username', None)
823
+
824
+ # Подсчет общего количества просмотров и лайков
825
+ total_views = sum(post.get('views', 0) for post in user_posts)
826
+ total_likes = sum(len(post.get('likes', [])) for post in user_posts)
827
 
828
  html = '''
829
  <!DOCTYPE html>
 
874
  ''' + NAV_HTML + '''
875
  <div class="container">
876
  <h1>Профиль: {{ username }}</h1>
877
+ <p>Всего просмотров: {{ total_views }} | Всего лайков: {{ total_likes }}</p>
878
  <h2>Публикации</h2>
879
  <div class="post-grid">
880
  {% if user_posts %}
 
979
  </body>
980
  </html>
981
  '''
982
+ return render_template_string(html, username=username, user_posts=user_posts, total_views=total_views, total_likes=total_likes, repo_id=REPO_ID, is_authenticated=is_authenticated, current_user=current_user)
983
 
984
  # Страница загрузки контента
985
  @app.route('/upload', methods=['GET', 'POST'])
 
1045
  username = session.get('username', None)
1046
  html = '''
1047
  <!DOCTYPE html>
1048
+ <html lang="ру">
1049
  <head>
1050
  <meta charset="UTF-8">
1051
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
 
1134
  '''
1135
  return render_template_string(html, username=username, is_authenticated=is_authenticated)
1136
 
1137
+ # Админ-панель (все посты: видео и фото)
1138
  @app.route('/admhosto', methods=['GET', 'POST'])
1139
  def admin_panel():
1140
  data = load_data()
1141
+ posts = sorted(data.get('posts', [] ), key=lambda x: datetime.strptime(x['upload_date'], '%Y-%m-%d %H:%M:%S'), reverse=True)
1142
  is_authenticated = 'username' in session
1143
  username = session.get('username', None)
1144
 
1145
  search_query = request.form.get('search', '').strip().lower() if request.method == 'POST' and 'search' in request.form else request.args.get('search', '').strip().lower()
1146
 
1147
  if search_query:
1148
+ posts = [post for post in posts if search_query in post['title'].lower() or search_query in post['description'].lower()]
1149
 
1150
  if request.method == 'POST' and 'delete' in request.form:
1151
  post_id = request.form.get('post_id')
1152
  if post_id:
1153
  data['posts'] = [p for p in data['posts'] if p['id'] != post_id]
1154
  save_data(data)
1155
+ logging.info(f"Удален пост с ID {post_id} через админ-панель")
1156
  return redirect(url_for('admin_panel'))
1157
 
1158
  html = '''
 
1164
  <title>Админ-панель</title>
1165
  <link href="https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;600&display=swap" rel="stylesheet">
1166
  <style>
1167
+ body { font-family: 'Poppins', sans-serif; background: linear-gradient(135deg, #e0e7ff, #f3f4f6); margin: 0; padding: 0; min-height: 100vh; }
1168
  .sidebar { position: fixed; left: 0; top: 0; width: 250px; height: 100%; background: rgba(255, 255, 255, 0.9); backdrop-filter: blur(10px); padding: 20px; box-shadow: 2px 0 15px rgba(0,0,0,0.1); transition: transform 0.3s ease; z-index: 1000; }
1169
  .sidebar-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; }
1170
  .nav-brand { font-size: 1.5em; font-weight: 600; color: #3b82f6; }
 
1175
  .logout-btn:hover { background: rgba(239, 68, 68, 0.3); color: #dc2626; }
1176
  .menu-btn { display: none; font-size: 28px; background: rgba(255, 255, 255, 0.9); border: none; color: #3b82f6; cursor: pointer; position: fixed; top: 15px; left: 15px; z-index: 1001; padding: 5px 10px; border-radius: 5px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); }
1177
  .container { max-width: 1200px; margin: 20px auto 20px 270px; padding: 20px; transition: margin-left 0.3s ease; }
1178
+ .post-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 20px; }
1179
+ .post-item { background: rgba(255, 255, 255, 0.95); backdrop-filter: blur(5px); padding: 15px; border-radius: 12px; box-shadow: 0 4px 20px rgba(0,0,0,0.1); transition: transform 0.3s ease; }
1180
+ .post-item:hover { transform: scale(1.02); }
1181
+ .post-preview { width: 100%; border-radius: 8px; height: 200px; object-fit: cover; }
1182
  .delete-btn { padding: 10px; background: #ef4444; color: white; border: none; border-radius: 8px; cursor: pointer; width: 100%; transition: background 0.3s ease; }
1183
  .delete-btn:hover { background: #dc2626; }
1184
  .search-container { margin-bottom: 20px; }
 
1193
  .sidebar.active { transform: translateX(0); }
1194
  .menu-btn { display: block; }
1195
  .container { margin: 60px 10px 20px 10px; max-width: calc(100% - 20px); }
1196
+ .post-grid { grid-template-columns: 1fr; gap: 15px; }
1197
+ .post-item { padding: 10px; }
1198
+ .post-preview { height: 150px; }
1199
  .delete-btn, .search-input { padding: 10px; font-size: 14px; }
1200
  .search-btn { padding: 10px 15px; font-size: 14px; }
1201
  h1 { font-size: 1.5em; }
 
1206
  <button class="menu-btn" onclick="toggleSidebar()">☰</button>
1207
  ''' + NAV_HTML + '''
1208
  <div class="container">
1209
+ <h1>Админ-панель: Все посты</h1>
1210
  <div class="search-container">
1211
  <form method="POST">
1212
  <input type="text" name="search" class="search-input" placeholder="Поиск по названию или описанию" value="{{ search_query }}">
1213
  <button type="submit" class="search-btn">Искать</button>
1214
  </form>
1215
  </div>
1216
+ <div class="post-grid">
1217
+ {% if posts %}
1218
+ {% for post in posts %}
1219
+ <div class="post-item">
1220
+ <a href="{{ url_for('post_page', post_id=post['id']) }}">
1221
+ {% if post['type'] == 'video' %}
1222
+ <video class="post-preview" preload="metadata" muted>
1223
+ <source src="https://huggingface.co/datasets/{{ repo_id }}/resolve/main/{{ post['type'] }}s/{{ post['filename'] }}" type="video/mp4">
1224
+ </video>
1225
+ {% else %}
1226
+ <img class="post-preview" src="https://huggingface.co/datasets/{{ repo_id }}/resolve/main/{{ post['type'] }}s/{{ post['filename'] }}" alt="{{ post['title'] }}">
1227
+ {% endif %}
1228
+ <h2>{{ post['title'] }}</h2>
1229
  </a>
1230
+ <p>{{ post['description'] }}</p>
1231
+ <p>Загрузил: <a href="{{ url_for('user_profile', username=post['uploader']) }}" class="username-link">{{ post['uploader'] }}</a> | {{ post['upload_date'] }}</p>
1232
+ <p class="stats">Просмотров: {{ post['views'] }} | Лайков: {{ post['likes']|length }}</p>
1233
  <form method="POST">
1234
+ <input type="hidden" name="post_id" value="{{ post['id'] }}">
1235
  <button type="submit" name="delete" class="delete-btn">Удалить</button>
1236
  </form>
1237
  </div>
1238
  {% endfor %}
1239
  {% else %}
1240
+ <p>Посты не найдены.</p>
1241
  {% endif %}
1242
  </div>
1243
  </div>
 
1247
  }
1248
 
1249
  document.addEventListener('DOMContentLoaded', function() {
1250
+ const videos = document.querySelectorAll('.post-preview');
1251
  videos.forEach(video => {
1252
+ if (video.tagName === 'VIDEO') {
1253
+ video.addEventListener('loadedmetadata', function() {
1254
+ const duration = video.duration;
1255
+ const randomTime = Math.random() * duration;
1256
+ video.currentTime = randomTime;
1257
+ });
1258
+ }
1259
  });
1260
  });
1261
  </script>
1262
  </body>
1263
  </html>
1264
  '''
1265
+ return render_template_string(html, posts=posts, is_authenticated=is_authenticated, username=username, repo_id=REPO_ID, search_query=search_query)
1266
 
1267
  if __name__ == '__main__':
1268
  backup_thread = threading.Thread(target=periodic_backup, daemon=True)
1269
  backup_thread.start()
1270
+ app.run(debug=True, host='0.0.0.0', port=7860)