Commits

Lars Yencken committed 70cc146

Back off to GeoBytes page for external geocoding.

  • Participants
  • Parent commits 407a74c

Comments (0)

Files changed (4)

 
 On OS X 10.6 (Mountain Lion) or later, you can enable Core Location in System Preferences, in the "Security" or "Security & Privacy" section.
 
+Using on the command-line
+-------------------------
+
+Using Core Services alone, you can just run the ``doko`` command::
+
+  $ doko
+  35.674851 139.701419
+
+However, it relies on using wifi, and being enabled. If you won't have a wifi connection, you may see this::
+
+  $ doko
+  location could not be found -- is wifi enabled?
+
+In this case, you can back off to a much more approximate service based on your external IP with the ``--approx`` command::
+
+  $ doko --approx
+  35.674 139.701
+
+This may return the location for the center of the nearest city. To debug the location returned, the ``--show`` option will open a Google Maps browser window displaying the coordinates on a map.
+
 Using as a module
 -----------------
 
 ::
 
   > import doko
-  > doko.whereami()
+  > doko.location()
   Location(latitude=35.674851, longitude=139.701419)
+  > doko.geobytes_location()  # approximate method
+  Location(latitude=35.674, longitude=139.701)
 
 
-Using on the command-line
--------------------------
+Changelog
+---------
 
-::
+0.1.0
+~~~~~
 
-  $ doko
-  35.674851 139.701419
+- Fetch latitude and longitude using Core Location
+- Provide backup method via GeoBytes page

File doko/__init__.py

 import optparse
 import time
 from collections import namedtuple
+import webbrowser
 
 import CoreLocation
+import requests
+import BeautifulSoup
 
 Location = namedtuple('Location', 'latitude longitude')
 
-DEFAULT_TIMEOUT = 5
+DEFAULT_TIMEOUT = 3
 DEFAULT_RETRIES = 10
 
 
     pass
 
 
-def whereami(timeout=DEFAULT_TIMEOUT):
+def location(timeout=DEFAULT_TIMEOUT):
     """
     Fetch and return a Location from OS X Core Location, or throw
     a LocationServiceException trying.
     return Location(c.latitude, c.longitude)
 
 
+def geobytes_location():
+    external_ip = requests.get('http://jsonip.com/').json['ip']
+    resp = requests.post(
+            'http://www.geobytes.com/iplocator.htm?getlocation',
+            data={'ipaddress': external_ip},
+        )
+    try:
+        s = BeautifulSoup.BeautifulSoup(resp.content)
+        latitude = float(s.find('td',
+            text='Latitude').parent.findNext('input')['value'])
+        longitude = float(s.find('td',
+            text='Longitude').parent.findNext('input')['value'])
+    except Exception:
+        raise LocationServiceException('error parsing geobytes page')
+
+    return Location(latitude, longitude)
+
+
 def _create_option_parser():
     usage = \
 """%prog [options]
 
     parser = optparse.OptionParser(usage)
     parser.add_option('--timeout', action='store', dest='timeout',
-            type='float', default=10,
+            type='float', default=DEFAULT_TIMEOUT,
             help='Time to keep trying for if no location is found.')
     parser.add_option('--quiet', action='store_true', dest='quiet',
             help='Suppress any error messages.')
+    parser.add_option('--show', action='store_true',
+            help='Show result on Google Maps in a browser.')
+    parser.add_option('--approx', action='store_true',
+            help='Use a GeoIP service if Core Location fails.')
 
     return parser
 
         parser.print_help()
         sys.exit(1)
 
+    l = None
+    error = None
     try:
-        l = whereami(options.timeout)
-        print ' '.join(map(str, l))
+        l = location(options.timeout)
     except LocationServiceException, e:
+        error = e.message
+
+    if not l and options.approx:
+        try:
+            l = geobytes_location()
+        except LocationServiceException, e:
+            error = e.message
+
+    if not l:
         if not options.quiet:
-            print >> sys.stderr, e.message
+            print >> sys.stderr, error
         sys.exit(1)
+
+    print ' '.join(map(str, l))
+
+    if options.show:
+        webbrowser.open(
+                'https://maps.google.com/?q=%s+%s' % l
+            )

File requirements.txt

 pyobjc-framework-SyncServices==2.4
 pyobjc-framework-SystemConfiguration==2.4
 pyobjc-framework-WebKit==2.4
+BeautifulSoup==3.2.1
+requests==0.14.0
             'pyobjc==2.4',
             'pyobjc-core==2.4',
             'pyobjc-framework-CoreLocation==2.4',
+            'BeautifulSoup==3.2.1',
+            'requests==0.14.0',
         ],
     )