Eluza133 commited on
Commit
a5e8401
·
verified ·
1 Parent(s): cdde7cc

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +187 -21
app.py CHANGED
@@ -1,4 +1,4 @@
1
- from flask import Flask, render_template_string, request, redirect, url_for, Response, jsonify
2
  import json
3
  import os
4
  import logging
@@ -7,11 +7,13 @@ import time
7
  from datetime import datetime
8
  from huggingface_hub import HfApi, hf_hub_download
9
  from werkzeug.utils import secure_filename
 
10
 
11
  app = Flask(__name__)
 
12
  DATA_FILE = 'datatest.json'
13
  REPO_ID = "Eluza133/w1f9"
14
- HF_TOKEN_WRITE = os.getenv("HF_TOKEN") # Убедитесь, что токен имеет права на запись
15
  HF_TOKEN_READ = os.getenv("HF_TOKEN_READ") or HF_TOKEN_WRITE
16
 
17
  # Настройка логирования
@@ -23,12 +25,16 @@ def load_data():
23
  download_db_from_hf()
24
  with open(DATA_FILE, 'r', encoding='utf-8') as file:
25
  data = json.load(file)
26
- if not isinstance(data, dict) or 'videos' not in data:
27
- return {'videos': []}
 
 
 
 
28
  return data
29
  except Exception as e:
30
  logging.error(f"Ошибка загрузки данных: {e}")
31
- return {'videos': []}
32
 
33
  def save_data(data):
34
  try:
@@ -74,9 +80,127 @@ def periodic_backup():
74
  upload_db_to_hf()
75
  time.sleep(15)
76
 
77
- # Главная страница - лента видео
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
78
  @app.route('/')
79
  def video_feed():
 
 
 
80
  data = load_data()
81
  videos = data['videos']
82
  html = '''
@@ -90,42 +214,84 @@ def video_feed():
90
  body { font-family: 'Poppins', sans-serif; background: #f0f2f5; padding: 20px; }
91
  .container { max-width: 1200px; margin: 0 auto; }
92
  .video-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 20px; }
93
- .video-item { background: #fff; padding: 15px; border-radius: 10px; box-shadow: 0 4px 15px rgba(0,0,0,0.1); }
94
- .video-item video { width: 100%; border-radius: 8px; }
95
- .upload-btn { display: block; margin: 20px auto; padding: 10px 20px; background: #3b82f6; color: white; text-align: center; text-decoration: none; border-radius: 8px; }
96
- #progress-bar { display: none; width: 100%; height: 20px; margin-top: 10px; }
97
  </style>
98
  </head>
99
  <body>
100
  <div class="container">
101
  <h1>Лента видео</h1>
102
  <a href="/upload" class="upload-btn">Загрузить видео</a>
 
103
  <div class="video-grid">
104
  {% for video in videos %}
105
- <div class="video-item">
 
106
  <h2>{{ video['title'] }}</h2>
107
  <p>{{ video['description'] }}</p>
108
- <video controls>
109
- <source src="https://huggingface.co/datasets/{{ repo_id }}/resolve/main/videos/{{ video['filename'] }}" type="video/mp4">
110
- </video>
111
  <p>Загрузил: {{ video['uploader'] }} | {{ video['upload_date'] }}</p>
112
- </div>
113
  {% endfor %}
114
  </div>
115
  </div>
116
  </body>
117
  </html>
118
  '''
119
- return render_template_string(html, videos=videos, repo_id=REPO_ID)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
120
 
121
- # Страница загрузки видео
122
  @app.route('/upload', methods=['GET', 'POST'])
123
- def upload视频():
 
 
 
124
  if request.method == 'POST':
125
  title = request.form.get('title')
126
  description = request.form.get('description')
127
  video_file = request.files.get('video')
128
- uploader = "user1" # Можно добавить авторизацию позже
129
 
130
  if not title or not video_file:
131
  return "Укажите название и выберите видео", 400
@@ -135,7 +301,7 @@ def upload视频():
135
  os.makedirs('uploads', exist_ok=True)
136
  video_file.save(temp_path)
137
 
138
- # Загрузка на Hugging Face с прогрессом
139
  api = HfApi()
140
  api.upload_file(
141
  path_or_fileobj=temp_path,
@@ -143,7 +309,7 @@ def upload视频():
143
  repo_id=REPO_ID,
144
  repo_type="dataset",
145
  token=HF_TOKEN_WRITE,
146
- commit_message=f"Добавлено видео: {title}"
147
  )
148
 
149
  # Обновление базы данных
 
1
+ from flask import Flask, render_template_string, request, redirect, url_for, session, flash
2
  import json
3
  import os
4
  import logging
 
7
  from datetime import datetime
8
  from huggingface_hub import HfApi, hf_hub_download
9
  from werkzeug.utils import secure_filename
10
+ import hashlib
11
 
12
  app = Flask(__name__)
13
+ app.secret_key = 'supersecretkey' # Для сессий, в продакшене замените на безопасный ключ
14
  DATA_FILE = 'datatest.json'
15
  REPO_ID = "Eluza133/w1f9"
16
+ HF_TOKEN_WRITE = os.getenv("HF_TOKEN") # Токен с правами записи
17
  HF_TOKEN_READ = os.getenv("HF_TOKEN_READ") or HF_TOKEN_WRITE
18
 
19
  # Настройка логирования
 
25
  download_db_from_hf()
26
  with open(DATA_FILE, 'r', encoding='utf-8') as file:
27
  data = json.load(file)
28
+ if not isinstance(data, dict):
29
+ return {'videos': [], 'users': {}}
30
+ if 'videos' not in data:
31
+ data['videos'] = []
32
+ if 'users' not in data:
33
+ data['users'] = {}
34
  return data
35
  except Exception as e:
36
  logging.error(f"Ошибка загрузки данных: {e}")
37
+ return {'videos': [], 'users': {}}
38
 
39
  def save_data(data):
40
  try:
 
80
  upload_db_to_hf()
81
  time.sleep(15)
82
 
83
+ # Регистрация пользователя
84
+ @app.route('/register', methods=['GET', 'POST'])
85
+ def register():
86
+ if request.method == 'POST':
87
+ username = request.form.get('username')
88
+ password = request.form.get('password')
89
+ data = load_data()
90
+
91
+ if username in data['users']:
92
+ flash('Пользователь уже существует!')
93
+ return redirect(url_for('register'))
94
+
95
+ # Хешируем пароль
96
+ hashed_password = hashlib.sha256(password.encode()).hexdigest()
97
+ data['users'][username] = {'password': hashed_password}
98
+ save_data(data)
99
+ flash('Регистрация успешна! Войдите в систему.')
100
+ return redirect(url_for('login'))
101
+
102
+ html = '''
103
+ <!DOCTYPE html>
104
+ <html lang="ru">
105
+ <head>
106
+ <meta charset="UTF-8">
107
+ <title>Регистрация</title>
108
+ <link href="https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;600&display=swap" rel="stylesheet">
109
+ <style>
110
+ body { font-family: 'Poppins', sans-serif; background: #f0f2f5; padding: 20px; }
111
+ .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); }
112
+ input { width: 100%; padding: 10px; margin: 10px 0; border: 1px solid #e2e8f0; border-radius: 8px; }
113
+ button { padding: 10px 20px; background: #3b82f6; color: white; border: none; border-radius: 8px; cursor: pointer; }
114
+ .flash { color: red; margin-bottom: 10px; }
115
+ </style>
116
+ </head>
117
+ <body>
118
+ <div class="container">
119
+ <h1>Регистрация</h1>
120
+ {% with messages = get_flashed_messages() %}
121
+ {% if messages %}
122
+ {% for message in messages %}
123
+ <div class="flash">{{ message }}</div>
124
+ {% endfor %}
125
+ {% endif %}
126
+ {% endwith %}
127
+ <form method="POST">
128
+ <input type="text" name="username" placeholder="Логин" required>
129
+ <input type="password" name="password" placeholder="Пароль" required>
130
+ <button type="submit">Зарегистрироваться</button>
131
+ </form>
132
+ <p>Уже есть аккаунт? <a href="{{ url_for('login') }}">Войти</a></p>
133
+ </div>
134
+ </body>
135
+ </html>
136
+ '''
137
+ return render_template_string(html)
138
+
139
+ # Авторизация пользователя
140
+ @app.route('/login', methods=['GET', 'POST'])
141
+ def login():
142
+ if request.method == 'POST':
143
+ username = request.form.get('username')
144
+ password = request.form.get('password')
145
+ data = load_data()
146
+
147
+ hashed_password = hashlib.sha256(password.encode()).hexdigest()
148
+ if username in data['users'] and data['users'][username]['password'] == hashed_password:
149
+ session['username'] = username
150
+ return redirect(url_for('video_feed'))
151
+ else:
152
+ flash('Неверный логин или пароль!')
153
+ return redirect(url_for('login'))
154
+
155
+ html = '''
156
+ <!DOCTYPE html>
157
+ <html lang="ru">
158
+ <head>
159
+ <meta charset="UTF-8">
160
+ <title>Вход</title>
161
+ <link href="https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;600&display=swap" rel="stylesheet">
162
+ <style>
163
+ body { font-family: 'Poppins', sans-serif; background: #f0f2f5; padding: 20px; }
164
+ .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); }
165
+ input { width: 100%; padding: 10px; margin: 10px 0; border: 1px solid #e2e8f0; border-radius: 8px; }
166
+ button { padding: 10px 20px; background: #3b82f6; color: white; border: none; border-radius: 8px; cursor: pointer; }
167
+ .flash { color: red; margin-bottom: 10px; }
168
+ </style>
169
+ </head>
170
+ <body>
171
+ <div class="container">
172
+ <h1>Вход</h1>
173
+ {% with messages = get_flashed_messages() %}
174
+ {% if messages %}
175
+ {% for message in messages %}
176
+ <div class="flash">{{ message }}</div>
177
+ {% endfor %}
178
+ {% endif %}
179
+ {% endwith %}
180
+ <form method="POST">
181
+ <input type="text" name="username" placeholder="Логин" required>
182
+ <input type="password" name="password" placeholder="Пароль" required>
183
+ <button type="submit">Войти</button>
184
+ </form>
185
+ <p>Нет аккаунта? <a href="{{ url_for('register') }}">Зарегистрироваться</a></p>
186
+ </div>
187
+ </body>
188
+ </html>
189
+ '''
190
+ return render_template_string(html)
191
+
192
+ # Выход из системы
193
+ @app.route('/logout')
194
+ def logout():
195
+ session.pop('username', None)
196
+ return redirect(url_for('login'))
197
+
198
+ # Главная страница - лента видео с превью
199
  @app.route('/')
200
  def video_feed():
201
+ if 'username' not in session:
202
+ return redirect(url_for('login'))
203
+
204
  data = load_data()
205
  videos = data['videos']
206
  html = '''
 
214
  body { font-family: 'Poppins', sans-serif; background: #f0f2f5; padding: 20px; }
215
  .container { max-width: 1200px; margin: 0 auto; }
216
  .video-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 20px; }
217
+ .video-item { background: #fff; padding: 15px; border-radius: 10px; box-shadow: 0 4px 15px rgba(0,0,0,0.1); text-decoration: none; color: #2d3748; }
218
+ .video-item img { width: 100%; border-radius: 8px; height: 200px; object-fit: cover; }
219
+ .upload-btn, .logout-btn { display: inline-block; margin: 20px 10px; padding: 10px 20px; background: #3b82f6; color: white; text-align: center; text-decoration: none; border-radius: 8px; }
220
+ .logout-btn { background: #ef4444; }
221
  </style>
222
  </head>
223
  <body>
224
  <div class="container">
225
  <h1>Лента видео</h1>
226
  <a href="/upload" class="upload-btn">Загрузить видео</a>
227
+ <a href="/logout" class="logout-btn">Выйти</a>
228
  <div class="video-grid">
229
  {% for video in videos %}
230
+ <a href="{{ url_for('video_page', title=video['title']) }}" class="video-item">
231
+ <img src="https://via.placeholder.com/300x200?text={{ video['title'] }}" alt="{{ video['title'] }}">
232
  <h2>{{ video['title'] }}</h2>
233
  <p>{{ video['description'] }}</p>
 
 
 
234
  <p>Загрузил: {{ video['uploader'] }} | {{ video['upload_date'] }}</p>
235
+ </a>
236
  {% endfor %}
237
  </div>
238
  </div>
239
  </body>
240
  </html>
241
  '''
242
+ return render_template_string(html, videos=videos)
243
+
244
+ # Страница отдельного видео
245
+ @app.route('/video/<title>')
246
+ def video_page(title):
247
+ if 'username' not in session:
248
+ return redirect(url_for('login'))
249
+
250
+ data = load_data()
251
+ video = next((v for v in data['videos'] if v['title'] == title), None)
252
+ if not video:
253
+ return "Видео не найдено", 404
254
+
255
+ html = '''
256
+ <!DOCTYPE html>
257
+ <html lang="ru">
258
+ <head>
259
+ <meta charset="UTF-8">
260
+ <title>{{ video['title'] }}</title>
261
+ <link href="https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;600&display=swap" rel="stylesheet">
262
+ <style>
263
+ body { font-family: 'Poppins', sans-serif; background: #f0f2f5; padding: 20px; }
264
+ .container { max-width: 800px; margin: 0 auto; background: #fff; padding: 20px; border-radius: 10px; box-shadow: 0 4px 15px rgba(0,0,0,0.1); }
265
+ video { width: 100%; border-radius: 8px; }
266
+ .back-btn { display: inline-block; margin-top: 20px; padding: 10px 20px; background: #3b82f6; color: white; text-decoration: none; border-radius: 8px; }
267
+ </style>
268
+ </head>
269
+ <body>
270
+ <div class="container">
271
+ <h1>{{ video['title'] }}</h1>
272
+ <video controls>
273
+ <source src="https://huggingface.co/datasets/{{ repo_id }}/resolve/main/videos/{{ video['filename'] }}" type="video/mp4">
274
+ </video>
275
+ <p>{{ video['description'] }}</p>
276
+ <p>Загрузил: {{ video['uploader'] }} | {{ video['upload_date'] }}</p>
277
+ <a href="{{ url_for('video_feed') }}" class="back-btn">Назад к ленте</a>
278
+ </div>
279
+ </body>
280
+ </html>
281
+ '''
282
+ return render_template_string(html, video=video, repo_id=REPO_ID)
283
 
284
+ # Страница загрузки видео (только для авторизованных)
285
  @app.route('/upload', methods=['GET', 'POST'])
286
+ def upload_video():
287
+ if 'username' not in session:
288
+ return redirect(url_for('login'))
289
+
290
  if request.method == 'POST':
291
  title = request.form.get('title')
292
  description = request.form.get('description')
293
  video_file = request.files.get('video')
294
+ uploader = session['username']
295
 
296
  if not title or not video_file:
297
  return "Укажите название и выберите видео", 400
 
301
  os.makedirs('uploads', exist_ok=True)
302
  video_file.save(temp_path)
303
 
304
+ # Загрузка на Hugging Face
305
  api = HfApi()
306
  api.upload_file(
307
  path_or_fileobj=temp_path,
 
309
  repo_id=REPO_ID,
310
  repo_type="dataset",
311
  token=HF_TOKEN_WRITE,
312
+ commit_message=f"Добавлено видео: {title} пользователем {uploader}"
313
  )
314
 
315
  # Обновление базы данных