"""OXRO console 0.2 client; defaults to read-only requests after login.""" import argparse import getpass import http.cookiejar import json import urllib.error import urllib.request ORIGIN = 'https://node.orc-server.roketdns.com' class NoRedirect(urllib.request.HTTPRedirectHandler): def redirect_request(self, req, fp, code, msg, headers, newurl): return None class ConsoleClient: def __init__(self): self.opener = urllib.request.build_opener( NoRedirect(), urllib.request.HTTPCookieProcessor(http.cookiejar.CookieJar())) self.csrf = None def request(self, path, payload=None): headers = {'Accept': 'application/json'} body = None if payload is not None: body = json.dumps(payload).encode('utf-8') headers.update({'Content-Type': 'application/json', 'Origin': ORIGIN}) if self.csrf: headers['X-CSRF-Token'] = self.csrf req = urllib.request.Request(ORIGIN + path, data=body, headers=headers) try: with self.opener.open(req, timeout=20) as response: return json.load(response) except urllib.error.HTTPError as exc: request_id = exc.headers.get('X-Request-ID', 'unknown') retry = exc.headers.get('Retry-After', 'none') try: data = json.loads(exc.read(65536)) code = data.get('error', 'HTTP_ERROR') if isinstance(data, dict) else 'HTTP_ERROR' except (ValueError, UnicodeError): code = 'NON_JSON_HTTP_ERROR' raise RuntimeError( f'HTTP {exc.code}: {code}; requestId={request_id}; Retry-After={retry}') from None except urllib.error.URLError: raise RuntimeError('Network/TLS failure; write outcome may be unknown.') from None def main(): parser = argparse.ArgumentParser(description=__doc__) parser.add_argument('--lab', action='store_true', help='Run seven live server diagnostics') parser.add_argument('--exercise-room', action='store_true', help='Create and archive a REAL room; keeps room/event history') args = parser.parse_args() client = ConsoleClient() username = input('Application username [admin]: ').strip() or 'admin' password = getpass.getpass('Application password: ') login = client.request('/api/login', {'username': username, 'password': password}) del password client.csrf = login['csrf'] try: me = client.request('/api/me') print('Authenticated:', me['username']) overview = client.request('/api/overview') print('Returned rooms:', len(overview['rooms']), 'Health:', overview['health']) if args.lab: report = client.request('/api/lab/run', {}) print(json.dumps(report, ensure_ascii=False, indent=2)) if any(item['status'] != 'passed' for item in report['results']): raise RuntimeError('One or more diagnostics failed (HTTP 200 is not test success).') if args.exercise_room: room = client.request('/api/rooms', { 'name': 'Integration example', 'description': 'Explicit client write exercise', 'capacity': 20}) print('Created room:', room['id']) client.request('/api/rooms/' + room['id'] + '/archive', {}) print('Archived room:', room['id']) finally: try: client.request('/api/logout', {}) except Exception as exc: print('Logout could not be confirmed:', exc) client.csrf = None if __name__ == '__main__': try: main() except (RuntimeError, TimeoutError, ValueError) as exc: raise SystemExit(str(exc)) from None