Ejemplo n.º 1
0
    def error(self, origin=None, trigger=None):
        """Called internally when a module causes an error."""
        try:
            trace = traceback.format_exc()
            if sys.version_info.major < 3:
                trace = trace.decode('utf-8', errors='xmlcharrefreplace')
            stderr(trace)
            try:
                lines = list(reversed(trace.splitlines()))
                report = [lines[0].strip()]
                for line in lines:
                    line = line.strip()
                    if line.startswith('File "'):
                        report.append(line[0].lower() + line[1:])
                        break
                else:
                    report.append('source unknown')

                signature = '%s (%s)' % (report[0], report[1])
                # TODO: make not hardcoded
                log_filename = os.path.join(
                    self.config.logdir, 'exceptions.log'
                )
                with codecs.open(
                    log_filename, 'a', encoding='utf-8'
                ) as logfile:
                    logfile.write('Signature: %s\n' % signature)
                    if origin:
                        logfile.write(
                            'from %s at %s:\n' % (
                                origin.sender, str(datetime.now())
                            )
                        )
                    if trigger:
                        logfile.write(
                            'Message was: <%s> %s\n' % (
                                trigger.nick, trigger.group(0)
                            )
                        )
                    logfile.write(trace)
                    logfile.write(
                        '----------------------------------------\n\n'
                    )
            except Exception as e:
                stderr("Could not save full traceback!")
                self.debug(__file__, "(From: " + origin.sender +
                           "), can't save traceback: " + str(e), 'always')

            if origin:
                #self.msg(origin.sender, signature)
                # Don't send the file name 
                self.msg(origin.sender, report[0])
        except Exception as e:
            if origin:
                self.msg(origin.sender, "Got an error.")
                self.debug(
                    __file__,
                    "(From: " + origin.sender + ") " + str(e),
                    'always'
                )
Ejemplo n.º 2
0
 def _modules(self):
     home = os.getcwd()
     modules_dir = os.path.join(home, 'modules')
     filenames = willie.loader.enumerate_modules(self)
     os.sys.path.insert(0, modules_dir)
     for name, mod_spec in iteritems(filenames):
         path, type_ = mod_spec
         try:
             module, _ = willie.loader.load_module(name, path, type_)
         except Exception as e:
             filename, lineno = willie.tools.get_raising_file_and_line()
             rel_path = os.path.relpath(filename, os.path.dirname(__file__))
             raising_stmt = "%s:%d" % (rel_path, lineno)
             stderr("Error loading %s: %s (%s)" % (name, e, raising_stmt))
         else:
             if hasattr(module, 'configure'):
                 prompt = name + ' module'
                 if module.__doc__:
                     doc = module.__doc__.split('\n', 1)[0]
                     if doc:
                         prompt = doc
                 prompt = 'Configure {} (y/n)? [n]'.format(prompt)
                 do_configure = get_input(prompt)
                 do_configure = do_configure and do_configure.lower() == 'y'
                 if do_configure:
                     module.configure(self)
     self.save()
Ejemplo n.º 3
0
    def unregister(self, variables):
        """Unregister all willie callables in variables, and their bindings.

        When unloading a module, this ensures that the unloaded modules will
        not get called and that the objects can be garbage collected. Objects
        that have not been registered are ignored.

        Args:
        variables -- A list of callable objects from a willie module.

        """
        def remove_func(func, commands):
            """Remove all traces of func from commands."""
            for func_list in itervalues(commands):
                if func in func_list:
                    func_list.remove(func)

        for obj in itervalues(variables):
            if obj in self.callables:
                self.callables.remove(obj)
                for commands in itervalues(self.commands):
                    remove_func(obj, commands)
            if obj in self.shutdown_methods:
                try:
                    obj(self)
                except Exception as e:
                    stderr("Error calling shutdown method for module %s:%s" %
                           (obj.__module__, e))
                self.shutdown_methods.remove(obj)
Ejemplo n.º 4
0
 def _modules(self):
     home = os.getcwd()
     modules_dir = os.path.join(home, 'modules')
     filenames = willie.loader.enumerate_modules(self)
     os.sys.path.insert(0, modules_dir)
     for name, mod_spec in iteritems(filenames):
         path, type_ = mod_spec
         try:
             module, _ = willie.loader.load_module(name, path, type_)
         except Exception as e:
             filename, lineno = willie.tools.get_raising_file_and_line()
             rel_path = os.path.relpath(filename, os.path.dirname(__file__))
             raising_stmt = "%s:%d" % (rel_path, lineno)
             stderr("Error loading %s: %s (%s)" % (name, e, raising_stmt))
         else:
             if hasattr(module, 'configure'):
                 prompt = name + ' module'
                 if module.__doc__:
                     doc = module.__doc__.split('\n', 1)[0]
                     if doc:
                         prompt = doc
                 prompt = 'Configure {} (y/n)? [n]'.format(prompt)
                 do_configure = get_input(prompt)
                 do_configure = do_configure and do_configure.lower() == 'y'
                 if do_configure:
                     module.configure(self)
     self.save()
Ejemplo n.º 5
0
    def handle_error(self):
        """Handle any uncaptured error in the core.

        Overrides asyncore's handle_error.

        """
        trace = traceback.format_exc()
        stderr(trace)
        LOGGER.error('Fatal error in core, please review exception log')
        # TODO: make not hardcoded
        logfile = codecs.open(os.path.join(self.config.logdir,
                                           'exceptions.log'),
                              'a',
                              encoding='utf-8')
        logfile.write('Fatal error in core, handle_error() was called\n')
        logfile.write('last raw line was %s' % self.raw)
        logfile.write(trace)
        logfile.write('Buffer:\n')
        logfile.write(self.buffer)
        logfile.write('----------------------------------------\n\n')
        logfile.close()
        if self.error_count > 10:
            if (datetime.now() - self.last_error_timestamp).seconds < 5:
                print >> sys.stderr, "Too many errors, can't continue"
                os._exit(1)
        self.last_error_timestamp = datetime.now()
        self.error_count = self.error_count + 1
        if self.config.exit_on_error:
            os._exit(1)
Ejemplo n.º 6
0
    def handle_error(self):
        """Handle any uncaptured error in the core.

        Overrides asyncore's handle_error.

        """
        trace = traceback.format_exc()
        stderr(trace)
        self.debug(
            __file__,
            'Fatal error in core, please review exception log',
            'always'
        )
        # TODO: make not hardcoded
        logfile = codecs.open(
            os.path.join(self.config.logdir, 'exceptions.log'),
            'a',
            encoding='utf-8'
        )
        logfile.write('Fatal error in core, handle_error() was called\n')
        logfile.write('last raw line was %s' % self.raw)
        logfile.write(trace)
        logfile.write('Buffer:\n')
        logfile.write(self.buffer)
        logfile.write('----------------------------------------\n\n')
        logfile.close()
        if self.error_count > 10:
            if (datetime.now() - self.last_error_timestamp).seconds < 5:
                print >> sys.stderr, "Too many errors, can't continue"
                os._exit(1)
        self.last_error_timestamp = datetime.now()
        self.error_count = self.error_count + 1
        if self.config.exit_on_error:
            os._exit(1)
Ejemplo n.º 7
0
    def unregister(self, variables):
        """Unregister all willie callables in variables, and their bindings.

        When unloading a module, this ensures that the unloaded modules will
        not get called and that the objects can be garbage collected. Objects
        that have not been registered are ignored.

        Args:
        variables -- A list of callable objects from a willie module.

        """

        def remove_func(func, commands):
            """Remove all traces of func from commands."""
            for func_list in itervalues(commands):
                if func in func_list:
                    func_list.remove(func)

        hostmask = "%s!%s@%s" % (self.nick, self.user, socket.gethostname())
        willie = self.WillieWrapper(self, irc.Origin(self, hostmask, [], {}))
        for obj in itervalues(variables):
            if obj in self.callables:
                self.callables.remove(obj)
                for commands in itervalues(self.commands):
                    remove_func(obj, commands)
            if obj in self.shutdown_methods:
                try:
                    obj(willie)
                except Exception as e:
                    stderr(
                        "Error calling shutdown method for module %s:%s" %
                        (obj.__module__, e)
                    )
                self.shutdown_methods.remove(obj)
Ejemplo n.º 8
0
    def __init__(self, config):
        ca_certs = '/etc/pki/tls/cert.pem'
        if config.ca_certs is not None:
            ca_certs = config.ca_certs
        elif not os.path.isfile(ca_certs):
            ca_certs = '/etc/ssl/certs/ca-certificates.crt'
        if not os.path.isfile(ca_certs):
            stderr('Could not open CA certificates file. SSL will not '
                   'work properly.')

        if config.log_raw is None:
            # Default is to log raw data, can be disabled in config
            config.log_raw = True
        asynchat.async_chat.__init__(self)
        self.set_terminator(b'\n')
        self.buffer = ''

        self.nick = Nick(config.nick)
        """Willie's current ``Nick``. Changing this while Willie is running is
        untested."""
        self.user = config.user
        """Willie's user/ident."""
        self.name = config.name
        """Willie's "real name", as used for whois."""

        self.channels = []
        """The list of channels Willie is currently in."""

        self.stack = {}
        self.ca_certs = ca_certs
        self.hasquit = False

        self.sending = threading.RLock()
        self.writing_lock = threading.Lock()
        self.raw = None

        # Right now, only accounting for two op levels.
        # This might be expanded later.
        # These lists are filled in startup.py, as of right now.
        self.ops = dict()
        """
        A dictionary mapping channels to a ``Nick`` list of their operators.
        """
        self.halfplus = dict()
        """
        A dictionary mapping channels to a ``Nick`` list of their half-ops and
        ops.
        """
        self.voices = dict()
        """
        A dictionary mapping channels to a ``Nick`` list of their voices,
        half-ops and ops.
        """

        # We need this to prevent error loops in handle_error
        self.error_count = 0

        self.connection_registered = False
        """ Set to True when a server has accepted the client connection and
Ejemplo n.º 9
0
Archivo: irc.py Proyecto: kmaglione/cfc
    def __init__(self, config):
        ca_certs = '/etc/pki/tls/cert.pem'
        if config.ca_certs is not None:
            ca_certs = config.ca_certs
        elif not os.path.isfile(ca_certs):
            ca_certs = '/etc/ssl/certs/ca-certificates.crt'
        if not os.path.isfile(ca_certs):
            stderr('Could not open CA certificates file. SSL will not '
                   'work properly.')

        if config.log_raw is None:
            # Default is to log raw data, can be disabled in config
            config.log_raw = True
        asynchat.async_chat.__init__(self)
        self.set_terminator(b'\n')
        self.buffer = ''

        self.nick = Nick(config.nick)
        """Willie's current ``Nick``. Changing this while Willie is running is
        untested."""
        self.user = config.user
        """Willie's user/ident."""
        self.name = config.name
        """Willie's "real name", as used for whois."""

        self.channels = []
        """The list of channels Willie is currently in."""

        self.stack = {}
        self.ca_certs = ca_certs
        self.hasquit = False

        self.sending = threading.RLock()
        self.writing_lock = threading.Lock()
        self.raw = None

        # Right now, only accounting for two op levels.
        # This might be expanded later.
        # These lists are filled in startup.py, as of right now.
        self.ops = dict()
        """
        A dictionary mapping channels to a ``Nick`` list of their operators.
        """
        self.halfplus = dict()
        """
        A dictionary mapping channels to a ``Nick`` list of their half-ops and
        ops.
        """
        self.voices = dict()
        """
        A dictionary mapping channels to a ``Nick`` list of their voices,
        half-ops and ops.
        """

        # We need this to prevent error loops in handle_error
        self.error_count = 0

        self.connection_registered = False
        """ Set to True when a server has accepted the client connection and
Ejemplo n.º 10
0
 def _timeout_check(self):
     while self.connected or self.connecting:
         if (datetime.now() - self.last_ping_time).seconds > int(self.config.timeout):
             stderr('Ping timeout reached after %s seconds, closing connection' % self.config.timeout)
             self.handle_close()
             break
         else:
             time.sleep(int(self.config.timeout))
Ejemplo n.º 11
0
    def handle_close(self):
        self.connection_registered = False

        self._shutdown()
        stderr('Closed!')

        # This will eventually call asyncore dispatchers close method, which
        # will release the main thread. This should be called last to avoid
        # race conditions.
        self.close()
Ejemplo n.º 12
0
    def handle_close(self):
        self.connection_registered = False

        self._shutdown()
        stderr('Closed!')

        # This will eventually call asyncore dispatchers close method, which
        # will release the main thread. This should be called last to avoid
        # race conditions.
        self.close()
Ejemplo n.º 13
0
Archivo: irc.py Proyecto: icook/willie
 def _timeout_check(self):
     while True:
         if (datetime.now() - self.last_ping_time).seconds > int(
                 self.config.timeout):
             stderr('Ping timeout reached after %s seconds,' +
                    ' closing connection' % self.config.timeout)
             self.handle_close()
             break
         else:
             time.sleep(int(self.config.timeout))
Ejemplo n.º 14
0
def run(config):
    if config.core.delay is not None:
        delay = config.core.delay
    elif config.core.timeout is not None:
        delay = 2 * int(config.core.timeout)
    else:
        delay = 300
    # Inject ca_certs from config to web for SSL validation of web requests
    if hasattr(config, 'ca_certs') and config.ca_certs is not None:
        web.ca_certs = config.ca_certs
    else:
        web.ca_certs = '/etc/pki/tls/certs/ca-bundle.crt'

    def signal_handler(sig, frame):
        if sig == signal.SIGUSR1 or sig == signal.SIGTERM:
            stderr('Got quit signal, shutting down.')
            p.quit('Closing')

    while True:
        try:
            p = bot.Willie(config)
            if hasattr(signal, 'SIGUSR1'):
                signal.signal(signal.SIGUSR1, signal_handler)
            if hasattr(signal, 'SIGTERM'):
                signal.signal(signal.SIGTERM, signal_handler)
            p.run(config.core.host, int(config.core.port))
        except KeyboardInterrupt:
            break
        except Exception as e:
            trace = traceback.format_exc()
            try:
                stderr(trace)
            except:
                pass
            logfile = open(os.path.join(config.logdir, 'exceptions.log'), 'a')
            logfile.write('Critical exception in core')
            logfile.write(trace)
            logfile.write('----------------------------------------\n\n')
            logfile.close()
            os.unlink(config.pid_file_path)
            os._exit(1)

        if not isinstance(delay, int):
            break
        if p.hasquit or config.exit_on_error:
            break
        stderr('Warning: Disconnected. Reconnecting in %s seconds...' % delay)
        time.sleep(delay)
    os.unlink(config.pid_file_path)
    os._exit(0)
Ejemplo n.º 15
0
def run(config):
    if config.core.delay is not None:
        delay = config.core.delay
    elif config.core.timeout is not None:
        delay = 2 * int(config.core.timeout)
    else:
        delay = 300
    # Inject ca_certs from config to web for SSL validation of web requests
    if hasattr(config, 'ca_certs') and config.ca_certs is not None:
        web.ca_certs  = config.ca_certs
    else:
        web.ca_certs = '/etc/pki/tls/certs/ca-bundle.crt'

    def signal_handler(sig, frame):
        if sig == signal.SIGUSR1 or sig == signal.SIGTERM:
            stderr('Got quit signal, shutting down.')
            p.quit('Closing')
    while True:
        try:
            p = bot.Willie(config)
            if hasattr(signal, 'SIGUSR1'):
                signal.signal(signal.SIGUSR1, signal_handler)
            if hasattr(signal, 'SIGTERM'):
                signal.signal(signal.SIGTERM, signal_handler)
            p.run(config.core.host, int(config.core.port))
        except KeyboardInterrupt:
            break
        except Exception as e:
            trace = traceback.format_exc()
            try:
                stderr(trace)
            except:
                pass
            logfile = open(os.path.join(config.logdir, 'exceptions.log'), 'a')
            logfile.write('Critical exception in core')
            logfile.write(trace)
            logfile.write('----------------------------------------\n\n')
            logfile.close()
            os.unlink(config.pid_file_path)
            os._exit(1)

        if not isinstance(delay, int):
            break
        if p.hasquit or config.exit_on_error:
            break
        stderr('Warning: Disconnected. Reconnecting in %s seconds...' % delay)
        time.sleep(delay)
    os.unlink(config.pid_file_path)
    os._exit(0)
Ejemplo n.º 16
0
    def error(self, origin=None, trigger=None):
        """Called internally when a module causes an error."""
        try:
            trace = traceback.format_exc()
            if sys.version_info.major < 3:
                trace = trace.decode('utf-8', errors='xmlcharrefreplace')
            stderr(trace)
            try:
                lines = list(reversed(trace.splitlines()))
                report = [lines[0].strip()]
                for line in lines:
                    line = line.strip()
                    if line.startswith('File "'):
                        report.append(line[0].lower() + line[1:])
                        break
                else:
                    report.append('source unknown')

                signature = '%s (%s)' % (report[0], report[1])
                # TODO: make not hardcoded
                log_filename = os.path.join(self.config.logdir,
                                            'exceptions.log')
                with codecs.open(log_filename, 'a',
                                 encoding='utf-8') as logfile:
                    logfile.write('Signature: %s\n' % signature)
                    if origin:
                        logfile.write('from %s at %s:\n' %
                                      (origin.sender, str(datetime.now())))
                    if trigger:
                        logfile.write('Message was: <%s> %s\n' %
                                      (trigger.nick, trigger.group(0)))
                    logfile.write(trace)
                    logfile.write(
                        '----------------------------------------\n\n')
            except Exception as e:
                stderr("Could not save full traceback!")
                self.debug(
                    __file__, "(From: " + origin.sender +
                    "), can't save traceback: " + str(e), 'always')

            if origin:
                #self.msg(origin.sender, signature)
                # Don't send the file name
                self.msg(origin.sender, report[0])
        except Exception as e:
            if origin:
                self.msg(origin.sender, "Got an error.")
                self.debug(__file__, "(From: " + origin.sender + ") " + str(e),
                           'always')
Ejemplo n.º 17
0
Archivo: irc.py Proyecto: kqzi/willie
 def initiate_connect(self, host, port):
     stderr("Connecting to %s:%s..." % (host, port))
     source_address = (self.config.core.bind_host, 0) if self.config.core.bind_address else None
     self.set_socket(socket.create_connection((host, port), source_address=source_address))
     if self.config.core.use_ssl and has_ssl:
         self.send = self._ssl_send
         self.recv = self._ssl_recv
     elif not has_ssl and self.config.core.use_ssl:
         stderr("SSL is not avilable on your system, attempting connection " "without it")
     self.connect((host, port))
     try:
         asyncore.loop()
     except KeyboardInterrupt:
         print("KeyboardInterrupt")
         self.quit("KeyboardInterrupt")
Ejemplo n.º 18
0
Archivo: irc.py Proyecto: jcguy/ATM
    def error(self, trigger=None):
        """Called internally when a module causes an error."""
        try:
            trace = traceback.format_exc()
            if sys.version_info.major < 3:
                trace = trace.decode('utf-8', errors='xmlcharrefreplace')
            stderr(trace)
            try:
                lines = list(reversed(trace.splitlines()))
                report = [lines[0].strip()]
                for line in lines:
                    line = line.strip()
                    if line.startswith('File "'):
                        report.append(line[0].lower() + line[1:])
                        break
                else:
                    report.append('source unknown')

                signature = '%s (%s)' % (report[0], report[1])
                # TODO: make not hardcoded
                log_filename = os.path.join(self.config.logdir,
                                            'exceptions.log')
                with codecs.open(log_filename, 'a',
                                 encoding='utf-8') as logfile:
                    logfile.write('Signature: %s\n' % signature)
                    if trigger:
                        logfile.write(
                            'from {} at {}. Message was: {}\n'.format(
                                trigger.nick, str(datetime.now()),
                                trigger.group(0)))
                    logfile.write(trace)
                    logfile.write(
                        '----------------------------------------\n\n')
            except Exception as e:
                stderr("Could not save full traceback!")
                LOGGER.error("Could not save traceback from %s to file: %s",
                             trigger.sender, str(e))

            if trigger:
                #self.msg(trigger.sender, signature)
                self.msg(trigger.sender, "I\'m afraid I can\'t do that.")
                print(signature)
        except Exception as e:
            if trigger:
                self.msg(trigger.sender, "Got an error.")
                LOGGER.error("Exception from %s: %s", trigger.sender, str(e))
Ejemplo n.º 19
0
Archivo: irc.py Proyecto: dkg/willie
    def found_terminator(self):
        line = self.buffer
        if line.endswith('\r'):
            line = line[:-1]
        self.buffer = ''
        pretrigger = PreTrigger(self.nick, line)

        if pretrigger.args[0] == 'PING':
            self.write(('PONG', pretrigger.args[-1]))
        elif pretrigger.args[0] == 'ERROR':
            self.debug(__file__, pretrigger.args[-1], 'always')
            if self.hasquit:
                self.close_when_done()
        elif pretrigger.args[0] == '433':
            stderr('Nickname already in use!')
            self.handle_close()

        self.dispatch(pretrigger)
Ejemplo n.º 20
0
    def found_terminator(self):
        line = self.buffer
        if line.endswith('\r'):
            line = line[:-1]
        self.buffer = ''
        pretrigger = PreTrigger(self.nick, line)

        if pretrigger.args[0] == 'PING':
            self.write(('PONG', pretrigger.args[-1]))
        elif pretrigger.args[0] == 'ERROR':
            self.debug(__file__, pretrigger.args[-1], 'always')
            if self.hasquit:
                self.close_when_done()
        elif pretrigger.args[0] == '433':
            stderr('Nickname already in use!')
            self.handle_close()

        self.dispatch(pretrigger)
Ejemplo n.º 21
0
Archivo: irc.py Proyecto: kqzi/willie
    def found_terminator(self):
        line = self.buffer
        if line.endswith("\r"):
            line = line[:-1]
        self.buffer = ""
        self.raw = line

        # Break off IRCv3 message tags, if present
        tags = {}
        if line.startswith("@"):
            tagstring, line = line.split(" ", 1)
            for tag in tagstring[1:].split(";"):
                tag = tag.split("=", 1)
                if len(tag) > 1:
                    tags[tag[0]] = tag[1]
                else:
                    tags[tag[0]] = None

        if line.startswith(":"):
            source, line = line[1:].split(" ", 1)
        else:
            source = None

        if " :" in line:
            argstr, text = line.split(" :", 1)
            args = argstr.split(" ")
            args.append(text)
        else:
            args = line.split(" ")
            text = args[-1]

        self.last_ping_time = datetime.now()
        if args[0] == "PING":
            self.write(("PONG", text))
        elif args[0] == "ERROR":
            self.debug(__file__, text, "always")
            if self.hasquit:
                self.close_when_done()
        elif args[0] == "433":
            stderr("Nickname already in use!")
            self.handle_close()

        origin = Origin(self, source, args, tags)
        self.dispatch(origin, text, args)
Ejemplo n.º 22
0
    def found_terminator(self):
        line = self.buffer
        if line.endswith('\r'):
            line = line[:-1]
        self.buffer = ''
        self.raw = line

        # Break off IRCv3 message tags, if present
        tags = {}
        if line.startswith('@'):
            tagstring, line = line.split(' ', 1)
            for tag in tagstring[1:].split(';'):
                tag = tag.split('=', 1)
                if len(tag) > 1:
                    tags[tag[0]] = tag[1]
                else:
                    tags[tag[0]] = None

        if line.startswith(':'):
            source, line = line[1:].split(' ', 1)
        else:
            source = None

        if ' :' in line:
            argstr, text = line.split(' :', 1)
            args = argstr.split(' ')
            args.append(text)
        else:
            args = line.split(' ')
            text = args[-1]

        self.last_ping_time = datetime.now()
        if args[0] == 'PING':
            self.write(('PONG', text))
        elif args[0] == 'ERROR':
            self.debug(__file__, text, 'always')
            if self.hasquit:
                self.close_when_done()
        elif args[0] == '433':
            stderr('Nickname already in use!')
            self.handle_close()

        origin = Origin(self, source, args, tags)
        self.dispatch(origin, text, args)
Ejemplo n.º 23
0
    def found_terminator(self):
        line = self.buffer
        if line.endswith('\r'):
            line = line[:-1]
        self.buffer = ''
        self.raw = line

        # Break off IRCv3 message tags, if present
        tags = {}
        if line.startswith('@'):
            tagstring, line = line.split(' ', 1)
            for tag in tagstring[1:].split(';'):
                tag = tag.split('=', 1)
                if len(tag) > 1:
                    tags[tag[0]] = tag[1]
                else:
                    tags[tag[0]] = None

        if line.startswith(':'):
            source, line = line[1:].split(' ', 1)
        else:
            source = None

        if ' :' in line:
            argstr, text = line.split(' :', 1)
            args = argstr.split(' ')
            args.append(text)
        else:
            args = line.split(' ')
            text = args[-1]

        self.last_ping_time = datetime.now()
        if args[0] == 'PING':
            self.write(('PONG', text))
        elif args[0] == 'ERROR':
            self.debug(__file__, text, 'always')
            if self.hasquit:
                self.close_when_done()
        elif args[0] == '433':
            stderr('Nickname already in use!')
            self.handle_close()

        origin = Origin(self, source, args, tags)
        self.dispatch(origin, text, args)
Ejemplo n.º 24
0
Archivo: irc.py Proyecto: Cadair/willie
    def found_terminator(self):
        line = self.buffer
        if line.endswith('\r'):
            line = line[:-1]
        self.buffer = ''
        self.last_ping_time = datetime.now()
        pretrigger = PreTrigger(self.nick, line)

        if pretrigger.event == 'PING':
            self.write(('PONG', pretrigger.args[-1]))
        elif pretrigger.event == 'ERROR':
            LOGGER.error("ERROR recieved from server: %s", pretrigger.args[-1])
            if self.hasquit:
                self.close_when_done()
        elif pretrigger.event == '433':
            stderr('Nickname already in use!')
            self.handle_close()

        self.dispatch(pretrigger)
Ejemplo n.º 25
0
 def initiate_connect(self, host, port):
     stderr('Connecting to %s:%s...' % (host, port))
     source_address = ((self.config.core.bind_host,
                        0) if self.config.core.bind_host else None)
     self.set_socket(
         socket.create_connection((host, port),
                                  source_address=source_address))
     if self.config.core.use_ssl and has_ssl:
         self.send = self._ssl_send
         self.recv = self._ssl_recv
     elif not has_ssl and self.config.core.use_ssl:
         stderr('SSL is not avilable on your system, attempting connection '
                'without it')
     self.connect((host, port))
     try:
         asyncore.loop()
     except KeyboardInterrupt:
         print('KeyboardInterrupt')
         self.quit('KeyboardInterrupt')
Ejemplo n.º 26
0
    def found_terminator(self):
        line = self.buffer
        if line.endswith('\r'):
            line = line[:-1]
        self.buffer = ''
        self.last_ping_time = datetime.now()
        pretrigger = PreTrigger(self.nick, line)

        if pretrigger.event == 'PING':
            self.write(('PONG', pretrigger.args[-1]))
        elif pretrigger.event == 'ERROR':
            LOGGER.error("ERROR recieved from server: %s", pretrigger.args[-1])
            if self.hasquit:
                self.close_when_done()
        elif pretrigger.event == '433':
            stderr('Nickname already in use!')
            self.handle_close()

        self.dispatch(pretrigger)
Ejemplo n.º 27
0
Archivo: irc.py Proyecto: Oracizan/ATM
    def error(self, trigger=None):
        """Called internally when a module causes an error."""
        try:
            trace = traceback.format_exc()
            if sys.version_info.major < 3:
                trace = trace.decode('utf-8', errors='xmlcharrefreplace')
            stderr(trace)
            try:
                lines = list(reversed(trace.splitlines()))
                report = [lines[0].strip()]
                for line in lines:
                    line = line.strip()
                    if line.startswith('File "'):
                        report.append(line[0].lower() + line[1:])
                        break
                else:
                    report.append('source unknown')

                signature = '%s (%s)' % (report[0], report[1])
                # TODO: make not hardcoded
                log_filename = os.path.join(self.config.logdir, 'exceptions.log')
                with codecs.open(log_filename, 'a', encoding='utf-8') as logfile:
                    logfile.write('Signature: %s\n' % signature)
                    if trigger:
                        logfile.write('from {} at {}. Message was: {}\n'.format(
                            trigger.nick, str(datetime.now()), trigger.group(0)))
                    logfile.write(trace)
                    logfile.write(
                        '----------------------------------------\n\n'
                    )
            except Exception as e:
                stderr("Could not save full traceback!")
                LOGGER.error("Could not save traceback from %s to file: %s", trigger.sender, str(e))

            if trigger:
                #self.msg(trigger.sender, signature)
				self.msg(trigger.sender, "I\'m afraid I can\'t do that.")
				print(signature)
        except Exception as e:
            if trigger:
                self.msg(trigger.sender, "Got an error.")
                LOGGER.error("Exception from %s: %s", trigger.sender, str(e))
Ejemplo n.º 28
0
    def _shutdown(self):
        stderr(
            'Calling shutdown for %d modules.' % (len(self.shutdown_methods),)
        )

        for moduleName in self.config.enumerate_modules():
            module = sys.modules[moduleName]
            if hasattr(module, "shutdown"):
                module.shutdown(self)

        hostmask = "%s!%s@%s" % (self.nick, self.user, socket.gethostname())
        willie = self.WillieWrapper(self, irc.Origin(self, hostmask, [], {}))
        for shutdown_method in self.shutdown_methods:
            try:
                stderr(
                    "calling %s.%s" % (
                        shutdown_method.__module__, shutdown_method.__name__,
                    )
                )
                shutdown_method(willie)
            except Exception as e:
                stderr(
                    "Error calling shutdown method for module %s:%s" % (
                        shutdown_method.__module__, e
                    )
                )
Ejemplo n.º 29
0
    def handle_connect(self):
        if self.config.core.use_ssl and has_ssl:
            if not self.config.core.verify_ssl:
                self.ssl = ssl.wrap_socket(self.socket,
                                           do_handshake_on_connect=True,
                                           suppress_ragged_eofs=True)
            else:
                self.ssl = ssl.wrap_socket(self.socket,
                                           do_handshake_on_connect=True,
                                           suppress_ragged_eofs=True,
                                           cert_reqs=ssl.CERT_REQUIRED,
                                           ca_certs=self.ca_certs)
                try:
                    ssl.match_hostname(self.ssl.getpeercert(),
                                       self.config.host)
                except ssl.CertificateError:
                    stderr("Invalid certficate, hostname mismatch!")
                    os.unlink(self.config.pid_file_path)
                    os._exit(1)
            self.set_socket(self.ssl)

        # Request list of server capabilities. IRCv3 servers will respond with
        # CAP * LS (which we handle in coretasks). v2 servers will respond with
        # 421 Unknown command, which we'll ignore
        self.write(('CAP', 'LS'))

        if self.config.core.auth_method == 'server' or self.config.core.server_password:
            password = self.config.core.auth_password or self.config.core.server_password
            self.write(('PASS', password))
        self.write(('NICK', self.nick))
        self.write(('USER', self.user, '+iw', self.nick), self.name)

        stderr('Connected.')
        self.last_ping_time = datetime.now()
        timeout_check_thread = threading.Thread(target=self._timeout_check)
        timeout_check_thread.start()
        ping_thread = threading.Thread(target=self._send_ping)
        ping_thread.start()
Ejemplo n.º 30
0
Archivo: irc.py Proyecto: Khabi/willie
    def handle_connect(self):
        if self.config.core.use_ssl and has_ssl:
            if not self.config.core.verify_ssl:
                self.ssl = ssl.wrap_socket(self.socket,
                                           do_handshake_on_connect=True,
                                           suppress_ragged_eofs=True)
            else:
                self.ssl = ssl.wrap_socket(self.socket,
                                           do_handshake_on_connect=True,
                                           suppress_ragged_eofs=True,
                                           cert_reqs=ssl.CERT_REQUIRED,
                                           ca_certs=self.ca_certs)
                try:
                    ssl.match_hostname(self.ssl.getpeercert(), self.config.host)
                except ssl.CertificateError:
                    stderr("Invalid certficate, hostname mismatch!")
                    os.unlink(self.config.pid_file_path)
                    os._exit(1)
            self.set_socket(self.ssl)

        if self.config.core.server_password is not None:
            self.write(('PASS', self.config.core.server_password))
        self.write(('NICK', self.nick))
        self.write(('USER', self.user, '+iw', self.nick), self.name)

        stderr('Connected.')
        self.last_ping_time = datetime.now()
        timeout_check_thread = threading.Thread(target=self._timeout_check)
        timeout_check_thread.start()
        ping_thread = threading.Thread(target=self._send_ping)
        ping_thread.start()

        # Request list of server capabilities. IRCv3 servers will respond with
        # CAP * LS (which we handle in coretasks). v2 servers will respond with
        # 421 Unknown command, which we'll ignore
        # This needs to come after Authentication as it can cause connection
        # Issues
        self.write(('CAP', 'LS'))
Ejemplo n.º 31
0
    def _shutdown(self):
        stderr("Calling shutdown for %d modules." % (len(self.shutdown_methods),))

        for shutdown_method in self.shutdown_methods:
            try:
                stderr("calling %s.%s" % (shutdown_method.__module__, shutdown_method.__name__))
                shutdown_method(self)
            except Exception as e:
                stderr("Error calling shutdown method for module %s:%s" % (shutdown_method.__module__, e))
Ejemplo n.º 32
0
def run(config):
    import willie.bot as bot
    import willie.web as web
    from willie.tools import stderr

    if config.core.delay is not None:
        delay = config.core.delay
    else:
        delay = 20
    # Inject ca_certs from config to web for SSL validation of web requests
    web.ca_certs = "/etc/pki/tls/certs/ca-bundle.crt"
    if hasattr(config, "ca_certs") and config.ca_certs is not None:
        web.ca_certs = config.ca_certs
    elif not os.path.isfile(web.ca_certs):
        web.ca_certs = "/etc/ssl/certs/ca-certificates.crt"
    if not os.path.isfile(web.ca_certs):
        stderr("Could not open CA certificates file. SSL will not " "work properly.")

    def signal_handler(sig, frame):
        if sig == signal.SIGUSR1 or sig == signal.SIGTERM:
            stderr("Got quit signal, shutting down.")
            p.quit("Closing")

    while True:
        try:
            p = bot.Willie(config)
            if hasattr(signal, "SIGUSR1"):
                signal.signal(signal.SIGUSR1, signal_handler)
            if hasattr(signal, "SIGTERM"):
                signal.signal(signal.SIGTERM, signal_handler)
            p.run(config.core.host, int(config.core.port))
        except KeyboardInterrupt:
            break
        except Exception as e:
            trace = traceback.format_exc()
            try:
                stderr(trace)
            except:
                pass
            logfile = open(os.path.join(config.logdir, "exceptions.log"), "a")
            logfile.write("Critical exception in core")
            logfile.write(trace)
            logfile.write("----------------------------------------\n\n")
            logfile.close()
            os.unlink(config.pid_file_path)
            os._exit(1)

        if not isinstance(delay, int):
            break
        if p.hasquit or config.exit_on_error:
            break
        stderr("Warning: Disconnected. Reconnecting in %s seconds..." % delay)
        time.sleep(delay)
    os.unlink(config.pid_file_path)
    os._exit(0)
Ejemplo n.º 33
0
def run(config, pid_file, daemon=False):
    import willie.bot as bot
    import willie.web as web
    import willie.logger
    from willie.tools import stderr
    delay = 20
    # Inject ca_certs from config to web for SSL validation of web requests
    if not config.core.ca_certs:
        stderr('Could not open CA certificates file. SSL will not '
               'work properly.')
    web.ca_certs = config.core.ca_certs

    def signal_handler(sig, frame):
        if sig == signal.SIGUSR1 or sig == signal.SIGTERM:
            stderr('Got quit signal, shutting down.')
            p.quit('Closing')

    while True:
        try:
            p = bot.Willie(config, daemon=daemon)
            if hasattr(signal, 'SIGUSR1'):
                signal.signal(signal.SIGUSR1, signal_handler)
            if hasattr(signal, 'SIGTERM'):
                signal.signal(signal.SIGTERM, signal_handler)
            willie.logger.setup_logging(p)
            p.run(config.core.host, int(config.core.port))
        except KeyboardInterrupt:
            break
        except Exception:
            trace = traceback.format_exc()
            try:
                stderr(trace)
            except:
                pass
            logfile = open(os.path.join(config.core.logdir, 'exceptions.log'),
                           'a')
            logfile.write('Critical exception in core')
            logfile.write(trace)
            logfile.write('----------------------------------------\n\n')
            logfile.close()
            os.unlink(pid_file)
            os._exit(1)

        if not isinstance(delay, int):
            break
        if p.hasquit:
            break
        stderr('Warning: Disconnected. Reconnecting in %s seconds...' % delay)
        time.sleep(delay)
    os.unlink(pid_file)
    os._exit(0)
Ejemplo n.º 34
0
    def _shutdown(self):
        stderr('Calling shutdown for %d modules.' %
               (len(self.shutdown_methods), ))

        for shutdown_method in self.shutdown_methods:
            try:
                stderr("calling %s.%s" % (
                    shutdown_method.__module__,
                    shutdown_method.__name__,
                ))
                shutdown_method(self)
            except Exception as e:
                stderr("Error calling shutdown method for module %s:%s" %
                       (shutdown_method.__module__, e))
Ejemplo n.º 35
0
    def _shutdown(self):
        stderr('Calling shutdown for %d modules.' %
               (len(self.shutdown_methods), ))

        hostmask = "%s!%s@%s" % (self.nick, self.user, socket.gethostname())
        willie = self.WillieWrapper(self, irc.Origin(self, hostmask, [], {}))
        for shutdown_method in self.shutdown_methods:
            try:
                stderr("calling %s.%s" % (
                    shutdown_method.__module__,
                    shutdown_method.__name__,
                ))
                shutdown_method(willie)
            except Exception as e:
                stderr("Error calling shutdown method for module %s:%s" %
                       (shutdown_method.__module__, e))
Ejemplo n.º 36
0
Archivo: irc.py Proyecto: ToTV/willie
    def log_raw(self, line, prefix):
        """Log raw line to the raw log."""
        if not self.config.core.log_raw:
            return
        if not os.path.isdir(self.config.core.logdir):
            try:
                os.mkdir(self.config.core.logdir)
            except Exception as e:
                stderr('There was a problem creating the logs directory.')
                stderr('%s %s' % (str(e.__class__), str(e)))
                stderr('Please fix this and then run Willie again.')
                os._exit(1)
        f = codecs.open(os.path.join(self.config.core.logdir, 'raw.log'),
                        'a', encoding='utf-8')
        f.write(prefix + unicode(time.time()) + "\t")
        temp = line.replace('\n', '')

        f.write(temp)
        f.write("\n")
        f.close()
Ejemplo n.º 37
0
    def _shutdown(self):
        stderr(
            'Calling shutdown for %d modules.' % (len(self.shutdown_methods),)
        )

        hostmask = "%s!%s@%s" % (self.nick, self.user, socket.gethostname())
        willie = self.WillieWrapper(self, irc.Origin(self, hostmask, [], {}))
        for shutdown_method in self.shutdown_methods:
            try:
                stderr(
                    "calling %s.%s" % (
                        shutdown_method.__module__, shutdown_method.__name__,
                    )
                )
                shutdown_method(willie)
            except Exception as e:
                stderr(
                    "Error calling shutdown method for module %s:%s" % (
                        shutdown_method.__module__, e
                    )
                )
Ejemplo n.º 38
0
    def log_raw(self, line, prefix):
        """Log raw line to the raw log."""
        if not self.config.core.log_raw:
            return
        if not os.path.isdir(self.config.core.logdir):
            try:
                os.mkdir(self.config.core.logdir)
            except Exception as e:
                stderr('There was a problem creating the logs directory.')
                stderr('%s %s' % (str(e.__class__), str(e)))
                stderr('Please fix this and then run Willie again.')
                os._exit(1)
        f = codecs.open(os.path.join(self.config.core.logdir, 'raw.log'),
                        'a',
                        encoding='utf-8')
        f.write(prefix + unicode(time.time()) + "\t")
        temp = line.replace('\n', '')

        f.write(temp)
        f.write("\n")
        f.close()
Ejemplo n.º 39
0
    def _shutdown(self):
        stderr('Calling shutdown for %d modules.' %
               (len(self.shutdown_methods), ))

        for moduleName in self.config.enumerate_modules():
            module = sys.modules[moduleName]
            if hasattr(module, "shutdown"):
                module.shutdown(self)

        hostmask = "%s!%s@%s" % (self.nick, self.user, socket.gethostname())
        willie = self.WillieWrapper(self, irc.Origin(self, hostmask, [], {}))
        for shutdown_method in self.shutdown_methods:
            try:
                stderr("calling %s.%s" % (
                    shutdown_method.__module__,
                    shutdown_method.__name__,
                ))
                shutdown_method(willie)
            except Exception as e:
                stderr("Error calling shutdown method for module %s:%s" %
                       (shutdown_method.__module__, e))
Ejemplo n.º 40
0
Archivo: irc.py Proyecto: kqzi/willie
    def log_raw(self, line, prefix):
        """Log raw line to the raw log."""
        if not self.config.core.log_raw:
            return
        if not self.config.core.logdir:
            self.config.core.logdir = os.path.join(self.config.dotdir, "logs")
        if not os.path.isdir(self.config.core.logdir):
            try:
                os.mkdir(self.config.core.logdir)
            except Exception as e:
                stderr("There was a problem creating the logs directory.")
                stderr("%s %s" % (str(e.__class__), str(e)))
                stderr("Please fix this and then run Willie again.")
                os._exit(1)
        f = codecs.open(os.path.join(self.config.core.logdir, "raw.log"), "a", encoding="utf-8")
        f.write(prefix + unicode(time.time()) + "\t")
        temp = line.replace("\n", "")

        f.write(temp)
        f.write("\n")
        f.close()
Ejemplo n.º 41
0
    def setup(self):
        stderr("\nWelcome to Willie. Loading modules...\n\n")

        modules = willie.loader.enumerate_modules(self.config)

        error_count = 0
        success_count = 0
        for name in modules:
            path, type_ = modules[name]

            try:
                module, _ = willie.loader.load_module(name, path, type_)
            except Exception as e:
                error_count = error_count + 1
                filename, lineno = tools.get_raising_file_and_line()
                rel_path = os.path.relpath(filename, os.path.dirname(__file__))
                raising_stmt = "%s:%d" % (rel_path, lineno)
                stderr("Error loading %s: %s (%s)" % (name, e, raising_stmt))
            else:
                try:
                    if hasattr(module, 'setup'):
                        module.setup(self)
                    relevant_parts = willie.loader.clean_module(
                        module, self.config)
                except Exception as e:
                    error_count = error_count + 1
                    filename, lineno = tools.get_raising_file_and_line()
                    rel_path = os.path.relpath(filename,
                                               os.path.dirname(__file__))
                    raising_stmt = "%s:%d" % (rel_path, lineno)
                    stderr("Error in %s setup procedure: %s (%s)" %
                           (name, e, raising_stmt))
                else:
                    self.register(*relevant_parts)
                    success_count += 1

        if len(modules) > 2:  # coretasks is counted
            stderr('\n\nRegistered %d modules,' % (success_count - 1))
            stderr('%d modules failed to load\n\n' % error_count)
        else:
            stderr("Warning: Couldn't load any modules")
Ejemplo n.º 42
0
 def run(self, host, port=6667):
     try:
         self.initiate_connect(host, port)
     except socket.error as e:
         stderr('Connection error: %s' % e)
         self.hasquit = True
Ejemplo n.º 43
0
 def signal_handler(sig, frame):
     if sig == signal.SIGUSR1 or sig == signal.SIGTERM:
         stderr('Got quit signal, shutting down.')
         p.quit('Closing')
Ejemplo n.º 44
0
"""
Willie - An IRC Bot
Copyright 2008, Sean B. Palmer, inamidst.com
Copyright © 2012-2014, Elad Alfassa <*****@*****.**>
Licensed under the Eiffel Forum License 2.

http://willie.dftba.net
"""
from __future__ import unicode_literals
from __future__ import print_function

import sys
from willie.tools import stderr

if sys.version_info < (2, 7):
    stderr('Error: Requires Python 2.7 or later. Try python2.7 willie')
    sys.exit(1)
if sys.version_info.major == 3 and sys.version_info.minor < 3:
    stderr('Error: When running on Python 3, Python 3.3 is required.')
    sys.exit(1)

import os
import argparse
import signal

from willie.__init__ import run
from willie.config import Config, create_config, ConfigurationError, wizard
import willie.tools as tools
import willie.web

homedir = os.path.join(os.path.expanduser('~'), '.willie')
Ejemplo n.º 45
0
def main(argv=None):
    global homedir
    # Step One: Parse The Command Line
    try:
        parser = optparse.OptionParser('%prog [options]')
        parser.add_option('-c', '--config', metavar='filename',
            help='use a specific configuration file')
        parser.add_option("-d", '--fork', action="store_true",
            dest="deamonize", help="Deamonize willie")
        parser.add_option("-q", '--quit', action="store_true", dest="quit",
            help="Gracefully quit Willie")
        parser.add_option("-k", '--kill', action="store_true", dest="kill",
            help="Kill Willie")
        parser.add_option('--exit-on-error', action="store_true", dest="exit_on_error",
            help="Exit immediately on every error instead of trying to recover")
        parser.add_option("-l", '--list', action="store_true",
            dest="list_configs", help="List all config files found")
        parser.add_option("-m", '--migrate', action="store_true",
            dest="migrate_configs",
            help="Migrate config files to the new format")
        parser.add_option('--quiet', action="store_true", dest="quiet",
            help="Supress all output")
        parser.add_option('-w', '--configure-all', action='store_true',
            dest='wizard', help='Run the configuration wizard.')
        parser.add_option('--configure-modules', action='store_true',
            dest='mod_wizard', help='Run the configuration wizard, but only for the module configuration options.')
        parser.add_option('--configure-database', action='store_true',
            dest='db_wizard', help='Run the configuration wizard, but only for the database configuration options.')
        opts, args = parser.parse_args(argv)

        if opts.wizard:
            wizard('all', opts.config)
            return
        elif opts.mod_wizard:
            wizard('mod', opts.config)
            return
        elif opts.db_wizard:
            wizard('db', opts.config)
            return

        check_python_version()
        if opts.list_configs is not None:
            configs = enumerate_configs()
            print 'Config files in ~/.willie:'
            if len(configs[0]) is 0:
                print '\tNone found'
            else:
                for config in configs:
                    print '\t%s' % config
            print '-------------------------'
            return

        config_name = opts.config or 'default'

        configpath = find_config(config_name)
        if not os.path.isfile(configpath):
            print "Welcome to Willie!\nI can't seem to find the configuration file, so let's generate it!\n"
            if not configpath.endswith('.cfg'):
                configpath = configpath + '.cfg'
            create_config(configpath)
            configpath = find_config(config_name)
        try:
            config_module = Config(configpath)
        except ConfigurationError as e:
            stderr(e)
            sys.exit(2)

        if config_module.core.not_configured:
            stderr('Bot is not configured, can\'t start')
            # exit with code 2 to prevent auto restart on fail by systemd
            sys.exit(2)

        if not config_module.has_option('core', 'homedir'):
            config_module.dotdir = homedir
            config_module.homedir = homedir
        else:
            homedir = config_module.core.homedir
            config_module.dotdir = config_module.core.homedir

        if not config_module.core.logdir:
            config_module.core.logdir = os.path.join(homedir, 'logs')
        logfile = os.path.os.path.join(config_module.logdir, 'stdio.log')
        if not os.path.isdir(config_module.logdir):
            os.mkdir(config_module.logdir)

        if opts.exit_on_error:
            config_module.exit_on_error = True
        else:
            config_module.exit_on_error = False

        if opts.quiet is None:
            opts.quiet = False

        sys.stderr = tools.OutputRedirect(logfile, True, opts.quiet)
        sys.stdout = tools.OutputRedirect(logfile, False, opts.quiet)

        #Handle --quit, --kill and saving the PID to file
        pid_dir = config_module.core.pid_dir or homedir
        if opts.config is None:
            pid_file_path = os.path.join(pid_dir, 'willie.pid')
        else:
            basename = os.path.basename(opts.config)
            if basename.endswith('.cfg'):
                basename = basename[:-4]
            pid_file_path = os.path.join(pid_dir, 'willie-%s.pid' % basename)
        if os.path.isfile(pid_file_path):
            pid_file = open(pid_file_path, 'r')
            old_pid = int(pid_file.read())
            pid_file.close()
            if tools.check_pid(old_pid):
                if opts.quit is None and opts.kill is None:
                    stderr('There\'s already a Willie instance running with this config file')
                    stderr('Try using the --quit or the --kill options')
                    sys.exit(1)
                elif opts.kill:
                    stderr('Killing the willie')
                    os.kill(old_pid, signal.SIGKILL)
                    sys.exit(0)
                elif opts.quit:
                    stderr('Signaling Willie to stop gracefully')
                    if hasattr(signal, 'SIGUSR1'):
                        os.kill(old_pid, signal.SIGUSR1)
                    else:
                        os.kill(old_pid, signal.SIGTERM)
                    sys.exit(0)
            elif not tools.check_pid(old_pid) and (opts.kill or opts.quit):
                stderr('Willie is not running!')
                sys.exit(1)
        elif opts.quit is not None or opts.kill is not None:
            stderr('Willie is not running!')
            sys.exit(1)
        if opts.deamonize is not None:
            child_pid = os.fork()
            if child_pid is not 0:
                sys.exit()
        pid_file = open(pid_file_path, 'w')
        pid_file.write(str(os.getpid()))
        pid_file.close()
        config_module.pid_file_path = pid_file_path

        # Step Five: Initialise And Run willie
        run(config_module)
    except KeyboardInterrupt:
        print "\n\nInterrupted"
        os._exit(1)
Ejemplo n.º 46
0
def check_python_version():
    if sys.version_info < (2, 7):
        stderr('Error: Requires Python 2.7 or later. Try python2.7 willie')
        sys.exit(1)
Ejemplo n.º 47
0
def main(argv=None):
    # Step One: Parse The Command Line
    try:
        parser = optparse.OptionParser('%prog [options]')
        parser.add_option('-c', '--config', metavar='filename', help='use a specific configuration file')
        parser.add_option("-d", '--fork', action="store_true", dest="deamonize", help="Deamonize willie")
        parser.add_option("-q", '--quit', action="store_true", dest="quit", help="Gracefully quit Willie")
        parser.add_option("-k", '--kill', action="store_true", dest="kill", help="Kill Willie")
        parser.add_option("-l", '--list', action="store_true", dest="list_configs", help="List all config files found")
        parser.add_option("-m", '--migrate', action="store_true", dest="migrate_configs", help="Migrate config files to the new format")
        parser.add_option('--quiet', action="store_true", dest="quiet", help="Supress all output")
        parser.add_option('-w', '--configure-all', action='store_true', dest='wizard', help='Run the configuration wizard.')
        parser.add_option('--configure-modules', action='store_true', dest='mod_wizard', help='Run the configuration wizard, but only for the module configuration options.')
        parser.add_option('--configure-database', action='store_true', dest='db_wizard', help='Run the configuration wizard, but only for the database configuration options.')
        opts, args = parser.parse_args(argv)

        if opts.wizard:
            wizard('all', opts.config)
            return
        elif opts.mod_wizard:
            wizard('mod', opts.config)
            return
        elif opts.db_wizard:
            wizard('db', opts.config)
            return
                    
        check_python_version()
        if opts.list_configs is not None:
            configs = enumerate_configs()
            stdout('Config files in ~/.willie:')
            if len(configs[0]) is 0:
                stdout('\tNone found')
            else:
                for config in configs[0]:
                    stdout('\t%s' % config)
            stdout('-------------------------')
            stdout('Config files in ~/.jenni:')
            if len(configs[1]) is 0:
                stdout('\tNone found')
            else:
                for config in configs[1]:
                    stdout('\t%s' % config)
            stdout('-------------------------')
            stdout('Config files in ~/.phenny:')
            if len(configs[2]) is 0:
                stdout('\tNone found')
            else:
                for config in configs[2]:
                    stdout('\t%s' % config)
            stdout('-------------------------')
            return

        config_name = opts.config or 'default'
        
        if opts.migrate_configs is not None:
            configpath = find_config(config_name, '.py')
            new_configpath = configpath[:-2]+'cfg'
            if os.path.isfile(new_configpath):
                valid_answer = False
                while not valid_answer:
                    answer = raw_input('Warning, new config file already exists. Overwrite? [y/n]')
                    if answer is 'n' or answer == 'no':
                        return
                    elif answer == 'y' or answer == 'yes':
                        valid_answer = True
            old_cfg = imp.load_source('Config', configpath)
            new_cfg = Config(new_configpath, load=False)
            new_cfg.add_section('core')
            for attrib in dir(old_cfg):
                if not attrib.startswith('_'):
                    value = getattr(old_cfg, attrib)
                    if value is None:
                        continue #Skip NoneTypes
                    if type(value) is list: #Parse lists
                        parsed_value = ','.join(value)
                    else:
                        parsed_value = str(value)
                    if attrib == 'password':
                        attrib = 'nickserv_password'
                    if attrib == 'serverpass':
                        attrib = 'server_password'
                    setattr(new_cfg.core, attrib, parsed_value)
            new_cfg.save()
            print 'Configuration migrated sucessfully, starting Willie'
            
        
        configpath = find_config(config_name)
        if not os.path.isfile(configpath):
            stdout("Welcome to Willie!\nI can't seem to find the configuration file, so let's generate it!\n")
            if not configpath.endswith('.cfg'):
                configpath = configpath + '.cfg'
            create_config(configpath)
            configpath = find_config(config_name)
        try:
            config_module = Config(configpath)
        except ConfigurationError as e:
            stderr(e)
            sys.exit(1)
        config_module.dotdir = dotdir

        if not config_module.core.logdir:
            config_module.core.logdir = os.path.join(dotdir, 'logs')
        logfile = os.path.os.path.join(config_module.logdir, 'stdio.log')
        if not os.path.isdir(config_module.logdir):
            os.mkdir(config_module.logdir)
        if opts.quiet is None:
            opts.quiet = False

        sys.stderr = tools.OutputRedirect(logfile, True, opts.quiet)
        sys.stdout = tools.OutputRedirect(logfile, False, opts.quiet)

        #Handle --quit, --kill and saving the PID to file
        if opts.config is None:
            pid_file_path = os.path.join(dotdir, '.pid-default')
        else:
            pid_file_path = os.path.join(dotdir, '.pid-%s' % opts.config)
        if os.path.isfile(pid_file_path):
            pid_file = open(pid_file_path, 'r')
            old_pid = int(pid_file.read())
            pid_file.close()
            if tools.check_pid(old_pid):
                if opts.quit is None and opts.kill is None:
                    stderr('There\'s already a Willie instance running with this config file')
                    stderr('Try using the --quit or the --kill options')
                    sys.exit(1)
                elif opts.kill:
                    stderr('Killing the willie')
                    os.kill(old_pid, signal.SIGKILL)
                    sys.exit(0)
                elif opts.quit:
                    stderr('Singaling Willie to stop gracefully')
                    os.kill(old_pid, signal.SIGUSR1)
                    sys.exit(0)
            elif not tools.check_pid(old_pid) and (opts.kill or opts.quit):
                stderr('Willie is not running!')
                sys.exit(1)
        elif opts.quit is not None or opts.kill is not None:
            stderr('Willie is not running!')
            sys.exit(1)
        if opts.deamonize is not None:
            child_pid = os.fork()
            if child_pid is not 0:
                sys.exit()
        pid_file = open(pid_file_path, 'w')
        pid_file.write(str(os.getpid()))
        pid_file.close()
        config_module.pid_file_path = pid_file_path

        # Step Five: Initialise And Run willie
        run(config_module)
    except KeyboardInterrupt:
        stdout("\n\nInterrupted")
        os._exit(1)
Ejemplo n.º 48
0
def check_python_version():
    if sys.version_info < (2, 7):
        stderr(u'Error: You need at least Python 2.7!')
        sys.exit(1)
Ejemplo n.º 49
0
    def setup(self):
        stderr("\nWelcome to Willie. Loading modules...\n\n")
        self.callables = set()
        self.shutdown_methods = set()

        filenames = self.config.enumerate_modules()
        # Coretasks is special. No custom user coretasks.
        this_dir = os.path.dirname(os.path.abspath(__file__))
        filenames['coretasks'] = os.path.join(this_dir, 'coretasks.py')

        modules = []
        error_count = 0
        for name, filename in iteritems(filenames):
            try:
                module = imp.load_source(name, filename)
            except Exception as e:
                error_count = error_count + 1
                filename, lineno = tools.get_raising_file_and_line()
                rel_path = os.path.relpath(filename, os.path.dirname(__file__))
                raising_stmt = "%s:%d" % (rel_path, lineno)
                stderr("Error loading %s: %s (%s)" % (name, e, raising_stmt))
            else:
                try:
                    if hasattr(module, 'setup'):
                        module.setup(self)
                    self.register(vars(module))
                    modules.append(name)
                except Exception as e:
                    error_count = error_count + 1
                    filename, lineno = tools.get_raising_file_and_line()
                    rel_path = os.path.relpath(filename,
                                               os.path.dirname(__file__))
                    raising_stmt = "%s:%d" % (rel_path, lineno)
                    stderr("Error in %s setup procedure: %s (%s)" %
                           (name, e, raising_stmt))

        if modules:
            stderr('\n\nRegistered %d modules,' % (len(modules) - 1))
            stderr('%d modules failed to load\n\n' % error_count)
        else:
            stderr("Warning: Couldn't find any modules")

        self.bind_commands()
Ejemplo n.º 50
0
def main(argv=None):
    global homedir
    # Step One: Parse The Command Line
    try:
        parser = optparse.OptionParser("%prog [options]")
        parser.add_option("-c", "--config", metavar="filename", help="use a specific configuration file")
        parser.add_option("-d", "--fork", action="store_true", dest="deamonize", help="Deamonize willie")
        parser.add_option("-q", "--quit", action="store_true", dest="quit", help="Gracefully quit Willie")
        parser.add_option("-k", "--kill", action="store_true", dest="kill", help="Kill Willie")
        parser.add_option(
            "--exit-on-error",
            action="store_true",
            dest="exit_on_error",
            help=("Exit immediately on every error instead of " "trying to recover"),
        )
        parser.add_option("-l", "--list", action="store_true", dest="list_configs", help="List all config files found")
        parser.add_option(
            "-m",
            "--migrate",
            action="store_true",
            dest="migrate_configs",
            help="Migrate config files to the new format",
        )
        parser.add_option("--quiet", action="store_true", dest="quiet", help="Supress all output")
        parser.add_option(
            "-w", "--configure-all", action="store_true", dest="wizard", help="Run the configuration wizard."
        )
        parser.add_option(
            "--configure-modules",
            action="store_true",
            dest="mod_wizard",
            help=("Run the configuration wizard, but only for the " "module configuration options."),
        )
        parser.add_option(
            "--configure-database",
            action="store_true",
            dest="db_wizard",
            help=("Run the configuration wizard, but only for the " "database configuration options."),
        )
        opts, args = parser.parse_args(argv)

        if opts.wizard:
            wizard("all", opts.config)
            return
        elif opts.mod_wizard:
            wizard("mod", opts.config)
            return
        elif opts.db_wizard:
            wizard("db", opts.config)
            return

        check_python_version()
        if opts.list_configs is not None:
            configs = enumerate_configs()
            print "Config files in ~/.willie:"
            if len(configs[0]) is 0:
                print "\tNone found"
            else:
                for config in configs:
                    print "\t%s" % config
            print "-------------------------"
            return

        config_name = opts.config or "default"

        configpath = find_config(config_name)
        if not os.path.isfile(configpath):
            print "Welcome to Willie!\nI can't seem to find the configuration file, so let's generate it!\n"
            if not configpath.endswith(".cfg"):
                configpath = configpath + ".cfg"
            create_config(configpath)
            configpath = find_config(config_name)
        try:
            config_module = Config(configpath)
        except ConfigurationError as e:
            stderr(e)
            sys.exit(2)

        if config_module.core.not_configured:
            stderr("Bot is not configured, can't start")
            # exit with code 2 to prevent auto restart on fail by systemd
            sys.exit(2)

        if not config_module.has_option("core", "homedir"):
            config_module.dotdir = homedir
            config_module.homedir = homedir
        else:
            homedir = config_module.core.homedir
            config_module.dotdir = config_module.core.homedir

        if not config_module.core.logdir:
            config_module.core.logdir = os.path.join(homedir, "logs")
        logfile = os.path.os.path.join(config_module.logdir, "stdio.log")
        if not os.path.isdir(config_module.logdir):
            os.mkdir(config_module.logdir)

        if opts.exit_on_error:
            config_module.exit_on_error = True
        else:
            config_module.exit_on_error = False

        if opts.quiet is None:
            opts.quiet = False

        sys.stderr = tools.OutputRedirect(logfile, True, opts.quiet)
        sys.stdout = tools.OutputRedirect(logfile, False, opts.quiet)

        # Handle --quit, --kill and saving the PID to file
        pid_dir = config_module.core.pid_dir or homedir
        if opts.config is None:
            pid_file_path = os.path.join(pid_dir, "willie.pid")
        else:
            basename = os.path.basename(opts.config)
            if basename.endswith(".cfg"):
                basename = basename[:-4]
            pid_file_path = os.path.join(pid_dir, "willie-%s.pid" % basename)
        if os.path.isfile(pid_file_path):
            pid_file = open(pid_file_path, "r")
            old_pid = int(pid_file.read())
            pid_file.close()
            if tools.check_pid(old_pid):
                if opts.quit is None and opts.kill is None:
                    stderr("There's already a Willie instance running with this config file")
                    stderr("Try using the --quit or the --kill options")
                    sys.exit(1)
                elif opts.kill:
                    stderr("Killing the willie")
                    os.kill(old_pid, signal.SIGKILL)
                    sys.exit(0)
                elif opts.quit:
                    stderr("Signaling Willie to stop gracefully")
                    if hasattr(signal, "SIGUSR1"):
                        os.kill(old_pid, signal.SIGUSR1)
                    else:
                        os.kill(old_pid, signal.SIGTERM)
                    sys.exit(0)
            elif not tools.check_pid(old_pid) and (opts.kill or opts.quit):
                stderr("Willie is not running!")
                sys.exit(1)
        elif opts.quit is not None or opts.kill is not None:
            stderr("Willie is not running!")
            sys.exit(1)
        if opts.deamonize is not None:
            child_pid = os.fork()
            if child_pid is not 0:
                sys.exit()
        pid_file = open(pid_file_path, "w")
        pid_file.write(str(os.getpid()))
        pid_file.close()
        config_module.pid_file_path = pid_file_path

        # Step Five: Initialise And Run willie
        run(config_module)
    except KeyboardInterrupt:
        print "\n\nInterrupted"
        os._exit(1)
Ejemplo n.º 51
0
def shutdown(bot):
    stderr("Shutdown ran!")
Ejemplo n.º 52
0
def main(argv=None):
    global homedir
    # Step One: Parse The Command Line
    try:
        parser = argparse.ArgumentParser(description='Willie IRC Bot',
                                         usage='%(prog)s [options]')
        parser.add_argument('-c', '--config', metavar='filename',
                            help='use a specific configuration file')
        parser.add_argument("-d", '--fork', action="store_true",
                            dest="deamonize", help="Deamonize willie")
        parser.add_argument("-q", '--quit', action="store_true", dest="quit",
                            help="Gracefully quit Willie")
        parser.add_argument("-k", '--kill', action="store_true", dest="kill",
                            help="Kill Willie")
        parser.add_argument('--exit-on-error', action="store_true",
                            dest="exit_on_error", help=(
                                "Exit immediately on every error instead of "
                                "trying to recover"))
        parser.add_argument("-l", '--list', action="store_true",
                            dest="list_configs",
                            help="List all config files found")
        parser.add_argument("-m", '--migrate', action="store_true",
                            dest="migrate_configs",
                            help="Migrate config files to the new format")
        parser.add_argument('--quiet', action="store_true", dest="quiet",
                            help="Supress all output")
        parser.add_argument('-w', '--configure-all', action='store_true',
                            dest='wizard', help='Run the configuration wizard.')
        parser.add_argument('--configure-modules', action='store_true',
                            dest='mod_wizard', help=(
                                'Run the configuration wizard, but only for the '
                                'module configuration options.'))
        parser.add_argument('-v', '--version', action="store_true",
                            dest="version", help="Show version number and exit")
        opts = parser.parse_args()

        # Step Two: "Do not run as root" checks.
        try:
            # Linux/Mac
            if os.getuid() == 0 or os.geteuid() == 0:
                stderr('Error: Do not run Willie with root privileges.')
                sys.exit(1)
        except AttributeError:
            # Windows
            if os.environ.get("USERNAME") == "Administrator":
                stderr('Error: Do not run Willie as Administrator.')
                sys.exit(1)

        if opts.version:
            py_ver = '%s.%s.%s' % (sys.version_info.major,
                                   sys.version_info.minor,
                                   sys.version_info.micro)
            print('Willie %s (running on python %s)' % (__version__, py_ver))
            print('http://willie.dftba.net/')
            return
        elif opts.wizard:
            wizard('all', opts.config)
            return
        elif opts.mod_wizard:
            wizard('mod', opts.config)
            return

        if opts.list_configs:
            configs = enumerate_configs()
            print('Config files in ~/.willie:')
            if len(configs) is 0:
                print('\tNone found')
            else:
                for config in configs:
                    print('\t%s' % config)
            print('-------------------------')
            return

        config_name = opts.config or 'default'

        configpath = find_config(config_name)
        if not os.path.isfile(configpath):
            print("Welcome to Willie!\nI can't seem to find the configuration file, so let's generate it!\n")
            if not configpath.endswith('.cfg'):
                configpath = configpath + '.cfg'
            create_config(configpath)
            configpath = find_config(config_name)
        try:
            config_module = Config(configpath)
        except ConfigurationError as e:
            stderr(e)
            sys.exit(2)

        if config_module.core.not_configured:
            stderr('Bot is not configured, can\'t start')
            # exit with code 2 to prevent auto restart on fail by systemd
            sys.exit(2)

        if not config_module.has_option('core', 'homedir'):
            config_module.dotdir = homedir
            config_module.homedir = homedir
        else:
            homedir = config_module.core.homedir
            config_module.dotdir = config_module.core.homedir

        if not config_module.core.logdir:
            config_module.core.logdir = os.path.join(homedir, 'logs')
        logfile = os.path.os.path.join(config_module.logdir, 'stdio.log')
        if not os.path.isdir(config_module.logdir):
            os.mkdir(config_module.logdir)

        config_module.exit_on_error = opts.exit_on_error
        config_module._is_deamonized = opts.deamonize

        sys.stderr = tools.OutputRedirect(logfile, True, opts.quiet)
        sys.stdout = tools.OutputRedirect(logfile, False, opts.quiet)

        # Handle --quit, --kill and saving the PID to file
        pid_dir = config_module.core.pid_dir or homedir
        if opts.config is None:
            pid_file_path = os.path.join(pid_dir, 'willie.pid')
        else:
            basename = os.path.basename(opts.config)
            if basename.endswith('.cfg'):
                basename = basename[:-4]
            pid_file_path = os.path.join(pid_dir, 'willie-%s.pid' % basename)
        if os.path.isfile(pid_file_path):
            with open(pid_file_path, 'r') as pid_file:
                try:
                    old_pid = int(pid_file.read())
                except ValueError:
                    old_pid = None
            if old_pid is not None and tools.check_pid(old_pid):
                if not opts.quit and not opts.kill:
                    stderr('There\'s already a Willie instance running with this config file')
                    stderr('Try using the --quit or the --kill options')
                    sys.exit(1)
                elif opts.kill:
                    stderr('Killing the willie')
                    os.kill(old_pid, signal.SIGKILL)
                    sys.exit(0)
                elif opts.quit:
                    stderr('Signaling Willie to stop gracefully')
                    if hasattr(signal, 'SIGUSR1'):
                        os.kill(old_pid, signal.SIGUSR1)
                    else:
                        os.kill(old_pid, signal.SIGTERM)
                    sys.exit(0)
            elif not tools.check_pid(old_pid) and (opts.kill or opts.quit):
                stderr('Willie is not running!')
                sys.exit(1)
        elif opts.quit or opts.kill:
            stderr('Willie is not running!')
            sys.exit(1)
        if opts.deamonize:
            child_pid = os.fork()
            if child_pid is not 0:
                sys.exit()
        with open(pid_file_path, 'w') as pid_file:
            pid_file.write(str(os.getpid()))
        config_module.pid_file_path = pid_file_path

        # Step Five: Initialise And Run willie
        run(config_module)
    except KeyboardInterrupt:
        print("\n\nInterrupted")
        os._exit(1)
Ejemplo n.º 53
0
def f_reload(bot, trigger):
    """Reloads a module, for use by admins only."""
    if not trigger.admin:
        stderr('joku prkl yritti reloadata')
        return

    name = trigger.group(2)
    if name == bot.config.owner:
        return bot.reply('What?')

    if (not name) or (name == '*') or (name.upper() == 'ALL THE THINGS'):
        # Calling the shutdown methods of the modules
        for moduleName in bot.config.enumerate_modules():
            module = sys.modules[moduleName]
            if hasattr(module, "shutdown"):
                module.shutdown(bot)
        bot.callables = None
        bot.commands = None
        bot.setup()
        return bot.reply('done reloading')

    if not name in sys.modules:
        return bot.reply('%s: no such module!' % name)

    old_module = sys.modules[name]

    old_callables = {}
    for obj_name, obj in iteritems(vars(old_module)):
        if bot.is_callable(obj) or bot.is_shutdown(obj):
            old_callables[obj_name] = obj

    # Call the shutdown method of the module
    if hasattr(old_module, "shutdown"):
        old_module.shutdown(bot)

    bot.unregister(old_callables)
    # Also remove all references to willie callables from top level of the
    # module, so that they will not get loaded again if reloading the
    # module does not override them.

    for obj_name in old_callables.keys():
        delattr(old_module, obj_name)

    # Also delete the setup and shutdown function
    if hasattr(old_module, "setup"):
        delattr(old_module, "setup")
    if hasattr(old_module, "shutdown"):
        delattr(old_module, "shutdown")

    # Thanks to moot for prodding me on this
    path = old_module.__file__
    if path.endswith('.pyc') or path.endswith('.pyo'):
        path = path[:-1]
    if not os.path.isfile(path):
        return bot.reply('Found %s, but not the source file' % name)

    module = imp.load_source(name, path)
    sys.modules[name] = module
    if hasattr(module, 'setup'):
        module.setup(bot)

    mtime = os.path.getmtime(module.__file__)
    modified = time.strftime('%Y-%m-%d %H:%M:%S', time.gmtime(mtime))

    bot.register(vars(module))
    bot.bind_commands()

    bot.reply('%r (version: %s)' % (module, modified))
Ejemplo n.º 54
0
 def run(self, host, port=6667):
     try:
         self.initiate_connect(host, port)
     except socket.error as e:
         stderr('Connection error: %s' % e)
         self.hasquit = True
Ejemplo n.º 55
0
    def setup(self):
        stderr("\nWelcome to Willie. Loading modules...\n\n")
        self.callables = set()
        self.shutdown_methods = set()

        filenames = self.config.enumerate_modules()
        # Coretasks is special. No custom user coretasks.
        this_dir = os.path.dirname(os.path.abspath(__file__))
        filenames['coretasks'] = os.path.join(this_dir, 'coretasks.py')

        modules = []
        error_count = 0
        for name, filename in iteritems(filenames):
            try:
                module = imp.load_source(name, filename)
            except Exception as e:
                error_count = error_count + 1
                filename, lineno = tools.get_raising_file_and_line()
                rel_path = os.path.relpath(filename, os.path.dirname(__file__))
                raising_stmt = "%s:%d" % (rel_path, lineno)
                stderr("Error loading %s: %s (%s)" % (name, e, raising_stmt))
            else:
                try:
                    if hasattr(module, 'setup'):
                        module.setup(self)
                    self.register(vars(module))
                    modules.append(name)
                except Exception as e:
                    error_count = error_count + 1
                    filename, lineno = tools.get_raising_file_and_line()
                    rel_path = os.path.relpath(
                        filename, os.path.dirname(__file__)
                    )
                    raising_stmt = "%s:%d" % (rel_path, lineno)
                    stderr("Error in %s setup procedure: %s (%s)"
                           % (name, e, raising_stmt))

        if modules:
            stderr('\n\nRegistered %d modules,' % (len(modules) - 1))
            stderr('%d modules failed to load\n\n' % error_count)
        else:
            stderr("Warning: Couldn't find any modules")

        self.bind_commands()
Ejemplo n.º 56
0
def setup(bot):
    stderr("setup ran!")
Ejemplo n.º 57
0
def main(argv=None):
    global homedir
    # Step One: Parse The Command Line
    try:
        parser = optparse.OptionParser('%prog [options]')
        parser.add_option('-c', '--config', metavar='filename',
            help='use a specific configuration file')
        parser.add_option("-d", '--fork', action="store_true",
            dest="deamonize", help="Deamonize willie")
        parser.add_option("-q", '--quit', action="store_true", dest="quit",
            help="Gracefully quit Willie")
        parser.add_option("-k", '--kill', action="store_true", dest="kill",
            help="Kill Willie")
        parser.add_option('--exit-on-error', action="store_true", dest="exit_on_error",
            help="Exit immediately on every error instead of trying to recover")
        parser.add_option("-l", '--list', action="store_true",
            dest="list_configs", help="List all config files found")
        parser.add_option("-m", '--migrate', action="store_true",
            dest="migrate_configs",
            help="Migrate config files to the new format")
        parser.add_option('--quiet', action="store_true", dest="quiet",
            help="Supress all output")
        parser.add_option('-w', '--configure-all', action='store_true',
            dest='wizard', help='Run the configuration wizard.')
        parser.add_option('--configure-modules', action='store_true',
            dest='mod_wizard', help='Run the configuration wizard, but only for the module configuration options.')
        parser.add_option('--configure-database', action='store_true',
            dest='db_wizard', help='Run the configuration wizard, but only for the database configuration options.')
        opts, args = parser.parse_args(argv)

        if opts.wizard:
            wizard('all', opts.config)
            return
        elif opts.mod_wizard:
            wizard('mod', opts.config)
            return
        elif opts.db_wizard:
            wizard('db', opts.config)
            return

        check_python_version()
        if opts.list_configs is not None:
            configs = enumerate_configs()
            print 'Config files in ~/.willie:'
            if len(configs[0]) is 0:
                print '\tNone found'
            else:
                for config in configs:
                    print '\t%s' % config
            print '-------------------------'
            return

        config_name = opts.config or 'default'

        configpath = find_config(config_name)
        if not os.path.isfile(configpath):
            print "Welcome to Willie!\nI can't seem to find the configuration file, so let's generate it!\n"
            if not configpath.endswith('.cfg'):
                configpath = configpath + '.cfg'
            create_config(configpath)
            configpath = find_config(config_name)
        try:
            config_module = Config(configpath)
        except ConfigurationError as e:
            stderr(e)
            sys.exit(2)

        if config_module.core.not_configured:
            stderr('Bot is not configured, can\'t start')
            # exit with code 2 to prevent auto restart on fail by systemd
            sys.exit(2)

        if not config_module.has_option('core', 'homedir'):
            config_module.dotdir = homedir
            config_module.homedir = homedir
        else:
            homedir = config_module.core.homedir
            config_module.dotdir = config_module.core.homedir

        if not config_module.core.logdir:
            config_module.core.logdir = os.path.join(homedir, 'logs')
        logfile = os.path.os.path.join(config_module.logdir, 'stdio.log')
        if not os.path.isdir(config_module.logdir):
            os.mkdir(config_module.logdir)

        if opts.exit_on_error:
            config_module.exit_on_error = True
        else:
            config_module.exit_on_error = False

        if opts.quiet is None:
            opts.quiet = False

        sys.stderr = tools.OutputRedirect(logfile, True, opts.quiet)
        sys.stdout = tools.OutputRedirect(logfile, False, opts.quiet)

        #Handle --quit, --kill and saving the PID to file
        pid_dir = config_module.core.pid_dir or homedir
        if opts.config is None:
            pid_file_path = os.path.join(pid_dir, 'willie.pid')
        else:
            basename = os.path.basename(opts.config)
            if basename.endswith('.cfg'):
                basename = basename[:-4]
            pid_file_path = os.path.join(pid_dir, 'willie-%s.pid' % basename)
        if os.path.isfile(pid_file_path):
            pid_file = open(pid_file_path, 'r')
            old_pid = int(pid_file.read())
            pid_file.close()
            if tools.check_pid(old_pid):
                if opts.quit is None and opts.kill is None:
                    stderr('There\'s already a Willie instance running with this config file')
                    stderr('Try using the --quit or the --kill options')
                    sys.exit(1)
                elif opts.kill:
                    stderr('Killing the willie')
                    os.kill(old_pid, signal.SIGKILL)
                    sys.exit(0)
                elif opts.quit:
                    stderr('Signaling Willie to stop gracefully')
                    if hasattr(signal, 'SIGUSR1'):
                        os.kill(old_pid, signal.SIGUSR1)
                    else:
                        os.kill(old_pid, signal.SIGTERM)
                    sys.exit(0)
            elif not tools.check_pid(old_pid) and (opts.kill or opts.quit):
                stderr('Willie is not running!')
                sys.exit(1)
        elif opts.quit is not None or opts.kill is not None:
            stderr('Willie is not running!')
            sys.exit(1)
        if opts.deamonize is not None:
            child_pid = os.fork()
            if child_pid is not 0:
                sys.exit()
        pid_file = open(pid_file_path, 'w')
        pid_file.write(str(os.getpid()))
        pid_file.close()
        config_module.pid_file_path = pid_file_path

        # Step Five: Initialise And Run willie
        run(config_module)
    except KeyboardInterrupt:
        print "\n\nInterrupted"
        os._exit(1)
Ejemplo n.º 58
0
def include(bot, filename):
    try:
        with open(filename) as f:
            bot.config.parser.readfp(f, filename)
    except Exception as exc:
        stderr("Failed to read included config file {}: {}".format(filename, exc))
Ejemplo n.º 59
0
def check_python_version():
    if sys.version_info < (2, 7):
        stderr("Error: Requires Python 2.7 or later. Try python2.7 willie")
        sys.exit(1)