from flask import Flask, render_template_string, request, redirect, url_for, session, flash import json import os import logging import threading import time from datetime import datetime from huggingface_hub import HfApi, hf_hub_download from werkzeug.utils import secure_filename import random app = Flask(__name__) app.secret_key = 'supersecretkey' # Замените на безопасный ключ в продакшене DATA_FILE = 'data_ostenhost.json' REPO_ID = "Eluza133/w1f9" HF_TOKEN_WRITE = os.getenv("HF_TOKEN") # Токен с правами записи HF_TOKEN_READ = os.getenv("HF_TOKEN_READ") or HF_TOKEN_WRITE # Настройка логирования logging.basicConfig(level=logging.DEBUG) # Функции работы с базой данных def load_data(): try: download_db_from_hf() with open(DATA_FILE, 'r', encoding='utf-8') as file: data = json.load(file) if not isinstance(data, dict): logging.warning("Данные не в формате dict, инициализация пустой базы") return {'posts': [], 'users': {}, 'pending_organizations': [], 'orders': {}, 'user_orders': {}} if 'posts' not in data: data['posts'] = [] if 'users' not in data: data['users'] = {} if 'pending_organizations' not in data: data['pending_organizations'] = [] if 'orders' not in data: data['orders'] = {} if 'user_orders' not in data: data['user_orders'] = {} logging.info("Данные успешно загружены") return data except Exception as e: logging.error(f"Ошибка загрузки данных: {e}") return {'posts': [], 'users': {}, 'pending_organizations': [], 'orders': {}, 'user_orders': {}} def save_data(data): try: with open(DATA_FILE, 'w', encoding='utf-8') as file: json.dump(data, file, ensure_ascii=False, indent=4) upload_db_to_hf() logging.info("Данные сохранены и загружены на HF") except Exception as e: logging.error(f"Ошибка сохранения данных: {e}") raise def upload_db_to_hf(): try: api = HfApi() api.upload_file( path_or_fileobj=DATA_FILE, path_in_repo=DATA_FILE, repo_id=REPO_ID, repo_type="dataset", token=HF_TOKEN_WRITE, commit_message=f"Backup {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}" ) logging.info("База данных загружена на Hugging Face") except Exception as e: logging.error(f"Ошибка загрузки базы: {e}") def download_db_from_hf(): try: hf_hub_download( repo_id=REPO_ID, filename=DATA_FILE, repo_type="dataset", token=HF_TOKEN_READ, local_dir=".", local_dir_use_symlinks=False ) logging.info("База данных скачана с Hugging Face") except Exception as e: logging.error(f"Ошибка скачивания базы: {e}") if not os.path.exists(DATA_FILE): with open(DATA_FILE, 'w', encoding='utf-8') as f: json.dump({'posts': [], 'users': {}, 'pending_organizations': [], 'orders': {}, 'user_orders': {}}, f) def periodic_backup(): while True: upload_db_to_hf() time.sleep(800) # Обновленный базовый стиль BASE_STYLE = ''' :root { --primary: #6b48ff; --secondary: #ff4785; --background-light: #f5f7ff; --background-dark: #1a1a2e; --card-bg-light: rgba(255, 255, 255, 0.95); --card-bg-dark: rgba(40, 40, 60, 0.95); --text-light: #1a1a2e; --text-dark: #e0e0e0; --shadow: 0 10px 40px rgba(0, 0, 0, 0.15); --glass-bg: rgba(255, 255, 255, 0.15); --transition: all 0.4s ease; --cart-btn: #10b981; } * { margin: 0; padding: 0; box-sizing: border-box; } body { font-family: 'Inter', sans-serif; background: var(--background-light); color: var(--text-light); line-height: 1.6; transition: var(--transition); overflow-x: hidden; } body.dark { background: var(--background-dark); color: var(--text-dark); } .sidebar { position: fixed; top: 0; left: 0; width: 300px; height: 100%; background: var(--glass-bg); backdrop-filter: blur(20px); padding: 30px; box-shadow: var(--shadow); z-index: 1000; transition: var(--transition); } .sidebar-header { margin-bottom: 40px; } .nav-brand { font-size: 2em; font-weight: 700; background: linear-gradient(45deg, var(--primary), var(--secondary)); -webkit-background-clip: text; color: transparent; } .nav-links { display: flex; flex-direction: column; gap: 20px; } .nav-link { display: flex; align-items: center; gap: 15px; padding: 18px; background: var(--card-bg-light); color: var(--text-light); text-decoration: none; border-radius: 15px; font-size: 1.1em; transition: var(--transition); position: relative; } body.dark .nav-link { background: var(--card-bg-dark); color: var(--text-dark); } .nav-link:hover { transform: translateX(15px); background: var(--primary); color: white; } .logout-btn { background: var(--secondary); color: white; } .logout-btn:hover { background: #e63970; } .order-count { position: absolute; right: 15px; top: 50%; transform: translateY(-50%); background: var(--secondary); color: white; border-radius: 50%; width: 20px; height: 20px; display: flex; align-items: center; justify-content: center; font-size: 0.9em; } .menu-btn { display: none; font-size: 32px; background: var(--glass-bg); border: none; color: var(--primary); cursor: pointer; position: fixed; top: 20px; left: 20px; z-index: 1001; padding: 12px; border-radius: 50%; box-shadow: var(--shadow); } .container { margin: 30px auto 30px 330px; max-width: 1200px; padding: 30px; transition: var(--transition); } .btn { padding: 14px 28px; background: var(--primary); color: white; border: none; border-radius: 15px; cursor: pointer; font-size: 1.1em; transition: var(--transition); display: inline-block; margin: 10px 0; } .btn:hover { transform: scale(1.08); background: #5439cc; } .cart-btn { background: var(--cart-btn); } .cart-btn:hover { background: #0d9f6e; } input, textarea, select { width: 100%; padding: 14px; margin: 15px 0; border: 2px solid rgba(0, 0, 0, 0.1); border-radius: 15px; background: var(--glass-bg); color: var(--text-light); font-size: 1.1em; transition: var(--transition); } body.dark input, body.dark textarea, body.dark select { border: 2px solid rgba(255, 255, 255, 0.1); color: var(--text-dark); } input:focus, textarea:focus, select:focus { outline: none; border-color: var(--primary); background: rgba(255, 255, 255, 0.2); } .modal { display: none; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0, 0, 0, 0.85); z-index: 2000; justify-content: center; align-items: center; } .modal img { max-width: 95%; max-height: 95%; object-fit: contain; border-radius: 15px; box-shadow: var(--shadow); } .theme-toggle { position: fixed; top: 20px; right: 20px; background: var(--glass-bg); border: none; padding: 12px; border-radius: 50%; cursor: pointer; font-size: 24px; box-shadow: var(--shadow); transition: var(--transition); } .cart-float { position: fixed; bottom: 20px; right: 20px; background: var(--cart-btn); color: white; border-radius: 50%; width: 60px; height: 60px; display: flex; align-items: center; justify-content: center; box-shadow: var(--shadow); cursor: pointer; z-index: 1000; transition: var(--transition); } .cart-float:hover { transform: scale(1.1); background: #0d9f6e; } .cart-modal { display: none; position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); background: var(--card-bg-light); padding: 30px; border-radius: 25px; box-shadow: var(--shadow); z-index: 2000; max-width: 500px; width: 90%; max-height: 80vh; overflow-y: auto; } body.dark .cart-modal { background: var(--card-bg-dark); } .cart-modal h2 { font-size: 1.8em; margin-bottom: 20px; background: linear-gradient(45deg, var(--primary), var(--secondary)); -webkit-background-clip: text; color: transparent; } .cart-item { background: var(--glass-bg); padding: 15px; border-radius: 15px; margin-bottom: 15px; } .cart-item h3 { font-size: 1.2em; margin-bottom: 10px; } .cart-total { font-size: 1.2em; font-weight: 600; margin-top: 20px; } @media (max-width: 768px) { .sidebar { transform: translateX(-100%); width: 280px; } .sidebar.active { transform: translateX(0); } .menu-btn { display: block; } .container { margin: 80px 15px 30px 15px; max-width: calc(100% - 30px); } .theme-toggle { top: 80px; right: 15px; } .btn, input, textarea, select { font-size: 1em; padding: 12px; } .cart-float { bottom: 15px; right: 15px; width: 50px; height: 50px; } } ''' NAV_HTML = ''' ''' # Регистрация @app.route('/register', methods=['GET', 'POST']) def register(): if request.method == 'POST': logging.debug(f"Получен POST-запрос: {request.form}") username = request.form.get('username') password = request.form.get('password') user_type = request.form.get('user_type') phone = request.form.get('phone') address = request.form.get('address') data = load_data() if not username or not password or not phone or (user_type == 'buyer' and not address): flash('Заполните все обязательные поля!', 'error') logging.debug("Не все обязательные поля заполнены") return redirect(url_for('register')) if username in data['users']: flash('Пользователь уже существует!', 'error') logging.debug(f"Пользователь {username} уже существует") return redirect(url_for('register')) if 'register_seller' in request.form: logging.debug("Нажата кнопка регистрации продавца") org_name = request.form.get('org_name') org_phone = request.form.get('org_phone') is_online = request.form.get('is_online') == 'on' org_address = request.form.get('org_address') if not is_online else None if not org_name or not org_phone: flash('Укажите название организации и рабочий номер!', 'error') logging.debug("Не указаны org_name или org_phone") return redirect(url_for('register')) data['users'][username] = { 'password': password, 'bio': '', 'link': '', 'avatar': None, 'type': 'seller', 'verified': False, 'phone': phone, 'org_phone': org_phone, 'org_address': org_address, 'is_online': is_online } data['pending_organizations'].append({ 'username': username, 'org_name': org_name, 'org_phone': org_phone, 'org_address': org_address, 'is_online': is_online, 'submitted_at': datetime.now().strftime('%Y-%m-%d %H:%M:%S') }) save_data(data) flash('Ваша заявка принята, мы с вами свяжемся в течение 2 суток', 'success') logging.debug(f"Продавец {username} зарегистрирован и отправлен на верификацию") return redirect(url_for('login')) elif 'register_buyer' in request.form: logging.debug("Нажата кнопка регистрации покупателя") data['users'][username] = { 'password': password, 'bio': '', 'link': '', 'avatar': None, 'type': 'buyer', 'verified': True, 'phone': phone, 'address': address } save_data(data) flash('Регистрация успешна! Войдите в систему.', 'success') logging.debug(f"Покупатель {username} зарегистрирован") return redirect(url_for('login')) else: flash('Неизвестная ошибка при выборе типа пользователя!', 'error') logging.debug("Ни одна из кнопок регистрации не была нажата") return redirect(url_for('register')) is_authenticated = 'username' in session username = session.get('username', None) html = ''' Регистрация ''' + NAV_HTML + '''

Регистрация

{% with messages = get_flashed_messages(with_categories=true) %} {% if messages %} {% for category, message in messages %}
{{ message }}
{% endfor %} {% endif %} {% endwith %}
''' return render_template_string(html, is_authenticated=is_authenticated, username=username) # Авторизация @app.route('/login', methods=['GET', 'POST']) def login(): if request.method == 'POST': username = request.form.get('username') password = request.form.get('password') data = load_data() if username in data['users'] and data['users'][username]['password'] == password: session['username'] = username session.permanent = True return redirect(url_for('feed')) flash('Неверный логин или пароль!', 'error') return redirect(url_for('login')) is_authenticated = 'username' in session username = session.get('username', None) html = ''' Вход ''' + NAV_HTML + '''

Вход

{% with messages = get_flashed_messages(with_categories=true) %} {% if messages %} {% for category, message in messages %}
{{ message }}
{% endfor %} {% endif %} {% endwith %}
''' return render_template_string(html, is_authenticated=is_authenticated, username=username) # Выход @app.route('/logout') def logout(): session.pop('username', None) return redirect(url_for('feed')) # Лента @app.route('/', methods=['GET', 'POST']) def feed(): data = load_data() posts = sorted(data.get('posts', []), key=lambda x: datetime.strptime(x['upload_date'], '%Y-%m-%d %H:%M:%S'), reverse=True) is_authenticated = 'username' in session username = session.get('username', None) user_type = data['users'].get(username, {}).get('type') if username else None verified = data['users'].get(username, {}).get('verified', False) if username else False order_count = len(data['orders'].get(username, [])) if user_type == 'seller' and verified else 0 search_query = request.form.get('search', '').strip().lower() if request.method == 'POST' else request.args.get('search', '').strip().lower() if search_query: posts = [post for post in posts if search_query in post['title'].lower() or search_query in post['description'].lower()] html = ''' Лента ''' + NAV_HTML + '''

Корзина

Итого: 0

Лента публикаций

{% for post in posts %}

{{ post['title'] }}

{{ post['description'] }}

Цена: {{ post['price'] }} {{ post['currency'] }}

Загрузил: {{ post['uploader'] }} | {{ post['upload_date'] }}

Просмотров: {{ post['views'] }} | Лайков: {{ post['likes']|length }}

{% if is_authenticated and user_type == 'buyer' and verified %} {% endif %}
{% endfor %}
''' return render_template_string(html, posts=posts, is_authenticated=is_authenticated, username=username, repo_id=REPO_ID, search_query=search_query, user_type=user_type, verified=verified, order_count=order_count) # Страница публикации @app.route('/post/', methods=['GET', 'POST']) def post_page(post_id): data = load_data() post = next((p for p in data['posts'] if p['id'] == post_id), None) if not post: return "Публикация не найдена", 404 is_authenticated = 'username' in session username = session.get('username', None) user_type = data['users'].get(username, {}).get('type') if username else None verified = data['users'].get(username, {}).get('verified', False) if username else False order_count = len(data['orders'].get(username, [])) if user_type == 'seller' and verified else 0 post['views'] = post.get('views', 0) + 1 save_data(data) if request.method == 'POST' and is_authenticated: if 'like' in request.form: if username not in post.get('likes', []): post['likes'] = post.get('likes', []) + [username] else: post['likes'] = [user for user in post.get('likes', []) if user != username] save_data(data) elif 'comment' in request.form: comment_text = request.form.get('comment') if comment_text: post['comments'] = post.get('comments', []) + [{'user': username, 'text': comment_text, 'date': datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] save_data(data) html = ''' {{ post['title'] }} ''' + NAV_HTML + '''

Корзина

Итого: 0

{{ post['title'] }}

{{ post['description'] }}

Цена: {{ post['price'] }} {{ post['currency'] }}

Загрузил: {{ post['uploader'] }} | {{ post['upload_date'] }}

Просмотров: {{ post['views'] }} | Лайков: {{ post['likes']|length }}

{% if is_authenticated %}
{% if user_type == 'buyer' and verified %} {% endif %}
{% endif %}

Комментарии

{% for comment in post.get('comments', []) %}

{{ comment['user'] }} ({{ comment['date'] }}): {{ comment['text'] }}

{% endfor %} Назад к ленте {% if not is_authenticated %}

Войдите, чтобы ставить лайки и комментировать.

{% endif %}
''' return render_template_string(html, post=post, repo_id=REPO_ID, is_authenticated=is_authenticated, username=username, user_type=user_type, verified=verified, order_count=order_count) # Профиль пользователя @app.route('/profile', methods=['GET', 'POST']) def profile(): if 'username' not in session: flash('Войдите, чтобы просмотреть профиль!', 'error') return redirect(url_for('login')) data = load_data() username = session['username'] 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) is_authenticated = 'username' in session total_views = sum(post.get('views', 0) for post in user_posts) total_likes = sum(len(post.get('likes', [])) for post in user_posts) user_data = data['users'].get(username, {}) bio = user_data.get('bio', '') link = user_data.get('link', '') avatar = user_data.get('avatar', None) user_type = user_data.get('type', 'buyer') verified = user_data.get('verified', False) phone = user_data.get('phone', '') address = user_data.get('address', '') org_phone = user_data.get('org_phone', '') org_address = user_data.get('org_address', '') is_online = user_data.get('is_online', False) order_count = len(data['orders'].get(username, [])) if user_type == 'seller' and verified else 0 if request.method == 'POST': if 'delete_post' in request.form: post_id = request.form.get('post_id') if post_id: data['posts'] = [p for p in data['posts'] if p['id'] != post_id or p['uploader'] != username] save_data(data) return redirect(url_for('profile')) elif 'update_profile' in request.form: bio = request.form.get('bio', '') link = request.form.get('link', '') phone = request.form.get('phone', '') address = request.form.get('address', '') if user_type == 'buyer' else address org_phone = request.form.get('org_phone', '') if user_type == 'seller' else org_phone org_address = request.form.get('org_address', '') if user_type == 'seller' and not is_online else None avatar_file = request.files.get('avatar') if avatar_file and avatar_file.filename: filename = secure_filename(avatar_file.filename) temp_path = os.path.join('uploads', filename) os.makedirs('uploads', exist_ok=True) avatar_file.save(temp_path) api = HfApi() avatar_path = f"avatars/{username}/{filename}" api.upload_file( path_or_fileobj=temp_path, path_in_repo=avatar_path, repo_id=REPO_ID, repo_type="dataset", token=HF_TOKEN_WRITE, commit_message=f"Добавлен аватар для {username}" ) data['users'][username]['avatar'] = avatar_path if os.path.exists(temp_path): os.remove(temp_path) data['users'][username]['bio'] = bio data['users'][username]['link'] = link data['users'][username]['phone'] = phone if user_type == 'buyer': data['users'][username]['address'] = address if user_type == 'seller' and verified: data['users'][username]['org_phone'] = org_phone data['users'][username]['org_address'] = org_address save_data(data) return redirect(url_for('profile')) elif 'checkout' in request.form: cart = json.loads(request.form.get('cart_data', '[]')) if cart: if not phone or (user_type == 'buyer' and not address): flash('Укажите номер телефона и адрес доставки в профиле перед оформлением заказа!', 'error') return redirect(url_for('profile')) for item in cart: seller = item['uploader'] order_id = f"order_{int(time.time())}_{random.randint(1, 1000)}" order_data = { 'order_id': order_id, 'buyer': username, 'post_id': item['postId'], 'title': item['title'], 'price': item['price'], 'currency': item['currency'], 'quantity': item['quantity'], 'date': datetime.now().strftime('%Y-%m-%d %H:%M:%S'), 'status': 'pending', 'buyer_phone': phone, 'buyer_address': address if user_type == 'buyer' else None } if seller not in data['orders']: data['orders'][seller] = [] data['orders'][seller].append(order_data) if username not in data['user_orders']: data['user_orders'][username] = [] data['user_orders'][username].append(order_data) save_data(data) flash('Заказ успешно оформлен!', 'success') return redirect(url_for('profile')) html = ''' Профиль - {{ username }} ''' + NAV_HTML + '''

Корзина

Итого: 0

{% if avatar %} Аватар {% endif %}

{{ username }}

{{ bio }}

{% if link %}

{{ link }}

{% endif %}

Тип: {{ 'Продавец' if user_type == 'seller' else 'Покупатель' }} {% if user_type == 'seller' and not verified %}(На проверке){% endif %}

Телефон: {{ phone }}

{% if user_type == 'buyer' %}

Адрес доставки: {{ address }}

{% endif %} {% if user_type == 'seller' and verified %}

Рабочий номер: {{ org_phone }}

Адрес организации: {{ org_address if org_address else 'Онлайн' }}

{% endif %}

Просмотров: {{ total_views }} | Лайков: {{ total_likes }}

Редактировать профиль

{% if user_type == 'buyer' %} {% endif %} {% if user_type == 'seller' and verified %} {% if not is_online %} {% endif %} {% endif %}
{% if user_type == 'seller' and verified %} Добавить видео {% endif %}

Корзина

Итого: 0

{% with messages = get_flashed_messages(with_categories=true) %} {% if messages %} {% for category, message in messages %}
{{ message }}
{% endfor %} {% endif %} {% endwith %}

Ваши видео

{% if user_posts %} {% for post in user_posts %}

{{ post['title'] }}

{{ post['description'] }}

Цена: {{ post['price'] }} {{ post['currency'] }}

{{ post['upload_date'] }}

{% endfor %} {% else %}

Вы пока не загрузили ни одного видео.

{% endif %}
''' return render_template_string(html, username=username, user_posts=user_posts, total_views=total_views, total_likes=total_likes, bio=bio, link=link, avatar=avatar, repo_id=REPO_ID, is_authenticated=is_authenticated, user_type=user_type, verified=verified, phone=phone, address=address, org_phone=org_phone, org_address=org_address, is_online=is_online, order_count=order_count) # Профиль другого пользователя @app.route('/profile/') def user_profile(username): data = load_data() if username not in data['users']: return "Пользователь не найден", 404 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) is_authenticated = 'username' in session current_user = session.get('username') total_views = sum(post.get('views', 0) for post in user_posts) total_likes = sum(len(post.get('likes', [])) for post in user_posts) user_data = data['users'].get(username, {}) bio = user_data.get('bio', '') link = user_data.get('link', '') avatar = user_data.get('avatar', None) user_type = user_data.get('type', 'buyer') verified = user_data.get('verified', False) phone = user_data.get('phone', '') address = user_data.get('address', '') org_phone = user_data.get('org_phone', '') org_address = user_data.get('org_address', '') is_online = user_data.get('is_online', False) order_count = len(data['orders'].get(current_user, [])) if data['users'].get(current_user, {}).get('type') == 'seller' and data['users'].get(current_user, {}).get('verified', False) else 0 html = ''' Профиль - {{ username }} ''' + NAV_HTML + '''

Корзина

Итого: 0

{% if avatar %} Аватар {% endif %}

{{ username }}

{{ bio }}

{% if link %}

{{ link }}

{% endif %}

Тип: {{ 'Продавец' if user_type == 'seller' else 'Покупатель' }} {% if user_type == 'seller' and not verified %}(На проверке){% endif %}

Телефон: {{ phone }}

{% if user_type == 'buyer' %}

Адрес доставки: {{ address }}

{% endif %} {% if user_type == 'seller' and verified %}

Рабочий номер: {{ org_phone }}

Адрес организации: {{ org_address if org_address else 'Онлайн' }}

{% endif %}

Просмотров: {{ total_views }} | Лайков: {{ total_likes }}

Видео

{% if user_posts %} {% for post in user_posts %}

{{ post['title'] }}

{{ post['description'] }}

Цена: {{ post['price'] }} {{ post['currency'] }}

{{ post['upload_date'] }}

{% endfor %} {% else %}

Этот пользователь пока не загрузил ни одного видео.

{% endif %}
''' return render_template_string(html, username=username, user_posts=user_posts, total_views=total_views, total_likes=total_likes, bio=bio, link=link, avatar=avatar, repo_id=REPO_ID, is_authenticated=is_authenticated, user_type=user_type, verified=verified, phone=phone, address=address, org_phone=org_phone, org_address=org_address, is_online=is_online, order_count=order_count) # Загрузка контента @app.route('/upload', methods=['GET', 'POST']) def upload(): if 'username' not in session: flash('Войдите, чтобы загрузить контент!', 'error') return redirect(url_for('login')) data = load_data() username = session['username'] user_data = data['users'].get(username, {}) if user_data.get('type') != 'seller' or not user_data.get('verified'): flash('Только проверенные продавцы могут загружать видео!', 'error') return redirect(url_for('profile')) if request.method == 'POST': title = request.form.get('title') description = request.form.get('description') price = request.form.get('price') currency = request.form.get('currency') file = request.files.get('file') uploader = session['username'] if not title or not price or not currency or not file: flash('Укажите название, цену, валюту и выберите видео!', 'error') return redirect(url_for('upload')) if not file.filename.lower().endswith(('.mp4', '.mov', '.avi')): flash('Загружайте только видео файлы (mp4, mov, avi)!', 'error') return redirect(url_for('upload')) filename = secure_filename(file.filename) temp_path = os.path.join('uploads', filename) os.makedirs('uploads', exist_ok=True) file.save(temp_path) api = HfApi() api.upload_file( path_or_fileobj=temp_path, path_in_repo=f"videos/{filename}", repo_id=REPO_ID, repo_type="dataset", token=HF_TOKEN_WRITE, commit_message=f"Добавлено видео: {title} пользователем {uploader}" ) data = load_data() post_id = f"post_{len(data['posts']) + 1}" while any(p['id'] == post_id for p in data['posts']): post_id = f"post_{len(data['posts']) + 1}_{int(time.time())}" data['posts'].append({ 'id': post_id, 'title': title, 'description': description, 'filename': filename, 'type': 'video', 'uploader': uploader, 'upload_date': datetime.now().strftime('%Y-%m-%d %H:%M:%S'), 'views': 0, 'likes': [], 'comments': [], 'price': price, 'currency': currency }) save_data(data) if os.path.exists(temp_path): os.remove(temp_path) return redirect(url_for('profile')) is_authenticated = 'username' in session username = session.get('username', None) user_type = user_data.get('type') verified = user_data.get('verified', False) order_count = len(data['orders'].get(username, [])) html = ''' Загрузка видео ''' + NAV_HTML + '''

Корзина

Итого: 0

Загрузить видео

{% with messages = get_flashed_messages(with_categories=true) %} {% if messages %} {% for category, message in messages %}
{{ message }}
{% endfor %} {% endif %} {% endwith %}
''' return render_template_string(html, username=username, is_authenticated=is_authenticated, user_type=user_type, verified=verified, order_count=order_count) # Заказы продавца @app.route('/seller_orders', methods=['GET', 'POST']) def seller_orders(): if 'username' not in session: flash('Войдите, чтобы просмотреть заказы!', 'error') return redirect(url_for('login')) data = load_data() username = session['username'] user_data = data['users'].get(username, {}) if user_data.get('type') != 'seller' or not user_data.get('verified'): flash('Только проверенные продавцы могут просматривать заказы!', 'error') return redirect(url_for('profile')) orders = data['orders'].get(username, []) is_authenticated = 'username' in session user_type = user_data.get('type') verified = user_data.get('verified', False) order_count = len(orders) if request.method == 'POST': if 'update_status' in request.form: order_id = request.form.get('order_id') new_status = request.form.get('status') for order in orders: if order['order_id'] == order_id: order['status'] = new_status # Обновляем статус в заказах пользователя for user_order in data['user_orders'].get(order['buyer'], []): if user_order['order_id'] == order_id: user_order['status'] = new_status break break save_data(data) return redirect(url_for('seller_orders')) html = ''' Заказы - {{ username }} ''' + NAV_HTML + '''

Корзина

Итого: 0

Ваши заказы

{% if orders %} {% for order in orders %}

{{ order['title'] }}

Цена: {{ order['price'] }} {{ order['currency'] }} x {{ order['quantity'] }} = {{ (order['price']|float * order['quantity'])|round(2) }} {{ order['currency'] }}

Покупатель: {{ order['buyer'] }}

Телефон покупателя: {{ order['buyer_phone'] }}

{% if order['buyer_address'] %}

Адрес доставки: {{ order['buyer_address'] }}

{% endif %}

Дата: {{ order['date'] }}

{% endfor %} {% else %}

У вас пока нет заказов.

{% endif %}
''' return render_template_string(html, username=username, orders=orders, is_authenticated=is_authenticated, user_type=user_type, verified=verified, order_count=order_count) # Мои заказы пользователя @app.route('/user_orders', methods=['GET']) def user_orders(): if 'username' not in session: flash('Войдите, чтобы просмотреть свои заказы!', 'error') return redirect(url_for('login')) data = load_data() username = session['username'] user_data = data['users'].get(username, {}) orders = data['user_orders'].get(username, []) is_authenticated = 'username' in session user_type = user_data.get('type') verified = user_data.get('verified', False) order_count = len(data['orders'].get(username, [])) if user_type == 'seller' and verified else 0 html = ''' Мои заказы - {{ username }} ''' + NAV_HTML + '''

Корзина

Итого: 0

Мои заказы

{% if orders %} {% for order in orders %}

{{ order['title'] }}

Цена: {{ order['price'] }} {{ order['currency'] }} x {{ order['quantity'] }} = {{ (order['price']|float * order['quantity'])|round(2) }} {{ order['currency'] }}

Продавец: {{ order['uploader'] }}

Дата: {{ order['date'] }}

Статус: {{ 'В ожидании' if order['status'] == 'pending' else 'В обработке' if order['status'] == 'processing' else 'Завершено' }}

{% endfor %} {% else %}

У вас пока нет заказов.

{% endif %}
''' return render_template_string(html, username=username, orders=orders, is_authenticated=is_authenticated, user_type=user_type, verified=verified, order_count=order_count) # Админ-панель @app.route('/admhosto', methods=['GET', 'POST']) def admin_panel(): data = load_data() posts = sorted(data.get('posts', []), key=lambda x: datetime.strptime(x['upload_date'], '%Y-%m-%d %H:%M:%S'), reverse=True) pending_orgs = data.get('pending_organizations', []) is_authenticated = 'username' in session username = session.get('username', None) user_type = data['users'].get(username, {}).get('type') if username else None verified = data['users'].get(username, {}).get('verified', False) if username else False order_count = len(data['orders'].get(username, [])) if user_type == 'seller' and verified else 0 if request.method == 'POST': if 'delete' in request.form: post_id = request.form.get('post_id') if post_id: data['posts'] = [p for p in data['posts'] if p['id'] != post_id] save_data(data) return redirect(url_for('admin_panel')) elif 'approve_org' in request.form: org_username = request.form.get('username') if org_username: data['users'][org_username]['verified'] = True data['pending_organizations'] = [org for org in pending_orgs if org['username'] != org_username] save_data(data) return redirect(url_for('admin_panel')) elif 'reject_org' in request.form: org_username = request.form.get('username') if org_username: data['pending_organizations'] = [org for org in pending_orgs if org['username'] != org_username] save_data(data) return redirect(url_for('admin_panel')) search_query = request.args.get('search', '').strip().lower() if search_query: posts = [post for post in posts if search_query in post['title'].lower() or search_query in post['description'].lower()] html = ''' Админ-панель ''' + NAV_HTML + '''

Корзина

Итого: 0

Админ-панель

Организации на проверке

{% if pending_orgs %} {% for org in pending_orgs %}

{{ org['org_name'] }}

Пользователь: {{ org['username'] }}

Телефон: {{ org['org_phone'] }}

Адрес: {{ org['org_address'] if org['org_address'] else 'Онлайн' }}

Дата подачи: {{ org['submitted_at'] }}

{% endfor %} {% else %}

Нет организаций на проверке.

{% endif %}

Все видео

{% if posts %} {% for post in posts %}

{{ post['title'] }}

{{ post['description'] }}

Цена: {{ post['price'] }} {{ post['currency'] }}

Загрузил: {{ post['uploader'] }} | {{ post['upload_date'] }}

{% endfor %} {% else %}

Видео не найдены.

{% endif %}
''' return render_template_string(html, posts=posts, pending_orgs=pending_orgs, is_authenticated=is_authenticated, username=username, repo_id=REPO_ID, search_query=search_query, user_type=user_type, verified=verified, order_count=order_count) if __name__ == '__main__': backup_thread = threading.Thread(target=periodic_backup, daemon=True) backup_thread.start() app.run(debug=True, host='0.0.0.0', port=7860)