summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Franke <nobody@nowhere.ws>2013-03-18 01:14:19 +0100
committerChristian Franke <nobody@nowhere.ws>2013-03-18 01:14:19 +0100
commitb12c6afddda080a293891bd53d61720eb31bca78 (patch)
treefd62d0d5b57922c7c4e5ea09d87eb8ebb4b32979
parent5de6385dca0974f422e71e27746510d4c15bd6e8 (diff)
Make bot backend reloadable
-rw-r--r--bot_backend.py99
-rw-r--r--subbot.py127
2 files changed, 129 insertions, 97 deletions
diff --git a/bot_backend.py b/bot_backend.py
new file mode 100644
index 0000000..6a2adfa
--- /dev/null
+++ b/bot_backend.py
@@ -0,0 +1,99 @@
+import liblo
+import urllib2
+
+# Known lights, terminal symbols
+lights_terminal = {}
+
+for i in range(1,5):
+ ident = '%02d' % i
+ lights_terminal[ident] = 'osc.udp://172.22.83.5:4243/dali/lamps/%s/bright' % ident
+
+# Production Rules/Aliases
+lights_production = {
+ u'lounge-stage': [u'01'],
+ u'lounge-office': [u'02'],
+ u'lounge-bar': [u'03'],
+ u'lounge-clock': [u'04'],
+ u'lounge-west': [u'lounge-bar', u'lounge-clock'],
+ u'lounge-east': [u'lounge-stage', u'lounge-office'],
+ u'lounge': [u'lounge-east', u'lounge-west'],
+}
+
+class OSCMessage(object):
+ def __init__(self, url):
+ parsed = urllib2.urlparse.urlparse(url)
+ self.path = parsed.path
+ self.url = urllib2.urlparse.urlunparse((parsed.scheme, parsed.netloc, '', '', '', ''))
+
+ self.msg = liblo.Message(self.path)
+
+ def __getattr__(self, name):
+ return getattr(self.msg, name)
+
+ def send(self):
+ liblo.send(self.url, self.msg)
+
+def on_pubmsg(self, c, e):
+ message = e.arguments[0]
+
+ light_command_prefix = '!light'
+ if message.startswith(light_command_prefix):
+ nick = e.source.nick
+ on_light_command(self, nick, message[len(light_command_prefix) + 1:])
+
+def on_light_command(self, nick, commandline):
+ tokens = commandline.split(' ')
+ if len(tokens) < 1:
+ self.light_usage()
+ return
+
+ if tokens[0].lower() == 'set':
+ on_light_set(self, tokens[1:])
+ elif tokens[0].lower() == 'list':
+ on_light_list(self, tokens[1:])
+ else:
+ light_usage(self)
+
+def on_light_list(self, tokens):
+ self.connection.privmsg(self.channel,
+ "The following ids are currently known: %s" % ', '.join(sorted(lights_production.keys())))
+
+def on_light_set(self, tokens):
+ if len(tokens) != 2:
+ return False
+
+ lights = tokens[0].split(',')
+ for i in range(32):
+ for i in range(len(lights)):
+ light = lights[i]
+ if light in lights_terminal:
+ continue
+ if light not in lights_production:
+ self.connection.privmsg(self.channel, "Unknown Alias: '%s'" % light)
+ return
+ lights = lights[:i] + lights_production[light] + lights[i+1:]
+ break
+
+ status = tokens[1]
+ if status.lower() == 'on':
+ status = 255
+ elif status.lower() == 'off':
+ status = 0
+ else:
+ try:
+ status = int(status, 0)
+ if status not in range(256):
+ raise ValueError
+ except ValueError:
+ self.connection.privmsg(self.channel, "Invalid light value: '%s'" % status)
+ return
+
+ for light in lights:
+ msg = OSCMessage(lights_terminal[light])
+ msg.add(status)
+ msg.send()
+ self.connection.privmsg(self.channel, "Light command processed.")
+
+def light_usage(self):
+ self.connection.privmsg(self.channel, "Usage: !light list")
+ self.connection.privmsg(self.channel, "Usage: !light set <id>[,...] <on|off|0..255>")
diff --git a/subbot.py b/subbot.py
index 0afa76b..5d309fb 100644
--- a/subbot.py
+++ b/subbot.py
@@ -2,47 +2,26 @@
import irc.bot
import json, time
-import traceback
-import liblo
import urllib2
import sys
import contextlib
-
+import signal
import settings
+import select
+import errno
svcpw = settings.bot_svcpw
-# Known lights, terminal symbols
-lights_terminal = {}
-
-for i in range(1,5):
- ident = '%02d' % i
- lights_terminal[ident] = 'osc.udp://172.22.83.5:4243/dali/lamps/%s/bright' % ident
-
-# Production Rules/Aliases
-lights_production = {
- u'lounge-stage': [u'01'],
- u'lounge-office': [u'02'],
- u'lounge-bar': [u'03'],
- u'lounge-clock': [u'04'],
- u'lounge-west': [u'lounge-bar', u'lounge-clock'],
- u'lounge-east': [u'lounge-stage', u'lounge-office'],
- u'lounge': [u'lounge-east', u'lounge-west'],
-}
-
-class OSCMessage(object):
- def __init__(self, url):
- parsed = urllib2.urlparse.urlparse(url)
- self.path = parsed.path
- self.url = urllib2.urlparse.urlunparse((parsed.scheme, parsed.netloc, '', '', '', ''))
-
- self.msg = liblo.Message(self.path)
-
- def __getattr__(self, name):
- return getattr(self.msg, name)
-
- def send(self):
- liblo.send(self.url, self.msg)
+import bot_backend
+def reload_backend(signum, frame):
+ try:
+ reload(bot_backend)
+ except Exception:
+ print >>sys.stderr, "Error reloading bot backend:"
+ sys.excepthook(*sys.exc_info())
+ else:
+ print >>sys.stderr, "Reloaded backend."
+signal.signal(signal.SIGUSR1, reload_backend)
class TestBot(irc.bot.SingleServerIRCBot):
def __init__(self, channel, nickname, server, port=6667):
@@ -53,6 +32,16 @@ class TestBot(irc.bot.SingleServerIRCBot):
irc.bot.SingleServerIRCBot.__init__(self, [(server, port)], self.nickname, self.nickname)
self.channel = channel
+ def start(self):
+ self._connect()
+ while True:
+ try:
+ self.ircobj.process_forever(30)
+ except select.error, e:
+ if e.args[0] == errno.EINTR:
+ continue
+ raise
+
def on_nicknameinuse(self, c, e):
self.nickname_base += '_'
self.update_nick()
@@ -63,68 +52,11 @@ class TestBot(irc.bot.SingleServerIRCBot):
c.join(self.channel)
def on_pubmsg(self, c, e):
- message = e.arguments[0]
-
- light_command_prefix = '!light'
- if message.startswith(light_command_prefix):
- nick = e.source.nick
- self.on_light_command(nick, message[len(light_command_prefix) + 1:])
-
- def on_light_command(self, nick, commandline):
- tokens = commandline.split(' ')
- if len(tokens) < 1:
- self.light_usage()
- return
-
- if tokens[0].lower() == 'set':
- self.on_light_set(tokens[1:])
- elif tokens[0].lower() == 'list':
- self.on_light_list(tokens[1:])
- else:
- self.light_usage()
-
- def on_light_list(self, tokens):
- self.connection.privmsg(self.channel,
- "The following ids are currently known: %s" % ', '.join(sorted(lights_production.keys())))
-
- def on_light_set(self, tokens):
- if len(tokens) != 2:
- return False
-
- lights = tokens[0].split(',')
- for i in range(32):
- for i in range(len(lights)):
- light = lights[i]
- if light in lights_terminal:
- continue
- if light not in lights_production:
- self.connection.privmsg(self.channel, "Unknown Alias: '%s'" % light)
- return
- lights = lights[:i] + lights_production[light] + lights[i+1:]
- break
-
- status = tokens[1]
- if status.lower() == 'on':
- status = 255
- elif status.lower() == 'off':
- status = 0
- else:
- try:
- status = int(status, 0)
- if status not in range(256):
- raise ValueError
- except ValueError:
- self.connection.privmsg(self.channel, "Invalid light value: '%s'" % status)
- return
-
- for light in lights:
- msg = OSCMessage(lights_terminal[light])
- msg.add(status)
- msg.send()
-
- def light_usage(self):
- self.connection.privmsg(self.channel, "Usage: !light list")
- self.connection.privmsg(self.channel, "Usage: !light set <id>[,...] <on|off|0..255>")
+ try:
+ bot_backend.on_pubmsg(self, c, e)
+ except Exception:
+ print >>sys.stderr, "Error in backend processing message:"
+ sys.excepthook(*sys.exc_info())
def update_nick(self, server_interaction=True):
"""Set new nickname from nickname base and current status"""
@@ -161,7 +93,8 @@ class TestBot(irc.bot.SingleServerIRCBot):
else:
self.status = 'error'
except Exception, e:
- traceback.print_exc()
+ print >>sys.stderr, "Error in door status retrieval:"
+ sys.excepthook(*sys.exc_info())
self.status = 'error'
self.update_nick()