Browse Source

Coordinates!

Douglas William Thrift 14 years ago
parent
commit
da1e234683
2 changed files with 31 additions and 18 deletions
  1. 30 18
      locationbot.py
  2. 1 0
      locationbot.sql

+ 30 - 18
locationbot.py

@@ -12,6 +12,7 @@ import ircbot
 import irclib
 import os
 import psycopg2
+import psycopg2.extensions
 import pytz
 import re
 import sys
@@ -95,11 +96,6 @@ class LocationBot(ircbot.SingleServerIRCBot):
 	def __admin(self, nickmask):
 		return _or(lambda admin: irclib.mask_matches(nickmask, admin), self.__admins)
 
-	def __db(self):
-		db = psycopg2.connect(self.__dsn)
-
-		return db, db.cursor()
-
 	def __channel(self, nick, exclude = None):
 		if exclude is not None:
 			exclude = irclib.irc_lower(exclude)
@@ -109,6 +105,20 @@ class LocationBot(ircbot.SingleServerIRCBot):
 
 		return _or(lambda channel: channel.has_user(nick), channels)
 
+	def __coordinates(self, coordinates):
+		return ' http://maps.google.com/maps?q=%f,%f' % coordinates if coordinates else ''
+
+	def __db(self):
+		db = psycopg2.connect(self.__dsn)
+
+		def point(value, cursor):
+			if value is not None:
+				return tuple(map(lambda a: float(a), re.match(r'^\(([^)]+),([^)]+)\)$', value).groups()))
+
+		psycopg2.extensions.register_type(psycopg2.extensions.new_type((600,), 'point', point), db)
+
+		return db, db.cursor()
+
 	def __help(self, connection, nick, admin, login, arguments):
 		command = irclib.irc_lower(arguments.split(None, 1)[0].lstrip('!')) if arguments else None
 		commands = {
@@ -201,7 +211,9 @@ class LocationBot(ircbot.SingleServerIRCBot):
 						continue
 
 					try:
-						properties = geo['features'][0]['properties']
+						feature = geo['features'][0]
+						coordinates = tuple(reversed(feature['geometry']['coordinates']))
+						properties = feature['properties']
 						new_location = properties['reverseGeocode']
 						locations[latitude] = new_location
 						updated = datetime.fromtimestamp(properties['timeStamp'], pytz.utc)
@@ -209,10 +221,10 @@ class LocationBot(ircbot.SingleServerIRCBot):
 						print error
 						continue
 
-					cursor.execute('update locationbot.nick set location = %s, updated = %s where latitude = %s', (new_location, updated, latitude))
+					cursor.execute('update locationbot.nick set location = %s, coordinates = point %s, updated = %s where latitude = %s', (new_location, coordinates, updated, latitude))
 					db.commit()
 
-				self.__location(nick, channels, old_location, new_location)
+				self.__location(nick, channels, old_location, new_location, coordinates)
 		except psycopg2.Error, error:
 			print error
 
@@ -221,11 +233,11 @@ class LocationBot(ircbot.SingleServerIRCBot):
 
 			self.__latitude_timer.start()
 
-	def __location(self, nick, channels, old_location, new_location):
+	def __location(self, nick, channels, old_location, new_location, coordinates = None):
 		if channels and new_location and new_location != old_location:
 			with self.__locations_lock:
 				for channel in self.__channels.intersection(channels):
-					self.__locations.append((nick, channel, new_location))
+					self.__locations.append((nick, channel, new_location, coordinates))
 
 	def __login(self, connection, nickmask, nick, arguments = ''):
 		login = nick
@@ -414,7 +426,7 @@ class LocationBot(ircbot.SingleServerIRCBot):
 					return invalid(value)
 
 			try:
-				cursor.execute('update locationbot.nick set ' + variable + ' = ' + ('md5(%s)' if variable == 'secret' else '%s') + (', updated = now()' if variable == 'location' else '') + ' where nick = %s', (value, login))
+				cursor.execute('update locationbot.nick set ' + variable + ' = ' + ('md5(%s)' if variable == 'secret' else '%s') + (', coordinates = null, updated = now()' if variable == 'location' else '') + ' where nick = %s', (value, login))
 				db.commit()
 			except psycopg2.IntegrityError:
 				if variable == 'nick':
@@ -433,7 +445,7 @@ class LocationBot(ircbot.SingleServerIRCBot):
 		_nick = arguments.split(None, 1)[0] if arguments else None
 		db, cursor = self.__db()
 
-		cursor.execute('select nick, location, updated from locationbot.nick where ' + ('nick = %s and ' if _nick is not None else '') + 'location is not null order by updated desc', (_nick,))
+		cursor.execute('select nick, location, coordinates, updated from locationbot.nick where ' + ('nick = %s and ' if _nick is not None else '') + 'location is not null order by updated desc', (_nick,))
 
 		if cursor.rowcount == 0:
 			return connection.privmsg(nick, 'no location information for ' + ('"%s"' % _nick if _nick is not None else 'anybody'))
@@ -447,10 +459,10 @@ class LocationBot(ircbot.SingleServerIRCBot):
 		else:
 			timezone = pytz.utc
 
-		connection.privmsg(nick, '\x02nick                    location                             when\x0f')
+		connection.privmsg(nick, '\x02nick                    location                            when                     map\x0f')
 
-		for _nick, location, updated in locations:
-			connection.privmsg(nick, '%-23s %-36s %s' % (_nick, location, timezone.normalize(updated.astimezone(timezone)).strftime('%Y-%m-%d %H:%M %Z')))
+		for _nick, location, coordinates, updated in locations:
+			connection.privmsg(nick, '%-23s %-35s %-23s %s' % (_nick, location, timezone.normalize(updated.astimezone(timezone)).strftime('%Y-%m-%d %H:%M %Z'), self.__coordinates(coordinates)))
 
 	def __unknown(self, connection, nick, command):
 		connection.privmsg(nick, 'unknown command ("%s"); try "help"' % command)
@@ -472,7 +484,7 @@ class LocationBot(ircbot.SingleServerIRCBot):
 
 		db, cursor = self.__db()
 
-		cursor.execute('update locationbot.nick set ' + variable + ' = null' + (', updated = null' if variable == 'location' else '') + ' where nick = %s and ' + variable + ' is not null', (login,))
+		cursor.execute('update locationbot.nick set ' + variable + ' = null' + (', coordinates = null, updated = null' if variable == 'location' else '') + ' where nick = %s and ' + variable + ' is not null', (login,))
 		db.commit()
 		connection.privmsg(nick, 'variable ("%s") %s unset' % (variable, 'successfuly' if cursor.rowcount == 1 else 'already'))
 
@@ -622,8 +634,8 @@ class LocationBot(ircbot.SingleServerIRCBot):
 		while not self.__reloading:
 			if self.__locations_lock.acquire(False):
 				if self.__locations and self.__channels.issubset(self.channels.keys()):
-					for nick, channel, location in self.__locations:
-						self.connection.notice(channel, '%s is in %s' % (nick, location))
+					for nick, channel, location, coordinates in self.__locations:
+						self.connection.notice(channel, '%s is in %s' % (nick, location + self.__coordinates(coordinates)))
 
 					self.__locations = []
 

+ 1 - 0
locationbot.sql

@@ -14,6 +14,7 @@ create table locationbot.nick (
 	channels text[],
 	timezone text,
 	location text,
+	coordinates point,
 	updated timestamp with time zone,
 	latitude bigint
 );