Exemple #1
0
    def conf_basic(self):
        print("")
        print(_("## Basic Setup ##"))

        from pyload.core.database import DatabaseBackend

        db = DatabaseBackend(None)
        db.setup()
        username = self.ask(_("Username"), "User")
        password = self.ask("", "", password=True)
        db.add_user(username, password)
        db.shutdown()

        print("")
        langs = self.config.get_meta_data("general", "language")
        self.config.set('general', 'language',
                        self.ask(_("Language"), "en", langs.type.split(";")))

        self.config.set('general', 'storage_folder',
                        self.ask(_("Storage folder"), "Storage"))
        self.config.set('connection', 'max_transfers',
                        self.ask(_("Max parallel transfers"), "3"))

        reconnect = self.ask(_("Use Reconnect?"), self.no, bool=True)
        self.config.set('reconnect', 'activated', reconnect)
        if reconnect:
            self.config.set(
                'reconnect', 'script',
                self.ask(_("Reconnection script"), "./reconnect.sh"))
Exemple #2
0
    def _init_database(self, restore):
        from pyload.core.database import DatabaseBackend
        from pyload.core.datatype import Permission, Role

        # TODO: Move inside DatabaseBackend
        newdb = not os.path.isfile(DatabaseBackend.DB_FILE)
        self.db = DatabaseBackend(self)
        self.db.setup()

        if restore or newdb:
            self.db.add_user(self.DEFAULT_USERNAME, self.DEFAULT_PASSWORD,
                             Role.Admin, Permission.All)
        if restore:
            self.log.warning(
                self._('Restored default login credentials `admin|pyload`'))
Exemple #3
0
 def setUpClass(cls):
     cls.core = Core()
     cls.db = DatabaseBackend(cls.core)
     cls.core.db = cls.db
     cls.db.manager = cls.core
     cls.db.manager.status_msg = defaultdict(lambda: "statusmsg")
     cls.parser = cls.core.config
     cls.config = ConfigManager(cls.core, cls.parser)
     cls.db.setup()
    def setUpClass(cls):
        cls.pids = [-1]
        cls.fids = []

        cls.db = DatabaseBackend(Core())
        cls.db.manager = cls.db.core

        cls.db.setup()
        cls.db.purge_all()
Exemple #5
0
    def _init_database(self, restore):
        from pyload.core.database import DatabaseBackend
        from pyload.core.datatype import Permission, Role

        # TODO: Move inside DatabaseBackend
        newdb = not os.path.isfile(DatabaseBackend.DB_FILE)
        self.db = DatabaseBackend(self)
        self.db.setup()

        if restore or newdb:
            self.db.add_user(
                self.DEFAULT_USERNAME, self.DEFAULT_PASSWORD, Role.Admin,
                Permission.All)
        if restore:
            self.log.warning(
                self._('Restored default login credentials `admin|pyload`'))
Exemple #6
0
class Core(object):

    DEFAULT_CONFIGNAME = 'config.ini'
    DEFAULT_LANGUAGE = 'english'
    DEFAULT_USERNAME = '******'
    DEFAULT_PASSWORD = '******'
    DEFAULT_STORAGENAME = 'downloads'

    @property
    def version(self):
        return __version__

    @property
    def version_info(self):
        return __version_info__

    @property
    def running(self):
        return self.__running.is_set()

    def __init__(self, cfgdir, tmpdir, debug=None, restore=False):
        self.__running = Event()
        self.__do_restart = False
        self.__do_exit = False
        self._ = lambda x: x

        self.cfgdir = fullpath(cfgdir)
        self.tmpdir = fullpath(tmpdir)

        os.chdir(self.cfgdir)

        # if self.tmpdir not in sys.path:
        # sys.path.append(self.tmpdir)

        # if refresh:
        # cleanpy(PACKDIR)

        self.config = ConfigParser(self.DEFAULT_CONFIGNAME)
        self.debug = self.config.get('log',
                                     'debug') if debug is None else debug
        self.log = LoggerFactory(self, self.debug)

        self._init_database(restore)
        self._init_managers()

        self.request = self.req = RequestFactory(self)

        self._init_api()

        atexit.register(self.exit)

    def _init_api(self):
        from pyload.api import Api
        self.api = Api(self)

    def _init_database(self, restore):
        from pyload.core.database import DatabaseBackend
        from pyload.core.datatype import Permission, Role

        # TODO: Move inside DatabaseBackend
        newdb = not os.path.isfile(DatabaseBackend.DB_FILE)
        self.db = DatabaseBackend(self)
        self.db.setup()

        if restore or newdb:
            self.db.add_user(self.DEFAULT_USERNAME, self.DEFAULT_PASSWORD,
                             Role.Admin, Permission.All)
        if restore:
            self.log.warning(
                self._('Restored default login credentials `admin|pyload`'))

    def _init_managers(self):
        from pyload.core.manager import (AccountManager, AddonManager,
                                         EventManager, ExchangeManager,
                                         FileManager, InfoManager,
                                         PluginManager, TransferManager)

        self.scheduler = sched.scheduler(time.time, time.sleep)
        self.filemanager = self.files = FileManager(self)
        self.pluginmanager = self.pgm = PluginManager(self)
        self.exchangemanager = self.exm = ExchangeManager(self)
        self.eventmanager = self.evm = EventManager(self)
        self.accountmanager = self.acm = AccountManager(self)
        self.infomanager = self.iom = InfoManager(self)
        self.transfermanager = self.tsm = TransferManager(self)
        # TODO: Remove builtins.ADDONMANAGER
        builtins.ADDONMANAGER = self.addonmanager = self.adm = AddonManager(
            self)
        # self.remotemanager = self.rem = RemoteManager(self)
        # self.servermanager = self.svm = ServerManager(self)
        self.db.manager = self.files  # ugly?

    def _setup_permissions(self):
        self.log.debug('Setup permissions...')

        if os.name == 'nt':
            return

        change_group = self.config.get('permission', 'change_group')
        change_user = self.config.get('permission', 'change_user')

        if change_group:
            try:
                group = self.config.get('permission', 'group')
                set_process_group(group)
            except Exception as exc:
                self.log.error(self._('Unable to change gid'))
                self.log.error(exc, exc_info=self.debug)

        if change_user:
            try:
                user = self.config.get('permission', 'user')
                set_process_user(user)
            except Exception as exc:
                self.log.error(self._('Unable to change uid'))
                self.log.error(exc, exc_info=self.debug)

    def set_language(self, lang):
        domain = 'core'
        localedir = resource_filename(__package__, 'locale')
        languages = (locale.locale_alias[lang.lower()].split('_', 1)[0], )
        self._set_language(domain, localedir, languages)

    def _set_language(self, *args, **kwargs):
        trans = gettext.translation(*args, **kwargs)
        try:
            self._ = trans.ugettext
        except AttributeError:
            self._ = trans.gettext

    def _setup_language(self):
        self.log.debug('Setup language...')

        lang = self.config.get('general', 'language')
        if not lang:
            lc = locale.getlocale()[0] or locale.getdefaultlocale()[0]
            lang = lc.split('_', 1)[0] if lc else 'en'

        try:
            self.set_language(lang)
        except IOError as exc:
            self.log.error(exc, exc_info=self.debug)
            self._set_language('core', fallback=True)

    # def _setup_niceness(self):
    # niceness = self.config.get('general', 'niceness')
    # renice(niceness=niceness)
    # ioniceness = int(self.config.get('general', 'ioniceness'))
    # ionice(niceness=ioniceness)

    def _setup_storage(self):
        self.log.debug('Setup storage...')

        storage_folder = self.config.get('general', 'storage_folder')
        if storage_folder is None:
            storage_folder = os.path.join(builtins.USERDIR,
                                          self.DEFAULT_STORAGENAME)
        self.log.info(self._('Storage: {0}'.format(storage_folder)))
        makedirs(storage_folder, exist_ok=True)
        avail_space = format.size(availspace(storage_folder))
        self.log.info(
            self._('Available storage space: {0}').format(avail_space))

    def _setup_network(self):
        self.log.debug('Setup network...')

        # TODO: Move to accountmanager
        self.log.info(self._('Activating accounts...'))
        self.acm.load_accounts()
        # self.scheduler.enter(0, 0, self.acm.load_accounts)
        self.adm.activate_addons()

    def run(self):
        self.log.info('Welcome to pyLoad v{0}'.format(self.version))
        if self.debug:
            self.log.warning('*** DEBUG MODE ***')
        try:
            self.log.debug('Starting pyLoad...')
            self.evm.fire('pyload:starting')
            self.__running.set()

            self._setup_language()
            self._setup_permissions()

            self.log.info(self._('Config directory: {0}').format(self.cfgdir))
            self.log.info(self._('Cache directory: {0}').format(self.tmpdir))

            self._setup_storage()
            self._setup_network()
            # self._setup_niceness()

            # # some memory stats
            # from guppy import hpy
            # hp=hpy()
            # print(hp.heap())
            # import objgraph
            # objgraph.show_most_common_types(limit=30)
            # import memdebug
            # memdebug.start(8002)
            # from meliae import scanner
            # scanner.dump_all_objects(os.path.join(PACKDIR, 'objs.json'))

            self.log.debug('pyLoad is up and running')
            self.evm.fire('pyload:started')

            self.tsm.pause = False  # NOTE: Recheck...
            while True:
                self.__running.wait()
                self.tsm.work()
                self.iom.work()
                self.exm.work()
                if self.__do_restart:
                    raise Restart
                if self.__do_exit:
                    raise Exit
                self.scheduler.run()
                time.sleep(1)

        except Restart:
            self.restart()

        except (Exit, KeyboardInterrupt, SystemExit):
            self.exit()

        except Exception as exc:
            self.log.critical(exc, exc_info=True)
            self.exit()

    def _remove_loggers(self):
        for handler in self.log.handlers:
            with closing(handler) as hdlr:
                self.log.removeHandler(hdlr)

    def restart(self):
        self.stop()
        self.log.info(self._('Restarting pyLoad...'))
        self.evm.fire('pyload:restarting')
        self.run()

    def exit(self):
        self.stop()
        self.log.info(self._('Exiting pyLoad...'))
        self.tsm.exit()
        self.db.exit()  # NOTE: Why here?
        self._remove_loggers()
        # if cleanup:
        # self.log.info(self._("Deleting temp files..."))
        # remove(self.tmpdir, ignore_errors=True)

    def stop(self):
        try:
            self.log.debug('Stopping pyLoad...')
            self.evm.fire('pyload:stopping')
            self.adm.deactivate_addons()
            self.api.stop_all_downloads()
        finally:
            self.files.sync_save()
            self.__running.clear()
            self.evm.fire('pyload:stopped')
Exemple #7
0
    def open_db(self):
        from pyload.core.database import DatabaseBackend

        if self.db is None:
            self.db = DatabaseBackend(None)
            self.db.setup()
Exemple #8
0
class SetupAssistant(object):
    """
    pyLoads initial setup configuration assistant.
    """
    __slots__ = [
        'config', 'db', 'lang', 'no', 'stdin_encoding', 'timestamp', 'yes'
    ]

    def __init__(self, file, version):
        self.config = ConfigParser(file, version)
        self.stdin_encoding = console_encoding(sys.stdin.encoding)
        self.lang = None
        self.db = None

        # We will create a timestamp so that the setup will be completed in a
        # specific interval
        self.timestamp = time()

        # TODO: probably unneeded
        self.yes = "yes"
        self.no = "no"

    def start(self):
        web = WebServer(pysetup=self)
        web.start()

        error = web.check_error()

        # TODO: start cli in this case
        if error:  # TODO: errno 44 port already in use
            print(error)

        url = "http://{0}:{1:d}/".format(
            socket.gethostbyname(socket.gethostname()), web.port)

        print("Setup is running at {0}".format(url))

        opened = webbrowser.open_new_tab(url)
        if not opened:
            print("Please point your browser to the url above")

        eval(input())

        return True

    def start_cli(self):
        self.ask_lang()

        print(_("Welcome to the pyLoad Configuration Assistent"))
        print(
            _("It will check your system and make a basic setup in order to run pyLoad"
              ))
        print("")
        print(_("The value in brackets [] always is the default value,"))
        print(
            _("in case you do not want to change it or you are unsure what to choose, just hit enter"
              ))
        print(
            _("Don't forget: You can always rerun this assistent with --setup or -s parameter, when you start pyLoadCore"
              ))
        print(_("If you have any problems with this assistent hit CTRL+C,"))
        print(
            _("to abort and do not let him start with pyLoadCore automatically anymore"
              ))
        print("")
        print(_("When you are ready for system check, hit enter"))
        eval(input())

        # TODO: new system check + deps

        con = self.ask(_("Continue with setup?"), self.yes, bool=True)

        if not con:
            return False

        print("")
        print(
            _("Do you want to change the config path? Current is {0}").format(
                os.path.abspath("")))
        print(
            _("If you use pyLoad on a server or the home partition lives on an internal flash it may be a good idea to change it"
              ))
        path = self.ask(_("Change config path?"), self.no, bool=True)
        if path:
            self.conf_path()
            # calls exit when changed

        print("")
        print(_("Do you want to configure login data and basic settings?"))
        print(_("This is recommend for first run"))
        con = self.ask(_("Make basic setup?"), self.yes, bool=True)
        if con:
            self.conf_basic()

        print("")
        print(_("Do you want to configure ssl?"))
        ssl = self.ask(_("Configure ssl?"), self.no, bool=True)
        if ssl:
            self.conf_ssl()

        print("")
        print(_("Do you want to configure the Web UI?"))
        web = self.ask(_("Configure the Web UI?"), self.yes, bool=True)
        if web:
            self.conf_web()

        print("")
        print(_("Setup finished successfully"))
        print(_("Hit enter to exit and restart pyLoad"))
        eval(input())
        return True

    def conf_basic(self):
        print("")
        print(_("## Basic Setup ##"))

        from pyload.core.database import DatabaseBackend

        db = DatabaseBackend(None)
        db.setup()
        username = self.ask(_("Username"), "User")
        password = self.ask("", "", password=True)
        db.add_user(username, password)
        db.shutdown()

        print("")
        langs = self.config.get_meta_data("general", "language")
        self.config.set('general', 'language',
                        self.ask(_("Language"), "en", langs.type.split(";")))

        self.config.set('general', 'storage_folder',
                        self.ask(_("Storage folder"), "Storage"))
        self.config.set('connection', 'max_transfers',
                        self.ask(_("Max parallel transfers"), "3"))

        reconnect = self.ask(_("Use Reconnect?"), self.no, bool=True)
        self.config.set('reconnect', 'activated', reconnect)
        if reconnect:
            self.config.set(
                'reconnect', 'script',
                self.ask(_("Reconnection script"), "./reconnect.sh"))

    def conf_web(self):
        print("")
        print(_("## Web UI Setup ##"))

        print("")
        self.config.set(
            'webui', 'activated',
            self.ask(_("Activate the Web UI?"), self.yes, bool=True))
        print("")
        print(
            _("Listen address, if you use 127.0.0.1 or localhost, the Web UI will only accessible locally"
              ))
        self.config.set('webui', 'host', self.ask(_("Address"), "localhost"))
        self.config.set('webui', 'port', self.ask(_("Port"), "8010"))
        print("")
        print(
            _("pyLoad offers several server backends, now following a short explanation"
              ))
        print(
            "threaded:",
            _("Default server, this server offers SSL and is a good alternative to builtin"
              ))
        print(
            "fastcgi:",
            _("Can be used by apache, lighttpd, requires you to configure them, which is not too easy job"
              ))
        print(
            "lightweight:",
            _("Very fast alternative written in C, requires libev and linux knowledge"
              ))
        print(
            "\t",
            _("Get it from here: https://github.com/jonashaag/bjoern, compile it"
              ))
        print("\t", _("and copy bjoern.so to pyload/lib"))

        print()
        print(
            _("Attention: In some rare cases the builtin server is not working, if you notice problems with the Web UI"
              ))
        print(
            _("come back here and change the builtin server to the threaded one here"
              ))

        self.config.set(
            'webui', 'server',
            self.ask(_("Server"), "threaded",
                     ["builtin", "threaded", "fastcgi", "lightweight"]))

    def conf_ssl(self):
        print("")
        print(_("## SSL Setup ##"))
        print("")
        print(
            _("Execute these commands from pyLoad config folder to make ssl certificates:"
              ))
        print("")
        print("openssl genrsa -out ssl.key 1024")
        print("openssl req -new -key ssl.key -out ssl.csr")
        print(
            "openssl req -days 36500 -x509 -key ssl.key -in ssl.csr > ssl.crt "
        )
        print("")
        print(
            _("If you're done and everything went fine, you can activate ssl now"
              ))
        self.config.set('ssl', 'activated',
                        self.ask(_("Activate SSL?"), self.yes, bool=True))

    def set_user(self):
        translation = gettext.translation(
            "setup",
            os.path.join(PACKDIR, "locale"),
            languages=[self.config.get('general', 'language'), "en"],
            fallback=True)
        translation.install(True)

        self.open_db()

        try:
            while True:
                print(_("Select action"))
                print(_("1 - Create/Edit user"))
                print(_("2 - List users"))
                print(_("3 - Remove user"))
                print(_("4 - Quit"))
                action = eval(input("[1]/2/3/4: "))
                if action not in ("1", "2", "3", "4"):
                    continue
                elif action == "1":
                    print("")
                    username = self.ask(_("Username"), "User")
                    password = self.ask("", "", password=True)
                    admin = self.ask("Admin?", self.yes, bool=True)

                    self.db.add_user(username, password,
                                     Role.Admin if admin else Role.User,
                                     int('1111111', 2))
                elif action == "2":
                    print("")
                    print(_("Users"))
                    print("-----")
                    users = self.db.get_all_user_data()
                    for user in users.values():
                        print(user.name)
                    print("-----")
                    print("")
                elif action == "3":
                    print("")
                    username = self.ask(_("Username"), "")
                    if username:
                        self.db.remove_user_by_name(username)
                elif action == "4":
                    self.db.sync_save()
                    break
        finally:
            self.close_db()

    def add_user(self, username, password, role=Role.Admin):
        self.open_db()
        try:
            self.db.add_user(username, password, role, int('1111111', 2))
        finally:
            self.close_db()

    def open_db(self):
        from pyload.core.database import DatabaseBackend

        if self.db is None:
            self.db = DatabaseBackend(None)
            self.db.setup()

    def close_db(self):
        if self.db is not None:
            self.db.sync_save()
            self.db.shutdown()

    def save(self):
        self.config.save()
        self.close_db()

    def conf_path(self, trans=False):
        if trans:
            translation = gettext.translation(
                "setup",
                os.path.join(PACKDIR, "locale"),
                languages=[self.config.get('general', 'language'), "en"],
                fallback=True)
            translation.install(True)

        print(
            _("Setting new configpath, current configuration will not be transferred!"
              ))
        path = self.ask(_("Config path"), os.path.abspath(""))
        try:
            path = os.path.join(COREDIR, path)
            if not os.path.exists(path):
                makedirs(path)
            with io.open(os.path.join(COREDIR, "pyload", "config",
                                      "configdir"),
                         mode='wb') as fp:
                fp.write(path)
            print(
                _("Config path changed, setup will now close, please restart to go on"
                  ))
            print(_("Press Enter to exit"))
            eval(input())
            exit()
        except Exception as e:
            print(_("Setting config path failed: {0}").format(e.message))

    def ask_lang(self):
        langs = self.config.get_meta_data("general",
                                          "language").type.split(";")
        self.lang = self.ask(u"Choose your Language / Wähle deine Sprache",
                             "en", langs)
        translation = gettext.translation("setup",
                                          os.path.join(PACKDIR, "locale"),
                                          languages=[self.lang, "en"],
                                          fallback=True)
        translation.install(True)

        # l10n Input shorthand for yes
        self.yes = _("y")
        # l10n Input shorthand for no
        self.no = _("n")

    def ask(self, qst, default, answers=[], bool=False, password=False):
        """
        Generate dialog on command line.
        """
        if answers:
            info = "("
            for i, answer in enumerate(answers):
                info += (", " if i != 0 else "") + str(
                    (answer == default and "[{0}]".format(answer)) or answer)

            info += ")"
        elif bool:
            if default == self.yes:
                info = "([{0}]/{1})".format(self.yes, self.no)
            else:
                info = "({0}/[{1}])".format(self.yes, self.no)
        else:
            info = "[{0}]".format(default)

        if password:
            p1 = True
            p2 = False
            while p1 != p2:
                # getpass(_("Password: "******"Password: "******"")

                if len(p1) < 4:
                    print(_("Password too short. Use at least 4 symbols"))
                    continue

                sys.stdout.write(_("Password (again): "))
                p2 = getpass("")

                if p1 == p2:
                    return p1
                else:
                    print(_("Passwords did not match"))

        while True:
            input = eval(input(qst + " {0}: ".format(info)))
            input = input.decode(self.stdin_encoding)

            if input.strip() == "":
                input = default

            if bool:
                # l10n yes, true,t are inputs for booleans with value true
                if input.lower().strip() in [
                        self.yes, _("yes"),
                        _("true"),
                        _("t"), "yes"
                ]:
                    return True
                # l10n no, false,f are inputs for booleans with value false
                elif input.lower().strip() in [
                        self.no, _("no"),
                        _("false"), _("f"), "no"
                ]:
                    return False
                else:
                    print(_("Invalid Input"))
                    continue

            if not answers:
                return input

            else:
                if input in answers:
                    return input
                else:
                    print(_("Invalid Input"))
Exemple #9
0
class Core(object):

    DEFAULT_CONFIGNAME = 'config.ini'
    DEFAULT_LANGUAGE = 'english'
    DEFAULT_USERNAME = '******'
    DEFAULT_PASSWORD = '******'
    DEFAULT_STORAGENAME = 'downloads'

    @property
    def version(self):
        return __version__

    @property
    def version_info(self):
        return __version_info__

    @property
    def running(self):
        return self.__running.is_set()

    def __init__(self, cfgdir, tmpdir, debug=None, restore=False):
        self.__running = Event()
        self.__do_restart = False
        self.__do_exit = False
        self._ = lambda x: x

        self.cfgdir = fullpath(cfgdir)
        self.tmpdir = fullpath(tmpdir)

        os.chdir(self.cfgdir)

        # if self.tmpdir not in sys.path:
        # sys.path.append(self.tmpdir)

        # if refresh:
        # cleanpy(PACKDIR)

        self.config = ConfigParser(self.DEFAULT_CONFIGNAME)
        self.debug = self.config.get(
            'log', 'debug') if debug is None else debug
        self.log = LoggerFactory(self, self.debug)

        self._init_database(restore)
        self._init_managers()

        self.request = self.req = RequestFactory(self)

        self._init_api()

        atexit.register(self.exit)

    def _init_api(self):
        from pyload.api import Api
        self.api = Api(self)

    def _init_database(self, restore):
        from pyload.core.database import DatabaseBackend
        from pyload.core.datatype import Permission, Role

        # TODO: Move inside DatabaseBackend
        newdb = not os.path.isfile(DatabaseBackend.DB_FILE)
        self.db = DatabaseBackend(self)
        self.db.setup()

        if restore or newdb:
            self.db.add_user(
                self.DEFAULT_USERNAME, self.DEFAULT_PASSWORD, Role.Admin,
                Permission.All)
        if restore:
            self.log.warning(
                self._('Restored default login credentials `admin|pyload`'))

    def _init_managers(self):
        from pyload.core.manager import (
            AccountManager, AddonManager, EventManager, ExchangeManager,
            FileManager, InfoManager, PluginManager, TransferManager)

        self.scheduler = sched.scheduler(time.time, time.sleep)
        self.filemanager = self.files = FileManager(self)
        self.pluginmanager = self.pgm = PluginManager(self)
        self.exchangemanager = self.exm = ExchangeManager(self)
        self.eventmanager = self.evm = EventManager(self)
        self.accountmanager = self.acm = AccountManager(self)
        self.infomanager = self.iom = InfoManager(self)
        self.transfermanager = self.tsm = TransferManager(self)
        # TODO: Remove builtins.ADDONMANAGER
        builtins.ADDONMANAGER = self.addonmanager = self.adm = AddonManager(
            self)
        # self.remotemanager = self.rem = RemoteManager(self)
        # self.servermanager = self.svm = ServerManager(self)
        self.db.manager = self.files  # ugly?

    def _setup_permissions(self):
        self.log.debug('Setup permissions...')

        if os.name == 'nt':
            return

        change_group = self.config.get('permission', 'change_group')
        change_user = self.config.get('permission', 'change_user')

        if change_group:
            try:
                group = self.config.get('permission', 'group')
                set_process_group(group)
            except Exception as exc:
                self.log.error(self._('Unable to change gid'))
                self.log.error(exc, exc_info=self.debug)

        if change_user:
            try:
                user = self.config.get('permission', 'user')
                set_process_user(user)
            except Exception as exc:
                self.log.error(self._('Unable to change uid'))
                self.log.error(exc, exc_info=self.debug)

    def set_language(self, lang):
        domain = 'core'
        localedir = resource_filename(__package__, 'locale')
        languages = (locale.locale_alias[lang.lower()].split('_', 1)[0],)
        self._set_language(domain, localedir, languages)

    def _set_language(self, *args, **kwargs):
        trans = gettext.translation(*args, **kwargs)
        try:
            self._ = trans.ugettext
        except AttributeError:
            self._ = trans.gettext

    def _setup_language(self):
        self.log.debug('Setup language...')

        lang = self.config.get('general', 'language')
        if not lang:
            lc = locale.getlocale()[0] or locale.getdefaultlocale()[0]
            lang = lc.split('_', 1)[0] if lc else 'en'

        try:
            self.set_language(lang)
        except IOError as exc:
            self.log.error(exc, exc_info=self.debug)
            self._set_language('core', fallback=True)

    # def _setup_niceness(self):
        # niceness = self.config.get('general', 'niceness')
        # renice(niceness=niceness)
        # ioniceness = int(self.config.get('general', 'ioniceness'))
        # ionice(niceness=ioniceness)

    def _setup_storage(self):
        self.log.debug('Setup storage...')

        storage_folder = self.config.get('general', 'storage_folder')
        if storage_folder is None:
            storage_folder = os.path.join(
                builtins.USERDIR, self.DEFAULT_STORAGENAME)
        self.log.info(self._('Storage: {0}'.format(storage_folder)))
        makedirs(storage_folder, exist_ok=True)
        avail_space = format.size(availspace(storage_folder))
        self.log.info(
            self._('Available storage space: {0}').format(avail_space))

    def _setup_network(self):
        self.log.debug('Setup network...')

        # TODO: Move to accountmanager
        self.log.info(self._('Activating accounts...'))
        self.acm.load_accounts()
        # self.scheduler.enter(0, 0, self.acm.load_accounts)
        self.adm.activate_addons()

    def run(self):
        self.log.info('Welcome to pyLoad v{0}'.format(self.version))
        if self.debug:
            self.log.warning('*** DEBUG MODE ***')
        try:
            self.log.debug('Starting pyLoad...')
            self.evm.fire('pyload:starting')
            self.__running.set()

            self._setup_language()
            self._setup_permissions()

            self.log.info(self._('Config directory: {0}').format(self.cfgdir))
            self.log.info(self._('Cache directory: {0}').format(self.tmpdir))

            self._setup_storage()
            self._setup_network()
            # self._setup_niceness()

            # # some memory stats
            # from guppy import hpy
            # hp=hpy()
            # print(hp.heap())
            # import objgraph
            # objgraph.show_most_common_types(limit=30)
            # import memdebug
            # memdebug.start(8002)
            # from meliae import scanner
            # scanner.dump_all_objects(os.path.join(PACKDIR, 'objs.json'))

            self.log.debug('pyLoad is up and running')
            self.evm.fire('pyload:started')

            self.tsm.pause = False  # NOTE: Recheck...
            while True:
                self.__running.wait()
                self.tsm.work()
                self.iom.work()
                self.exm.work()
                if self.__do_restart:
                    raise Restart
                if self.__do_exit:
                    raise Exit
                self.scheduler.run()
                time.sleep(1)

        except Restart:
            self.restart()

        except (Exit, KeyboardInterrupt, SystemExit):
            self.exit()

        except Exception as exc:
            self.log.critical(exc, exc_info=True)
            self.exit()

    def _remove_loggers(self):
        for handler in self.log.handlers:
            with closing(handler) as hdlr:
                self.log.removeHandler(hdlr)

    def restart(self):
        self.stop()
        self.log.info(self._('Restarting pyLoad...'))
        self.evm.fire('pyload:restarting')
        self.run()

    def exit(self):
        self.stop()
        self.log.info(self._('Exiting pyLoad...'))
        self.tsm.exit()
        self.db.exit()  # NOTE: Why here?
        self._remove_loggers()
        # if cleanup:
        # self.log.info(self._("Deleting temp files..."))
        # remove(self.tmpdir, ignore_errors=True)

    def stop(self):
        try:
            self.log.debug('Stopping pyLoad...')
            self.evm.fire('pyload:stopping')
            self.adm.deactivate_addons()
            self.api.stop_all_downloads()
        finally:
            self.files.sync_save()
            self.__running.clear()
            self.evm.fire('pyload:stopped')