Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/env python
- # -*- coding: utf-8 -*-
- #
- # SYNPOPSIS: This bot parses the RC feed for CentralAuth using regex,
- # and reports to a freenode channel.
- # LICENSE: GPL
- # CREDITS: Mike.lifeguard, Erwin, Dungodung (Filip Maljkovic)
- #
- """
- An IRC bot to read data from one IRC channel (using one connecction),
- filter it, then put it into another channel (using two connections).
- This bot parses the RC feed for CentralAuth using regex, and reports
- to a freenode channel
- """
- # system imports
- import ConfigParser
- import math
- import re
- import string
- import sys
- import time
- import urllib
- # twisted imports
- try:
- from twisted.words.protocols import irc
- from twisted.internet import reactor, protocol
- from twisted.python import log
- except ImportError:
- print "Couldn't import twisted; please install python-twisted."
- sys.exit(1)
- class SULWatcherException(Exception):
- """A single base exception class for all other SULWatcher errors."""
- pass
- class CommanderError(SULWatcherException):
- """This exception is raised when the command parser fails."""
- def __init__(self,value):
- self.value = value
- def __str__(self):
- return repr(self.value)
- #class Logger():
- # """An independent logger class to handle logging from everything else."""
- # def __init__(self, file='log'):
- # self.file = file
- #
- # def log(self, message):
- # """Write a log message to file."""
- # timestamp = '[%s] ' % time.strftime('%d.%m.%Y %H:%M:%S',
- # time.localtime(time.time()))
- # self.file.write('%s %s\n' %(timestamp, message)) # Does this append?
- # self.file.flush()
- # self.file.close()
- class Logger:
- """
- An independent logger class (because separation of application
- and protocol logic is a good thing).
- """
- def __init__(self, file):
- self.file = file
- def log(self, message):
- """Write a message to the file."""
- timestamp = time.strftime("[%H:%M:%S]", time.localtime(time.time()))
- self.file.write('%s %s\n' % (timestamp, message))
- self.file.flush()
- def close(self):
- self.file.close()
- class FreenodeBot(irc.IRCClient):
- """An output bot."""
- # Where should this actually log? Probably stdout so you can see it
- # in terminal and phoenix can simply redirect it to file?
- def connectionMade(self):
- irc.IRCClient.connectionMade(self)
- logfile = "awm11.txt"
- self.logger = Logger(open(logfile, "a"))
- self.logger.log("Connected.")
- def connectionLost(self, reason):
- irc.IRCClient.connectionLost(self, reason)
- self.logger.log("Disconnected")
- def _getIndex(self, option, value):
- self.logger.log("_getIndex(self, '%s', '%s')" % (option, value))
- for section in configdb.sections():
- if section != 'Setup':
- if config.get(section, option) == value:
- return section
- def _getRegex(self, regex, cloak, target):
- self.logger.log("_getRegex(self, '%s', '%s', '%s')"
- % (regex, cloak, target))
- for section in configdb.sections():
- if section != 'Setup':
- if configdb.get(section, 'regex') == regex:
- adder = configdb.get(section, 'adder')
- if config.has_option(section, 'reason'):
- reason = config.get(section, 'reason')
- self.msg(target, '%s is already listed as a '
- "regex. It was added by %s with a note: %s" %
- (regex, cloak, reason))
- else:
- self.msg(target, '%s is already listed as a '
- "regex. It was added by %s" % (regex, cloak))
- break # Needed?
- def _removeRegex(self, regex, cloak, target):
- self.logger.log("_removeRegex(self, '%s', '%s', '%s')"
- % (regex, cloak, target))
- found = False
- for section in configdb.sections():
- if section != 'Setup':
- if configdb.get(section, 'regex') == regex:
- configdb.remove_section(section)
- self.saveConfig()
- found = True
- if found == True:
- self.msg(target, "Removed %s from the regex list." % regex)
- else:
- self.msg(target, "%s isn't in the regex list." % regex)
- def _setConfig(self, section, option, value):
- self.logger.log("_setConfig(self, '%s', '%s', '%s')"
- % (section, option, value))
- configdb.set(section, option, value)
- def _parseUsermask(self, what, usermask):
- self.logger.log("_getCloak(self, '%s')" % usermask)
- if what == 'cloak' or what == 'host' or what == 'hostmask':
- if re.search('@', usermask):
- return usermask.split('@', 1)[1]
- elif what == 'nick':
- if re.search('!', usermask):
- return usermask.split('!', 1)[0]
- else:
- self.logger.log("Error: You didn't specify what to parse "
- "out of the usermask; assuming you want "
- "the nick")
- return _parseUsermask('nick', usermask) # Recurse
- def _saveConfig(self):
- self.logger.log("_saveConfig(self)")
- try:
- configdb.write("SULWatcher.ini")
- except IOError:
- self.logger.log("IOError!")
- else:
- self.logger.log("Done!")
- def doCommand(self, target, usermask, command):
- """Parses the user's command, and calls the appropriate methods."""
- self.logger.log("doCommand(self, '%s', '%s', '%s')"
- % (target, usermask, command))
- nick = self._parseUsermask(usermask)
- args = command.split(" ")
- if args[0] == 'help':
- self._help(nick)
- elif args[0] == 'test':
- if len(args) >= 4:
- self._testRegex(target, command)
- elif len(args) == 1:
- self._help(nick)
- elif args[0] == 'find' or args[0] == 'search':
- if args[1] == 'regex' or args[1] == 'badword':
- regex = ' '.join(args[2:])
- self._findRegex(target, regex)
- elif args[1] == 'match' or args[1] == 'matches':
- needle = ' '.join(args[2:])
- self._findMatches(target, needle)
- elif args[1] == 'adder':
- adder = args[2]
- self._findAdder(target, adder)
- elif args[1] == 'number':
- number == args[2]
- self._findNumber(target, number)
- else:
- raise CommanderError("Syntax?")
- elif args[0] == 'edit' or args[0] == 'change':
- try:
- self._edit(target, command)
- except NoSectionError, e:
- raise CommanderError("No such section as %s" % args[2])
- elif args[0] == 'list':
- """..."""
- # Callbacks for events
- def signedOn(self):
- """Called when the bot has successfully signed onto the server."""
- self.logger.log("signedOn")
- self.join(self.factory.channel)
- def joined(self, channel):
- """Called when the bot actually joins the channel successfully."""
- self.logger.log("Joined %s" % channel)
- def noticed(self, usermask, channel, message):
- """
- Called when the bot recieves a notice to itself or a channel.
- By default, this is equivalent to IRCClient.privmsg, but
- since we make automated replies and whatnot, we *must*
- override the default.
- """
- pass
- def privmsg(self, usermask, channel, msg):
- """Called when the bot recieves any message (private or public)."""
- nick = usermask.split('!', 1)[0]
- # Check if it is a PM
- if channel == self.nickname:
- target = nick
- # If they talk to us in PM, guess what, they're talking to us
- talkintome = True
- else:
- if msg.startswith(self.nickname + ":"):
- talkintome = True
- target = channel
- else:
- talkintome = False
- target = None # Is this needed?
- if talkintome is True:
- try:
- pass # doCommand()
- except CommanderError, e:
- self.logger.log("Error: %s (from %s)" % (e, usermask))
- finally:
- self.logger.log("Command: %s (from %s)" % (command, usermask))
- def action(self, user, channel, msg):
- """Called when a user emotes."""
- user = user.split('!', 1)[0] # nick!
- # Do we want to do anything here? A novelty function might be fun.
- class FreenodeBotFactory(protocol.ClientFactory):
- """
- A factory for FreenodeBots. A new protocol instance will be
- created each time we connect to the server.
- """
- # The class of the protocol to build when new connections are made
- protocol = FreenodeBot
- def __init__(self, channel, nick, password,
- server="irc.freenode.net", port=8001,
- opernick=None, operpass=None):
- self.channel = channel
- self.nick = nick
- self.password = password
- self.server = server
- self.port = port
- if opernick and operpass:
- self.opernick = opernick
- self.operpass = operpass
- def clientConnectionLost(self, connector, reason):
- """If we get disconnected, reconnect to the server."""
- connector.connect()
- def clientConnectionFailed(self, connector, reason):
- print "connection failed:", reason # use Logger
- reactor.stop() # don't stop, just retry?
- # Callbacks for events
- def signedOn(self):
- """Called when the bot has successfuly signed on to the server."""
- # Send nickserv id
- # Send oper id
- self.join(self.factory.channel)
- class WikimediaBotFactory(protocol.ClientFactory):
- """
- A factory for WikimediaBots. A new protocol instance will be created
- each time we connect to the server.
- """
- # The class of the protocol to build when new connections are made
- protocol = 'WikimediaBot'
- def __init__(self, channel, nick, server="irc.freenode.net", port=6667):
- self.channel = channel
- self.nick = nick
- self.server = server
- self.port = port
- def clientConnectionList(self, connector, reason):
- """If we get disconnected, reconnect to the server."""
- connector.connect()
- def clientConnectionFailed(self, connector, reason):
- print "connection failed:", reason # Use logger
- reactor.stop() # don't stop, just retry?
- # Callbacks for events
- def signedOn(self):
- """Called when the bot has successfully signed on to the server."""
- self.join(self.factory.channel)
- class WikimediaBot(irc.IRCClient):
- pass # Implement
- def main():
- # Initialize logging
- log.startLogging(sys.stdout) # Whaa?
- configdb = ConfigParser.ConfigParser()
- configdb.read('awm11.ini')
- nick = configdb.get('Setup', 'nick')
- alias = configdb.get('Setup', 'alias')
- password = configdb.get('Setup', 'password')
- channel = configdb.get('Setup', 'channel')
- channel2 = configdb.get('Setup', 'channel2')
- rcfeed = configdb.get('Setup', 'rcfeed')
- # will this work?
- f1 = FreenodeBotFactory(channel, nick, password)
- f2 = FreenodeBotFactory(channel, alias, password)
- w = WikimediaBotFactory(rcfeed, nick)
- # Connect factory to this host and port
- reactor.connectTCP("irc.freenode.net", 6667, f1)
- reactor.connectTCP("irc.freenode.net", 6667, f2)
- #reactor.connectTCP(w)
- # Run bot
- reactor.run()
- if __name__ == '__main__':
- """Main method"""
- main()
- #try...except block?
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement