# -*- coding: utf-8 -*- # Copyright © 2005, Simon E. Ward # # This file is part of SvnBot. # # SvnBot is free software; you can redistribute it and/or modify it # under the terms of version 2 of the GNU General Public License as # published by the Free Software Foundation. # # SvnBot is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with SvnBot; if not, write to the Free Software Foundation, # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA import sys from twisted.application import service, internet from twisted.words.protocols import irc from twisted.internet import protocol from twisted.python import log from twisted.web import server, xmlrpc class SvnBotXmlrpc(xmlrpc.XMLRPC): def __init__(self, bot, channel, tracurl=None): self.bot = bot self.channel = channel self.tracurl = tracurl xmlrpc.XMLRPC.__init__(self) def xmlrpc_say(self, msg): self.bot.say(self.channel, msg) return 0 def xmlrpc_showCommitSummary(self, rev, author): self.bot.say(self.channel, "Revision %s committed by %s: %s" % ( rev, author, self.tracurl+'changeset/'+rev)) return 0 class SvnBot(irc.IRCClient): """A bot that retrieves subversion repository metadata.""" xmlrpcService = None pingerService = None def __init__(self): self.nickname = "svnbot" self.realname = "Subversion Bot" #def sendLine(self, line): # irc.IRCClient.sendLine(self, line) #def join(self, channel, key=None): # irc.IRCClient.join(self, channel, key) #def mode(self, chan, set, modes, limit = None, user = None, mask = None): # irc.IRCClient.mode(self, chan, set, modes, limit, user, mask) #def say(self, channel, message, length = None): # irc.IRCClient.say(self, channel, message, length) #def ping(self, user, text=None): # irc.IRCClient.ping(self, user, text) #def pong(self, user, secs): # irc.IRCClient.pong(self, user, secs) def connectionMade(self): irc.IRCClient.connectionMade(self) x = SvnBotXmlrpc(self, self.factory.channel, tracurl=self.factory.tracurl) if self.xmlrpcService is None: self.xmlrpcService = internet.TCPServer(7080, server.Site(x), interface='localhost') self.xmlrpcService.setServiceParent(serviceCollection) else: self.xmlrpcService.startService() #if self.pingerService is None: # self.pingerService = internet.TimerService(120, # self.ping, self.nickname, text=None) # self.pingerService.setServiceParent(serviceCollection) #else: # self.pingerService.startService() def connectionLost(self, reason): irc.IRCClient.connectionLost(self, reason) self.xmlrpcService.stopService() #self.pingerService.stopService() def signedOn(self): """Called when bot has succesfully signed on to server.""" irc.IRCClient.signedOn(self) self.mode(self.nickname, 1, 'B') self.join(self.factory.channel) #def lineReceived(self, line): # irc.IRCClient.dataReceived(self, line) #def joined(self, channel): # irc.IRCClient.joined(self, channel) #def left(self, channel): # irc.IRCClient.left(self, channel) #def irc_PING(self, prefix, params): # irc.IRCClient.irc_PING(self, prefix, params) #def irc_unknown(self, prefix, command, params): # irc.IRCClient.irc_unknown(self, prefix, command, params) class SvnBotFactory(protocol.ReconnectingClientFactory): """A factory for SvnBots. A new protocol instance will be created each time we connect to the server. """ # The class of the protocol to build when new connection is made protocol = SvnBot def __init__(self, channel, tracurl=None): self.channel = channel self.tracurl = tracurl #def clientConnectionFailed(self, connector, reason): # """Called when a connection has failed to connect.""" # protocol.ReconnectingClientFactory.clientConnectionFailed( # self, connector, reason) #def clientConnectionLost(self, connector, unused_reason): # protocol.ReconnectingClientFactory.clientConnectionLost( # self, connector, unused_reason) #def resetDelay(self): # """Call me after a successful connection to reset.""" # protocol.ReconnectingClientFactory.resetDelay(self) #def retry(self, connector=None): # """Have this connector connect again, after a suitable delay.""" # protocol.ReconnectingClientFactory.retry(self, connector) #def stopTrying(self): # """I put a stop to any attempt to reconnect in progress.""" # protocol.ReconnectingClientFactory.stopTrying(self) #def startedConnecting(self, connector): # """Called when a connection has been started.""" # protocol.ReconnectingClientFactory.startedConnecting(self, connector) def buildProtocol(self, addr): """Create an instance of a subclass of Protocol.""" self.resetDelay() return protocol.ReconnectingClientFactory.buildProtocol(self, addr) #def doStart(self): # """Make sure startFactory is called.""" # protocol.ReconnectingClientFactory.doStart(self) #def doStop(self): # """Make sure stopFactory is called.""" # protocol.ReconnectingClientFactory.doStop(self) #def startFactory(self): # """This will be called before I begin listening on a Port or # Connector.""" # protocol.ReconnectingClientFactory.startFactory(self) #def stopFactory(self): # """This will be called before I stop listening on all # Ports/Connectors.""" # protocol.ReconnectingClientFactory.stopFactory(self) application = service.Application('svnbot') serviceCollection = service.IServiceCollection(application) svnBot = SvnBotFactory(channel='#test') tcpClient = internet.TCPClient('irc.example.com', 6667, svnBot) tcpClient.setServiceParent(serviceCollection)