|
@@ -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 = []
|
|
|
|