Browse Source

Report all of the extra info Latitude might give us.

Douglas William Thrift 14 years ago
parent
commit
57fa766e70
2 changed files with 55 additions and 14 deletions
  1. 50 14
      locationbot.py
  2. 5 0
      locationbot.sql

+ 50 - 14
locationbot.py

@@ -116,6 +116,10 @@ class LocationBot(ircbot.SingleServerIRCBot):
 
 		return _or(lambda channel: channel.has_user(nick), channels)
 
+	def __distance(self, distance):
+		if distance is not None:
+			return '%.1f m (%.1f ft)' % (distance, _meters_to_feet(distance))
+
 	def __db(self):
 		db = psycopg2.connect(self.__dsn)
 
@@ -205,6 +209,10 @@ class LocationBot(ircbot.SingleServerIRCBot):
 
 			self.__geocode_cache_clean_timer.start()
 
+	def __heading(self, heading):
+		if heading is not None:
+			return (u'%.1f\xb0 (%s)' % (heading, _heading_to_direction(heading))).encode('latin1')
+
 	def __help(self, connection, nick, admin, login, arguments):
 		command = irclib.irc_lower(arguments.split(None, 1)[0].lstrip('!')) if arguments else None
 		commands = {
@@ -294,9 +302,9 @@ class LocationBot(ircbot.SingleServerIRCBot):
 					print error
 					continue
 
-				cursor.execute('update locationbot.nick set granularity = %s, location = %s, coordinates = point %s, updated = %s where nick = %s', (granularity, new_location, coordinates, updated, nick))
+				cursor.execute('update locationbot.nick set granularity = %s, location = %s, coordinates = point %s, accuracy = %s, speed = %s, heading = %s, altitude = %s, altitude_accuracy = %s, updated = %s where nick = %s', (granularity, new_location, coordinates, accuracy, speed, heading, altitude, altitude_accuracy, updated, nick))
 				db.commit()
-				self.__location(nick, channels, granularity, old_location, new_location, coordinates)
+				self.__location(nick, channels, granularity, old_location, new_location, coordinates, accuracy, speed, heading, altitude, altitude_accuracy)
 		except psycopg2.Error, error:
 			print error
 
@@ -305,11 +313,11 @@ class LocationBot(ircbot.SingleServerIRCBot):
 
 			self.__latitude_timer.start()
 
-	def __location(self, nick, channels, granularity, old_location, new_location, coordinates):
+	def __location(self, nick, channels, granularity, old_location, new_location, coordinates, accuracy, speed, heading, altitude, altitude_accuracy):
 		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, granularity, new_location, coordinates))
+					self.__locations.append((nick, channel, granularity, new_location, coordinates, accuracy, speed, heading, altitude, altitude_accuracy))
 
 	def __login(self, connection, nickmask, nick, arguments = ''):
 		login = nick
@@ -574,6 +582,8 @@ class LocationBot(ircbot.SingleServerIRCBot):
 
 					if int(response['status']) != 200:
 						raise Exception(content.strip())
+
+				accuracy = speed = heading = altitude = altitude_accuracy = None
 			elif variable == 'nick':
 				_nick = value.split(None, 1)
 
@@ -585,7 +595,7 @@ class LocationBot(ircbot.SingleServerIRCBot):
 
 			try:
 				if variable in self.__geocode_variables:
-					cursor.execute('update locationbot.nick set granularity = %s, location = %s, coordinates = point %s, updated = now() where nick = %s', (granularity, new_location, coordinates, login))
+					cursor.execute('update locationbot.nick set granularity = %s, location = %s, coordinates = point %s, accuracy = %s, speed = %s, heading = %s, altitude = %s, altitude_accuracy = %s, updated = now() where nick = %s', (granularity, new_location, coordinates, accuracy, speed, heading, altitude, altitude_accuracy, login))
 				elif variable == 'latitude':
 					if authorized:
 						cursor.execute('update locationbot.latitude set token = %s, secret = %s, authorized = %s from locationbot.nick where latitude.id = nick.id and nick = %s', (token, secret, authorized, login))
@@ -610,15 +620,19 @@ class LocationBot(ircbot.SingleServerIRCBot):
 				if variable == 'latitude':
 					updated, coordinates, accuracy, speed, heading, altitude, altitude_accuracy, new_location = self.__latitude(granularity, token, secret)
 
-					cursor.execute('update locationbot.nick set granularity = %s, location = %s, coordinates = point %s, updated = %s where nick = %s', (granularity, new_location, coordinates, updated, login))
+					cursor.execute('update locationbot.nick set granularity = %s, location = %s, coordinates = point %s, accuracy = %s, speed = %s, heading = %s, altitude = %s, altitude_accuracy = %s, updated = %s where nick = %s', (granularity, new_location, coordinates, accuracy, speed, heading, altitude, altitude_accuracy, updated, login))
 
-				self.__location(login, channels, granularity, old_location, new_location, coordinates)
+				self.__location(login, channels, granularity, old_location, new_location, coordinates, accuracy, speed, heading, altitude, altitude_accuracy)
+
+	def __speed(self, speed):
+		if speed is not None:
+			return '%.1f m/s (%.1f mph)' % (speed, _meters_per_second_to_miles_per_hour(speed))
 
 	def __status(self, connection, nick, login, arguments):
 		_nick = arguments.split(None, 1)[0] if arguments else None
 		db, cursor = self.__db()
 
-		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,))
+		cursor.execute('select nick, granularity, location, coordinates, accuracy, speed, heading, altitude, altitude_accuracy, 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'))
@@ -632,10 +646,10 @@ class LocationBot(ircbot.SingleServerIRCBot):
 		else:
 			timezone = pytz.utc
 
-		connection.privmsg(nick, '\x02nick                    location                            when                    map\x0f')
+		connection.privmsg(nick, '\x02%-24s%-36s%-24s%-24s%-16s%-24s%-24s%-24s%s\x0f' % ('nick', 'location', 'accuracy', 'speed', 'heading', 'altitude', 'altitude accuracy', 'when', 'map'))
 
-		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.__url(_nick, 'best', location, coordinates)))
+		for _nick, granularity, location, coordinates, accuracy, speed, heading, altitude, altitude_accuracy, updated in locations:
+			connection.privmsg(nick, '%-23s %-35s %-23s %-23s %-15s %-23s %-23s %-23s %s' % (_nick, location, self.__distance(accuracy), self.__speed(speed), self.__heading(heading), self.__distance(altitude), self.__distance(altitude_accuracy), timezone.normalize(updated.astimezone(timezone)).strftime('%Y-%m-%d %H:%M %Z'), self.__url(_nick, granularity, location, coordinates)))
 
 	def __unknown(self, connection, nick, command):
 		connection.privmsg(nick, 'unknown command ("%s"); try "help"' % command)
@@ -665,7 +679,7 @@ class LocationBot(ircbot.SingleServerIRCBot):
 		if granularity == 'best':
 			location = '%f,%f' % coordinates
 
-		return 'http://maps.google.com/maps?' + urllib.urlencode({'q': '%s (%s)' % (location, nick)})
+		return 'http://maps.google.com/maps?' + re.sub('%(2[89cC])', lambda match: chr(int(match.group(1), 16)), urllib.urlencode({'q': '%s (%s)' % (location, nick)}))
 
 	def __who(self, connection, nick):
 		if self.__logins:
@@ -818,8 +832,30 @@ 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, granularity, location, coordinates in self.__locations:
-						self.connection.notice(channel, '%s is in %s %s' % (nick, location, self.__url(nick, granularity, location, coordinates)))
+					for nick, channel, granularity, location, coordinates, accuracy, speed, heading, altitude, altitude_accuracy in self.__locations:
+						aux = []
+
+						if accuracy is not None:
+							aux.append('accuracy: ' + self.__distance(accuracy))
+
+						if speed is not None:
+							aux.append('speed: ' + self.__speed(speed))
+
+						if heading is not None:
+							aux.append(u'heading: ' + self.__heading(heading))
+
+						if altitude is not None:
+							aux.append('altitude: ' + self.__distance(altitude))
+
+						if altitude_accuracy is not None:
+							aux.append('altitude accuracy: ' + self.__distance(altitude_accuracy))
+
+						if aux:
+							aux = ' [%s]' % ', '.join(aux)
+						else:
+							aux = ''
+
+						self.connection.notice(channel, '%s is in %s%s %s' % (nick, location, aux, self.__url(nick, granularity, location, coordinates)))
 
 					self.__locations = []
 

+ 5 - 0
locationbot.sql

@@ -18,6 +18,11 @@ create table locationbot.nick (
 	granularity locationbot.granularity,
 	location text,
 	coordinates point,
+	accuracy float,
+	speed float,
+	heading float,
+	altitude float,
+	altitude_accuracy float,
 	updated timestamp with time zone
 );