from flask import Flask, render_template_string, request, redirect, url_for import json import os import logging import threading import time 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_firecollection.json' # Настройки Hugging Face REPO_ID = "Kgshop/Clients2" # Замените, если нужно HF_TOKEN_WRITE = os.getenv("HF_TOKEN") HF_TOKEN_READ = os.getenv("HF_TOKEN_READ") # Настройка логирования 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) logging.info("Данные успешно загружены из JSON") if not isinstance(data, dict) or 'products' not in data or 'categories' not in data: return {'products': [], 'categories': []} 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': []} except Exception as e: logging.error(f"Произошла ошибка при загрузке данных: {e}") return {'products': [], 'categories': []} def save_data(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 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.") 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("JSON база успешно скачана из Hugging Face.") except RepositoryNotFoundError as e: logging.error(f"Репозиторий не найден: {e}") raise except Exception as e: logging.error(f"Ошибка при скачивании JSON базы: {e}") raise def periodic_backup(): while True: upload_db_to_hf() time.sleep(800) @app.route('/') def catalog(): data = load_data() products = data['products'] catalog_html = ''' Fire collection

Fire collection

Наш адрес

Рынок Дордой, 0 проход, 2034 контейнер

График работы

По адресу: без выходных с 8:00 до 16:00
Онлайн: круглосуточно

{% for product in products %}
{% if product.get('photos') and product['photos']|length > 0 %}
{{ product['name'] }}
{% endif %} {% if product.get('discount') %} Скидка {{ product['discount'] }}% {% endif %}

{{ product['name'] }}

{% if product.get('discount') %} {{ (product['price'] * (1 - product['discount'] / 100))|round(2) }} с Скидка: {{ product['discount'] }}% {% else %} {{ product['price'] }} с {% endif %}

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

{% endfor %}
''' return render_template_string(catalog_html, products=products, repo_id=REPO_ID) @app.route('/categories') def categories_page(): data = load_data() categories = data['categories'] categories_html = ''' Категории - Fire collection

Fire collection

{% for category in categories %}

{{ category }}

{% endfor %}
''' return render_template_string(category_html, products=products, category=category, repo_id=REPO_ID) @app.route('/favorites') def favorites_page(): data = load_data() favorites = JSON.parse(localStorage.getItem('favorites') || '[]') products = [data['products'][int(i)] for i in favorites if int(i) < len(data['products'])] favorites_html = ''' Избранное - Fire collection

Избранное

{% for product in products %}
{% if product.get('photos') and product['photos']|length > 0 %}
{{ product['name'] }}
{% endif %} {% if product.get('discount') %} Скидка {{ product['discount'] }}% {% endif %}

{{ product['name'] }}

{% if product.get('discount') %} {{ (product['price'] * (1 - product['discount'] / 100))|round(2) }} с Скидка: {{ product['discount'] }}% {% else %} {{ product['price'] }} с {% endif %}

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

{% endfor %}
''' return render_template_string(favorites_html, products=products, repo_id=REPO_ID) @app.route('/discounts') def discounts_page(): data = load_data() products = [p for p in data['products'] if p.get('discount')] discounts_html = ''' Скидки - Fire collection

Скидки

{% for product in products %}
{% if product.get('photos') and product['photos']|length > 0 %}
{{ product['name'] }}
{% endif %} Скидка {{ product['discount'] }}%

{{ product['name'] }}

{{ (product['price'] * (1 - product['discount'] / 100))|round(2) }} с Скидка: {{ product['discount'] }}%

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

{% endfor %}
''' return render_template_string(discounts_html, products=products, repo_id=REPO_ID) @app.route('/product/') def product_details(index): data = load_data() if index >= len(data['products']): return "Товар не найден", 404 product = data['products'][index] modal_html = '''
{% if product.get('photos') and product['photos']|length > 0 %} {% for photo in product['photos'] %}
{{ product['name'] }}
{% endfor %} {% else %}

Фото отсутствует

{% endif %}

{{ product['name'] }}

{% if product.get('discount') %} {{ (product['price'] * (1 - product['discount'] / 100))|round(2) }} с Скидка: {{ product['discount'] }}% {% else %} {{ product['price'] }} с {% endif %}

{{ product['description'] }}

{% if product.get('colors') and product['colors']|length > 0 %}
Доступные цвета: {% for color in product['colors'] %} {{ color }} {% endfor %}
{% endif %}
''' return render_template_string(modal_html, product=product, repo_id=REPO_ID) @app.route('/admin', methods=['GET', 'POST']) def admin_panel(): data = load_data() if request.method == 'POST': if 'add_product' in request.form: new_product = { 'name': request.form['name'], 'price': float(request.form['price']), 'description': request.form['description'], 'category': request.form['category'], 'photos': request.form.getlist('photos'), 'colors': request.form.getlist('colors'), 'discount': float(request.form.get('discount', 0)) } data['products'].append(new_product) if request.form['category'] not in data['categories']: data['categories'].append(request.form['category']) save_data(data) return redirect(url_for('admin_panel')) elif 'upload_photos' in request.files: photos = request.files.getlist('photos') uploaded_photos = [] api = HfApi() for photo in photos: if photo: filename = secure_filename(photo.filename) photo.save(filename) api.upload_file( path_or_fileobj=filename, path_in_repo=f"photos/{filename}", repo_id=REPO_ID, repo_type="dataset", token=HF_TOKEN_WRITE ) uploaded_photos.append(filename) os.remove(filename) return jsonify({'photos': uploaded_photos}) admin_html = ''' Админ-панель - Fire collection

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

''' return render_template_string(admin_html) if __name__ == '__main__': threading.Thread(target=periodic_backup, daemon=True).start() app.run(host='0.0.0.0', port=7860, debug=True)