Example #1
0
def run_init(storage_path, use_sso=False, skip_cert_verify=False):
    config = ConfigHelper(storage_path)

    if config.is_present():
        do_override_input = cutie.prompt_yes_or_no(
            Log.error_str('Do you want to override the existing config?'))

        if not do_override_input:
            sys.exit(0)

    MailService(config).interactively_configure()
    TelegramService(config).interactively_configure()
    XmppService(config).interactively_configure()

    do_sentry = cutie.prompt_yes_or_no(
        'Do you want to configure Error Reporting via Sentry?')
    if do_sentry:
        sentry_dsn = input('Please enter your Sentry DSN:   ')
        config.set_property('sentry_dsn', sentry_dsn)

    moodle = MoodleService(config, storage_path, skip_cert_verify)

    if use_sso:
        moodle.interactively_acquire_sso_token()
    else:
        moodle.interactively_acquire_token()

    Log.success('Configuration finished and saved!')

    if os.name != 'nt':
        if storage_path == '.':
            Log.info(
                '  To set a cron-job for this program on your Unix-System:\n' +
                '    1. `crontab -e`\n' +
                '    2. Add `*/15 * * * * cd "{}" && moodle-dl`\n'.format(
                    os.getcwd()) + '    3. Save and you\'re done!')
        else:
            Log.info(
                '  To set a cron-job for this program on your Unix-System:\n' +
                '    1. `crontab -e`\n' +
                '    2. Add `*/15 * * * * cd "{}" && moodle-dl -p "{}"`\n'.
                format(os.getcwd(), storage_path) +
                '    3. Save and you\'re done!')

    print('')

    Log.info(
        'You can always do the additional configuration later with the --config option.'
    )

    do_config = cutie.prompt_yes_or_no(
        'Do you want to make additional configurations now?')

    if do_config:
        run_configure(storage_path, skip_cert_verify)

    print('')
    Log.success('All set and ready to go!')
Example #2
0
def run_init(storage_path, use_sso=False, skip_cert_verify=False):
    config = ConfigHelper(storage_path)

    if config.is_present():
        do_override_input = cutie.prompt_yes_or_no(Log.error_str('Do you want to override the existing config?'))

        if not do_override_input:
            sys.exit(0)

    MailService(config).interactively_configure()
    TelegramService(config).interactively_configure()
    XmppService(config).interactively_configure()

    do_sentry = cutie.prompt_yes_or_no('Do you want to configure Error Reporting via Sentry?')
    if do_sentry:
        sentry_dsn = input('Please enter your Sentry DSN:   ')
        config.set_property('sentry_dsn', sentry_dsn)

    moodle = MoodleService(config, storage_path, skip_cert_verify)

    if use_sso:
        moodle.interactively_acquire_sso_token()
    else:
        moodle.interactively_acquire_token()

    Log.success('Configuration finished and saved!')

    if os.name != 'nt':
        working_dir = os.path.abspath(storage_path)
        moodle_dl_path = os.path.abspath(sys.argv[0])
        Log.info(
            '  To set a cron-job for this program on your Unix-System:\n'
            + '    1. `crontab -e`\n'
            + '    2. Add `*/15 * * * * cd "{}" && "{}" >/dev/null 2>&1`\n'.format(working_dir, moodle_dl_path)
            + '    3. Save and you\'re done!'
        )

        Log.info(
            'For more ways to run `moodle-dl` periodically, take a look at the wiki (https://github.com/C0D3D3V/Moodle-Downloader-2/wiki/Start-Moodle-dl-periodically-or-via-Telegram)'
        )
    else:
        Log.info(
            'If you want to run moodle-dl periodically, you can take a look at the wiki (https://github.com/C0D3D3V/Moodle-Downloader-2/wiki/Start-Moodle-dl-periodically-or-via-Telegram)'
        )

    print('')

    Log.info('You can always do the additional configuration later with the --config option.')

    do_config = cutie.prompt_yes_or_no('Do you want to make additional configurations now?')

    if do_config:
        run_configure(storage_path, skip_cert_verify)

    print('')
    Log.success('All set and ready to go!')
    def _select_should_userid_and_version_be_saved(self, userid, version):
        """
        Asks the user if the userid and version should be saved in the configuration
        """

        print('')
        Log.info('The user id and version number of Moodle are downloaded' +
                 ' at the beginning of each run of the downloader.' +
                 ' Since this data rarely changes, it can be saved in the' +
                 ' configuration.')

        Log.critical(
            f'Your user id is `{userid}` and the moodle version is `{version}`'
        )

        print('')

        save_userid_and_version = cutie.prompt_yes_or_no(
            Log.special_str(
                'Do you want to store the user id and version number of Moodle in the configuration?'
            ),
            default_is_yes=False,
        )

        if save_userid_and_version:
            Log.warning('Remember to delete the version number from the' +
                        ' configuration once Moodle has been updated' +
                        ' and then run the configurator again!')

            self.config_helper.set_property('userid', userid)
            self.config_helper.set_property('version', version)

        self.section_seperator()
Example #4
0
    def _select_should_download_descriptions(self):
        """
        Asks the user if descriptions should be downloaded
        """
        download_descriptions = self.config_helper.get_download_descriptions()

        self.section_seperator()
        Log.info(
            'In Moodle courses, descriptions can be added to all kinds' +
            ' of resources, such as files, tasks, assignments or simply' +
            ' free text. These descriptions are usually unnecessary to' +
            ' download because you have already read the information or' +
            ' know it from context. However, there are situations where' +
            ' it might be interesting to download these descriptions. The' +
            ' descriptions are created as Markdown files and can be' +
            ' deleted as desired.')
        Log.debug(
            'Creating the description files does not take extra time, but they can be annoying'
            + ' if they only contain unnecessary information.')

        print('')

        download_descriptions = cutie.prompt_yes_or_no(
            Log.special_str(
                'Would you like to download descriptions of the courses you have selected?'
            ),
            default_is_yes=download_descriptions,
        )

        self.config_helper.set_property('download_descriptions',
                                        download_descriptions)
Example #5
0
    def _select_should_download_linked_files(self):
        """
        Asks the user if linked files should be downloaded
        """
        download_linked_files = self.config_helper.get_download_linked_files()

        self.section_seperator()
        Log.info('In Moodle courses the teacher can also link to external' +
                 ' files. This can be audio, video, text or anything else.' +
                 ' In particular, the teacher can link to Youtube videos.')
        Log.debug('To download videos correctly you have to install ffmpeg. ')

        Log.error('These files can increase the download volume considerably.')

        Log.info('If you want to filter the external links by their domain,' +
                 ' you can manually set a whitelist and a blacklist' +
                 ' (https://github.com/C0D3D3V/Moodle-Downloader-2/' +
                 'wiki/Download-(external)-linked-files' +
                 ' for more details).')
        Log.warning(
            'Please note that the size of the external files is determined during the download, so the total size'
            + ' changes during the download.')
        print('')

        download_linked_files = cutie.prompt_yes_or_no(
            Log.special_str(
                'Would you like to download linked files of the courses you have selected?'
            ),
            default_is_yes=download_linked_files,
        )

        self.config_helper.set_property('download_linked_files',
                                        download_linked_files)
Example #6
0
    def _select_should_load_default_filename_character_map(self):
        """
        Asks the user if the default filename character map should be loaded
        """
        filename_character_map = self.config_helper.get_filename_character_map(
        )

        if os.name != 'nt':
            self.section_seperator()

            Log.info(
                'On Windows many characters are forbidden in filenames and paths, if you want, these characters can be'
                + ' automatically removed from filenames.')

            Log.warning(
                'If you want to view the downloaded files on Windows this is important!'
            )

            print('Current filename character map: {}'.format(
                filename_character_map))
            Log.special(
                'Do you want to load the default filename character map for Windows?'
            )

            choices = [
                'No, leave it as it was.',
                'No, load the default linux filename character map.',
                'Yes, load the default windows filename character map.',
            ]

            print('[Confirm your selection with the Enter key]')
            print('')

            selected_map = cutie.select(options=choices)

            if selected_map == 0:
                return
            elif selected_map == 1:
                self.config_helper.set_default_filename_character_map(False)
            elif selected_map == 2:
                self.config_helper.set_default_filename_character_map(True)
        else:
            if filename_character_map != ConfigHelper.windows_map:

                self.section_seperator()
                Log.warning(
                    'Warning: Your current filename character map does not match the standard Windows'
                    + ' filename character map!')
                print('Current filename character map: {}'.format(
                    filename_character_map))
                load_default_map = cutie.prompt_yes_or_no(
                    Log.special_str(
                        'Do you want to load the default filename character map for Windows?'
                    ),
                    default_is_yes=False,
                )
                if load_default_map:
                    self.config_helper.set_default_filename_character_map(True)
    def interactively_configure(self) -> None:
        """
        Guides the user through the configuration of the telegram notification.
        """

        do_telegram = cutie.prompt_yes_or_no(
            'Do you want to activate Notifications via Telegram?')

        if not do_telegram:
            self.config_helper.remove_property('telegram')
        else:
            print('[The following Inputs are not validated!]')
            print(
                'Open the following link for help in setting up telegram notifications:'
                +
                ' https://github.com/C0D3D3V/Moodle-Downloader-2/wiki/Telegram-Notification'
            )
            config_valid = False
            while not config_valid:
                telegram_token = input('Telegram Token:    ')
                telegram_chatID = input('Telegram Chat ID:   ')

                print('Testing Telegram-Config...')

                try:
                    telegram_shooter = TelegramShooter(telegram_token,
                                                       telegram_chatID)
                    telegram_shooter.send(
                        'This is a Testmessage from Moodle Downloader!')
                except BaseException as e:
                    print('Error while sending the test message: %s' %
                          (str(e)))
                    continue

                else:
                    input('Please check if you received the Testmessage.' +
                          ' If yes, confirm with Return.\nIf not, exit' +
                          ' this program ([CTRL]+[C]) and try again later.')
                    config_valid = True

                raw_send_error_msg = ''
                while raw_send_error_msg not in ['y', 'n']:
                    raw_send_error_msg = input(
                        'Do you want to also get error reports sent in telegram? [y/n]   '
                    )

                do_send_error_msg = raw_send_error_msg == 'y'

                telegram_cfg = {
                    'token': telegram_token,
                    'chat_id': telegram_chatID,
                    'send_error_msg': do_send_error_msg,
                }

                self.config_helper.set_property('telegram', telegram_cfg)
Example #8
0
    def _change_settings_of(self, course: Course, options_of_courses: {}):
        """
        Ask for a new Name for the course.
        Then asks if a file structure should be created.
        """

        current_course_settings = options_of_courses.get(str(course.id), None)

        # create default settings
        if current_course_settings is None:
            current_course_settings = {
                'original_name': course.fullname,
                'overwrite_name_with': None,
                'create_directory_structure': True,
            }

        changed = False

        # Ask for new name
        overwrite_name_with = input(
            Log.special_str(
                'Enter a new name for this Course [leave blank for "%s"]:   ' %
                (course.fullname, )))

        if overwrite_name_with == '':
            overwrite_name_with = None

        if (overwrite_name_with != course.fullname
                and current_course_settings.get('overwrite_name_with',
                                                None) != overwrite_name_with):
            current_course_settings.update(
                {'overwrite_name_with': overwrite_name_with})
            changed = True

        # Ask if a file structure should be created
        create_directory_structure = current_course_settings.get(
            'create_directory_structure', True)

        create_directory_structure = cutie.prompt_yes_or_no(
            Log.special_str(
                'Should a directory structure be created for this course?'),
            default_is_yes=create_directory_structure,
        )

        if create_directory_structure is not current_course_settings.get(
                'create_directory_structure', True):
            changed = True
            current_course_settings.update(
                {'create_directory_structure': create_directory_structure})

        if changed:
            options_of_courses.update(
                {str(course.id): current_course_settings})
            self.config_helper.set_property('options_of_courses',
                                            options_of_courses)
    def interactively_configure(self) -> None:
        """
        Guides the user through the configuration of the xmpp notification.
        """

        do_xmpp = cutie.prompt_yes_or_no(
            'Do you want to activate Notifications via XMPP?')

        if not do_xmpp:
            self.config_helper.remove_property('xmpp')
        else:
            print('[The following Inputs are not validated!]')
            config_valid = False
            while not config_valid:
                sender = input('JID of the Sender:   ')
                password = getpass('Password for the Sender [no output]:   ')
                target = input('JID of the Target:   ')
                print('Testing XMPP-Config...')

                try:
                    xmpp_shooter = XmppShooter(sender, password, target)
                    xmpp_shooter.send(
                        'This is a Testmessage from Moodle Downloader!')
                except BaseException as e:
                    print('Error while sending the test message: %s' %
                          (str(e)))
                    continue

                else:
                    input('Please check if you received the Testmessage.' +
                          ' If yes, confirm with Return.\nIf not, exit' +
                          ' this program ([CTRL]+[C]) and try again later.')
                    config_valid = True

                raw_send_error_msg = ''
                while raw_send_error_msg not in ['y', 'n']:
                    raw_send_error_msg = input(
                        'Do you want to also get error reports sent in xmpp? [y/n]   '
                    )

                do_send_error_msg = raw_send_error_msg == 'y'

                xmpp_cfg = {
                    'sender': sender,
                    'password': password,
                    'target': target,
                    'send_error_msg': do_send_error_msg,
                }

                self.config_helper.set_property('xmpp', xmpp_cfg)
    def _select_should_download_forums(self):
        """
        Asks the user if forums should be downloaded
        """
        download_forums = self.config_helper.get_download_forums()

        self.section_seperator()
        Log.info(
            'In forums, students and teachers can discuss and exchange information together.'
        )
        print('')

        download_forums = cutie.prompt_yes_or_no(
            Log.special_str('Do you want to download forums of your courses?'),
            default_is_yes=download_forums)

        self.config_helper.set_property('download_forums', download_forums)
    def _select_should_download_workshops(self):
        """
        Asks the user if workshops should be downloaded
        """
        download_workshops = self.config_helper.get_download_workshops()

        self.section_seperator()
        Log.info(
            'Workshops function according to the peer review process.' +
            ' Students can make submissions and have to assess submissions of other students. '
        )
        print('')

        download_workshops = cutie.prompt_yes_or_no(
            Log.special_str(
                'Do you want to download workshops of your courses?'),
            default_is_yes=download_workshops)

        self.config_helper.set_property('download_workshops',
                                        download_workshops)
    def _select_should_download_quizzes(self):
        """
        Asks the user if quizzes should be downloaded
        """
        download_quizzes = self.config_helper.get_download_quizzes()

        self.section_seperator()
        Log.info(
            'Quizzes are tests that a student must complete in a course and are graded on.'
            +
            ' Only quizzes that are in progress or have been completed will be downloaded.'
        )
        print('')

        download_quizzes = cutie.prompt_yes_or_no(
            Log.special_str(
                'Do you want to download quizzes of your courses?'),
            default_is_yes=download_quizzes)

        self.config_helper.set_property('download_quizzes', download_quizzes)
    def _select_should_download_lessons(self):
        """
        Asks the user if lessons should be downloaded
        """
        download_lessons = self.config_helper.get_download_lessons()

        self.section_seperator()
        Log.info(
            'Lessons are a kind of self-teaching with pages of information and other pages with questions to answer.'
            +
            ' A student can be graded on their answers after completing a lesson. Currently, only lessons without'
            +
            ' the answers are downloaded. The answers are potentially also available for download,'
            + ' but this has not been implemented.')
        print('')

        download_lessons = cutie.prompt_yes_or_no(
            Log.special_str(
                'Do you want to download lessons of your courses?'),
            default_is_yes=download_lessons)

        self.config_helper.set_property('download_lessons', download_lessons)
Example #14
0
    def _select_should_download_links_in_descriptions(self):
        """
        Asks the user if links in descriptions should be downloaded
        """
        download_links_in_descriptions = self.config_helper.get_download_links_in_descriptions(
        )

        self.section_seperator()
        Log.info(
            'In the descriptions of files, sections, assignments or courses the teacher can add links to webpages,'
            +
            ' files or videos. That links can pont to a internal page on moodle or to an external webpage.'
        )
        print('')

        download_links_in_descriptions = cutie.prompt_yes_or_no(
            Log.special_str(
                'Would you like to download links in descriptions?'),
            default_is_yes=download_links_in_descriptions,
        )

        self.config_helper.set_property('download_links_in_descriptions',
                                        download_links_in_descriptions)
Example #15
0
    def _select_should_download_databases(self):
        """
        Asks the user if databases should be downloaded
        """
        download_databases = self.config_helper.get_download_databases()

        self.section_seperator()
        Log.info('In the database module of Moodle data can be stored' +
                 ' structured with information. Often it is also' +
                 ' possible for students to upload data there.  Because' +
                 ' the implementation of the downloader has not yet been' +
                 ' optimized at this point, it is optional to download the' +
                 ' databases. Currently only files are downloaded, thumbails' +
                 ' are ignored.')
        print('')

        download_databases = cutie.prompt_yes_or_no(
            Log.special_str(
                'Do you want to download databases of your courses?'),
            default_is_yes=download_databases)

        self.config_helper.set_property('download_databases',
                                        download_databases)
Example #16
0
    def _select_should_download_submissions(self):
        """
        Asks the user if submissions should be downloaded
        """
        download_submissions = self.config_helper.get_download_submissions()

        self.section_seperator()
        Log.info('Submissions are files that you or a teacher have uploaded' +
                 ' to your assignments. Moodle does not provide an' +
                 ' interface for downloading information from all' +
                 ' submissions to a course at once.')
        Log.warning(
            'Therefore, it may be slow to monitor changes to submissions.')
        print('')

        download_submissions = cutie.prompt_yes_or_no(
            Log.special_str(
                'Do you want to download submissions of your assignments?'),
            default_is_yes=download_submissions,
        )

        self.config_helper.set_property('download_submissions',
                                        download_submissions)
    def _select_should_download_also_with_cookie(self):
        """
        Ask the user whether files for which a cookie is required should be downloaded.
        """
        download_also_with_cookie = self.config_helper.get_download_also_with_cookie(
        )

        self.section_seperator()
        Log.info(
            'Descriptions may contain links to files that require a browser cookie so they can be downloaded.'
            +
            ' There are also several Moodle plugins that cannot be displayed in the Moodle app,'
            + ' so you need a browser cookie to download these plugin files.')

        Log.debug(
            'The Moodle browser cookie is created using your private token and stored in the `Configs.txt` file.'
            +
            ' As long as this option is activated, the file always contains a valid cookie.'
        )

        if self.config_helper.get_privatetoken() is None:
            Log.error(
                'Currently no private token is stored in the configuration.' +
                ' Create a private token with moodle-dl --new-token (if necessary with --sso)'
            )

        print('')

        download_also_with_cookie = cutie.prompt_yes_or_no(
            Log.special_str(
                'Would you like to download files for which a cookie is required?'
            ),
            default_is_yes=download_also_with_cookie,
        )

        self.config_helper.set_property('download_also_with_cookie',
                                        download_also_with_cookie)
Example #18
0
    def interactively_acquire_sso_token(self, use_stored_url: bool = False) -> str:
        """
        Walks the user through the receiving of a SSO token for the
        Moodle-System and saves it.
        @return: The Token for Moodle.
        """
        if not use_stored_url:

            moodle_url = input('URL of Moodle:   ')

            moodle_uri = urlparse(moodle_url)

            moodle_domain, moodle_path = self._split_moodle_uri(moodle_uri)

        else:
            moodle_domain = self.config_helper.get_moodle_domain()
            moodle_path = self.config_helper.get_moodle_path()

        use_http = self.config_helper.get_use_http()
        scheme = 'https://'
        if use_http:
            scheme = 'http://'

        atomatic_procedure_warning = (
            'Between version 3.81 and 3.82 a change was added to'
            + ' Moodle so that automatic copying of the SSO token'
            + ' might not work.'
        )
        try:
            version = RequestHelper(
                moodle_domain,
                moodle_path,
                skip_cert_verify=self.skip_cert_verify,
                use_http=use_http,
            ).get_simple_moodle_version()

            if StrictVersion(version) > StrictVersion("3.8.1"):
                Log.warning(atomatic_procedure_warning + '\nYou can still try it, your version is: ' + str(version))

        except ConnectionError:
            Log.warning(
                atomatic_procedure_warning
                + '\nThe version of your Moodle could not be detected, you can still try the automatic procedure.'
            )

        print(' If you want to copy the login-token manual, you will be guided through the manual copy process.')
        do_automatic = cutie.prompt_yes_or_no('Do you want to try to receive the SSO token automatically?')

        print('Please log into Moodle on this computer and then visit the following address in your web browser: ')

        if do_automatic:
            print(
                scheme
                + moodle_domain
                + moodle_path
                + 'admin/tool/mobile/launch.php?service='
                + 'moodle_mobile_app&passport=12345&'
                + 'urlscheme=http%3A%2F%2Flocalhost'
            )
            moodle_token = sso_token_receiver.receive_token()
        else:
            print(
                scheme
                + moodle_domain
                + moodle_path
                + 'admin/tool/mobile/launch.php?service='
                + 'moodle_mobile_app&passport=12345&urlscheme=moodledownloader'
            )

            print(
                'If you open the link in the browser, no web page should'
                + ' load, instead an error will occur. Open the'
                + ' developer console (press F12) and go to the Network Tab,'
                + ' if there is no error, reload the web page.'
            )

            print(
                'Copy the link address of the website that could not be'
                + ' loaded (right click, then click on Copy, then click'
                + ' on copy link address).'
            )

            print(
                'The script expects a URL that looks something like this:'
                + '`moodledownloader://token=$apptoken`.'
                + ' Where $apptoken looks random. In reality it is a Base64'
                + ' encoded hash and the token we need to access moodle.'
            )

            token_address = input('Then insert the address here:   ')

            moodle_token, moodle_privatetoken = sso_token_receiver.extract_token(token_address)
            if moodle_token is None:
                raise ValueError('Invalid URL!')

        # Saves the created token and the successful Moodle parameters.
        self.config_helper.set_property('token', moodle_token)
        if moodle_privatetoken is not None:
            self.config_helper.set_property('privatetoken', moodle_privatetoken)
        self.config_helper.set_property('moodle_domain', moodle_domain)
        self.config_helper.set_property('moodle_path', moodle_path)

        return moodle_token
    def interactively_configure(self) -> None:
        """
        Guides the user through the configuration of the mail notification.
        """

        do_mail = cutie.prompt_yes_or_no(
            'Do you want to activate Notifications via mail?')

        if not do_mail:
            self.config_helper.remove_property('mail')
        else:
            print('[The following Inputs are not validated!]')

            config_valid = False
            while not config_valid:
                sender = input('E-Mail-Address of the Sender:   ')
                server_host = input('Host of the SMTP-Server:   ')
                server_port = input(
                    'Port of the SMTP-Server [STARTTLS, default 587]:   ')
                if server_port == '':
                    print('Using default port 587!')
                    server_port = '587'
                username = input('Username for the SMTP-Server:   ')
                password = getpass(
                    'Password for the SMTP-Server [no output]:   ')
                target = input('E-Mail-Address of the Target:   ')

                print('Testing Mail-Config...')
                welcome_content = create_full_welcome_mail()
                mail_shooter = MailShooter(sender, server_host,
                                           int(server_port), username,
                                           password)
                try:
                    mail_shooter.send(target, 'Hey!', welcome_content[0],
                                      welcome_content[1])
                except BaseException as e:
                    print('Error while sending the test mail: %s' % (str(e)))
                    continue
                else:
                    input('Please check if you received the Welcome-Mail.' +
                          ' If yes, confirm with Return.\nIf not, exit' +
                          ' this program ([CTRL]+[C]) and try again later.')
                    config_valid = True

                raw_send_error_msg = ''
                while raw_send_error_msg not in ['y', 'n']:
                    raw_send_error_msg = input(
                        'Do you want to also get error reports sent by mail? [y/n]   '
                    )
                do_send_error_msg = raw_send_error_msg == 'y'

                mail_cfg = {
                    'sender': sender,
                    'server_host': server_host,
                    'server_port': server_port,
                    'username': username,
                    'password': password,
                    'target': target,
                    'send_error_msg': do_send_error_msg,
                }

                self.config_helper.set_property('mail', mail_cfg)
    def interactively_add_all_visible_courses(self):
        """
        Guides the user through the process of adding all visible courses
        to the list of courses to download in the configuration
        """

        token = self.config_helper.get_token()
        moodle_domain = self.config_helper.get_moodle_domain()
        moodle_path = self.config_helper.get_moodle_path()
        use_http = self.config_helper.get_use_http()

        request_helper = RequestHelper(moodle_domain,
                                       moodle_path,
                                       token,
                                       self.skip_cert_verify,
                                       use_http=use_http)
        first_contact_handler = FirstContactHandler(request_helper)

        print('')
        Log.info(
            'It is possible to automatically complete the moodle-dl configuration'
            +
            ' with all the courses you can see on your moodle. These are either'
            + ' courses to which you have the appropriate rights to see the' +
            ' course or the course is visible without enrollment.')

        Log.critical(
            'This process can take several minutes for large Moodels, as is common at'
            + ' large universities. Timeout is set to 20 minutes.')

        print('')

        add_all_visible_courses = cutie.prompt_yes_or_no(
            Log.special_str(
                'Do you want to add all visible courses of your Moodle to the configuration?'
            ),
            default_is_yes=False,
        )

        if not add_all_visible_courses:
            return
        else:
            Log.warning(
                'Please wait for the result, this may take several minutes.' +
                ' In addition to adding the courses to the configuration,' +
                ' it will also create an `all_courses.json` file with all' +
                ' the courses available on your Moodle.')

        courses = []
        all_visible_courses = []
        try:
            userid, version = self.config_helper.get_userid_and_version()
            if userid is None or version is None:
                userid, version = first_contact_handler.fetch_userid_and_version(
                )
            else:
                first_contact_handler.version = version

            courses = first_contact_handler.fetch_courses(userid)
            log_all_courses_to = str(
                Path(self.storage_path) / 'all_courses.json')
            all_visible_courses = first_contact_handler.fetch_all_visible_courses(
                log_all_courses_to)

        except (RequestRejectedError, ValueError, RuntimeError,
                ConnectionError) as error:
            Log.error(
                'Error while communicating with the Moodle System! (%s)' %
                (error))
            sys.exit(1)

        # Filter out courses the user is enroled in
        filtered_all_courses = []
        for visible_course in all_visible_courses:
            add_to_final_list = True
            for course in courses:
                if visible_course.id == course.id:
                    add_to_final_list = False
                    break
            if add_to_final_list:
                filtered_all_courses.append(visible_course)

        # Update Public Courses IDs
        download_public_course_ids = self.config_helper.get_download_public_course_ids(
        )
        # Update Course settings List for all new Courses
        options_of_courses = self.config_helper.get_options_of_courses()
        for course in filtered_all_courses:
            current_course_settings = options_of_courses.get(
                str(course.id), None)

            # create default settings
            if current_course_settings is None:
                current_course_settings = {
                    'original_name': course.fullname,
                    'overwrite_name_with': None,
                    'create_directory_structure': True,
                }

                options_of_courses.update(
                    {str(course.id): current_course_settings})

            if course.id not in download_public_course_ids:
                download_public_course_ids.append(course.id)

        self.config_helper.set_property('options_of_courses',
                                        options_of_courses)
        self.config_helper.set_property('download_public_course_ids',
                                        download_public_course_ids)
Example #21
0
def run_init(storage_path, use_sso=False, skip_cert_verify=False):
    config = ConfigHelper(storage_path)

    if config.is_present():
        do_override_input = cutie.prompt_yes_or_no(Log.error_str('Do you want to override the existing config?'))

        if not do_override_input:
            sys.exit(0)

    MailService(config).interactively_configure()
    TelegramService(config).interactively_configure()

    do_sentry = cutie.prompt_yes_or_no('Do you want to configure Error Reporting via Sentry?')
    if do_sentry:
        sentry_dsn = input('Please enter your Sentry DSN:   ')
        config.set_property('sentry_dsn', sentry_dsn)

    moodle = MoodleService(config, storage_path, skip_cert_verify)

    if use_sso:
        moodle.interactively_acquire_sso_token()
    else:
        moodle.interactively_acquire_token()

    if os.name != 'nt':
        Log.info(
            'On Windows many characters are forbidden in filenames and paths, if you want, these characters can be'
            + ' automatically removed from filenames.'
        )

        Log.warning('If you want to view the downloaded files on Windows this is important!')

        default_windows_map = cutie.prompt_yes_or_no(
            'Do you want to load the default filename character map for windows?'
        )
        if default_windows_map:
            config.set_default_filename_character_map(True)
        else:
            config.set_default_filename_character_map(False)
    else:
        config.set_default_filename_character_map(True)

    Log.success('Configuration finished and saved!')

    if os.name != 'nt':
        if storage_path == '.':
            Log.info(
                '  To set a cron-job for this program on your Unix-System:\n'
                + '    1. `crontab -e`\n'
                + '    2. Add `*/15 * * * * cd %s && python3 %smain.py`\n'
                % (os.getcwd(), os.path.join(os.path.dirname(os.path.realpath(__file__)), ''))
                + '    3. Save and you\'re done!'
            )
        else:
            Log.info(
                '  To set a cron-job for this program on your Unix-System:\n'
                + '    1. `crontab -e`\n'
                + '    2. Add `*/15 * * * *'
                + ' cd %s && python3 %smain.py --path %s`\n'
                % (os.getcwd(), os.path.join(os.path.dirname(os.path.realpath(__file__)), ''), storage_path)
                + '    3. Save and you\'re done!'
            )

    print('')

    Log.info('You can always do the additional configuration later with the --config option.')

    do_config = cutie.prompt_yes_or_no('Do you want to make additional configurations now?')

    if do_config:
        run_configure(storage_path, skip_cert_verify)

    print('')
    Log.success('All set and ready to go!')