Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Added the ability to register domains from CLI #6

Closed
wants to merge 8 commits into from

3 participants

Connor Montgomery Tal Safran Eric Case
Connor Montgomery

I love the domai.nr CLI, but sometimes I wish I could register them from it, too.

So, I made this so you can (kind of). I'm utilizing the webbrowser module, and just seeing if the user's first parameter is register. If It is, then I open up a new tab with the URL set as the registration URL for that domain.

Not the best code quality, but gets the job done ;)

Connor Montg... added some commits April 15, 2012
Tal Safran
Owner

Awesome dude, thanks! I have a suggestion for a nicer interface.

WIth the original CLI, I like not having to pass in an actual address but a phrase. That's the fun part about domainr. I wonder if we can change the results of the domainr command to have numbered results for available domains.

  $ domainr talsafran
    Looking up domains for talsafran...
        talsafran.com - taken
        talsafran.net - available [1]
        talsafran.org - available [2]
        talsafr.an - available     [3]
        talsa.fr - available         [4]
        tals.af - available          [etc I am lazy :)]
        tal.sa - available
        ta.ls - unavailable
        tls.fr - taken
        t.al - unavailable
        t.ls - unavailable
        tl - tld

After each run, write those results to a file.

Then do something like domainr register 3 and it'll try to register talsafr.an. What do you think?

I can hack on it this weekend but you're more than welcome to give it a crack first! :)

Connor Montgomery

I'm totally down for this. Busy until tomorrow night, but should have some time :D

Tal Safran
Owner

No presh, whenever you feel like it

Eric Case
case commented April 20, 2012

Thanks for working on this, gents — lemme know when it's committed and we'll mention on @domainr.

Cheers!
-Eric

Connor Montgomery

Yep - not a problem fellas! Got it about 95% there - just need to log multiple arguments, ex:

$ domainr connormontgomery talsafran case

Working great for single domains passed in, though.

Connor Montg... added some commits April 20, 2012
better register workflow c5791a9
added example to readme 9650e04
Connor Montgomery

Alright - there we go fellas. Should be pretty solid. I have tested it with several domains, and it's working great. Code quality isn't the best - I tried using descriptive variable names. Take a look and if it doesn't make sense to you, let me know!

Tal Safran
Owner

Couldn't get this to work. :(

tal:~/Projects/connor/domainr $ ./domainr talsafran
Looking up domains for talsafran...
    talsafran.com - taken
    talsafran.net - available [1]
    talsafran.org - available [2]
    talsafr.an - unavailable
    talsa.fr/an - available [3]
    tals.af/ran - available [4]
    tal.sa/fran - available [5]
    tls.fr/n - taken
    ta.ls/afran - unavailable
    t.al/safran - unavailable
    t.ls/frn - unavailable
    tl/sfrn - tld
tal:~/Projects/connor/domainr $ ./domainr register 1
Traceback (most recent call last):
  File "./domainr", line 169, in <module>
    main(argv[1:])
  File "./domainr", line 84, in main
    available_domain_data = ast.literal_eval("%s" % external_available_domains )
  File "/usr/local/Cellar/python/2.7.2/lib/python2.7/ast.py", line 49, in literal_eval
    node_or_string = parse(node_or_string, mode='eval')
  File "/usr/local/Cellar/python/2.7.2/lib/python2.7/ast.py", line 37, in parse
    return compile(source, filename, mode, PyCF_ONLY_AST)
  File "<unknown>", line 1
    {1: u'talsafran.net', 2: u'talsafran.org', 3: u'talsa.fr', 4: u'tals.af', 5: u'tal.sa'
                                                                                         ^
SyntaxError: unexpected EOF while parsing

Also... spacing should be more consistent... need to appease the Python gods..

Connor Montgomery

hmm interesting. was working fine for me, but I'll dig into it.

re: spacing - super apologies dude. will fix that up.

Connor Montgomery

@talsafran fixed it up - I accidentally removed a line that added the closing } to the JSON that is stored. That's fixed, now just gotta get the white space all cleaned up.

now it's working. other notes:
-  made it 4 spaces per tab instead of 2.
- if second argument is 'register', and there is no number to register, it'll search for domains using 'register', like it should.
76684e9
Connor Montgomery

Don't pull this in yet. I was testing it and just found out it works only with 1 domain searches. Really sorry for this messy PR - i may just open up a clean new one when it's 100% done.

my bad dude.

Connor Montg... added some commits April 23, 2012
Connor Montgomery connor closed this April 23, 2012
Connor Montgomery

Closing to make it an easy PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Showing 8 unique commits by 1 author.

Apr 15, 2012
added ability to register domains from CLI 134df57
updated README 5ab85e7
Apr 20, 2012
better register workflow c5791a9
added example to readme 9650e04
don't need to require tempfile c51f267
Apr 23, 2012
now it's working. other notes:
-  made it 4 spaces per tab instead of 2.
- if second argument is 'register', and there is no number to register, it'll search for domains using 'register', like it should.
76684e9
working for all cases f73eab0
check multiple domains even if first arg is register 4851782
This page is out of date. Refresh to see the latest.

Showing 2 changed files with 196 additions and 56 deletions. Show diff stats Hide diff stats

  1. 70  README.md
  2. 182  domainr
70  README.md
Source Rendered
@@ -4,12 +4,12 @@ Disclaimer: This is one of the first things I've written in Python. So be gentle
4 4
     $ domainr talsafran
5 5
     Looking up domains for talsafran...
6 6
         talsafran.com - taken
7  
-        talsafran.net - available
8  
-        talsafran.org - available
9  
-        talsafr.an - available
10  
-        talsa.fr - available
11  
-        tals.af - available
12  
-        tal.sa - available
  7
+        talsafran.net - available [1]
  8
+        talsafran.org - available [2]
  9
+        talsafr.an - available [3]
  10
+        talsa.fr - available [4]
  11
+        tals.af - available [5]
  12
+        tal.sa - available [6]
13 13
         ta.ls - unavailable
14 14
         tls.fr - taken
15 15
         t.al - unavailable
@@ -44,12 +44,12 @@ Very simple. Just type in ``domainr`` and the name of the site you're looking fo
44 44
     $ domainr talsafran
45 45
     Looking up domains for talsafran...
46 46
         talsafran.com - taken
47  
-        talsafran.net - available
48  
-        talsafran.org - available
49  
-        talsafr.an - available
50  
-        talsa.fr - available
51  
-        tals.af - available
52  
-        tal.sa - available
  47
+        talsafran.net - available [1]
  48
+        talsafran.org - available [2]
  49
+        talsafr.an - available [3]
  50
+        talsa.fr - available [4]
  51
+        tals.af - available [5]
  52
+        tal.sa - available [6]
53 53
         ta.ls - unavailable
54 54
         tls.fr - taken
55 55
         t.al - unavailable
@@ -63,34 +63,44 @@ It even works with multiple domains.
63 63
     $ domainr talsafran sharonsafran
64 64
     Looking up domains for talsafran...
65 65
         talsafran.com - taken
66  
-        talsafran.net - available
67  
-        talsafran.org - available
68  
-        talsafr.an - available
69  
-        talsa.fr - available
70  
-        tals.af - available
71  
-        tal.sa - available
  66
+        talsafran.net - available [1]
  67
+        talsafran.org - available [2]
  68
+        talsafr.an - available [3]
  69
+        talsa.fr - available [4]
  70
+        tals.af - available [5]
  71
+        tal.sa - available [6]
72 72
         ta.ls - unavailable
73 73
         tls.fr - taken
74 74
         t.al - unavailable
75 75
         t.ls - unavailable
76 76
         tl - tld
77 77
     Looking up domains for sharonsafran...
78  
-        sharonsafran.com - available
79  
-        sharonsafran.net - available
80  
-        sharonsafran.org - available
81  
-        sharonsafr.an - available
82  
-        sharonsa.fr - available
83  
-        sharons.af - available
84  
-        sharon.sa - available
85  
-        sha.ro - available
86  
-        shrns.fr - available
87  
-        shar.nsafr.an - available
  78
+        sharonsafran.com - available [7]
  79
+        sharonsafran.net - available [8]
  80
+        sharonsafran.org - available [9]
  81
+        sharonsafr.an - available [10]
  82
+        sharonsa.fr - available [11]
  83
+        sharons.af - available [12]
  84
+        sharon.sa - available [13]
  85
+        sha.ro - available [14]
  86
+        shrns.fr - available [15]
  87
+        shar.nsafr.an - available [16]
88 88
         shar.nsa.fr - taken
89 89
         shar.ns.af - taken
90  
-        shar.n.sa - available
  90
+        shar.n.sa - available [17]
91 91
         sh.ar - unavailable
92  
-        s.hr - available
  92
+        s.hr - available [18]
93 93
         sh - tld
94 94
 ```
95 95
 
  96
+And, you can even register a domain from the CLI. All you have to do is pass in the number associated with the **available** domain. So, you'd be running something like:
  97
+
  98
+```bash
  99
+
  100
+    $ domainr register 3
  101
+
  102
+```
  103
+
  104
+Will bring up a new tab in your default browser (if the domain is available), to register the domain!
  105
+
96 106
 -- [@talsafran](http://twitter.com/talsafran)
182  domainr
@@ -3,40 +3,170 @@
3 3
 from sys import argv
4 4
 from httplib import HTTPConnection
5 5
 
6  
-import json
  6
+import json, webbrowser, os, commands, pprint, ast
7 7
 
8 8
 colors = {
9  
-  'green':  '\033[92m',
10  
-  'yellow': '\033[93m',
11  
-  'red':    '\033[91m',
12  
-  'endc':   '\033[0m'
  9
+    'green':  '\033[92m',
  10
+    'yellow': '\033[93m',
  11
+    'red':    '\033[91m',
  12
+    'endc':   '\033[0m'
13 13
 }
14 14
 
15 15
 status_color = {
16  
-  'available':    colors['green'],
17  
-  'maybe':        colors['yellow'],
18  
-  'taken':        colors['red'],
19  
-  'unavailable':  colors['red']
  16
+    'available':    colors['green'],
  17
+    'maybe':        colors['yellow'],
  18
+    'taken':        colors['red'],
  19
+    'unavailable':  colors['red']
20 20
 }
21 21
 
  22
+def checkAvailability(domain):
  23
+
  24
+    con = HTTPConnection('domai.nr')
  25
+    req = con.request('GET', '/api/json/info?q=%s' % domain)
  26
+    res = con.getresponse()
  27
+
  28
+    if res.status == 200:
  29
+        data = json.loads( res.read() )
  30
+        availability = data['availability']
  31
+        return availability
  32
+
  33
+    else:
  34
+        print "Uh oh, you got a %s %s. What the dilly?" % (res.status, res.reason)
  35
+
  36
+def registerDomain(domain):
  37
+    webbrowser.open_new_tab("http://domai.nr/" + domain + "/register")
  38
+
  39
+def convert_keys_to_string(dictionary):
  40
+    """Recursively converts dictionary keys to strings."""
  41
+    if not isinstance(dictionary, dict):
  42
+        return dictionary
  43
+    return dict((str(k), convert_keys_to_string(v))
  44
+        for k, v in dictionary.items())
  45
+
22 46
 def main(args):
23  
-    for arg in args:
24  
-        print "Looking up domains for %s..." % arg
25  
-        
26  
-        con = HTTPConnection('domai.nr')
27  
-        req = con.request('GET', '/api/json/search?q=%s' % arg)
28  
-        res = con.getresponse()
29  
-        
30  
-        if res.status == 200:
31  
-            data = res.read()
32  
-            sites = json.loads(data)
33  
-            
34  
-            for s in sites['results']:
35  
-                status = "%s%s - %s" % (s['domain'], s['path'], s['availability'])
36  
-                print "\t" + status_color.get(s['availability'], '') + status + colors['endc']
  47
+
  48
+    # see where the domainr executable is (the path)
  49
+    status, domainr_path = commands.getstatusoutput("which domainr")  # ex: "/usr/local/bin/domainr"
  50
+
  51
+    # split that, so we get the parent of it
  52
+    path_to_bin = domainr_path.rsplit('/', 1)  # ex: ["/usr/local/bin", "domainr"]
  53
+
  54
+    # what our folder & file will be named
  55
+    log_file_dir_name = "_domainr"
  56
+    log_file_name = "logs.txt"
  57
+
  58
+    # the path we need to check for
  59
+    path_to_check_for = path_to_bin[0] + "/" + log_file_dir_name
  60
+
  61
+
  62
+    # see if the user doesn't already has `_domainr` in their $path_to_bin
  63
+    if not os.path.exists( path_to_check_for ):
  64
+        os.makedirs( path_to_check_for ) # make the $path_to_bin/_domainr/ directory
  65
+
  66
+  # if the first argument is 'register'
  67
+    if args[0] == "register" and len(args) == 2 and args[1].isdigit():
  68
+
  69
+
  70
+
  71
+        # make sure this is an int - otherwise, dictionary won't be happy
  72
+        index_to_register = int(args[1])
  73
+
  74
+        # grab the file contents
  75
+        external_available_domains = open( path_to_check_for + "/" + log_file_name ).read()
  76
+
  77
+        # convert the string to a dict
  78
+        available_domain_data = ast.literal_eval("%s" % external_available_domains )
  79
+
  80
+        # the dict should be in string format, not unicode
  81
+        new_dict = convert_keys_to_string(available_domain_data)
  82
+
  83
+        if index_to_register <= len(new_dict):
  84
+            registerDomain(available_domain_data[index_to_register])
  85
+
37 86
         else:
38  
-            print "Uh oh, you got a %s %s. What the dilly?" % (res.status, res.reason)
  87
+            print "Whoah, something went wrong there. Please try again, using the digit that corresponds with the domain you want. Here are your options:"
  88
+            pprint.pprint(available_domain_data)
39 89
 
40  
-if __name__ == "__main__":
41  
-    main(argv[1:])
  90
+    else:
  91
+
  92
+        # erase the old file here, and immediately close it so it's fresh for appending the domains to
  93
+        log = open(path_to_check_for + "/" + log_file_name, 'w')
  94
+        log.write('')
  95
+        log.close()
  96
+
  97
+        for index, arg in enumerate(args):
  98
+
  99
+            available_domains = {}
42 100
 
  101
+            print "Looking up domains for %s..." % arg
  102
+
  103
+            con = HTTPConnection('domai.nr')
  104
+            req = con.request('GET', '/api/json/search?q=%s' % arg)
  105
+            res = con.getresponse()
  106
+
  107
+            if res.status == 200:
  108
+                data = res.read()
  109
+                sites = json.loads(data)
  110
+
  111
+                if index == 0:
  112
+                    availability_count = 1
  113
+
  114
+                for s in sites['results']:
  115
+                    status = "%s%s - %s" % (s['domain'], s['path'], s['availability'])
  116
+
  117
+                    # if the domain is available
  118
+                    if s['availability'] == "available":
  119
+
  120
+                        # output the index of availability
  121
+                        status += " [" + str(availability_count) + "]"
  122
+
  123
+                        # tack it on to the available_domains dict
  124
+                        available_domains[availability_count] = s['domain']
  125
+
  126
+                        availability_count += 1
  127
+
  128
+                    print "\t" + status_color.get(s['availability'], '') + status + colors['endc']
  129
+
  130
+                # if there are actually any domains available...
  131
+                if availability_count > 1:
  132
+
  133
+                    # convert the dict to a string
  134
+                    json_available_domains = str(available_domains)
  135
+
  136
+                    # hooray! we get to keep a log of the previous-searched domains & their availability!
  137
+                    log = open(path_to_check_for + "/" + log_file_name, 'a')
  138
+
  139
+
  140
+
  141
+                    # if it's the first site they passed in
  142
+                    if index == 0 and len(args) == 1:
  143
+                        log.write(json_available_domains)
  144
+
  145
+                    elif index == 0:
  146
+                        available_domains_missing_right_bracket = json_available_domains.rsplit("}", 1)
  147
+                        log.write( available_domains_missing_right_bracket[0] ) # remove the final } so we can append other k/v pairs to it
  148
+
  149
+                    elif index + 1 < len(args):
  150
+                        log.write(", ") # separate these objects by a comma
  151
+
  152
+                        # remove both brackets
  153
+                        available_domains_missing_left_bracket = json_available_domains.split("{", 1)
  154
+                        available_domains_no_brackets = available_domains_missing_left_bracket[1].rsplit("}", 1)
  155
+                        log.write( available_domains_no_brackets[0] )
  156
+                    else:
  157
+                        log.write(", ") # separate these objects by a comma
  158
+
  159
+                        # remove both brackets
  160
+                        available_domains_missing_left_bracket = json_available_domains.split("{", 1)
  161
+                        available_domains_no_brackets = available_domains_missing_left_bracket[1].rsplit("}", 1)
  162
+                        log.write( available_domains_no_brackets[0] )
  163
+
  164
+                        log.write("}")
  165
+                    log.close()
  166
+
  167
+
  168
+            else:
  169
+                print "Uh oh, you got a %s %s. What the dilly?" % (res.status, res.reason)
  170
+
  171
+if __name__ == "__main__":
  172
+    main(argv[1:])
Commit_comment_tip

Tip: You can add notes to lines in a file. Hover to the left of a line to make a note

Something went wrong with that request. Please try again.