Browse Source

Refactored RCON shell.

pull/2/head 1.1.8
Richard Neumann 4 years ago
parent
commit
af6ef6aeec
  1. 137
      rcon/console.py
  2. 5
      rcon/rconshell.py

137
rcon/console.py

@ -1,7 +1,6 @@
"""An interactive console.""" """An interactive console."""
from getpass import getpass from getpass import getpass
from typing import Union
from rcon.config import Config from rcon.config import Config
from rcon.exceptions import RequestIdMismatch, WrongPassword from rcon.exceptions import RequestIdMismatch, WrongPassword
@ -12,119 +11,102 @@ __all__ = ['rconcmd']
EXIT_COMMANDS = {'exit', 'quit'} EXIT_COMMANDS = {'exit', 'quit'}
MSG_QUERY_LATER = '\nOkay, I will ask again later.'
MSG_ABORTED = '\nAborted...'
MSG_LOGIN_ABORTED = '\nLogin aborted. Bye.' MSG_LOGIN_ABORTED = '\nLogin aborted. Bye.'
MSG_EXIT = 'Bye.' MSG_EXIT = '\nBye.'
MSG_SESSION_TIMEOUT = 'Session timed out. Please login again.' MSG_SESSION_TIMEOUT = 'Session timed out. Please login again.'
MSG_EXIT_USAGE = 'Usage: {} [<exit_code>].'
PROMPT = 'RCON> ' PROMPT = 'RCON> '
def read(prompt: str, typ: type = None) -> type: def read_host() -> str:
"""Reads input and converts it to the respective type.""" """Reads the host."""
while True: while True:
raw = input(prompt)
if typ is not None:
try: try:
return typ(raw) return input('Host: ')
except (TypeError, ValueError): except KeyboardInterrupt:
print(f'Invalid {typ}: {raw}')
continue continue
return raw
def read_port() -> int:
"""Reads the port."""
def read_or_none(prompt: str, typ: type = None) -> type: while True:
"""Reads the input and returns None on EOFError.""" try:
port = input('Port: ')
except KeyboardInterrupt:
continue
try: try:
return read(prompt, typ=typ) port = int(port)
except EOFError: except KeyboardInterrupt:
print(MSG_QUERY_LATER) print(f'Invalid integer: {port}')
return None continue
if 0 <= port <= 65535:
return port
def login(client: Client, passwd: str) -> str: print(f'Invalid port: {port}')
"""Performs a login.""" continue
if passwd is None:
passwd = getpass('Password: ')
logged_in = False def read_passwd() -> str:
"""Reads the password."""
while not logged_in: while True:
try: try:
logged_in = client.login(passwd) return getpass('Password: ')
except WrongPassword: except KeyboardInterrupt:
print('Invalid password.') continue
passwd = getpass('Password: ')
return passwd
def get_config(host: str, port: int, passwd: str) -> Config: def get_config(host: str, port: int, passwd: str) -> Config:
"""Reads the necessary arguments.""" """Reads the necessary arguments."""
while any(item is None for item in (host, port, passwd)):
if host is None: if host is None:
host = read_or_none('Host: ') host = read_host()
if port is None: if port is None:
port = read_or_none('Port: ', typ=int) port = read_port()
if passwd is None: if passwd is None:
passwd = getpass('Password: ') passwd = read_passwd()
return Config(host, port, passwd) return Config(host, port, passwd)
def exit(exit_code: Union[int, str] = 0) -> int: # pylint: disable=W0622 def login(client: Client, passwd: str) -> str:
"""Exits the interactive shell via exit command.""" """Performs a login."""
print(MSG_EXIT)
return int(exit_code)
while True:
try:
client.login(passwd)
except WrongPassword:
print('Invalid password.')
passwd = read_passwd()
continue
def rconcmd(host: str, port: int, passwd: str, *, prompt: str = PROMPT) -> int: return passwd
"""Initializes the console."""
try:
config = get_config(host, port, passwd)
except KeyboardInterrupt:
print(MSG_ABORTED)
return 1
with Client(config.host, config.port) as client: def process_input(client: Client, passwd: str, prompt: str) -> bool:
try: """Processes the CLI input."""
passwd = login(client, config.passwd)
except (EOFError, KeyboardInterrupt):
print(MSG_LOGIN_ABORTED)
return 1
while True:
try: try:
command = input(prompt) command = input(prompt)
except EOFError:
print(f'\n{MSG_EXIT}')
break
except KeyboardInterrupt: except KeyboardInterrupt:
print() print()
continue return True
except EOFError:
print(MSG_EXIT)
return False
try: try:
command, *args = command.split() command, *args = command.split()
except ValueError: except ValueError:
continue return True
if command in EXIT_COMMANDS: if command in EXIT_COMMANDS:
try: return False
return exit(*args) # pylint: disable=R1722
except (TypeError, ValueError):
print(MSG_EXIT_USAGE.format(command))
continue
try: try:
result = client.run(command, *args) result = client.run(command, *args)
@ -133,10 +115,29 @@ def rconcmd(host: str, port: int, passwd: str, *, prompt: str = PROMPT) -> int:
try: try:
passwd = login(client, passwd) passwd = login(client, passwd)
except (EOFError, KeyboardInterrupt): except EOFError:
print(MSG_LOGIN_ABORTED) print(MSG_LOGIN_ABORTED)
return 2 return False
print(result) print(result)
return True
def rconcmd(host: str, port: int, passwd: str, *, prompt: str = PROMPT):
"""Initializes the console."""
try:
host, port, passwd = get_config(host, port, passwd)
except EOFError:
print(MSG_EXIT)
return
with Client(host, port) as client:
try:
passwd = login(client, passwd)
except EOFError:
print(MSG_LOGIN_ABORTED)
return
return 0 while process_input(client, passwd, prompt):
pass

5
rcon/rconshell.py

@ -4,7 +4,6 @@ from argparse import ArgumentParser, Namespace
from logging import INFO, basicConfig, getLogger from logging import INFO, basicConfig, getLogger
from pathlib import Path from pathlib import Path
from socket import timeout from socket import timeout
from sys import exit # pylint: disable=W0622
from rcon.errorhandler import ErrorHandler from rcon.errorhandler import ErrorHandler
from rcon.exceptions import RequestIdMismatch from rcon.exceptions import RequestIdMismatch
@ -49,6 +48,4 @@ def main() -> None:
with ErrorHandler(ERRORS, LOGGER): with ErrorHandler(ERRORS, LOGGER):
with CommandHistory(LOGGER): with CommandHistory(LOGGER):
returncode = rconcmd(host, port, passwd, prompt=args.prompt) rconcmd(host, port, passwd, prompt=args.prompt)
exit(returncode)

Loading…
Cancel
Save