File size: 4,888 Bytes
a39cafb
 
 
a38ca42
a39cafb
 
 
 
 
 
 
 
a38ca42
 
 
a39cafb
 
 
 
a38ca42
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
a39cafb
 
a38ca42
 
 
 
a39cafb
a38ca42
 
 
a39cafb
a38ca42
 
 
 
 
 
 
a39cafb
 
a38ca42
a39cafb
 
 
 
a38ca42
a39cafb
 
 
a38ca42
 
 
 
 
 
 
a39cafb
 
a38ca42
a39cafb
 
 
 
a38ca42
a39cafb
 
a38ca42
 
 
a39cafb
 
a38ca42
 
 
a39cafb
a38ca42
 
a39cafb
 
 
 
 
a38ca42
a39cafb
 
a38ca42
 
 
a39cafb
 
 
 
 
 
 
a38ca42
 
 
 
 
a39cafb
 
 
 
a38ca42
a39cafb
 
 
 
a38ca42
 
a39cafb
 
 
a38ca42
 
 
 
 
 
 
a39cafb
 
 
a38ca42
a39cafb
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
"""
VTX Studio beta key administration utility.

Keys are stored in the private ManChildTechnologies/VTX-BetaKeys dataset.
"""
from __future__ import annotations

import argparse
import json
from pathlib import Path
from typing import Any

from beta_keys_schema import generate_unique_key, new_record, normalize_record
from beta_keys_store import keys_path, load_keys, save_keys

APP_DIR = Path(__file__).resolve().parent
DEFAULT_KEYS_PATH = APP_DIR / "keys.json"


def generate_key(
    *,
    name: str,
    notes: str = "",
    path: str | Path | None = None,
    push: bool = True,
) -> str:
    """Generate a new ACTIVE beta key and persist it to the dataset."""
    if not str(name or "").strip():
        raise ValueError("Tester name is required.")

    keys = load_keys(force=True)
    beta_key = generate_unique_key(keys)
    record = new_record(name=name, notes=notes)
    record["key"] = beta_key
    keys[beta_key] = normalize_record(beta_key, record)
    if push:
        save_keys(keys, commit_message=f"Generate beta key for {name.strip()}")
    elif path:
        from beta_keys_store import _write_json_file

        _write_json_file(Path(path), keys)
    return beta_key


def revoke_key(beta_key: str, path: str | Path | None = None, push: bool = True) -> dict[str, Any]:
    key = str(beta_key or "").strip()
    if not key:
        raise ValueError("Beta key is required.")

    keys = load_keys(force=True)
    if key not in keys:
        raise KeyError(f"Beta key not found: {key}")

    record = normalize_record(key, keys[key])
    record["active"] = False
    record["status"] = "REVOKED"
    keys[key] = record
    if push:
        save_keys(keys, commit_message=f"Revoke beta key {key}")
    return record


def reactivate_key(beta_key: str, path: str | Path | None = None, push: bool = True) -> dict[str, Any]:
    key = str(beta_key or "").strip()
    if not key:
        raise ValueError("Beta key is required.")

    keys = load_keys(force=True)
    if key not in keys:
        raise KeyError(f"Beta key not found: {key}")

    record = normalize_record(key, keys[key])
    record["active"] = True
    record["status"] = "ACTIVE"
    keys[key] = record
    if push:
        save_keys(keys, commit_message=f"Reactivate beta key {key}")
    return record


def delete_key(beta_key: str, push: bool = True) -> None:
    key = str(beta_key or "").strip()
    if not key:
        raise ValueError("Beta key is required.")

    keys = load_keys(force=True)
    if key not in keys:
        raise KeyError(f"Beta key not found: {key}")
    del keys[key]
    if push:
        save_keys(keys, commit_message=f"Delete beta key {key}")


def export_json(output: str | Path | None = None) -> Path:
    keys = load_keys(force=True)
    out = Path(output) if output else keys_path()
    out.parent.mkdir(parents=True, exist_ok=True)
    ordered = {key: normalize_record(key, record) for key, record in sorted(keys.items())}
    out.write_text(json.dumps(ordered, indent=2) + "\n", encoding="utf-8")
    return out


def main() -> int:
    parser = argparse.ArgumentParser(description="VTX Studio beta key manager")
    parser.add_argument("--keys", default="", help="Optional local export path")
    sub = parser.add_subparsers(dest="command", required=True)

    generate = sub.add_parser("generate", help="Generate a new ACTIVE beta key")
    generate.add_argument("--name", required=True, help="Tester name")
    generate.add_argument("--notes", default="", help="Optional notes")

    revoke = sub.add_parser("revoke", help="Revoke an existing beta key")
    revoke.add_argument("beta_key", help="Beta key to revoke")

    reactivate = sub.add_parser("reactivate", help="Reactivate a revoked beta key")
    reactivate.add_argument("beta_key", help="Beta key to reactivate")

    delete = sub.add_parser("delete", help="Delete an existing beta key")
    delete.add_argument("beta_key", help="Beta key to delete")

    export = sub.add_parser("export", help="Export keys.json snapshot")
    export.add_argument("-o", "--output", default="", help="Optional output path")

    args = parser.parse_args()

    if args.command == "generate":
        beta_key = generate_key(name=args.name, notes=args.notes)
        print(beta_key)
        return 0

    if args.command == "revoke":
        record = revoke_key(args.beta_key)
        print(json.dumps(record, indent=2))
        return 0

    if args.command == "reactivate":
        record = reactivate_key(args.beta_key)
        print(json.dumps(record, indent=2))
        return 0

    if args.command == "delete":
        delete_key(args.beta_key)
        print("deleted")
        return 0

    if args.command == "export":
        out = export_json(args.output or None)
        print(str(out))
        return 0

    parser.error("Unknown command")
    return 1


if __name__ == "__main__":
    raise SystemExit(main())