#!/usr/bin/env python3 """Управление пользователями сервиса hh_auto. Примеры: python3 manage_users.py add friend1 # спросит пароль python3 manage_users.py add friend1 --password 123 --limit 50 python3 manage_users.py list python3 manage_users.py passwd friend1 python3 manage_users.py limit friend1 100 python3 manage_users.py remove friend1 """ import argparse import datetime import getpass import json import os import shutil import sys from werkzeug.security import generate_password_hash BASE_DIR = os.path.dirname(os.path.abspath(__file__)) USERS_FILE = os.path.join(BASE_DIR, "users.json") def load(): if os.path.exists(USERS_FILE): with open(USERS_FILE, encoding="utf-8") as f: return json.load(f) return {} def save(users): tmp = USERS_FILE + ".tmp" with open(tmp, "w", encoding="utf-8") as f: json.dump(users, f, ensure_ascii=False, indent=2) os.replace(tmp, USERS_FILE) os.chmod(USERS_FILE, 0o600) def add(username, password, limit): users = load() if username in users: sys.exit(f"Пользователь «{username}» уже существует") users[username] = { "password_hash": generate_password_hash(password), "llm_limit": limit, "llm_usage": {}, "created": datetime.date.today().isoformat(), } save(users) os.makedirs(os.path.join(BASE_DIR, "users", username, "accounts"), exist_ok=True) print(f"Пользователь «{username}» создан") print(f" Данные: {BASE_DIR}/users/{username}/") print(f" Дневной лимит генераций: {limit or 'без лимита'}") print(f" Вход: https://ВАШ-ДОМЕН/ (логин: {username})") def remove(username): users = load() if username not in users: sys.exit(f"Пользователь «{username}» не найден") del users[username] save(users) shutil.rmtree(os.path.join(BASE_DIR, "users", username), ignore_errors=True) print(f"Пользователь «{username}» удалён вместе с данными") def set_password(username, password): users = load() if username not in users: sys.exit(f"Пользователь «{username}» не найден") users[username]["password_hash"] = generate_password_hash(password) save(users) print(f"Пароль «{username}» обновлён") def set_limit(username, limit): users = load() if username not in users: sys.exit(f"Пользователь «{username}» не найден") users[username]["llm_limit"] = limit save(users) print(f"Лимит «{username}»: {limit or 'без лимита'} генераций в день") def list_users(): users = load() if not users: print("Пользователей нет") return today = datetime.date.today().isoformat() print(f"{'Логин':20} {'Генерации сегодня':18} Создан") for name, u in sorted(users.items()): used = (u.get("llm_usage") or {}).get(today, 0) limit = u.get("llm_limit") or 0 lim = f"{used}/{limit}" if limit else f"{used}/∞" print(f" {name:18} {lim:16} {u.get('created', '?')}") def main(): ap = argparse.ArgumentParser(description="Управление пользователями hh_auto") sub = ap.add_subparsers(dest="cmd", required=True) a = sub.add_parser("add", help="Создать пользователя") a.add_argument("username") a.add_argument("--password", help="Пароль (иначе спросит)") a.add_argument("--limit", type=int, default=50, help="Дневной лимит генераций (0 = без лимита)") sub.add_parser("list", help="Список пользователей") p = sub.add_parser("passwd", help="Сменить пароль") p.add_argument("username") l = sub.add_parser("limit", help="Установить дневной лимит генераций") l.add_argument("username") l.add_argument("limit", type=int) r = sub.add_parser("remove", help="Удалить пользователя с данными") r.add_argument("username") args = ap.parse_args() if args.cmd == "add": password = args.password or getpass.getpass(f"Пароль для «{args.username}»: ") add(args.username, password, args.limit) elif args.cmd == "list": list_users() elif args.cmd == "passwd": password = getpass.getpass(f"Новый пароль для «{args.username}»: ") set_password(args.username, password) elif args.cmd == "limit": set_limit(args.username, args.limit) elif args.cmd == "remove": if input(f"Удалить «{args.username}» и все его данные? [y/N]: ").strip().lower() \ in ("y", "д", "yes", "да"): remove(args.username) if __name__ == "__main__": main()