You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@gump.apache.org by le...@apache.org on 2005/07/06 18:40:34 UTC
svn commit: r209476 - /gump/branches/Gump3/pygump/python/gump/plugins/irc.py
Author: leosimons
Date: Wed Jul 6 09:40:29 2005
New Revision: 209476
URL: http://svn.apache.org/viewcvs?rev=209476&view=rev
Log:
Make gump run even when --irc is specified and the irclib is not available.
Modified:
gump/branches/Gump3/pygump/python/gump/plugins/irc.py
Modified: gump/branches/Gump3/pygump/python/gump/plugins/irc.py
URL: http://svn.apache.org/viewcvs/gump/branches/Gump3/pygump/python/gump/plugins/irc.py?rev=209476&r1=209475&r2=209476&view=diff
==============================================================================
--- gump/branches/Gump3/pygump/python/gump/plugins/irc.py (original)
+++ gump/branches/Gump3/pygump/python/gump/plugins/irc.py Wed Jul 6 09:40:29 2005
@@ -1,308 +1,320 @@
-#!/usr/bin/env python
-
-# Copyright 2004-2005 The Apache Software Foundation
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-__copyright__ = "Copyright (c) 2004-2005 The Apache Software Foundation"
-__license__ = "http://www.apache.org/licenses/LICENSE-2.0"
-
-import os
-import sys
-import string
-import threading, Queue
-
-from irclib import nm_to_n, nm_to_h, \
- irc_lower, ip_numstr_to_quad, ip_quad_to_numstr,SimpleIRCClient
-from ircbot import SingleServerIRCBot
-
-from gump.model.util import check_failure, check_skip
-from gump.plugins import AbstractPlugin
-
-GUMPBOT_NAME='GumpBot'
-GUMPBOT_VERSION='1.0.0alpha'
-DEFAULT_IRC_PORT=6667
-CONFIG_FORMAT='{user}@{server[:port]}/{channel}'
-
-def parseAddressInfo(data):
- """
- Parse {user}@{server[:port]}/{channel}
- returning
- (channel,nickname,server,port)
- """
-
- # Extract nickname@ from front...
- s = string.split(data,'@',1)
- if not 2 == len(s):
- raise Error, 'Unable to extract nickname for %s from %s' % (CONFIG_FORMAT, data)
- nickname=s[0]
-
- s = string.split(s[1], '/', 1)
- if not 2 == len(s):
- raise Error, 'Unable to extract channel for %s from %s' % (CONFIG_FORMAT, data)
-
- channel=s[1]
- s = string.split(s[0], ":", 1)
- server = s[0]
- if len(s) == 2:
- try:
- port = int(s[1])
- except ValueError:
- raise Error, 'Unable to extract port for %s from %s using %s' % (CONFIG_FORMAT, data, s[1])
- else:
- port = DEFAULT_IRC_PORT
-
- return (channel,nickname,server,port)
-
-class GumpBotRunner(threading.Thread):
- """
- Run the IRCbot in a background thread
-
- set self.running=False to shut down (once started)
- """
- def __init__(self, log, bot):
- # A deamon thread
- threading.Thread.__init__(self,name=GUMPBOT_NAME+'Runner')
- self.setDaemon(True)
- self.commands = Queue.Queue()
-
- # able to log
- self.log = log
-
- # That manages a bot, sending messages from
- # time to time.
- self.messages = Queue.Queue()
- self.bot = bot
-
- def run(self):
- """
- Run the bot...
- Allowing it cycles, but injecting messages from a queue
- when available. Stopping when there is a command message
- to do so.
- """
- self.log.info("Run the IRCbot...")
- self.bot.start()
-
- # Allow it to perform welcome, get nickname, etc.
- self.grant_bot_some_cycles()
-
- while True:
- # Pass along messages
- try:
- while True:
- self.bot.put_message(self.messages.get_nowait())
- except Queue.Empty:
- pass
- except Exception, details:
- self.log.warn('Failed to send IRC put_message: %s' % details)
- pass # Ignore queue empty/write failures
-
- # Process commands/events
- self.bot.process_once(0.2)
-
- # Exit the loopng, if nothing to send.
- if self.messages.empty() and not self.commands.empty():
- break
-
- # Shutdown...
- self.log.info("End the IRCbot...")
- self.bot.stop()
- self.grant_bot_some_cycles(10,0.2)
-
- def grant_bot_some_cycles(self,spins=10,timeout=1):
- self.bot.process_some(spins,timeout)
-
- def put_message(self,m):
- """ Pass messages to the bot (for delivery) via the bot. """
- self.messages.put_nowait(m)
-
-class GumpBot(SingleServerIRCBot):
- """
- An IRC bot that lives throughout the life of a gump run.
- """
- def __init__(self, log, channel, nickname, server, port=6667):
- SingleServerIRCBot.__init__(self, [(server, port)], nickname, nickname)
- self.channel_name = channel
- self.channel = channel
- self.log = log
-
- def put_message(self,m):
- c=self.connection
- ch=self.channel_name
- self.log.info('Send IRC message [%s : %s]' % (ch,m))
- c.privmsg(ch,m)
-
- def on_nicknameinuse(self, c, e):
- """ If Nickname in use, try again """
- c.nick(c.get_nickname() + "_")
-
- def on_welcome(self, c, e):
- """ Once welcomed, join the channel """
- c.join(self.channel)
-
- def on_privmsg(self, c, e):
- """ Proces messagesa as commands """
- self.do_command(e, e.arguments()[0])
-
- def on_pubmsg(self, c, e):
- """ Process public messages, looking for this directed to this bot """
- a = string.split(e.arguments()[0], ":", 1)
- if len(a) > 1 and irc_lower(a[0]) == irc_lower(self.connection.get_nickname()):
- self.do_command(e, string.strip(a[1]))
- return
-
- def on_dccmsg(self, c, e):
- c.privmsg("You said: " + e.arguments()[0])
-
- def on_dccchat(self, c, e):
- if len(e.arguments()) != 2:
- return
- args = string.split(e.arguments()[1])
- if len(args) == 4:
- try:
- address = ip_numstr_to_quad(args[2])
- port = int(args[3])
- except ValueError:
- return
- self.dcc_connect(address, port)
-
- def do_command(self, e, cmd):
- """
- Perform a command received over the wire (from the folks in the IRC channel).
- """
- peer_nick = nm_to_n(e.source())
-
- c = self.connection
-
- # What is the request?
- if cmd == 'version':
- c.notice(peer_nick,'%s:%s' % (GUMPBOT_NAME, GUMPBOT_VERSION))
- elif cmd =='help':
- c.notice(peer_nick,'help,disconnect,die,stats,dcc,version')
- elif cmd == "disconnect":
- self.disconnect()
- elif cmd == "die":
- self.die()
- elif cmd == "stats":
- for chname, chobj in self.channels.items():
- c.notice(peer_nick, "--- Channel statistics ---")
- c.notice(peer_nick, "Channel: " + chname)
- users = chobj.users()
- users.sort()
- c.notice(peer_nick, "Users: " + string.join(users, ", "))
- opers = chobj.opers()
- opers.sort()
- c.notice(peer_nick, "Opers: " + string.join(opers, ", "))
- voiced = chobj.voiced()
- voiced.sort()
- c.notice(peer_nick, "Voiced: " + string.join(voiced, ", "))
- elif cmd == "dcc":
- dcc = self.dcc_listen()
- c.ctcp("DCC", peer_nick, "CHAT chat %s %d" % (
- ip_quad_to_numstr(dcc.localaddress),
- dcc.localport))
- else:
- c.notice(peer_nick, "Not understood: " + cmd)
-
- def start(self):
- """
- Start the bot, performing initial
- """
- self._connect()
-
- def process_some(self,spins=10,timeout=1):
- for i in range(1,spins):
- self.process_once(timeout)
-
- def process_once(self,timeout):
- self.ircobj.process_once(timeout)
-
- def stop(self):
- """Shutdown the bot."""
- self.disconnect('Bye from Gump.')
-
-
-class IrcBotPlugin(AbstractPlugin):
- """Execute all commands for all projects."""
- def __init__(self, log, verbose=False, channel='#asfgump', nickname='gump3', server='irc.freenode.net', port=DEFAULT_IRC_PORT):
- self.log = log
- self.verbose = verbose
-
- self.log.info('IRC: Using %s on %s into %s:%s' % (channel,nickname,server,port))
-
- # Create a background IRC bot (in it's own thread)
- self.bot_runner = GumpBotRunner(log, \
- GumpBot(log,channel,nickname,server,port))
-
- def initialize(self):
- self.bot_runner.start()
- self.bot_runner.put_message('Gump signing in.')
-
- def visit_module(self,module):
- if self.verbose:
- self.bot_runner.put_message('Processing Module %s.' % module.name)
-
- if check_skip(module):
- self.bot_runner.put_message('Module %s SKIPPED' % module.name)
- elif check_failure(module):
- self.bot_runner.put_message('Module %s FAILED' % module.name)
-
- def visit_project(self,project):
- if self.verbose:
- self.bot_runner.put_message('Processing Project %s.' % project.name)
-
- if check_skip(project):
- self.bot_runner.put_message('Project %s SKIPPED' % project.name)
- elif check_failure(project):
- self.bot_runner.put_message('Project %s FAILED' % project.name)
-
- def visit_workspace(self,workspace):
- self.bot_runner.put_message('Processing Workspace %s' % workspace.name)
-
- def finalize(self):
- """ :TODO: Disconnect from the IRC service, allowing a graceful shutdown """
- self.bot_runner.put_message('Gump signing out.')
- self.bot_runner.commands.put('shutdown')
-
- if self.bot_runner.isAlive:
- self.bot_runner.join(60)
- if sys.platform == 'win32':
- import time
- time.sleep(60)
- if self.bot_runner.isAlive:
- self.log.warn('Failed to shutdown %s on %s.' % (self.bot_runner.getName(), sys.platform))
-
-def main():
- if len(sys.argv) != 4:
- print "Usage: ircbot <server[:port]> <channel> <nickname>"
- sys.exit(1)
-
- s = string.split(sys.argv[1], ":", 1)
- server = s[0]
- if len(s) == 2:
- try:
- port = int(s[1])
- except ValueError:
- print "Error: Erroneous port."
- sys.exit(1)
- else:
- port = DEFAULT_IRC_PORT
- channel = sys.argv[2]
- nickname = sys.argv[3]
-
- bot=GumpBot(channel, nickname, server, port)
- bot.start()
-
-if __name__ == "__main__":
- main()
+#!/usr/bin/env python
+
+# Copyright 2004-2005 The Apache Software Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+__copyright__ = "Copyright (c) 2004-2005 The Apache Software Foundation"
+__license__ = "http://www.apache.org/licenses/LICENSE-2.0"
+
+import os
+import sys
+import string
+import threading, Queue
+
+GUMPBOT_NAME='GumpBot'
+GUMPBOT_VERSION='1.0.0alpha'
+DEFAULT_IRC_PORT=6667
+CONFIG_FORMAT='{user}@{server[:port]}/{channel}'
+
+def parseAddressInfo(data):
+ """
+ Parse {user}@{server[:port]}/{channel}
+ returning
+ (channel,nickname,server,port)
+ """
+
+ # Extract nickname@ from front...
+ s = string.split(data,'@',1)
+ if not 2 == len(s):
+ raise Error, 'Unable to extract nickname for %s from %s' % (CONFIG_FORMAT, data)
+ nickname=s[0]
+
+ s = string.split(s[1], '/', 1)
+ if not 2 == len(s):
+ raise Error, 'Unable to extract channel for %s from %s' % (CONFIG_FORMAT, data)
+
+ channel=s[1]
+ s = string.split(s[0], ":", 1)
+ server = s[0]
+ if len(s) == 2:
+ try:
+ port = int(s[1])
+ except ValueError:
+ raise Error, 'Unable to extract port for %s from %s using %s' % (CONFIG_FORMAT, data, s[1])
+ else:
+ port = DEFAULT_IRC_PORT
+
+ return (channel,nickname,server,port)
+
+try:
+ from irclib import nm_to_n, nm_to_h, \
+ irc_lower, ip_numstr_to_quad, ip_quad_to_numstr,SimpleIRCClient
+ from ircbot import SingleServerIRCBot
+
+ from gump.model.util import check_failure, check_skip
+ from gump.plugins import AbstractPlugin
+
+ class GumpBotRunner(threading.Thread):
+ """
+ Run the IRCbot in a background thread
+
+ set self.running=False to shut down (once started)
+ """
+ def __init__(self, log, bot):
+ # A deamon thread
+ threading.Thread.__init__(self,name=GUMPBOT_NAME+'Runner')
+ self.setDaemon(True)
+ self.commands = Queue.Queue()
+
+ # able to log
+ self.log = log
+
+ # That manages a bot, sending messages from
+ # time to time.
+ self.messages = Queue.Queue()
+ self.bot = bot
+
+ def run(self):
+ """
+ Run the bot...
+ Allowing it cycles, but injecting messages from a queue
+ when available. Stopping when there is a command message
+ to do so.
+ """
+ self.log.info("Run the IRCbot...")
+ self.bot.start()
+
+ # Allow it to perform welcome, get nickname, etc.
+ self.grant_bot_some_cycles()
+
+ while True:
+ # Pass along messages
+ try:
+ while True:
+ self.bot.put_message(self.messages.get_nowait())
+ except Queue.Empty:
+ pass
+ except Exception, details:
+ self.log.warn('Failed to send IRC put_message: %s' % details)
+ pass # Ignore queue empty/write failures
+
+ # Process commands/events
+ self.bot.process_once(0.2)
+
+ # Exit the loopng, if nothing to send.
+ if self.messages.empty() and not self.commands.empty():
+ break
+
+ # Shutdown...
+ self.log.info("End the IRCbot...")
+ self.bot.stop()
+ self.grant_bot_some_cycles(10,0.2)
+
+ def grant_bot_some_cycles(self,spins=10,timeout=1):
+ self.bot.process_some(spins,timeout)
+
+ def put_message(self,m):
+ """ Pass messages to the bot (for delivery) via the bot. """
+ self.messages.put_nowait(m)
+
+ class GumpBot(SingleServerIRCBot):
+ """
+ An IRC bot that lives throughout the life of a gump run.
+ """
+ def __init__(self, log, channel, nickname, server, port=6667):
+ SingleServerIRCBot.__init__(self, [(server, port)], nickname, nickname)
+ self.channel_name = channel
+ self.channel = channel
+ self.log = log
+
+ def put_message(self,m):
+ c=self.connection
+ ch=self.channel_name
+ self.log.info('Send IRC message [%s : %s]' % (ch,m))
+ c.privmsg(ch,m)
+
+ def on_nicknameinuse(self, c, e):
+ """ If Nickname in use, try again """
+ c.nick(c.get_nickname() + "_")
+
+ def on_welcome(self, c, e):
+ """ Once welcomed, join the channel """
+ c.join(self.channel)
+
+ def on_privmsg(self, c, e):
+ """ Proces messagesa as commands """
+ self.do_command(e, e.arguments()[0])
+
+ def on_pubmsg(self, c, e):
+ """ Process public messages, looking for this directed to this bot """
+ a = string.split(e.arguments()[0], ":", 1)
+ if len(a) > 1 and irc_lower(a[0]) == irc_lower(self.connection.get_nickname()):
+ self.do_command(e, string.strip(a[1]))
+ return
+
+ def on_dccmsg(self, c, e):
+ c.privmsg("You said: " + e.arguments()[0])
+
+ def on_dccchat(self, c, e):
+ if len(e.arguments()) != 2:
+ return
+ args = string.split(e.arguments()[1])
+ if len(args) == 4:
+ try:
+ address = ip_numstr_to_quad(args[2])
+ port = int(args[3])
+ except ValueError:
+ return
+ self.dcc_connect(address, port)
+
+ def do_command(self, e, cmd):
+ """
+ Perform a command received over the wire (from the folks in the IRC channel).
+ """
+ peer_nick = nm_to_n(e.source())
+
+ c = self.connection
+
+ # What is the request?
+ if cmd == 'version':
+ c.notice(peer_nick,'%s:%s' % (GUMPBOT_NAME, GUMPBOT_VERSION))
+ elif cmd =='help':
+ c.notice(peer_nick,'help,disconnect,die,stats,dcc,version')
+ elif cmd == "disconnect":
+ self.disconnect()
+ elif cmd == "die":
+ self.die()
+ elif cmd == "stats":
+ for chname, chobj in self.channels.items():
+ c.notice(peer_nick, "--- Channel statistics ---")
+ c.notice(peer_nick, "Channel: " + chname)
+ users = chobj.users()
+ users.sort()
+ c.notice(peer_nick, "Users: " + string.join(users, ", "))
+ opers = chobj.opers()
+ opers.sort()
+ c.notice(peer_nick, "Opers: " + string.join(opers, ", "))
+ voiced = chobj.voiced()
+ voiced.sort()
+ c.notice(peer_nick, "Voiced: " + string.join(voiced, ", "))
+ elif cmd == "dcc":
+ dcc = self.dcc_listen()
+ c.ctcp("DCC", peer_nick, "CHAT chat %s %d" % (
+ ip_quad_to_numstr(dcc.localaddress),
+ dcc.localport))
+ else:
+ c.notice(peer_nick, "Not understood: " + cmd)
+
+ def start(self):
+ """
+ Start the bot, performing initial
+ """
+ self._connect()
+
+ def process_some(self,spins=10,timeout=1):
+ for i in range(1,spins):
+ self.process_once(timeout)
+
+ def process_once(self,timeout):
+ self.ircobj.process_once(timeout)
+
+ def stop(self):
+ """Shutdown the bot."""
+ self.disconnect('Bye from Gump.')
+
+
+ class IrcBotPlugin(AbstractPlugin):
+ """Execute all commands for all projects."""
+ def __init__(self, log, verbose=False, channel='#asfgump', nickname='gump3', server='irc.freenode.net', port=DEFAULT_IRC_PORT):
+ self.log = log
+ self.verbose = verbose
+
+ self.log.info('IRC: Using %s on %s into %s:%s' % (channel,nickname,server,port))
+
+ # Create a background IRC bot (in it's own thread)
+ self.bot_runner = GumpBotRunner(log, \
+ GumpBot(log,channel,nickname,server,port))
+
+ def initialize(self):
+ self.bot_runner.start()
+ self.bot_runner.put_message('Gump signing in.')
+
+ def visit_module(self,module):
+ if self.verbose:
+ self.bot_runner.put_message('Processing Module %s.' % module.name)
+
+ if check_skip(module):
+ self.bot_runner.put_message('Module %s SKIPPED' % module.name)
+ elif check_failure(module):
+ self.bot_runner.put_message('Module %s FAILED' % module.name)
+
+ def visit_project(self,project):
+ if self.verbose:
+ self.bot_runner.put_message('Processing Project %s.' % project.name)
+
+ if check_skip(project):
+ self.bot_runner.put_message('Project %s SKIPPED' % project.name)
+ elif check_failure(project):
+ self.bot_runner.put_message('Project %s FAILED' % project.name)
+
+ def visit_workspace(self,workspace):
+ self.bot_runner.put_message('Processing Workspace %s' % workspace.name)
+
+ def finalize(self):
+ """ :TODO: Disconnect from the IRC service, allowing a graceful shutdown """
+ self.bot_runner.put_message('Gump signing out.')
+ self.bot_runner.commands.put('shutdown')
+
+ if self.bot_runner.isAlive:
+ self.bot_runner.join(60)
+ if sys.platform == 'win32':
+ import time
+ time.sleep(60)
+ if self.bot_runner.isAlive:
+ self.log.warn('Failed to shutdown %s on %s.' % (self.bot_runner.getName(), sys.platform))
+
+ def main():
+ if len(sys.argv) != 4:
+ print "Usage: ircbot <server[:port]> <channel> <nickname>"
+ sys.exit(1)
+
+ s = string.split(sys.argv[1], ":", 1)
+ server = s[0]
+ if len(s) == 2:
+ try:
+ port = int(s[1])
+ except ValueError:
+ print "Error: Erroneous port."
+ sys.exit(1)
+ else:
+ port = DEFAULT_IRC_PORT
+ channel = sys.argv[2]
+ nickname = sys.argv[3]
+
+ bot=GumpBot(channel, nickname, server, port)
+ bot.start()
+
+except:
+ # too bad, the library isn't here. No-op stubs it is, then.
+ from gump.plugins import AbstractPlugin
+
+ def main():
+ print "The IRC plugin is disabled because python-irclib is not available!"
+
+ class IrcBotPlugin(AbstractPlugin):
+ def __init__(self, log, verbose=False, channel='#asfgump', nickname='gump3', server='irc.freenode.net', port=DEFAULT_IRC_PORT):
+ log.warn("The IRC plugin is disabled because python-irclib is not available!")
+
+if __name__ == "__main__":
+ main()