"""Run PyNetgear from the command-line.""" import sys import os from argparse import ArgumentParser from pynetgear import Netgear, BLOCK, ALLOW def make_formatter(format_name): """Returns a callable that outputs the data. Defaults to print.""" if "json" in format_name: from json import dumps import datetime def jsonhandler(obj): obj.isoformat() if isinstance( obj, (datetime.datetime, datetime.date) ) else obj if format_name == "prettyjson": def jsondumps(data): return dumps( data, default=jsonhandler, indent=2, separators=(",", ": ") ) else: def jsondumps(data): return dumps(data, default=jsonhandler) def jsonify(data): if isinstance(data, dict): print(jsondumps(data)) elif isinstance(data, list): print(jsondumps([device._asdict() for device in data])) else: print(dumps({"result": data})) return jsonify else: def printer(data): if isinstance(data, dict): print(data) else: for row in data: print(row) return printer def argparser(): """Constructs the ArgumentParser for the CLI""" parser = ArgumentParser(prog="pynetgear") parser.add_argument( "--format", choices=["json", "prettyjson", "py"], default="prettyjson" ) router_args = parser.add_argument_group("router connection config") router_args.add_argument("--host", help="Hostname for the router") router_args.add_argument("--user", help="Account for login") router_args.add_argument("--port", help="Port exposed on the router") router_args.add_argument( "--login-v2", help="Force the use of the cookie-based authentication", dest="force_login_v2", default=False, action="store_true", ) router_args.add_argument( "--password", help="Not required with a wired connection." + "Optionally, set the PYNETGEAR_PASSWORD environment variable", ) router_args.add_argument( "--url", help="Overrides host:port and ssl with url to router" ) router_args.add_argument( "--no-ssl", dest="ssl", default=True, action="store_false", help="Connect with https", ) subparsers = parser.add_subparsers( description="Runs subcommand against the specified router", dest="subcommand", ) block_parser = subparsers.add_parser( "block_device", help="Blocks a device from connecting by mac address" ) block_parser.add_argument("--mac-addr") allow_parser = subparsers.add_parser( "allow_device", help="Allows a device with the mac address to connect" ) allow_parser.add_argument("--mac-addr") subparsers.add_parser("login", help="Attempts to login to router.") attached_devices = subparsers.add_parser( "attached_devices", help="Outputs all attached devices" ) attached_devices.add_argument( "-v", "--verbose", action="store_true", default=False, help="Choose between verbose and slower or terse and fast.", ) subparsers.add_parser("traffic_meter", help="Output router's traffic meter data") return parser def run_subcommand(netgear, args): """Runs the subcommand configured in args on the netgear session""" subcommand = args.subcommand if subcommand == "block_device" or subcommand == "allow_device": return netgear.allow_block_device( args.mac_addr, BLOCK if subcommand == "block_device" else ALLOW ) if subcommand == "attached_devices": if args.verbose: return netgear.get_attached_devices_2() else: return netgear.get_attached_devices() if subcommand == "traffic_meter": return netgear.get_traffic_meter() if subcommand == "login": return netgear.login() print("Unknown subcommand") def main(): """Scan for devices and print results.""" args = argparser().parse_args(sys.argv[1:]) password = os.environ.get("PYNETGEAR_PASSWORD") or args.password netgear = Netgear( password, args.host, args.user, args.port, args.ssl, args.url, args.force_login_v2, ) results = run_subcommand(netgear, args) formatter = make_formatter(args.format) if results is None: print("Error communicating with the Netgear router") else: formatter(results) if __name__ == "__main__": main()