Browse Source

Refactor functors and functions and move to top.

Douglas William Thrift 11 years ago
parent
commit
acddfb40af
1 changed files with 45 additions and 96 deletions
  1. 45 96
      locationbot.py

+ 45 - 96
locationbot.py

@@ -8,6 +8,7 @@
 import apiclient.discovery
 from ConfigParser import NoOptionError, SafeConfigParser
 from datetime import datetime, timedelta
+import functools
 import getpass
 import ircbot
 import irclib
@@ -33,6 +34,46 @@ try:
 except ImportError:
 	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):
 	def start(self):
 		self.thread.daemon = True
@@ -326,7 +367,7 @@ class LocationBot(ircbot.SingleServerIRCBot):
 		self.__unsetable = self.__variables.difference(['nick', 'secret'])
 
 	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):
 		if exclude is not None:
@@ -335,11 +376,7 @@ class LocationBot(ircbot.SingleServerIRCBot):
 		else:
 			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):
 		db = psycopg2.connect(self.__dsn)
@@ -352,10 +389,6 @@ class LocationBot(ircbot.SingleServerIRCBot):
 
 		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):
 		command = irclib.irc_lower(arguments.split(None, 1)[0].lstrip('!')) if arguments else None
 		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))
 
 		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)
 
 				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)
 
-	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()
@@ -1044,7 +1073,7 @@ class LocationBot(ircbot.SingleServerIRCBot):
 							else:
 								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 = []
 
@@ -1069,86 +1098,6 @@ class LocationBot(ircbot.SingleServerIRCBot):
 	def success(self):
 		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__':
 	os.chdir(os.path.abspath(os.path.dirname(__file__)))