import os, base64, re, json DEFAULT_CONTACTS = { "phone": "+380675745662", "phone_display": "+38 067 574 56 62", "tg_link": "https://t.me/unstop_retail", "tg_display": "Telegram", "map_iframe": 'https://www.google.com/maps/d/embed?mid=1pn9YLjrvuNJtrxwioRFoS-RC3eAdPAA&ehbc=2E312F&noprof=1', "address": "м. Харків, Основ'янський район" } def read_file(path, fallback=""): if os.path.exists(path): with open(path, "r", encoding="utf-8") as f: return f.read() return fallback def img_b64(path): ext = os.path.splitext(path)[1].lower() mime = "image/png" if ext == ".png" else "image/jpeg" if ext in [".jpg", ".jpeg"] else "image/webp" with open(path, "rb") as f: return f"data:{mime};base64," + base64.b64encode(f.read()).decode() def _read_config(base_dir): config_path = os.path.join(base_dir, "config.json") if os.path.exists(config_path): with open(config_path, "r", encoding="utf-8") as f: return json.load(f) return {"models": [], "contacts": DEFAULT_CONTACTS.copy()} def _write_config(base_dir, data): config_path = os.path.join(base_dir, "config.json") with open(config_path, "w", encoding="utf-8") as f: json.dump(data, f, ensure_ascii=False, indent=4) def get_contacts(base_dir): cfg = _read_config(base_dir) contacts = cfg.get("contacts", {}) # Fill missing keys with defaults for k, v in DEFAULT_CONTACTS.items(): contacts.setdefault(k, v) return contacts def save_contacts(base_dir, contacts: dict): cfg = _read_config(base_dir) cfg["contacts"] = contacts _write_config(base_dir, cfg) def get_models_data(base_dir): config_path = os.path.join(base_dir, "config.json") models_dir = os.path.join(base_dir, "models") if not os.path.exists(config_path): models_list = [] if os.path.exists(models_dir) and os.path.isdir(models_dir): for i, folder in enumerate(sorted(os.listdir(models_dir))): folder_path = os.path.join(models_dir, folder) if os.path.isdir(folder_path): opis = read_file(os.path.join(folder_path, "Opis.txt"), fallback="") price = read_file(os.path.join(folder_path, "Price.txt"), fallback="49 000 грн").strip() subtitle = read_file(os.path.join(folder_path, "Subtitle.txt"), fallback="🔋 Надійна енергія для вашого бізнесу").strip() models_list.append({ "id": f"m_{i}", "folder": folder, "name": folder, "title": folder, "subtitle": subtitle, "price": price, "opis_raw": opis }) if not models_list: models_list.append({ "id": "m_main", "folder": "", "name": "Базова", "title": "Unstop Retail 4032W", "subtitle": "🔋 LiFePO4 • 4032 Wh • 8+ годин автономної роботи", "price": "49 000 грн", "opis_raw": read_file(os.path.join(base_dir, "Opis.txt"), fallback="") }) _write_config(base_dir, {"models": models_list, "contacts": DEFAULT_CONTACTS.copy()}) cfg = _read_config(base_dir) models = cfg.get("models", []) for m in models: folder_name = m.get("folder", "") folder_path = os.path.join(models_dir, folder_name) if folder_name else base_dir images = [] if os.path.exists(folder_path): images = sorted([ os.path.join(folder_path, img) for img in os.listdir(folder_path) if img.lower().endswith(('.webp', '.png', '.jpg', '.jpeg')) ]) if not images and not folder_name: candidates = ["image (1).webp", "image (2).webp", "image.webp"] images = [os.path.join(base_dir, p) for p in candidates if os.path.exists(os.path.join(base_dir, p))] m["images"] = images return models def save_config(base_dir, models_data): cfg = _read_config(base_dir) clean_models = [] for m in models_data: clean_models.append({ "id": m.get("id"), "folder": m.get("folder", ""), "name": m.get("name", ""), "title": m.get("title", ""), "subtitle": m.get("subtitle", ""), "price": m.get("price", ""), "opis_raw": m.get("opis_raw", "") }) cfg["models"] = clean_models _write_config(base_dir, cfg) def opis_to_html(text): if not text: return "
Опис не знайдено.
" lines, parts, in_tbl, tbuf = text.split("\n"), [], False, [] for line in lines: if line.startswith("## "): parts.append(f"{line[2:].strip()}') elif line.strip(): l = re.sub(r"\*\*(.+?)\*\*", r"\1", line) l = re.sub(r"\*(.+?)\*", r"\1", l) if l.strip().startswith("- "): parts.append(f"
{l.strip()}
") else: parts.append("") if in_tbl: parts.append(_tbl(tbuf)) res = "\n".join(parts) return re.sub(r"((?: