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 + '''
'''
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', []) %}
{% 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 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 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
'''
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)
{{ comment['user'] }} ({{ comment['date'] }}): {{ comment['text'] }}