import os import json from flask import Flask, request, jsonify, render_template_string, send_from_directory from urllib.parse import urlparse, urlunparse # --- Конфигурация --- APP_HOST = '0.0.0.0' APP_PORT = 7860 # BOT_API_TOKEN = "7835463659:AAGNePbelZIAOeaglyQi1qulOqnjs4BGQn4" # Не используется напрямую в этом коде, но указан в запросе DB_FILE = 'mini_app_browser_db.json' # --- Инициализация Flask --- app = Flask(__name__) # --- База данных (JSON) --- def load_db(): if not os.path.exists(DB_FILE): return {"search_history": [], "saved_passwords": []} try: with open(DB_FILE, 'r', encoding='utf-8') as f: data = json.load(f) # Проверка наличия ключей if "search_history" not in data: data["search_history"] = [] if "saved_passwords" not in data: data["saved_passwords"] = [] return data except (json.JSONDecodeError, IOError): # Если файл поврежден или пуст, возвращаем структуру по умолчанию return {"search_history": [], "saved_passwords": []} def save_db(data): with open(DB_FILE, 'w', encoding='utf-8') as f: json.dump(data, f, indent=4, ensure_ascii=False) # --- HTML, CSS, JS --- HTML_TEMPLATE = """ Mini App Browser
""" # --- Flask Routes --- @app.route('/') def index(): return render_template_string(HTML_TEMPLATE) @app.route('/add_history', methods=['POST']) def add_history(): data = request.get_json() query = data.get('query') url = data.get('url') # URL, который реально загружается is_search = data.get('is_search', False) if not query: return jsonify({"status": "error", "message": "Query is required"}), 400 db_data = load_db() # Ограничим историю, например, 100 последними записями db_data['search_history'] = db_data['search_history'][-99:] import datetime timestamp = datetime.datetime.now().isoformat() db_data['search_history'].append({"query": query, "url": url, "is_search": is_search, "timestamp": timestamp}) save_db(db_data) return jsonify({"status": "success"}) @app.route('/get_history', methods=['GET']) def get_history(): db_data = load_db() return jsonify({"history": db_data.get('search_history', [])}) @app.route('/save_password', methods=['POST']) def save_password_route(): data = request.get_json() site_url = data.get('url') username = data.get('username') password = data.get('password') if not all([site_url, username, password]): return jsonify({"status": "error", "message": "URL, username, and password are required"}), 400 db_data = load_db() import uuid new_password_entry = { "id": str(uuid.uuid4()), # Уникальный ID для возможности удаления "url": site_url, "username": username, "password": password # ВНИМАНИЕ: ХРАНИТСЯ В ОТКРЫТОМ ВИДЕ! } db_data['saved_passwords'].append(new_password_entry) save_db(db_data) return jsonify({"status": "success", "message": "Password saved (INSECURELY!)"}) @app.route('/get_passwords', methods=['GET']) def get_passwords(): db_data = load_db() return jsonify({"passwords": db_data.get('saved_passwords', [])}) @app.route('/delete_password', methods=['POST']) def delete_password_route(): data = request.get_json() password_id = data.get('id') if not password_id: return jsonify({"status": "error", "message": "Password ID is required"}), 400 db_data = load_db() initial_len = len(db_data['saved_passwords']) db_data['saved_passwords'] = [p for p in db_data['saved_passwords'] if p.get('id') != password_id] if len(db_data['saved_passwords']) < initial_len: save_db(db_data) return jsonify({"status": "success", "message": "Password deleted"}) else: return jsonify({"status": "error", "message": "Password not found"}), 404 # Для favicon, если браузер запросит (иначе будет ошибка 404 в консоли) @app.route('/favicon.ico') def favicon(): return send_from_directory(os.path.join(app.root_path, 'static'), 'favicon.ico', mimetype='image/vnd.microsoft.icon') # --- Запуск приложения --- if __name__ == '__main__': # Создаем пустой favicon.ico, если его нет, чтобы избежать ошибки 404 # В реальном приложении здесь должен быть ваш favicon static_dir = os.path.join(app.root_path, 'static') if not os.path.exists(static_dir): os.makedirs(static_dir) favicon_path = os.path.join(static_dir, 'favicon.ico') if not os.path.exists(favicon_path): with open(favicon_path, 'w') as f: # Создаем пустой файл, браузеры обычно его игнорируют pass print(f"Mini App Browser backend running on http://{APP_HOST}:{APP_PORT}") print("WARNING: Password saving in this app is EXTREMELY INSECURE.") print("DO NOT USE THIS FOR REAL PASSWORDS.") app.run(host=APP_HOST, port=APP_PORT, debug=False) # debug=True для разработки