Spaces:
Sleeping
Sleeping
Download database.py from Kostya-Lolinger/EchoReader: direct link, hf CLI and curl.
- Browser
- Download file 6.85 kB
-
https://huggingface.co/spaces/Kostya-Lolinger/EchoReader/resolve/main/database.py
- Command line
-
hf download hf://spaces/Kostya-Lolinger/EchoReader/database.py
-
curl -L -o database.py https://huggingface.co/spaces/Kostya-Lolinger/EchoReader/resolve/main/database.py
6.85 kB
| import json | |
| import os | |
| import shutil | |
| import bcrypt | |
| from datetime import datetime | |
| DATA_DIR = "user_data" | |
| def _ensure_dirs(): | |
| os.makedirs(DATA_DIR, exist_ok=True) | |
| def _user_dir(username: str) -> str: | |
| path = os.path.join(DATA_DIR, username) | |
| os.makedirs(path, exist_ok=True) | |
| return path | |
| def _voices_dir(username: str) -> str: | |
| path = os.path.join(_user_dir(username), "voices") | |
| os.makedirs(path, exist_ok=True) | |
| return path | |
| def _files_dir(username: str) -> str: | |
| path = os.path.join(_user_dir(username), "files") | |
| os.makedirs(path, exist_ok=True) | |
| return path | |
| def _users_file() -> str: | |
| _ensure_dirs() | |
| return os.path.join(DATA_DIR, "users.json") | |
| def _load_users() -> dict: | |
| path = _users_file() | |
| if os.path.exists(path): | |
| with open(path, "r") as f: | |
| return json.load(f) | |
| return {} | |
| def _save_users(users: dict): | |
| with open(_users_file(), "w") as f: | |
| json.dump(users, f, indent=2) | |
| def register_user(username: str, password: str) -> tuple[bool, str]: | |
| if not username or not password: | |
| return False, "Username and password required" | |
| if len(username) < 3: | |
| return False, "Username must be at least 3 characters" | |
| if len(password) < 6: | |
| return False, "Password must be at least 6 characters" | |
| users = _load_users() | |
| if username.lower() in users: | |
| return False, "user_exists" | |
| hashed = bcrypt.hashpw(password.encode(), bcrypt.gensalt()).decode() | |
| users[username.lower()] = { | |
| "password_hash": hashed, | |
| "created": datetime.now().isoformat(), | |
| "settings": {"app_language": "en", "tts_language": "en", "speed": 1.0}, | |
| } | |
| _save_users(users) | |
| _user_dir(username.lower()) | |
| _voices_dir(username.lower()) | |
| _files_dir(username.lower()) | |
| return True, "register_success" | |
| def verify_user(username: str, password: str) -> bool: | |
| users = _load_users() | |
| user = users.get(username.lower()) | |
| if not user: | |
| return False | |
| return bcrypt.checkpw(password.encode(), user["password_hash"].encode()) | |
| def delete_user(username: str, password: str) -> bool: | |
| if not verify_user(username, password): | |
| return False | |
| users = _load_users() | |
| username = username.lower() | |
| if username in users: | |
| del users[username] | |
| _save_users(users) | |
| user_path = os.path.join(DATA_DIR, username) | |
| if os.path.exists(user_path): | |
| shutil.rmtree(user_path) | |
| return True | |
| def get_user_settings(username: str) -> dict: | |
| users = _load_users() | |
| user = users.get(username.lower(), {}) | |
| return user.get("settings", {"app_language": "en", "tts_language": "en", "speed": 1.0}) | |
| def update_user_settings(username: str, settings: dict): | |
| users = _load_users() | |
| username = username.lower() | |
| if username in users: | |
| users[username]["settings"] = settings | |
| _save_users(users) | |
| def save_user_file(username: str, filename: str, content: str) -> str: | |
| files_dir = _files_dir(username.lower()) | |
| meta_path = os.path.join(files_dir, "files_meta.json") | |
| if os.path.exists(meta_path): | |
| with open(meta_path, "r") as f: | |
| meta = json.load(f) | |
| else: | |
| meta = {} | |
| safe_name = "".join(c for c in filename if c.isalnum() or c in "._- ").strip() | |
| file_id = f"{datetime.now().strftime('%Y%m%d%H%M%S')}_{safe_name}" | |
| content_path = os.path.join(files_dir, f"{file_id}.txt") | |
| with open(content_path, "w", encoding="utf-8") as f: | |
| f.write(content) | |
| meta[file_id] = { | |
| "original_name": filename, | |
| "saved_at": datetime.now().isoformat(), | |
| "char_count": len(content), | |
| } | |
| with open(meta_path, "w") as f: | |
| json.dump(meta, f, indent=2) | |
| return file_id | |
| def get_user_files(username: str) -> dict: | |
| files_dir = _files_dir(username.lower()) | |
| meta_path = os.path.join(files_dir, "files_meta.json") | |
| if os.path.exists(meta_path): | |
| with open(meta_path, "r") as f: | |
| return json.load(f) | |
| return {} | |
| def load_file_content(username: str, file_id: str) -> str: | |
| files_dir = _files_dir(username.lower()) | |
| content_path = os.path.join(files_dir, f"{file_id}.txt") | |
| if os.path.exists(content_path): | |
| with open(content_path, "r", encoding="utf-8") as f: | |
| return f.read() | |
| return "" | |
| def delete_user_file(username: str, file_id: str) -> bool: | |
| files_dir = _files_dir(username.lower()) | |
| meta_path = os.path.join(files_dir, "files_meta.json") | |
| content_path = os.path.join(files_dir, f"{file_id}.txt") | |
| if os.path.exists(meta_path): | |
| with open(meta_path, "r") as f: | |
| meta = json.load(f) | |
| if file_id in meta: | |
| del meta[file_id] | |
| with open(meta_path, "w") as f: | |
| json.dump(meta, f, indent=2) | |
| if os.path.exists(content_path): | |
| os.remove(content_path) | |
| return True | |
| return False | |
| def save_cloned_voice(username: str, voice_name: str, audio_path: str) -> str: | |
| voices_dir = _voices_dir(username.lower()) | |
| meta_path = os.path.join(voices_dir, "voices_meta.json") | |
| if os.path.exists(meta_path): | |
| with open(meta_path, "r") as f: | |
| meta = json.load(f) | |
| else: | |
| meta = {} | |
| voice_id = f"{datetime.now().strftime('%Y%m%d%H%M%S')}_{voice_name}" | |
| ext = os.path.splitext(audio_path)[1] | |
| voice_file = os.path.join(voices_dir, f"{voice_id}{ext}") | |
| shutil.copy2(audio_path, voice_file) | |
| meta[voice_id] = { | |
| "name": voice_name, | |
| "file": f"{voice_id}{ext}", | |
| "created": datetime.now().isoformat(), | |
| } | |
| with open(meta_path, "w") as f: | |
| json.dump(meta, f, indent=2) | |
| return voice_id | |
| def get_user_voices(username: str) -> dict: | |
| voices_dir = _voices_dir(username.lower()) | |
| meta_path = os.path.join(voices_dir, "voices_meta.json") | |
| if os.path.exists(meta_path): | |
| with open(meta_path, "r") as f: | |
| return json.load(f) | |
| return {} | |
| def get_voice_path(username: str, voice_id: str) -> str: | |
| voices = get_user_voices(username.lower()) | |
| if voice_id in voices: | |
| voices_dir = _voices_dir(username.lower()) | |
| return os.path.join(voices_dir, voices[voice_id]["file"]) | |
| return "" | |
| def delete_user_voice(username: str, voice_id: str) -> bool: | |
| voices_dir = _voices_dir(username.lower()) | |
| meta_path = os.path.join(voices_dir, "voices_meta.json") | |
| if os.path.exists(meta_path): | |
| with open(meta_path, "r") as f: | |
| meta = json.load(f) | |
| if voice_id in meta: | |
| voice_file = os.path.join(voices_dir, meta[voice_id]["file"]) | |
| if os.path.exists(voice_file): | |
| os.remove(voice_file) | |
| del meta[voice_id] | |
| with open(meta_path, "w") as f: | |
| json.dump(meta, f, indent=2) | |
| return True | |
| return False |