Commit 9a5ae04

Dan Krause <dan@dankrause.net>
2013-05-15 23:40:22
1 parent 36d7075
hoverapi.py → _example.py
@@ -1,19 +1,26 @@
 import requests
 
+class HoverException(Exception):
+    pass
+
+
 class HoverAPI(object):
     def __init__(self, username, password):
         params = {"username": username, "password": password}
         r = requests.post("https://www.hover.com/signin", params=params)
-        if not r.ok:
-            raise Exception(r)
+        if not r.ok or "hoverauth" not in r.cookies:
+            raise HoverException(r)
         self.cookies = {"hoverauth": r.cookies["hoverauth"]}
     def call(self, method, resource, data=None):
         url = "https://www.hover.com/api/{0}".format(resource)
         r = requests.request(method, url, data=data, cookies=self.cookies)
         if not r.ok:
-            raise Exception(r)
+            raise HoverException(r)
         if r.content:
-            return r.json()
+            body = r.json()
+            if "succeeded" not in body or body["succeeded"] is not True:
+                raise HoverException(body)
+            return body
 
 
 # connect to the API using your account
dynhover.py
@@ -5,18 +5,6 @@ import requests
 import optparse
 import sys
 
-# This is a command-line script to update a hover.com DNS record with your
-# current public-facing IP address. (think dyndns) Run it like so:
-# ./dynhover.py -u USERNAME -p PASSWORD -d DOMAIN
-# or create a config file like this:
-# 
-# [dynhover]
-# username=USERNAME
-# password=PASSWORD
-# domain=DOMAIN
-#
-# and run it like this:
-# ./dynhover.py -c PATH_TO_CONF
 
 class HoverException(Exception):
     pass
@@ -35,7 +23,10 @@ class HoverAPI(object):
         if not r.ok:
             raise HoverException(r)
         if r.content:
-            return r.json()
+            body = r.json()
+            if "succeeded" not in body or body["succeeded"] is not True:
+                raise HoverException(body)
+            return body
 
 
 def get_public_ip():
@@ -69,28 +60,32 @@ def update_dns(username, password, fqdn):
     
 
 def main():
-    usage = "usage: %prog (-c CONF|-u USERNAME -p PASSWORD -d DOMAIN)"
+    usage = "usage: %prog (-c CONF|-u USERNAME -p PASSWORD) DOMAIN"
     description = "Update a hover.com DNS record with the current IP of this machine."
     parser = optparse.OptionParser(usage=usage, description=description)
-    parser.add_option("-c", "--conf", default=None, help="The conf file that contains your username, password, and fully qualified domain name")
+    parser.add_option("-c", "--conf", default=None, help="The conf file that contains your username and password")
     parser.add_option("-u", "--username", default=None, help="Your hover.com username")
     parser.add_option("-p", "--password", default=None, help="Your hover.com password")
-    parser.add_option("-d", "--domain", default=None, help="The fully qualified domain name you're updating")
     (options, args) = parser.parse_args()
-
+    
+    if len(args) < 1:
+        parser.error("You must specify a domain")
+    
+    domain = args[0]
+    
     def get_conf(filename):
         config = ConfigParser.ConfigParser()
         config.read(filename)
-        items = dict(config.items("dynhover"))
-        return items["username"], items["password"], items["domain"]
+        items = dict(config.items("hover"))
+        return items["username"], items["password"]
 
     if options.conf is None:
-        if not all((options.username, options.password, options.domain)):
-            parser.error("You must specifiy either a conf file, or a username, password, and domain")
+        if not all((options.username, options.password)):
+            parser.error("You must specifiy either a conf file, or a username and password")
         else:
-            username, password, domain = options.username, options.password, options.domain
+            username, password = options.username, options.password
     else:
-        username, password, domain = get_conf(options.conf)
+        username, password = get_conf(options.conf)
 
     update_dns(username, password, domain)
 
hoverimport.py
@@ -0,0 +1,91 @@
+#!/usr/bin/python
+
+import ConfigParser
+import requests
+import optparse
+import sys
+
+
+class HoverException(Exception):
+    pass
+
+
+class HoverAPI(object):
+    def __init__(self, username, password):
+        params = {"username": username, "password": password}
+        r = requests.post("https://www.hover.com/signin", params=params)
+        if not r.ok or "hoverauth" not in r.cookies:
+            raise HoverException(r)
+        self.cookies = {"hoverauth": r.cookies["hoverauth"]}
+    def call(self, method, resource, data=None):
+        url = "https://www.hover.com/api/{0}".format(resource)
+        r = requests.request(method, url, data=data, cookies=self.cookies)
+        if not r.ok:
+            raise HoverException(r)
+        if r.content:
+            body = r.json()
+            if "succeeded" not in body or body["succeeded"] is not True:
+                raise HoverException(body)
+            return body
+
+
+def import_dns(username, password, domain, filename, flush=False):
+    try:
+        client = HoverAPI(username, password)
+    except HoverException as e:
+        raise HoverException("Authentication failed")
+    if flush:
+        records = client.call("get", "domains/{0}/dns".format(domain))["domains"][0]["entries"]
+        for record in records:
+            client.call("delete", "dns/{0}".format(record["id"]))
+            print "Deleted {name} {type} {content}".format(**record)
+    
+    domain_id = client.call("get", "domains/{0}".format(domain))["domain"]["id"]
+    
+    with open(filename, "r") as f:
+        for line in f:
+            parts = line.strip().split(" ", 2)
+            record = {"name": parts[0], "type": parts[1], "content": parts[2]}
+            client.call("post", "domains/{0}/dns".format(domain), record)
+            print "Created {name} {type} {content}".format(**record)
+
+
+def main():
+    usage = "usage: %prog (-c CONF|-u USERNAME -p PASSWORD) DOMAIN FILE"
+    description = "Import a file of DNS records for a single domain into a hover account."
+    parser = optparse.OptionParser(usage=usage, description=description)
+    parser.add_option("-c", "--conf", default=None, help="The conf file that contains your username and password")
+    parser.add_option("-u", "--username", default=None, help="Your hover.com username")
+    parser.add_option("-p", "--password", default=None, help="Your hover.com password")
+    parser.add_option("-f", "--flush", default=False, action="store_true", help="Flush all DNS records associated with the domain before importing")
+    (options, args) = parser.parse_args()
+    
+    if len(args) < 2:
+        parser.error("You must specify both a domain, and a file to import")
+    
+    domain, filename = args
+    
+    def get_conf(filename):
+        config = ConfigParser.ConfigParser()
+        config.read(filename)
+        items = dict(config.items("hover"))
+        return items["username"], items["password"]
+
+    if options.conf is None:
+        if not all((options.username, options.password)):
+            parser.error("You must specifiy either a conf file, or a username and password")
+        else:
+            username, password = options.username, options.password
+    else:
+        username, password = get_conf(options.conf)
+
+    import_dns(username, password, domain, filename, options.flush)
+
+
+if __name__ == "__main__":
+    try:
+        main()
+    except HoverException as e:
+        print "Failed while importing DNS: {0}".format(e)
+        sys.exit(1)
+    sys.exit(0)