|
@@ -8,6 +8,7 @@
|
|
import apiclient.discovery
|
|
import apiclient.discovery
|
|
from ConfigParser import NoOptionError, SafeConfigParser
|
|
from ConfigParser import NoOptionError, SafeConfigParser
|
|
from datetime import datetime, timedelta
|
|
from datetime import datetime, timedelta
|
|
|
|
+import functools
|
|
import getpass
|
|
import getpass
|
|
import ircbot
|
|
import ircbot
|
|
import irclib
|
|
import irclib
|
|
@@ -33,6 +34,46 @@ try:
|
|
except ImportError:
|
|
except ImportError:
|
|
import json
|
|
import json
|
|
|
|
|
|
|
|
+def shortcutting_or(function, values):
|
|
|
|
+ if values:
|
|
|
|
+ for value in values:
|
|
|
|
+ if function(value):
|
|
|
|
+ return True
|
|
|
|
+
|
|
|
|
+ return False
|
|
|
|
+
|
|
|
|
+def address_mask(function):
|
|
|
|
+ @functools.wraps(function)
|
|
|
|
+ def address_mask(nick, mask):
|
|
|
|
+ if not function(nick, mask):
|
|
|
|
+ nick, address = nick.split('@', 1)
|
|
|
|
+
|
|
|
|
+ try:
|
|
|
|
+ host = socket.gethostbyaddr(address)[0]
|
|
|
|
+ except socket.herror:
|
|
|
|
+ traceback.print_exc()
|
|
|
|
+ else:
|
|
|
|
+ if host != address:
|
|
|
|
+ return function(nick + '@' + host, mask)
|
|
|
|
+
|
|
|
|
+ return False
|
|
|
|
+
|
|
|
|
+ return True
|
|
|
|
+
|
|
|
|
+ return address_mask
|
|
|
|
+
|
|
|
|
+def encode(function):
|
|
|
|
+ @functools.wraps(function)
|
|
|
|
+ def encode(self, target, text):
|
|
|
|
+ return function(self, target, text.encode('utf8'))
|
|
|
|
+
|
|
|
|
+ return encode
|
|
|
|
+
|
|
|
|
+irclib.mask_matches = address_mask(reload(irclib).mask_matches)
|
|
|
|
+irclib.ServerConnection.notice = encode(irclib.ServerConnection.notice)
|
|
|
|
+irclib.ServerConnection.privmsg = encode(irclib.ServerConnection.privmsg)
|
|
|
|
+irclib.ServerConnection.privmsg_many = encode(irclib.ServerConnection.privmsg_many)
|
|
|
|
+
|
|
class ThreadTimerServiceMixin(object):
|
|
class ThreadTimerServiceMixin(object):
|
|
def start(self):
|
|
def start(self):
|
|
self.thread.daemon = True
|
|
self.thread.daemon = True
|
|
@@ -326,7 +367,7 @@ class LocationBot(ircbot.SingleServerIRCBot):
|
|
self.__unsetable = self.__variables.difference(['nick', 'secret'])
|
|
self.__unsetable = self.__variables.difference(['nick', 'secret'])
|
|
|
|
|
|
def __admin(self, nickmask):
|
|
def __admin(self, nickmask):
|
|
- return _or(lambda admin: irclib.mask_matches(nickmask, admin), self.__admins)
|
|
|
|
|
|
+ return shortcutting_or(lambda admin: irclib.mask_matches(nickmask, admin), self.__admins)
|
|
|
|
|
|
def __channel(self, nick, exclude = None):
|
|
def __channel(self, nick, exclude = None):
|
|
if exclude is not None:
|
|
if exclude is not None:
|
|
@@ -335,11 +376,7 @@ class LocationBot(ircbot.SingleServerIRCBot):
|
|
else:
|
|
else:
|
|
channels = self.channels.values()
|
|
channels = self.channels.values()
|
|
|
|
|
|
- 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))
|
|
|
|
|
|
+ return shortcutting_or(lambda channel: channel.has_user(nick), channels)
|
|
|
|
|
|
def __db(self):
|
|
def __db(self):
|
|
db = psycopg2.connect(self.__dsn)
|
|
db = psycopg2.connect(self.__dsn)
|
|
@@ -352,10 +389,6 @@ class LocationBot(ircbot.SingleServerIRCBot):
|
|
|
|
|
|
return db, db.cursor()
|
|
return db, db.cursor()
|
|
|
|
|
|
- def __heading(self, heading):
|
|
|
|
- if heading is not None:
|
|
|
|
- return _encode(u'%.1f\xb0 (%s)' % (heading, _heading_to_direction(heading)))
|
|
|
|
-
|
|
|
|
def __help(self, connection, nick, admin, login, arguments):
|
|
def __help(self, connection, nick, admin, login, arguments):
|
|
command = irclib.irc_lower(arguments.split(None, 1)[0].lstrip('!')) if arguments else None
|
|
command = irclib.irc_lower(arguments.split(None, 1)[0].lstrip('!')) if arguments else None
|
|
commands = {
|
|
commands = {
|
|
@@ -539,7 +572,7 @@ class LocationBot(ircbot.SingleServerIRCBot):
|
|
cursor.execute('select nick, masks from locationbot.nick where nick in (%s, %s)', (login, secret if len(arguments) != 2 else None))
|
|
cursor.execute('select nick, masks from locationbot.nick where nick in (%s, %s)', (login, secret if len(arguments) != 2 else None))
|
|
|
|
|
|
for login, masks in cursor.fetchall():
|
|
for login, masks in cursor.fetchall():
|
|
- if _or(lambda mask: irclib.mask_matches(nickmask, mask), masks):
|
|
|
|
|
|
+ if shortcutting_or(lambda mask: irclib.mask_matches(nickmask, mask), masks):
|
|
self.__logins[nick] = (login, nickmask)
|
|
self.__logins[nick] = (login, nickmask)
|
|
|
|
|
|
return success() if connection else login
|
|
return success() if connection else login
|
|
@@ -805,10 +838,6 @@ class LocationBot(ircbot.SingleServerIRCBot):
|
|
|
|
|
|
self.__location(login, channels, granularity, old_location, new_location, None, coordinates, None, accuracy, None, speed, None, heading, None, altitude, None, altitude_accuracy, None, updated)
|
|
self.__location(login, channels, granularity, old_location, new_location, None, coordinates, None, accuracy, None, speed, None, heading, None, altitude, None, altitude_accuracy, None, updated)
|
|
|
|
|
|
- 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):
|
|
def __status(self, connection, nick, login, arguments):
|
|
_nick = arguments.split(None, 1)[0] if arguments else None
|
|
_nick = arguments.split(None, 1)[0] if arguments else None
|
|
db, cursor = self.__db()
|
|
db, cursor = self.__db()
|
|
@@ -1044,7 +1073,7 @@ class LocationBot(ircbot.SingleServerIRCBot):
|
|
else:
|
|
else:
|
|
aux = ''
|
|
aux = ''
|
|
|
|
|
|
- self.connection.notice(channel, '%s is in %s%s %s' % (nick, _encode(location), aux, self.__url(nick, granularity, location, coordinates)))
|
|
|
|
|
|
+ self.connection.notice(channel, '%s is in %s%s %s' % (nick, location, aux, self.__url(nick, granularity, location, coordinates)))
|
|
|
|
|
|
self.__locations = []
|
|
self.__locations = []
|
|
|
|
|
|
@@ -1069,86 +1098,6 @@ class LocationBot(ircbot.SingleServerIRCBot):
|
|
def success(self):
|
|
def success(self):
|
|
self.connection.privmsg(self.__nick, 'successfully reloaded')
|
|
self.connection.privmsg(self.__nick, 'successfully reloaded')
|
|
|
|
|
|
-class _AddressMask(object):
|
|
|
|
- def __init__(self, function):
|
|
|
|
- self.function = function
|
|
|
|
-
|
|
|
|
- def __call__(self, nick, mask):
|
|
|
|
- if not self.function(nick, mask):
|
|
|
|
- nick, address = nick.split('@', 1)
|
|
|
|
-
|
|
|
|
- try:
|
|
|
|
- host = socket.gethostbyaddr(address)[0]
|
|
|
|
- except socket.herror:
|
|
|
|
- pass
|
|
|
|
- else:
|
|
|
|
- if host != address:
|
|
|
|
- return self.function(nick + '@' + host, mask)
|
|
|
|
-
|
|
|
|
- return False
|
|
|
|
-
|
|
|
|
- return True
|
|
|
|
-
|
|
|
|
-irclib.mask_matches = _AddressMask(reload(irclib).mask_matches)
|
|
|
|
-
|
|
|
|
-def _encode(string):
|
|
|
|
- string = unicode(string)
|
|
|
|
-
|
|
|
|
- try:
|
|
|
|
- return string.encode('latin1')
|
|
|
|
- except UnicodeEncodeError:
|
|
|
|
- return string.encode('utf8')
|
|
|
|
-
|
|
|
|
-def _meters_per_second_to_miles_per_hour(meters_per_second):
|
|
|
|
- return meters_per_second * 2.23693629
|
|
|
|
-
|
|
|
|
-def _meters_to_feet(meters):
|
|
|
|
- return meters * 3.2808399
|
|
|
|
-
|
|
|
|
-def _heading_to_direction(heading):
|
|
|
|
- heading %= 360
|
|
|
|
-
|
|
|
|
- if 348.75 < heading or heading <= 11.25:
|
|
|
|
- return 'N'
|
|
|
|
- elif 11.25 < heading <= 33.75:
|
|
|
|
- return 'NNE'
|
|
|
|
- elif 33.75 < heading <= 56.25:
|
|
|
|
- return 'NE'
|
|
|
|
- elif 56.25 < heading <= 78.75:
|
|
|
|
- return 'ENE'
|
|
|
|
- elif 78.75 < heading <= 101.25:
|
|
|
|
- return 'E'
|
|
|
|
- elif 101.25 < heading <= 123.75:
|
|
|
|
- return 'ESE'
|
|
|
|
- elif 123.75 < heading <= 146.25:
|
|
|
|
- return 'SE'
|
|
|
|
- elif 146.25 < heading <= 168.75:
|
|
|
|
- return 'SSE'
|
|
|
|
- elif 168.75 < heading <= 191.25:
|
|
|
|
- return 'S'
|
|
|
|
- elif 191.25 < heading <= 213.75:
|
|
|
|
- return 'SSW'
|
|
|
|
- elif 213.75 < heading <= 236.25:
|
|
|
|
- return 'SW'
|
|
|
|
- elif 236.25 < heading <= 258.75:
|
|
|
|
- return 'WSW'
|
|
|
|
- elif 258.75 < heading <= 281.25:
|
|
|
|
- return 'W'
|
|
|
|
- elif 281.25 < heading <= 303.75:
|
|
|
|
- return 'WNW'
|
|
|
|
- elif 303.75 < heading <= 326.25:
|
|
|
|
- return 'NW'
|
|
|
|
- else:
|
|
|
|
- return 'NNW'
|
|
|
|
-
|
|
|
|
-def _or(function, values):
|
|
|
|
- if values:
|
|
|
|
- for value in values:
|
|
|
|
- if function(value):
|
|
|
|
- return True
|
|
|
|
-
|
|
|
|
- return False
|
|
|
|
-
|
|
|
|
if __name__ == '__main__':
|
|
if __name__ == '__main__':
|
|
os.chdir(os.path.abspath(os.path.dirname(__file__)))
|
|
os.chdir(os.path.abspath(os.path.dirname(__file__)))
|
|
|
|
|