{{ post.title }}
- -{{ post.content[:150] }}...
-diff --git "a/app.py" "b/app.py" --- "a/app.py" +++ "b/app.py" @@ -1,191 +1,55 @@ -# --- START OF FILE app (1) (9).py --- import os import uuid -import json -import logging -import threading -import time -from datetime import datetime -from flask import Flask, request, jsonify, Response, send_from_directory, render_template_string, flash, redirect, url_for +import subprocess +import sys +import shutil +from flask import Flask, request, jsonify, Response # Removed send_from_directory import google.generativeai as genai -from huggingface_hub import HfApi, hf_hub_download -from huggingface_hub.utils import RepositoryNotFoundError, HfHubHTTPError -from werkzeug.utils import secure_filename from dotenv import load_dotenv -import requests -import zipfile -import shutil +import logging +import socket # For finding available port -load_dotenv() +load_dotenv() # Load .env file for API keys app = Flask(__name__) -app.secret_key = 'your_unique_secret_key_for_site_generator_12345' -# --- Настройки Hugging Face из кода 2 --- -DATA_FILE = 'data.json' # Для метаданных или настроек, если понадобятся -SYNC_FILES = [DATA_FILE] # Какие файлы синхронизировать по умолчанию (можно добавить шаблоны проектов) +# --- Configuration --- +GOOGLE_AI_API_KEY = os.getenv("GOOGLE_AI_API_KEY") +HF_TOKEN_WRITE = os.getenv("HF_TOKEN") +HF_TOKEN_READ = os.getenv("HF_TOKEN_READ") # Can be the same as HF_TOKEN if fine-grained access is not used -# Для записи в репозиторий (хранение сгенерированных сайтов) -REPO_ID_WRITE = os.getenv("HF_TOKEN_WRITE", "Kgshop/generated-sites-storage") # Используйте ваш токен для записи -# Для чтения из репозитория (если потребуется скачивать шаблоны и т.п.) -HF_TOKEN_READ = os.getenv("HF_TOKEN_READ") +REPO_ID = "Kgshop/testsynk" # Target Hugging Face repository -# Настройки для репозитория, куда будут загружаться сгенерированные сайты -GENERATED_SITES_REPO_ID = "Kgshop/testsynk" # Убедитесь, что этот репозиторий существует и вы имеете к нему доступ для записи +GENERATED_APPS_DIR = 'generated_apps' +BASE_PORT_FOR_GENERATED_APPS = 7861 # Start assigning ports from here for generated apps -GENERATED_PROJECTS_DIR = 'generated_projects' # Директория для временного хранения сгенерированных проектов - -if not os.path.exists(GENERATED_PROJECTS_DIR): - os.makedirs(GENERATED_PROJECTS_DIR) +# In-memory store for running generated app processes +running_generated_apps = {} # {app_id: {'process': process_obj, 'port': port, 'url': url}} +# --- Logging --- logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') -# --- Функции синхронизации с Hugging Face (адаптировано из кода 2) --- - -def download_db_from_hf(specific_file=None, retries=3, delay=5): - """Скачивает файлы с Hugging Face. Используется для шаблонов проектов или общих данных.""" - if not HF_TOKEN_READ and not os.getenv("HF_TOKEN_WRITE"): # Проверяем наличие хотя бы одного токена - logging.warning("HF_TOKEN_READ or HF_TOKEN_WRITE not set. Download might fail for private repos.") - - token_to_use = HF_TOKEN_READ if HF_TOKEN_READ else os.getenv("HF_TOKEN_WRITE") # Предпочитаем токен для чтения, если есть - - files_to_download = [specific_file] if specific_file else SYNC_FILES - logging.info(f"Attempting download for {files_to_download} from {GENERATED_SITES_REPO_ID}...") - all_successful = True - - for file_name in files_to_download: - success = False - for attempt in range(retries + 1): - try: - logging.info(f"Downloading {file_name} (Attempt {attempt + 1}/{retries + 1})...") - local_path = hf_hub_download( - repo_id=GENERATED_SITES_REPO_ID, - filename=file_name, - repo_type="dataset", # Считаем, что сайты хранятся как датасеты - token=token_to_use, - local_dir=".", - local_dir_use_symlinks=False, - force_download=True, - resume_download=False - ) - logging.info(f"Successfully downloaded {file_name} to {local_path}.") - success = True - break - except RepositoryNotFoundError: - logging.error(f"Repository {GENERATED_SITES_REPO_ID} not found. Download cancelled for all files.") - return False - except HfHubHTTPError as e: - if e.response.status_code == 404: - logging.warning(f"File {file_name} not found in repo {GENERATED_SITES_REPO_ID} (404). Skipping this file.") - if attempt == 0 and not os.path.exists(file_name): - # Создаем пустой файл, если его нет локально и он не найден на HF - try: - if file_name == DATA_FILE: # Пример для data.json - with open(file_name, 'w', encoding='utf-8') as f: - json.dump({'products': [], 'categories': [], 'orders': {}}, f) - logging.info(f"Created empty local file {file_name} because it was not found on HF.") - except Exception as create_e: - logging.error(f"Failed to create empty local file {file_name}: {create_e}") - success = False - break - else: - logging.error(f"HTTP error downloading {file_name} (Attempt {attempt + 1}): {e}. Retrying in {delay}s...") - except requests.exceptions.RequestException as e: - logging.error(f"Network error downloading {file_name} (Attempt {attempt + 1}): {e}. Retrying in {delay}s...") - except Exception as e: - logging.error(f"Unexpected error downloading {file_name} (Attempt {attempt + 1}): {e}. Retrying in {delay}s...", exc_info=True) - - if attempt < retries: - time.sleep(delay) - - if not success: - logging.error(f"Failed to download {file_name} after {retries + 1} attempts.") - all_successful = False - - logging.info(f"Download process finished. Overall success: {all_successful}") - return all_successful - -def upload_file_to_hf(local_filepath, repo_id, path_in_repo, token, repo_type="dataset", commit_message="Sync file"): - """Загружает один файл на Hugging Face.""" - if not token: - logging.warning(f"HF token not provided for upload to {repo_id}. Skipping upload.") - return False - try: - api = HfApi() - logging.info(f"Uploading {local_filepath} to {repo_id}/{path_in_repo}...") - api.upload_file( - path_or_fileobj=local_filepath, - path_in_repo=path_in_repo, - repo_id=repo_id, - repo_type=repo_type, - token=token, - commit_message=commit_message - ) - logging.info(f"File {local_filepath} successfully uploaded to Hugging Face.") - return True - except Exception as e: - logging.error(f"Error uploading file {local_filepath} to Hugging Face ({repo_id}/{path_in_repo}): {e}", exc_info=True) - return False - -def upload_project_to_hf(project_dir, unique_id, token): - """Загружает весь сгенерированный проект на Hugging Face как dataset.""" - if not token: - logging.warning("HF_TOKEN_WRITE not set. Skipping project upload.") - return False - - repo_name = f"user-generated-sites/{unique_id}" # Создаем отдельный репозиторий для каждого сайта - repo_id = f"Kgshop/{repo_name}" - - if not os.path.exists(project_dir): - logging.error(f"Project directory {project_dir} does not exist for upload.") - return False +if not os.path.exists(GENERATED_APPS_DIR): + os.makedirs(GENERATED_APPS_DIR) - try: - api = HfApi() - - # Создаем репозиторий, если он еще не существует - try: - api.create_repo(repo_id=repo_id, repo_type="dataset", token=token, exist_ok=True) - logging.info(f"Repository {repo_id} ensured to exist.") - except Exception as create_repo_e: - logging.error(f"Failed to create repository {repo_id}: {create_repo_e}") - return False - - # Загружаем все файлы из директории проекта - success = True - for root, _, files in os.walk(project_dir): - for file in files: - local_path = os.path.join(root, file) - # Определяем путь в репозитории относительно корневой директории проекта - path_in_repo = os.path.relpath(local_path, project_dir) - - if not upload_file_to_hf(local_path, repo_id, path_in_repo, token, repo_type="dataset", commit_message=f"Add file {path_in_repo}"): - success = False - break # Прерываем, если один из файлов не удалось загрузить - if not success: - break - - if success: - logging.info(f"Project {repo_id} successfully uploaded.") - # Возвращаем URL для доступа к файлам (например, чтобы скачать) - # Это не прямой URL для запус��а, а URL репозитория на HF - return f"https://huggingface.co/datasets/{repo_id}" - else: - logging.error(f"Failed to upload all files for project {repo_id}.") - return False +if not GOOGLE_AI_API_KEY: + logging.warning("GOOGLE_AI_API_KEY not found in environment variables. AI generation will fail.") +if not HF_TOKEN_WRITE: + logging.warning("HF_TOKEN (for writing) not found. Generated apps might not be able to save/upload data to Hugging Face.") +if not HF_TOKEN_READ and HF_TOKEN_WRITE: + logging.info("HF_TOKEN_READ not found, will use HF_TOKEN (write token) for read operations in generated apps.") +elif not HF_TOKEN_READ and not HF_TOKEN_WRITE: + logging.warning("Neither HF_TOKEN nor HF_TOKEN_READ found. Generated apps will likely fail HF operations.") - except Exception as e: - logging.error(f"General error during Hugging Face project upload: {e}", exc_info=True) - return False -# --- Основной шаблон для UI --- +# --- Main UI Template (Modified) --- html_template = """
-{{ post.content[:150] }}...
-Записей в блоге пока нет.
- {% endif %} - -{{ item.description }}
- {% if item.project_url %}{% endif %} -Элементов портфолио пока нет.
- {% endif %} - - - -{{ post.content[:200] }}...
-Записей в блоге пока нет.
- {% endfor %} - -
- {% endif %}
- {{ item.description }}
- {% if item.tags %}Теги: {{ item.tags }}
{% endif %} - {% if item.project_url %}{% endif %} -Элементов портфолио пока нет.
- {% endfor %} - -
- {% endif %}
- {{ item.description }}
- {% if item.tags %}Теги: {{ item.tags }}
{% endif %} - {% if item.project_url %}{% endif %} - -