--- /dev/null
+#!/usr/bin/env python3
+
+"""Update HS DNS settings behind Google WiFi systems."""
+
+import argparse
+import json
+import urllib.request
+import urllib.parse
+import sys
+
+import dns.resolver
+
+
+WIFI_STATUS_URI = 'http://192.168.86.1/api/v1/status'
+
+
+def get_wan_ip():
+ with urllib.request.urlopen(WIFI_STATUS_URI) as req:
+ data = req.read()
+ status = json.loads(data)
+ return status['wan']['localIpAddress']
+
+
+def update_ip(hostname, password, ip=None):
+ """Update HE DNS with new settings."""
+ params = {
+ 'hostname': hostname,
+ 'password': password,
+ }
+ if ip:
+ params['myip'] = ip
+ body = urllib.parse.urlencode(params).encode()
+
+ url = 'https://dyn.dns.he.net/nic/update'
+ req = urllib.request.Request(url, body)
+
+ with urllib.request.urlopen(req) as response:
+ return response.read()
+
+
+def get_parser():
+ """Get CLI parser."""
+ parser = argparse.ArgumentParser(description=__doc__)
+ parser.add_argument('--hostname', required=True)
+ parser.add_argument('-p', '--password', '--key', required=True)
+ parser.add_argument('-a', '--address', '--ip')
+ parser.add_argument('-q', '--quiet', action='store_true')
+ return parser
+
+
+def main(argv):
+ """The main entry point for scripts."""
+ parser = get_parser()
+ opts = parser.parse_args(argv)
+
+ if opts.quiet:
+ p = lambda *args: None
+ else:
+ p = print
+
+ curr_ip = get_wan_ip()
+ p('Current IP', curr_ip)
+
+ p('Looking up', opts.hostname, '...')
+ answers = dns.resolver.resolve(opts.hostname, 'A')
+ for msg in answers:
+ p('Current DNS', msg.to_text())
+ if curr_ip != msg.to_text():
+ p('Updating IP')
+ resp = update_ip(opts.hostname, opts.password, opts.address)
+ p(resp)
+ else:
+ p('Up-to-date!')
+ break
+
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv[1:]))