123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206 |
- #!/usr/bin/env python
- # Location Bot
- #
- # Douglas Thrift
- #
- # $Id$
- from ConfigParser import NoOptionError, SafeConfigParser
- import geojson
- import getpass
- import ircbot
- import irclib
- import os
- import sys
- import threading
- import urllib, urllib2
- import warnings
- class LocationBot(ircbot.SingleServerIRCBot):
- def __init__(self):
- config = SafeConfigParser({'hostname': ''})
- config.read('locationbot.ini')
- try:
- nick = config.sections()[0]
- except IndexError:
- sys.exit('No nick configured')
- servers = []
- try:
- for server in config.get(nick, 'servers').split():
- server = server.split(':', 2)
- if len(server) == 1:
- servers.append((server[0], 6667))
- else:
- host = server[0]
- port = int(server[1])
- ssl = server[1].startswith('+')
- if len(server) == 3:
- servers.append((host, port, ssl, server[2]))
- else:
- servers.append((host, port, ssl))
- self.__admins = config.get(nick, 'admins').split()
- self.__channels = config.get(nick, 'channels').split()
- self.__hostname = config.get(nick, 'hostname')
- except NoOptionError, error:
- sys.exit(error)
- self.__locations_lock = threading.Lock()
- self.__locations = []
- ircbot.SingleServerIRCBot.__init__(self, servers, nick, 'Location Bot')
- def __admin(self, nick):
- if isinstance(nick, irclib.Event):
- nick = nick.source()
- for admin in self.__admins:
- if irclib.mask_matches(nick, admin):
- return True
- return False
- def __do_latitude(self):
- #with self.__locations_lock:
- # self.__locations.append(('douglaswth', 'Isla Vista, CA, USA'))
- #try:
- # url = 'http://www.google.com/latitude/apps/badge/api?' + urllib.urlencode({'user': 0, 'type': 'json'})
- # response = urllib2.urlopen(url)
- # geo = geojson.load(response, object_hook = geojson.GeoJSON.to_instance)
- # print geo.features[0].properties['reverseGeocode']
- #except urllib2.URLError, error:
- # print error
- self.__latitude = threading.Timer(5 * 60, self.__do_latitude)
- self.__latitude.start()
- def __restart(self, connection):
- connection.disconnect('Restarting')
- os.execvp(sys.argv[0], sys.argv)
- def __unknown(self, connection, nick, command):
- connection.privmsg(nick, 'unknown command (%s); try "!help"' % command)
- def _connect(self):
- password = None
- if len(self.server_list[0]) != 2:
- ssl = self.server_list[0][2]
- if len(self.server_list[0]) == 4:
- password = self.server_list[0][3]
- try:
- with warnings.catch_warnings():
- warnings.filterwarnings('ignore', r'socket\.ssl\(\) is deprecated\. Use ssl\.wrap_socket\(\) instead\.', DeprecationWarning)
- self.connect(self.server_list[0][0], self.server_list[0][1], self._nickname, password, getpass.getuser(), self._realname, localaddress = self.__hostname, ssl = ssl)
- except irclib.ServerConnectionError:
- pass
- def get_version(self):
- return 'locationbot ' + sys.platform
- def on_nicknameinuse(self, connection, event):
- connection.nick(connection.get_nickname() + '_')
- def on_privmsg(self, connection, event):
- nick = irclib.nm_to_n(event.source())
- admin = self.__admin(event)
- if not admin:
- ok = False
- for channel in self.channels.values():
- if channel.has_user(nick):
- ok = True
- break
- if not ok:
- return
- try:
- command, arguments = event.arguments()[0].split(None, 1)
- except ValueError:
- command = event.arguments()[0].strip()
- arguments = ''
- if command.startswith('!'):
- command = command[1:]
- if command == 'help':
- connection.privmsg(nick, 'Command Arguments Description')
- commands = [
- ('help', '', 'show this help message'),
- ('login', 'user secret', 'login as user with secret'),
- ('register', 'user secret', 'register as user with secret'),
- ('status', '[user]', 'show where everybody or a user is'),
- ]
- if True:
- commands += [
- ('latitude', '[id]', 'shortcut for !set latitude [id]'),
- ('set', '[key [value]]', 'display or set variables'),
- ('unset', 'key', 'unset a variable'),
- ]
- if admin:
- commands += [
- ('restart', '', 'quit and join running more up to date code'),
- ]
- commands.sort()
- for command in commands:
- connection.privmsg(nick, '!%-10s %-16s %s' % command)
- elif admin:
- if command == 'restart':
- self.__restart(connection)
- else:
- self.__unknown(connection, nick, command)
- else:
- self.__unknown(connection, nick, command)
- elif event.eventtype() == 'privmsg':
- self.__unknown(connection, nick, command)
- def on_welcome(self, connection, event):
- for channel in self.__channels:
- connection.join(channel)
- def start(self):
- self.__latitude = threading.Thread(None, self.__do_latitude)
- self.__latitude.daemon = True
- self.__latitude.start()
- self._connect()
- while True:
- self.ircobj.process_once(0.2)
- if self.__locations_lock.acquire(False):
- if self.__locations and sorted(self.__channels) == sorted(self.channels.keys()):
- for user, location in self.__locations:
- for channel in self.__channels:
- self.connection.notice(channel, '%s is in %s' % (user, location))
- self.__locations = []
- self.__locations_lock.release()
- if __name__ == '__main__':
- locationbot = LocationBot()
- try:
- locationbot.start()
- except KeyboardInterrupt:
- locationbot.connection.disconnect('Oh no!')
|