コード例 #1
0
ファイル: user_prompter.py プロジェクト: wlmeng11/CanvasSync
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
コード例 #2
0
ファイル: user_prompter.py プロジェクト: wlmeng11/CanvasSync
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
コード例 #3
0
ファイル: user_prompter.py プロジェクト: wlmeng11/CanvasSync
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
コード例 #4
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)
コード例 #5
0
ファイル: user_prompter.py プロジェクト: wlmeng11/CanvasSync
def ask_for_use_nicknames(settings):
    choice = -1

    while choice not in (1, 2):
        settings.print_advanced_settings(clear=True)
        print(ANSI.format(u"\n\nCourse display name settings", u"announcer"))
        print(
            ANSI.format(
                u"In addition to identifying courses by their couse code,\n"
                u"Canvas can also identify courses using user-defined\n"
                u"nicknames that can be specified from within the Canvas UI.\n"
                u"Do you want CanvasSync to use course nicknames rather than\n"
                u"course codes for display and directory structure?\n",
                u"white"))

        print(ANSI.format(u"1) No, use course codes (default)", u"bold"))
        print(
            ANSI.format(
                u"2) Yes, use course nicknames (you will be \n"
                u"     prompted to reselect courses)", u"bold"))

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

        if choice == 1:
            return False
        elif choice == 2:
            return True
        else:
            continue
コード例 #6
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:
            static_functions.clear_console()

        if first_time_setup:
            print(
                ANSI.format(
                    u"This is a first time setup.\nYou must specify 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)
コード例 #7
0
ファイル: user_prompter.py プロジェクト: wlmeng11/CanvasSync
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
コード例 #8
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)
コード例 #9
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()
コード例 #10
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:
            static_functions.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)
        print(ANSI.BOLD + u"[*] Use course nicknames:     \t" + ANSI.ENDC +
              (ANSI.GREEN if self.use_nicknames else ANSI.RED) +
              str(self.use_nicknames) + ANSI.ENDC)
コード例 #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
ファイル: user_prompter.py プロジェクト: wlmeng11/CanvasSync
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
ファイル: user_prompter.py プロジェクト: wlmeng11/CanvasSync
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):
        static_functions.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 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()
コード例 #15
0
ファイル: user_prompter.py プロジェクト: wlmeng11/CanvasSync
def ask_for_courses(settings, api):

    courses = api.get_courses()

    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
ファイル: synchronizer.py プロジェクト: wlmeng11/CanvasSync
    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. Please wait...",
                u"red"))

        self.add_courses()

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

        return counter
コード例 #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 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)
            settings += u"Use nicknames$" + str(self.use_nicknames)

            out_file.write(encrypt(settings))
コード例 #19
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 static_functions.validate_token(self.domain, self.token)

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

        encrypted_message = open(self.settings_path, u"rb").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 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]

        # 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])

            if message[:6] == u"Files$":
                self.modules_settings[u"Files"] = True if message.split(
                    u"$")[-1] == u"True" else False

            if message[:11] == u"HTML pages$":
                self.modules_settings[u"HTML pages"] = True if message.split(
                    u"$")[-1] == u"True" else False

            if message[:14] == u"External URLs$":
                self.modules_settings[
                    u"External URLs"] = True if message.split(
                        u"$")[-1] == u"True" else False

            if message[:12] == u"Assignments$":
                self.sync_assignments = True if message.split(
                    u"$")[-1] == u"True" else False

            if message[:13] == u"Linked files$":
                self.download_linked = True if message.split(
                    u"$")[-1] == u"True" else False

            if message[:17] == u"Avoid duplicates$":
                self.avoid_duplicates = True if message.split(
                    u"$")[-1] == u"True" else False

            if message[:14] == u"Use nicknames$":
                self.use_nicknames = True if message.split(
                    u"$")[-1] == u"True" else False

        if not static_functions.validate_token(self.domain, self.token):
            return False
        else:
            return True
コード例 #20
0
ファイル: module.py プロジェクト: wlmeng11/CanvasSync
 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
    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"))


# If main module
if __name__ == u"__main__":

    if os.name == u"nt":
        # Warn Windows users
        static_functions.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()
コード例 #22
0
ファイル: file.py プロジェクト: wlmeng11/CanvasSync
 def __repr__(self):
     """ String representation, overwriting base class method """
     return u" " * 15 + u"|   " + u"\t" * self.indent + u"%s: %s" % (
         ANSI.format(u"File", formatting=u"file"), self.name)