Advertisement
Guest User

Untitled

a guest
Jun 6th, 2017
87
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 12.07 KB | None | 0 0
  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. #
  4. # SYNPOPSIS:    This bot parses the RC feed for CentralAuth using regex,
  5. #               and reports to a freenode channel.
  6. # LICENSE:      GPL
  7. # CREDITS:      Mike.lifeguard, Erwin, Dungodung (Filip Maljkovic)
  8. #
  9.  
  10. """
  11. An IRC bot to read data from one IRC channel (using one connecction),
  12. filter it, then put it into another channel (using two connections).
  13.  
  14. This bot parses the RC feed for CentralAuth using regex, and reports
  15. to a freenode channel
  16. """
  17.  
  18. # system imports
  19. import ConfigParser
  20. import math
  21. import re
  22. import string
  23. import sys
  24. import time
  25. import urllib
  26.  
  27. # twisted imports
  28. try:
  29.     from twisted.words.protocols import irc
  30.     from twisted.internet import reactor, protocol
  31.     from twisted.python import log
  32. except ImportError:
  33.     print "Couldn't import twisted; please install python-twisted."
  34.     sys.exit(1)
  35.  
  36. class SULWatcherException(Exception):
  37.     """A single base exception class for all other SULWatcher errors."""
  38.     pass
  39.  
  40. class CommanderError(SULWatcherException):
  41.     """This exception is raised when the command parser fails."""
  42.     def __init__(self,value):
  43.         self.value = value
  44.     def __str__(self):
  45.         return repr(self.value)
  46.  
  47. #class Logger():
  48. #    """An independent logger class to handle logging from everything else."""
  49. #    def __init__(self, file='log'):
  50. #        self.file = file
  51. #
  52. #    def log(self, message):
  53. #        """Write a log message to file."""
  54. #        timestamp = '[%s] ' % time.strftime('%d.%m.%Y %H:%M:%S',
  55. #                                            time.localtime(time.time()))
  56. #        self.file.write('%s %s\n' %(timestamp, message)) # Does this append?
  57. #        self.file.flush()
  58. #        self.file.close()
  59.  
  60. class Logger:
  61.     """
  62.    An independent logger class (because separation of application
  63.    and protocol logic is a good thing).
  64.    """
  65.     def __init__(self, file):
  66.         self.file = file
  67.  
  68.     def log(self, message):
  69.         """Write a message to the file."""
  70.         timestamp = time.strftime("[%H:%M:%S]", time.localtime(time.time()))
  71.         self.file.write('%s %s\n' % (timestamp, message))
  72.         self.file.flush()
  73.  
  74.     def close(self):
  75.         self.file.close()    
  76.  
  77. class FreenodeBot(irc.IRCClient):
  78.     """An output bot."""
  79.  
  80.     # Where should this actually log? Probably stdout so you can see it
  81.     # in terminal and phoenix can simply redirect it to file?
  82.  
  83.  
  84.     def connectionMade(self):
  85.         irc.IRCClient.connectionMade(self)
  86.         logfile = "awm11.txt"
  87.         self.logger = Logger(open(logfile, "a"))
  88.         self.logger.log("Connected.")
  89.  
  90.     def connectionLost(self, reason):
  91.         irc.IRCClient.connectionLost(self, reason)
  92.         self.logger.log("Disconnected")
  93.  
  94.     def _getIndex(self, option, value):
  95.         self.logger.log("_getIndex(self, '%s', '%s')" % (option, value))
  96.         for section in configdb.sections():
  97.             if section != 'Setup':
  98.                 if config.get(section, option) == value:
  99.                     return section
  100.  
  101.     def _getRegex(self, regex, cloak, target):
  102.         self.logger.log("_getRegex(self, '%s', '%s', '%s')"
  103.                         % (regex, cloak, target))
  104.         for section in configdb.sections():
  105.             if section != 'Setup':
  106.                 if configdb.get(section, 'regex') == regex:
  107.                     adder = configdb.get(section, 'adder')
  108.                     if config.has_option(section, 'reason'):
  109.                         reason = config.get(section, 'reason')
  110.                         self.msg(target, '%s is already listed as a '
  111.                                  "regex. It was added by %s with a note: %s" %
  112.                                  (regex, cloak, reason))
  113.                     else:
  114.                         self.msg(target, '%s is already listed as a '
  115.                                  "regex. It was added by %s" % (regex, cloak))
  116.                     break # Needed?
  117.     def _removeRegex(self, regex, cloak, target):
  118.         self.logger.log("_removeRegex(self, '%s', '%s', '%s')"
  119.                         % (regex, cloak, target))
  120.         found = False
  121.         for section in configdb.sections():
  122.             if section != 'Setup':
  123.                 if configdb.get(section, 'regex') == regex:
  124.                     configdb.remove_section(section)
  125.                     self.saveConfig()
  126.                     found = True
  127.         if found == True:
  128.             self.msg(target, "Removed %s from the regex list." % regex)
  129.         else:
  130.             self.msg(target, "%s isn't in the regex list." % regex)
  131.  
  132.     def _setConfig(self, section, option, value):
  133.         self.logger.log("_setConfig(self, '%s', '%s', '%s')"
  134.                         % (section, option, value))
  135.         configdb.set(section, option, value)
  136.  
  137.     def _parseUsermask(self, what, usermask):
  138.         self.logger.log("_getCloak(self, '%s')" % usermask)
  139.         if what == 'cloak' or what == 'host' or what == 'hostmask':
  140.             if re.search('@', usermask):
  141.                 return usermask.split('@', 1)[1]
  142.         elif what == 'nick':
  143.             if re.search('!', usermask):
  144.                 return usermask.split('!', 1)[0]
  145.         else:
  146.             self.logger.log("Error: You didn't specify what to parse "
  147.                             "out of the usermask; assuming you want "
  148.                             "the nick")
  149.             return _parseUsermask('nick', usermask) # Recurse
  150.  
  151.     def _saveConfig(self):
  152.         self.logger.log("_saveConfig(self)")
  153.         try:
  154.             configdb.write("SULWatcher.ini")
  155.         except IOError:
  156.             self.logger.log("IOError!")
  157.         else:
  158.             self.logger.log("Done!")
  159.  
  160.     def doCommand(self, target, usermask, command):
  161.         """Parses the user's command, and calls the appropriate methods."""
  162.         self.logger.log("doCommand(self, '%s', '%s', '%s')"
  163.                         % (target, usermask, command))
  164.         nick = self._parseUsermask(usermask)
  165.         args = command.split(" ")
  166.  
  167.         if args[0] == 'help':
  168.             self._help(nick)
  169.         elif args[0] == 'test':
  170.             if len(args) >= 4:
  171.                 self._testRegex(target, command)
  172.             elif len(args) == 1:
  173.                 self._help(nick)
  174.         elif args[0] == 'find' or args[0] == 'search':
  175.             if args[1] == 'regex' or args[1] == 'badword':
  176.                 regex = ' '.join(args[2:])
  177.                 self._findRegex(target, regex)
  178.             elif args[1] == 'match' or args[1] == 'matches':
  179.                 needle = ' '.join(args[2:])
  180.                 self._findMatches(target, needle)
  181.             elif args[1] == 'adder':
  182.                 adder = args[2]
  183.                 self._findAdder(target, adder)
  184.             elif args[1] == 'number':
  185.                 number == args[2]
  186.                 self._findNumber(target, number)
  187.             else:
  188.                 raise CommanderError("Syntax?")
  189.         elif args[0] == 'edit' or args[0] == 'change':
  190.             try:
  191.                 self._edit(target, command)
  192.             except NoSectionError, e:
  193.                 raise CommanderError("No such section as %s" % args[2])
  194.         elif args[0] == 'list':
  195.             """..."""
  196.        
  197.  
  198.     # Callbacks for events
  199.  
  200.     def signedOn(self):
  201.         """Called when the bot has successfully signed onto the server."""
  202.         self.logger.log("signedOn")
  203.         self.join(self.factory.channel)
  204.  
  205.     def joined(self, channel):
  206.         """Called when the bot actually joins the channel successfully."""
  207.         self.logger.log("Joined %s" % channel)
  208.  
  209.     def noticed(self, usermask, channel, message):
  210.         """
  211.        Called when the bot recieves a notice to itself or a channel.
  212.        By default, this is equivalent to IRCClient.privmsg, but
  213.        since we make automated replies and whatnot, we *must*
  214.        override the default.
  215.        """
  216.         pass
  217.  
  218.     def privmsg(self, usermask, channel, msg):
  219.         """Called when the bot recieves any message (private or public)."""
  220.  
  221.         nick = usermask.split('!', 1)[0]
  222.         # Check if it is a PM
  223.         if channel == self.nickname:
  224.             target = nick
  225.             # If they talk to us in PM, guess what, they're talking to us
  226.             talkintome = True
  227.         else:
  228.             if msg.startswith(self.nickname + ":"):
  229.                 talkintome = True
  230.                 target = channel
  231.             else:
  232.                 talkintome = False
  233.                 target = None # Is this needed?
  234.         if talkintome is True:
  235.             try:
  236.                 pass # doCommand()
  237.             except CommanderError, e:
  238.                 self.logger.log("Error: %s (from %s)" % (e, usermask))
  239.             finally:
  240.                 self.logger.log("Command: %s (from %s)" % (command, usermask))
  241.  
  242.     def action(self, user, channel, msg):
  243.         """Called when a user emotes."""
  244.         user = user.split('!', 1)[0] # nick!
  245.         # Do we want to do anything here? A novelty function might be fun.
  246.  
  247. class FreenodeBotFactory(protocol.ClientFactory):
  248.     """
  249.    A factory for FreenodeBots. A new protocol instance will be
  250.    created each time we connect to the server.
  251.    """
  252.  
  253.     # The class of the protocol to build when new connections are made
  254.     protocol = FreenodeBot
  255.  
  256.     def __init__(self, channel, nick, password,
  257.                  server="irc.freenode.net", port=8001,
  258.                  opernick=None, operpass=None):
  259.         self.channel = channel
  260.         self.nick = nick
  261.         self.password = password
  262.         self.server = server
  263.         self.port = port
  264.         if opernick and operpass:
  265.             self.opernick = opernick
  266.             self.operpass = operpass
  267.  
  268.     def clientConnectionLost(self, connector, reason):
  269.         """If we get disconnected, reconnect to the server."""
  270.         connector.connect()
  271.  
  272.     def clientConnectionFailed(self, connector, reason):
  273.         print "connection failed:", reason # use Logger
  274.         reactor.stop() # don't stop, just retry?
  275.  
  276.     # Callbacks for events
  277.  
  278.     def signedOn(self):
  279.         """Called when the bot has successfuly signed on to the server."""
  280.         # Send nickserv id
  281.         # Send oper id
  282.         self.join(self.factory.channel)
  283.  
  284. class WikimediaBotFactory(protocol.ClientFactory):
  285.     """
  286.    A factory for WikimediaBots. A new protocol instance will be created
  287.    each time we connect to the server.
  288.    """
  289.  
  290.     # The class of the protocol to build when new connections are made
  291.     protocol = 'WikimediaBot'
  292.  
  293.     def __init__(self, channel, nick, server="irc.freenode.net", port=6667):
  294.         self.channel = channel
  295.         self.nick = nick
  296.         self.server = server
  297.         self.port = port
  298.  
  299.     def clientConnectionList(self, connector, reason):
  300.         """If we get disconnected, reconnect to the server."""
  301.         connector.connect()
  302.  
  303.     def clientConnectionFailed(self, connector, reason):
  304.         print "connection failed:", reason # Use logger
  305.         reactor.stop() # don't stop, just retry?
  306.  
  307.     # Callbacks for events
  308.  
  309.     def signedOn(self):
  310.         """Called when the bot has successfully signed on to the server."""
  311.         self.join(self.factory.channel)
  312.  
  313. class WikimediaBot(irc.IRCClient):
  314.     pass # Implement
  315.  
  316. def main():
  317.     # Initialize logging
  318.     log.startLogging(sys.stdout) # Whaa?
  319.    
  320.     configdb = ConfigParser.ConfigParser()
  321.     configdb.read('awm11.ini')
  322.     nick = configdb.get('Setup', 'nick')
  323.     alias = configdb.get('Setup', 'alias')
  324.     password = configdb.get('Setup', 'password')
  325.     channel = configdb.get('Setup', 'channel')
  326.     channel2 = configdb.get('Setup', 'channel2')
  327.     rcfeed = configdb.get('Setup', 'rcfeed')
  328.     # will this work?
  329.     f1 = FreenodeBotFactory(channel, nick,  password)
  330.     f2 = FreenodeBotFactory(channel, alias, password)
  331.     w = WikimediaBotFactory(rcfeed, nick)
  332.  
  333.     # Connect factory to this host and port
  334.     reactor.connectTCP("irc.freenode.net", 6667, f1)
  335.     reactor.connectTCP("irc.freenode.net", 6667, f2)
  336.     #reactor.connectTCP(w)
  337.  
  338.     # Run bot
  339.     reactor.run()
  340.  
  341. if __name__ == '__main__':
  342.     """Main method"""
  343.     main()
  344.     #try...except block?
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement