from flask import Flask, render_template_string, request, redirect, url_for, session, flash, send_file, jsonify from flask_caching import Cache import json import os import logging import threading import time from datetime import datetime from huggingface_hub import HfApi, hf_hub_download from werkzeug.utils import secure_filename import requests from io import BytesIO app = Flask(__name__) app.secret_key = os.getenv("FLASK_SECRET_KEY", "supersecretkey") DATA_FILE = 'cloudeng_data.json' REPO_ID = "Eluza133/Z1e1u" HF_TOKEN_WRITE = os.getenv("HF_TOKEN") HF_TOKEN_READ = os.getenv("HF_TOKEN_READ") or HF_TOKEN_WRITE cache = Cache(app, config={'CACHE_TYPE': 'simple'}) logging.basicConfig(level=logging.INFO) # Database and Hugging Face functions @cache.memoize(timeout=300) def load_data(): try: download_db_from_hf() with open(DATA_FILE, 'r', encoding='utf-8') as file: data = json.load(file) if not isinstance(data, dict): logging.warning("Data is not in dict format, initializing empty database") return {'users': {}, 'files': {}} data.setdefault('users', {}) data.setdefault('files', {}) logging.info("Data successfully loaded") return data except Exception as e: logging.error(f"Error loading data: {e}") return {'users': {}, 'files': {}} def save_data(data): try: with open(DATA_FILE, 'w', encoding='utf-8') as file: json.dump(data, file, ensure_ascii=False, indent=4) upload_db_to_hf() cache.clear() logging.info("Data saved and uploaded to HF") except Exception as e: logging.error(f"Error saving data: {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"Backup {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}" ) logging.info("Database uploaded to Hugging Face") except Exception as e: logging.error(f"Error uploading database: {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("Database downloaded from Hugging Face") except Exception as e: logging.error(f"Error downloading database: {e}") if not os.path.exists(DATA_FILE): with open(DATA_FILE, 'w', encoding='utf-8') as f: json.dump({'users': {}, 'files': {}}, f) def periodic_backup(): while True: upload_db_to_hf() time.sleep(1800) def get_file_type(filename): video_extensions = ('.mp4', '.mov', '.avi') image_extensions = ('.jpg', '.jpeg', '.png', '.gif') if filename.lower().endswith(video_extensions): return 'video' elif filename.lower().endswith(image_extensions): return 'image' return 'other' BASE_STYLE = ''' :root { --primary: #ff4d6d; --secondary: #00ddeb; --accent: #8b5cf6; --background-light: #f5f6fa; --background-dark: #1a1625; --card-bg: rgba(255, 255, 255, 0.95); --card-bg-dark: rgba(40, 35, 60, 0.95); --text-light: #2a1e5a; --text-dark: #e8e1ff; --shadow: 0 10px 30px rgba(0, 0, 0, 0.2); --glass-bg: rgba(255, 255, 255, 0.15); --transition: all 0.3s ease; --delete-color: #ff4444; } * { margin: 0; padding: 0; box-sizing: border-box; } body { font-family: 'Inter', sans-serif; background: var(--background-light); color: var(--text-light); line-height: 1.6; } body.dark { background: var(--background-dark); color: var(--text-dark); } .container { margin: 20px auto; max-width: 1200px; padding: 25px; background: var(--card-bg); border-radius: 20px; box-shadow: var(--shadow); } body.dark .container { background: var(--card-bg-dark); } h1 { font-size: 2em; font-weight: 800; text-align: center; margin-bottom: 25px; background: linear-gradient(135deg, var(--primary), var(--accent)); -webkit-background-clip: text; color: transparent; } h2 { font-size: 1.5em; margin-top: 30px; color: var(--text-light); } body.dark h2 { color: var(--text-dark); } input, textarea { width: 100%; padding: 14px; margin: 12px 0; border: none; border-radius: 14px; background: var(--glass-bg); color: var(--text-light); font-size: 1.1em; box-shadow: inset 0 3px 10px rgba(0, 0, 0, 0.1); } body.dark input, body.dark textarea { color: var(--text-dark); } input:focus, textarea:focus { outline: none; box-shadow: 0 0 0 4px var(--primary); } .btn { padding: 14px 28px; background: var(--primary); color: white; border: none; border-radius: 14px; cursor: pointer; font-size: 1.1em; font-weight: 600; transition: var(--transition); box-shadow: var(--shadow); display: inline-block; text-decoration: none; } .btn:hover { transform: scale(1.05); background: #e6415f; } .download-btn { background: var(--secondary); margin-top: 10px; } .download-btn:hover { background: #00b8c5; } .delete-btn { background: var(--delete-color); margin-top: 10px; } .delete-btn:hover { background: #cc3333; } .flash { color: var(--secondary); text-align: center; margin-bottom: 15px; } .file-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); gap: 20px; margin-top: 20px; } .user-list { margin-top: 20px; } .user-item { padding: 15px; background: var(--card-bg); border-radius: 16px; margin-bottom: 10px; box-shadow: var(--shadow); transition: var(--transition); } body.dark .user-item { background: var(--card-bg-dark); } .user-item:hover { transform: translateY(-5px); } .user-item a { color: var(--primary); text-decoration: none; font-weight: 600; } .user-item a:hover { color: var(--accent); } @media (max-width: 768px) { .file-grid { grid-template-columns: repeat(2, 1fr); } } @media (max-width: 480px) { .file-grid { grid-template-columns: 1fr; } } .file-item { background: var(--card-bg); padding: 15px; border-radius: 16px; box-shadow: var(--shadow); text-align: center; transition: var(--transition); } body.dark .file-item { background: var(--card-bg-dark); } .file-item:hover { transform: translateY(-5px); } .file-preview { max-width: 100%; max-height: 200px; object-fit: cover; border-radius: 10px; margin-bottom: 10px; loading: lazy; } .file-item p { font-size: 0.9em; margin: 5px 0; } .file-item a { color: var(--primary); text-decoration: none; } .file-item a:hover { color: var(--accent); } .modal { display: none; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0, 0, 0, 0.85); z-index: 2000; justify-content: center; align-items: center; } .modal img, .modal video { max-width: 95%; max-height: 95%; object-fit: contain; border-radius: 20px; box-shadow: var(--shadow); } #progress-container { width: 100%; background: var(--glass-bg); border-radius: 10px; margin: 15px 0; display: none; } #progress-bar { width: 0%; height: 20px; background: var(--primary); border-radius: 10px; transition: width 0.3s ease; } ''' @app.route('/register', methods=['GET', 'POST']) def register(): if request.method == 'POST': username = request.form.get('username') password = request.form.get('password') data = load_data() if username in data['users']: flash('A user with this username already exists!') return redirect(url_for('register')) if not username or not password: flash('Username and password are required!') return redirect(url_for('register')) data['users'][username] = { 'password': password, 'created_at': datetime.now().strftime('%Y-%m-%d %H:%M:%S'), 'files': [] } save_data(data) session['username'] = username flash('Registration successful!') return redirect(url_for('dashboard')) html = '''
Already have an account? Log in
No account? Register
User: {{ username }}
{% with messages = get_flashed_messages() %} {% if messages %} {% for message in messages %}{{ file['filename'] }}
{% endif %}{{ file['upload_date'] }}
Download DeleteYou haven't uploaded any files yet.
{% endif %}Registration Date: {{ user_data['created_at'] }}
File Count: {{ user_data['files'] | length }}
No users yet.
{% endif %}{{ file['filename'] }}
{% endif %}{{ file['upload_date'] }}
DownloadThis user has no files yet.
{% endif %}