diff --git "a/app.py" "b/app.py" --- "a/app.py" +++ "b/app.py" @@ -1,1112 +1,2087 @@ -from flask import Flask, render_template_string, request, redirect, url_for +from flask import Flask, render_template_string, request, redirect, url_for, session +import random +import string import json import os -import logging -import threading +from flask_socketio import SocketIO, join_room, leave_room, emit +import hashlib import time +import threading from datetime import datetime from huggingface_hub import HfApi, hf_hub_download from huggingface_hub.utils import RepositoryNotFoundError -from werkzeug.utils import secure_filename app = Flask(__name__) -DATA_FILE = 'data_luxoff.json' +app.config['SECRET_KEY'] = 'your-very-secret-key-here' +socketio = SocketIO(app) -# Настройки Hugging Face -REPO_ID = "flpolprojects/Clients" -HF_TOKEN_WRITE = os.getenv("HF_TOKEN") -HF_TOKEN_READ = os.getenv("HF_TOKEN_READ") +# --- Hugging Face Hub Settings --- +REPO_ID = "flpolprojects/Clients" # ваш репозиторий +HF_TOKEN_WRITE = os.getenv("HF_TOKEN") # токен с правами на запись +HF_TOKEN_READ = os.getenv("HF_TOKEN_READ") # токен с правами на чтение (можно тот же, если у него есть и чтение, и запись) -# Ссылка на логотип -LOGO_URL = "https://cdn-avatars.huggingface.co/v1/production/uploads/63b6a710ccebeadccc864577/j1KeCVskZ3ZxI7oYQuu7o.png" +# --- File Paths --- +ROOMS_DB = os.path.join(app.root_path, 'rooms.json') +USERS_DB = os.path.join(app.root_path, 'users.json') +GAMES_DB = os.path.join(app.root_path, 'games.json') -# Настройка логирования -logging.basicConfig(level=logging.DEBUG) +# --- Data Loading and Saving with Hugging Face Backup --- -def load_data(): +def load_json(file_path, default={}): try: - download_db_from_hf() - with open(DATA_FILE, 'r', encoding='utf-8') as file: - data = json.load(file) - logging.info("Данные успешно загружены из JSON") - if not isinstance(data, dict) or 'products' not in data or 'categories' not in data: - return {'products': [], 'categories': [] if not isinstance(data, list) else data} - return data - except FileNotFoundError: - logging.warning("Локальный файл базы данных не найден после скачивания.") - return {'products': [], 'categories': []} - except json.JSONDecodeError: - logging.error("Ошибка: Невозможно декодировать JSON файл.") - return {'products': [], 'categories': []} - except RepositoryNotFoundError: - logging.error("Репозиторий не найден. Создание локальной базы данных.") - return {'products': [], 'categories': []} + download_db_from_hf() # Скачиваем перед загрузкой + if os.path.exists(file_path): + with open(file_path, 'r', encoding='utf-8') as f: + return json.load(f) + return default + except (FileNotFoundError, json.JSONDecodeError) as e: + print(f"Ошибка загрузки JSON из {file_path}: {e}") + return default except Exception as e: - logging.error(f"Произошла ошибка при загрузке данных: {e}") - return {'products': [], 'categories': []} + print(f"Непредвиденная ошибка при загрузке: {e}") #Добавил обработку + return default -def save_data(data): +def save_json(file_path, data): try: - with open(DATA_FILE, 'w', encoding='utf-8') as file: - json.dump(data, file, ensure_ascii=False, indent=4) - logging.info("Данные успешно сохранены в JSON") - upload_db_to_hf() - except Exception as e: - logging.error(f"Ошибка при сохранении данных: {e}") - raise + with open(file_path, 'w', encoding='utf-8') as f: + json.dump(data, f, indent=4, ensure_ascii=False) + upload_db_to_hf() # Загружаем после сохранения + except OSError as e: + print(f"Ошибка сохранения JSON в {file_path}: {e}") + except Exception as e: #Добавил обработку + print(f"Непредвиденная ошибка при сохранении: {e}") 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"Автоматическое резервное копирование базы данных {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}" - ) - logging.info("Резервная копия JSON базы успешно загружена на Hugging Face.") + # Загружаем все три JSON файла + for file_path, repo_path in [(ROOMS_DB, "rooms.json"), (USERS_DB, "users.json"), (GAMES_DB, "games.json")]: + if os.path.exists(file_path): # Проверяем наличие файла + api.upload_file( + path_or_fileobj=file_path, + path_in_repo=repo_path, + repo_id=REPO_ID, + repo_type="dataset", + token=HF_TOKEN_WRITE, + commit_message=f"Backup: {repo_path} ({datetime.now().strftime('%Y-%m-%d %H:%M:%S')})" + ) + print(f"Файл {file_path} успешно загружен на Hugging Face Hub.") + else: + print(f"Файл {file_path} не существует, пропуск загрузки.") except Exception as e: - logging.error(f"Ошибка при загрузке резервной копии: {e}") + print(f"Ошибка при загрузке файлов на Hugging Face Hub: {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("JSON база успешно скачана из Hugging Face.") - except RepositoryNotFoundError as e: - logging.error(f"Репозиторий не найден: {e}") - raise + api = HfApi() + # Скачиваем все три JSON файла + for file_path, repo_path in [(ROOMS_DB, "rooms.json"), (USERS_DB, "users.json"), (GAMES_DB, "games.json")]: + try: + hf_hub_download( + repo_id=REPO_ID, + filename=repo_path, + repo_type="dataset", + token=HF_TOKEN_READ, + local_dir=".", # Сохраняем в текущую директорию + local_dir_use_symlinks=False # Важно для корректной работы на некоторых платформах + ) + print(f"Файл {repo_path} успешно скачан с Hugging Face Hub.") + except RepositoryNotFoundError: + print(f"Файл {repo_path} не найден в репозитории. Создание локального.") + # Создаем пустой файл, если его нет в репозитории + if not os.path.exists(file_path): + with open(file_path, 'w') as f: + json.dump({}, f) # Создание пустого + except Exception as e: + print(f"Ошибка при скачивании файла {repo_path}: {e}") + + except Exception as e: - logging.error(f"Ошибка при скачивании JSON базы: {e}") - raise + print(f"Ошибка при скачивании файлов с Hugging Face Hub: {e}") def periodic_backup(): while True: upload_db_to_hf() - time.sleep(15) + time.sleep(15) # Резервное копирование каждые 15 секунд -@app.route('/') -def catalog(): - data = load_data() - products = data['products'] - categories = data['categories'] - - catalog_html = ''' - - - - - - LUXoff женская одежда оптом - - - - + + + +
+

Видеоконференция

+
+ + + + +
+
+ +''') + + +@app.route('/dashboard', methods=['GET', 'POST']) +def dashboard(): + if 'username' not in session: + return redirect(url_for('index')) + + if request.method == 'POST': + action = request.form.get('action') + if action == 'create': + token = generate_token() + rooms[token] = {'users': [], 'max_users': 5, 'admin': session['username'], 'current_game': None} + save_json(ROOMS_DB, rooms) + return redirect(url_for('room', token=token)) + elif action == 'join': + token = request.form.get('token') + if token in rooms and len(rooms[token]['users']) < rooms[token]['max_users']: + return redirect(url_for('room', token=token)) + return "Комната не найдена или переполнена", 404 + + return render_template_string(''' + + + + + Панель управления + + + + +
+

Добро пожаловать, {{ session['username'] }}

+
+ +
+
+ + +
+
+ +
+
+ +''', session=session) + + +@app.route('/logout', methods=['POST']) +def logout(): + session.pop('username', None) + return redirect(url_for('index')) + + +@app.route('/room/') +def room(token): + if 'username' not in session: + return redirect(url_for('index')) + + if token not in rooms: + return redirect(url_for('dashboard')) + + is_admin = rooms[token]['admin'] == session['username'] + current_game = rooms[token].get('current_game') + + return render_template_string(''' + + + + + + Комната {{ token }} + - - -
-
- -

Каталог

- -
-
- - {% for category in categories %} - - {% endfor %} -
-
- -
-
- {% for product in products %} -
- {% if product.get('photos') and product['photos']|length > 0 %} -
- {{ product['name'] }} -
- {% endif %} -

{{ product['name'] }}

-
{{ product['price'] }} с
-

{{ product['description'][:50] }}{% if product['description']|length > 50 %}...{% endif %}

- - -
- {% endfor %} -
-
+ + } + @media (prefers-color-scheme: dark) { + :root { + --background-color: #121212; + --surface-color: #1e1e1e; + --text-color: #ffffff; + --control-bg-color: #333; + --control-icon-color: #eee; + } + } + + + + + + + +

Комната: {{ token }}

+
Пользователи: {% for user in rooms[token]['users'] %}{{ user }}{% if not loop.last %}, {% endif %}{% endfor %}
- -