예제 #1
0
def ask_for_avoid_duplicates(settings):
    choice = -1

    while choice not in (1, 2):
        settings.print_advanced_settings(clear=True)
        print(ANSI.format(u"\n\nVarious files settings", u"announcer"))
        print(ANSI.format(u"In addition to synchronizing modules and assignments,\n"
                          u"CanvasSync will sync files located under the 'Files'\n"
                          u"section in Canvas into a 'Various Files' folder.\n"
                          u"Often some of the files stored under 'Files' is mentioned in\n"
                          u"modules and assignments and may thus already exist in another\n"
                          u"folder after running CanvasSync.\n\n"
                          u"Do you want CanvasSync to avoid duplicates by only downloading\n"
                          u"files into the 'Various Files' folder, if they are not already\n"
                          u"present in one of the modules or assignments folders?\n", u"white"))

        print(ANSI.format(u"1) Yes, avoid duplicates (default)", u"bold"))
        print(ANSI.format(u"2) No, download all files to 'Various files'", u"bold"))

        try:
            choice = int(input(u"\nChoose number: "))
        except ValueError:
            continue

        if choice == 1:
            return True
        elif choice == 2:
            return False
        else:
            continue
예제 #2
0
 def __repr__(self):
     """ String representation, overwriting base class method """
     status = ANSI.format(
         u"[SYNCED]" if self.to_be_synced else u"[SKIPPED]",
         formatting=u"green" if self.to_be_synced else u"yellow")
     return status + u" " * (7 if self.to_be_synced else 6) + u"|   " + u"\t" * self.indent + u"%s: %s" \
                                                     % (ANSI.format(u"Course", formatting=u"course"), self.name)
예제 #3
0
def ask_for_assignment_sync(settings):
    choice = -1

    while choice not in (1, 2):
        settings.print_advanced_settings(clear=True)
        print(ANSI.format(u"\n\nAssignments settings", u"announcer"))
        print(ANSI.format(u"Would you like CanvasSync to synchronize assignments?\n\n"
                          u"The assignment description will be downloaded as a HTML to be viewed offline\n"
                          u"and files hosted on the Canvas server that are described in the assignment\n"
                          u"description section will be downloaded to the same folder.\n", u"white"))

        print(ANSI.format(u"1) Sync assignments (default)", u"bold"))
        print(ANSI.format(u"2) Do not sync assignments", u"bold"))

        try:
            choice = int(input(u"\nChoose number: "))
        except ValueError:
            continue

        if choice == 1:
            return True
        elif choice == 2:
            return False
        else:
            continue
예제 #4
0
def ask_for_download_linked(settings):
    choice = -1

    while choice not in (1, 2):
        settings.print_advanced_settings(clear=True)
        print(ANSI.format(u"\n\nAssignments settings", u"announcer"))
        print(ANSI.format(u"You have chosen to synchronise assignments. URLs detected in the\n"
                          u"description field that point to files on Canvas will be downloaded\n"
                          u"to the assignment folder.\n\n"
                          u"CanvasSync may also attempt to download linked files that are NOT\n"
                          u"hosted on the Canvas server itself. CanvasSync is looking for URLs that\n"
                          u"end in a filename to avoid downloading other linked material such as\n"
                          u"web-sites. However, be aware that errors could occur.\n"
                          u"\nDo you wish to enable this feature?\n", u"white"))

        print(ANSI.format(u"1) Enable linked file downloading (default)", u"bold"))
        print(ANSI.format(u"2) Disable linked file downloading", u"bold"))

        try:
            choice = int(input(u"\nChoose number: "))
        except ValueError:
            continue

        if choice == 1:
            return True
        elif choice == 2:
            return False
        else:
            continue
예제 #5
0
    def print_settings(self, first_time_setup=True, clear=True):
        """
        Print the settings currently in memory.
        Clear the console first if specified by the 'clear' parameter
        """
        if clear:
            helpers.clear_console()

        if first_time_setup:
            print(ANSI.format(u"This is a first time setup.\nYou must specify "
                              u"at least the following settings"
                              u" in order to run CanvasSync:\n", u"announcer"))
        else:
            print(ANSI.format(u"-----------------------------", u"file"))
            print(ANSI.format(u"CanvasSync - Current settings", u"file"))
            print(ANSI.format(u"-----------------------------\n", u"file"))
            print(ANSI.format(u"Standard settings", u"announcer"))

        print(ANSI.BOLD + u"[*] Sync path:             \t" + ANSI.ENDC + ANSI.BLUE + self.sync_path + ANSI.ENDC)
        print(ANSI.BOLD + u"[*] Canvas domain:         \t" + ANSI.ENDC + ANSI.BLUE + self.domain + ANSI.ENDC)
        print(ANSI.BOLD + u"[*] Authentication token:  \t" + ANSI.ENDC + ANSI.BLUE + self.token + ANSI.ENDC)

        if len(self.courses_to_sync) != 0:
            if self.courses_to_sync[0] == u"Not set":
                d = u""
            else:
                d = u"1) "
            print(ANSI.BOLD + u"[*] Courses to be synced:  \t%s" % d + ANSI.ENDC + ANSI.BLUE + self.courses_to_sync[0] + ANSI.ENDC)

            for index, course in enumerate(self.courses_to_sync[1:]):
                print(u" "*27 + u"\t%s) " % (index+2) + ANSI.BLUE + course + ANSI.ENDC)
예제 #6
0
def ask_for_advanced_settings(settings):
    choice = -1
    while choice not in (1, 2):
        settings.print_settings(clear=True)

        print(
            ANSI.format(
                u"\n\nAll mandatory settings are set. Do you wish see advanced settings?",
                u"announcer"))

        print(
            ANSI.format(u"\n[1]\tShow advanced settings (recommended)",
                        u"bold"))
        print(ANSI.format(u"[2]\tUse default settings", u"bold"))

        try:
            choice = int(input(u"\nChoose number: "))
        except ValueError:
            continue

        if choice == 1:
            return True
        elif choice == 2:
            return False
        else:
            continue
예제 #7
0
 def __repr__(self):
     """ String representation, overwriting base class method """
     status = ANSI.format(u"[SYNCED]", formatting=u"green")
     return status + u" " * 7 + u"|   " + u"\t" * self.indent + u"%s: %s" \
                                                                % (ANSI.format(u"Assignments Folder",
                                                                               formatting=u"assignments"),
                                                                   self.name)
예제 #8
0
    def print_status(self, status, color, overwrite_previous_line=False):
        """ Print status to console """
        if overwrite_previous_line:
            # Move up one line
            sys.stdout.write(ANSI.format(u"", formatting=u"lineup"))
            sys.stdout.flush()

        print(
            ANSI.format(u"[%s]" % status, formatting=color) +
            str(self)[len(status) + 2:])
        sys.stdout.flush()
예제 #9
0
    def print_advanced_settings(self, clear=True):
        """
        Print the advanced settings currently in memory.
        Clear the console first if specified by the 'clear' parameter
        """
        if clear:
            helpers.clear_console()

        print(ANSI.format(u"\nAdvanced settings", u"announcer"))

        module_settings_string = ANSI.BOLD + u"[*] Sync module items:        \t" + ANSI.ENDC

        count = 0
        for item in self.modules_settings:
            if self.modules_settings[item]:
                d = u" & " if count != 0 else u""
                module_settings_string += d + ANSI.BLUE + item + ANSI.ENDC
                count += 1

        if count == 0:
            module_settings_string += ANSI.RED + u"False" + ANSI.ENDC

        print(module_settings_string)
        print(ANSI.BOLD + u"[*] Sync assignments:         \t" + ANSI.ENDC + (ANSI.GREEN if self.sync_assignments else ANSI.RED) + str(self.sync_assignments) + ANSI.ENDC)
        print(ANSI.BOLD + u"[*] Download linked files:    \t" + ANSI.ENDC + (ANSI.GREEN if self.download_linked else ANSI.RED) + str(self.download_linked) + ANSI.ENDC)
        print(ANSI.BOLD + u"[*] Avoid item duplicates:    \t" + ANSI.ENDC + (ANSI.GREEN if self.avoid_duplicates else ANSI.RED) + str(self.avoid_duplicates) + ANSI.ENDC)
예제 #10
0
    def load_settings(self, password):
        """
        Loads the current settings from the settings file and sets the
        attributes of the Settings object
        """
        if self.is_loaded():
            return helpers.validate_token(self.domain, self.token)

        if not self.settings_file_exists():
            self.set_settings()
            return True

        with open(self.settings_path, u"rb") as settings_f:
            encrypted_message = settings_f.read()
        messages = decrypt(encrypted_message, password)
        if not messages:
            # Password file did not exist, set new settings
            print(ANSI.format(u"\n[ERROR] The hashed password file does not"
                              u"longer exist. You must re-enter settings.",
                              u"announcer"))
            input(u"\nPres enter to continue.")
            self.set_settings()
            return self.load_settings("")
        else:
            messages = messages.decode(u"utf-8").split(u"\n")

        # Set sync path, domain and auth token
        self.sync_path, self.domain, self.token = messages[:3]

        def read_setting(settings_string):
            return settings_string.split(u"$")[-1] == u"True"

        # Extract synchronization settings
        for message in messages:
            if message[:12] == u"SYNC COURSE$":
                if self.courses_to_sync[0] == u"Not set":
                    self.courses_to_sync.pop(0)
                self.courses_to_sync.append(message.split(u"$")[-1])

            setting = read_setting(message)
            if message[:6] == u"Files$":
                self.modules_settings[u"Files"] = setting
            if message[:11] == u"HTML pages$":
                self.modules_settings[u"HTML pages"] = setting
            if message[:14] == u"External URLs$":
                self.modules_settings[u"External URLs"] = setting
            if message[:12] == u"Assignments$":
                self.sync_assignments = setting
            if message[:13] == u"Linked files$":
                self.download_linked = setting
            if message[:17] == u"Avoid duplicates$":
                self.avoid_duplicates = setting
            if message[:14] == u"Use nicknames$":
                self.use_nicknames = setting

        if not helpers.validate_token(self.domain, self.token):
            return False
        else:
            return True
예제 #11
0
    def set_settings(self):
        try:
            self._set_settings()
        except KeyboardInterrupt:
            print(ANSI.format(u"\n\n[*] Setup interrupted, nothing was saved.", formatting=u"red"))
            sys.exit()

        self.write_settings()
예제 #12
0
def ask_for_module_settings(module_settings, settings):
    choice = -1
    while choice != 0:
        settings.print_advanced_settings(clear=True)
        print(ANSI.format(u"\n\nModule settings", u"announcer"))
        print(
            ANSI.format(
                u"In Canvas, 'Modules' may contain various items such as files, HTML pages of\n"
                u"exercises or reading material as well as links to external web-pages.\n\n"
                u"Below you may specify, if you would like CanvasSync to avoid syncing some of these items.\n"
                u"OBS: If you chose 'False' to all items, Modules will be skipped all together.",
                u"white"))

        print(ANSI.format(u"\nSync this item\tNumber\t\tItem", u"blue"))

        list_of_keys = list(module_settings.keys())
        for index, item in enumerate(list_of_keys):

            boolean = module_settings[item]

            print(u"%s\t\t[%s]\t\t%s" %
                  (ANSI.format(str(boolean), u"green" if boolean else u"red"),
                   index + 1, item))

        print(u"\n\t\t[%s]\t\t%s" %
              (0, ANSI.format(u"Confirm selection", u"blue")))

        try:
            choice = int(input(u"\nChoose number: "))
            if choice < 0 or choice > len(module_settings):
                continue
        except ValueError:
            continue

        if choice == 0:
            break
        else:
            module_settings[list_of_keys[choice - 1]] = module_settings[
                list_of_keys[choice - 1]] is not True

    return module_settings
예제 #13
0
def show_main_screen(settings_file_exists):
    """
    Prompt the user for initial choice of action. Does not allow Synchronization before settings file has been set
    """

    choice = -1
    to_do = "quit"
    while choice not in (0, 1, 2, 3, 4):
        helpers.clear_console()

        # Load version string
        import CanvasSync
        version = CanvasSync.__version__

        title = u"CanvasSync, "
        pretty_string = u"-" * (len(title) + len(version))

        print(
            ANSI.format(
                u"%s\n%s%s\n%s" %
                (pretty_string, title, version, pretty_string), u"file"))

        print(
            ANSI.format(
                u"Automatically synchronize modules, assignments & files located on a Canvas web server.",
                u"announcer"))
        print(ANSI.format(u"\nWhat would you like to do?", u"underline"))
        print(u"\n\t1) " + ANSI.format(u"Synchronize my Canvas", u"blue"))
        print(u"\t2) " + ANSI.format(u"Set new settings", u"white"))
        print(u"\t3) " + ANSI.format(u"Show current settings", u"white"))
        print(u"\t4) " + ANSI.format(u"Show help", u"white"))
        print(u"\n\t0) " + ANSI.format(u"Quit", u"yellow"))

        try:
            choice = int(input(u"\nChoose number: "))
            if choice < 0 or choice > 4:
                continue
        except ValueError:
            continue

        if choice == 1 and not settings_file_exists:
            to_do = u"set_settings"
        else:
            to_do = [
                u"quit", u"sync", u"set_settings", u"show_settings",
                u"show_help"
            ][choice]

    return to_do
예제 #14
0
    def walk(self):
        """ Walk by adding all Courses to the list of children """

        # Print initial walk message
        print(self)
        print(ANSI.format(u"\n[*] Mapping out the Canvas folder hierarchy. "
                          u"Please wait...", u"red"))
        self.add_courses()

        counter = [2]
        for course in self:
            course.walk(counter)

        return counter
예제 #15
0
def ask_for_courses(settings, api):

    courses = api.get_courses()
    for name in courses[:]:
        if not 'course_code' in name:
            courses.remove(name)
    if settings.use_nicknames:
        courses = [name[u"name"] for name in courses]
    else:
        courses = [name[u"course_code"].split(";")[-1] for name in courses]

    choices = [True] * len(courses)

    choice = -1
    while choice != 0:
        settings.print_settings(clear=True)
        print(
            ANSI.format(
                u"\n\nPlease choose which courses you would like CanvasSync to sync for you:\n",
                u"white"))

        print(ANSI.format(u"Sync this item\tNumber\tCourse Title", u"blue"))
        for index, course in enumerate(courses):
            print(u"%s\t\t[%s]\t%s" %
                  (ANSI.format(str(choices[index]), u"green" if choices[index]
                               else u"red"), index + 1, courses[index]))
        print(u"\n\n\t\t[%s]\t%s" %
              (0,
               ANSI.format(u"Confirm selection (at least one course required)",
                           "blue")))
        print(u"\t\t[%s]\t%s" % (-1, ANSI.format(u"Select all", u"green")))
        print(u"\t\t[%s]\t%s" % (-2, ANSI.format(u"Deselect all", u"red")))

        try:
            choice = int(input(u"\nChoose number: "))
            if choice < -2 or choice > len(courses):
                continue
        except ValueError:
            continue

        if choice == 0:
            if sum(choices) == 0:
                choice = -1
                continue
            else:
                break
        elif choice == -1:
            choices = [True] * len(courses)
        elif choice == -2:
            choices = [False] * len(courses)
        else:
            choices[choice - 1] = choices[choice - 1] is not True

    print(choices)

    return [x for index, x in enumerate(courses) if choices[index]]
예제 #16
0
    def sync(self):
        """
        Synchronize by creating a local URL shortcut file in in at the sync_pat
        ExternalUrl objects have no children objects and represents an end point of a folder traverse.
        """
        make_url_shortcut(url=self.url_info[u"external_url"],
                          path=self.sync_path)

        # As opposed to the File and Page classes we never write the "DOWNLOAD" status as we already have
        # all information needed to create the URL shortcut at this point. Here we just print the SYNCED status
        # no matter if the shortcut was recreated or not
        print(
            ANSI.format(u"[SYNCED]", formatting=u"green") +
            str(self)[len(u"[SYNCED]"):])
        sys.stdout.flush()
예제 #17
0
def do_sync(settings, password=None):
    # Initialize the Instructure Api object used to make API
    # calls to the Canvas server
    valid_token = settings.load_settings(password)
    if not valid_token:
        settings.print_auth_token_reset_error()
        sys.exit()

    # Initialize the API object
    api = InstructureApi(settings)

    # Start Synchronizer with the current settings
    synchronizer = Synchronizer(settings=settings, api=api)
    synchronizer.sync()

    # If here, sync was completed, show prompt
    print(ANSI.format(u"\n\n[*] Sync complete", formatting=u"bold"))
예제 #18
0
def entry():
    if os.name == u"nt":
        # Warn Windows users
        helpers.clear_console()
        input(
            u"\n[OBS] You are running CanvasSync on a Windows operating system.\n"
            u"      The application is not developed for Windows machines and may be\n"
            u"      unstable. Some pretty output formatting and tab-autocompletion\n"
            u"      is not supported... :-(\n"
            u"\n    Anyway, hit enter to start.")

    try:
        run_canvas_sync()
    except KeyboardInterrupt:
        print(
            ANSI.format(u"\n\n[*] Synchronization interrupted",
                        formatting=u"red"))
        sys.exit()
예제 #19
0
    def write_settings(self):
        self.print_settings(first_time_setup=False, clear=True)
        self.print_advanced_settings(clear=False)
        print(ANSI.format(u"\n\nThese settings will be saved", u"announcer"))

        # Write password encrypted settings to hidden file in home directory
        with open(self.settings_path, u"wb") as out_file:
            settings = self.sync_path + u"\n" + self.domain + u"\n" + self.token + u"\n"

            for course in self.courses_to_sync:
                settings += u"SYNC COURSE$" + course + u"\n"

            settings += u"Files$" + str(self.modules_settings[u"Files"]) + u"\n"
            settings += u"HTML pages$" + str(self.modules_settings[u"HTML pages"]) + u"\n"
            settings += u"External URLs$" + str(self.modules_settings[u"External URLs"]) + u"\n"
            settings += u"Assignments$" + str(self.sync_assignments) + u"\n"
            settings += u"Linked files$" + str(self.download_linked) + u"\n"
            settings += u"Avoid duplicates$" + str(self.avoid_duplicates) + u"\n"

            out_file.write(encrypt(settings))
예제 #20
0
 def __repr__(self):
     """ String representation, overwriting base class method """
     status = ANSI.format(u"[SYNCED]", formatting=u"green")
     return (status + u" " * 7 + u"|   " + u"\t" * self.indent + u"%s: %s" %
             (ANSI.format(u"Module", formatting=u"module"), self.name))
예제 #21
0
 def __repr__(self):
     """ String representation, overwriting base class method """
     return u" " * 15 + u"|   " + u"\t" * self.indent + u"%s: %s" % (
         ANSI.format(u"ExternalUrl", formatting=u"externalurl"), self.name)