Beispiel #1
0
def redvest_creator():
    # Build service
    service = util.build_service()

    # Read folder locations
    redvest_options = util.parse_options("redvest_options.json")
    if redvest_options == None: return 1

    # Verify all needed folders exist and retrieve their ids
    print("Verifying DigitalLibrary format...")
    lib_ids = util.get_digital_library(service)
    current_chartz_id = lib_ids.get("current_id")
    future_chartz_id = lib_ids.get("future_id")
    if current_chartz_id == None or future_chartz_id == None: return 1

    # Verify (and collect) all chart ids
    print("Validating Chartz...")
    chart_ids = [
        verify_chart_name(service, chart,
                          [current_chartz_id, future_chartz_id])
        for chart in redvest_options["chartz"]
    ]
    if None in chart_ids:
        print('Try double-check your spelling, chart names are case-sensitive')
        print('ERROR: Redvest folder will not be created')
        return 1

    print("Verifying Redvest folder...")
    new_folder_id, new_resources_id = verify_redvest(service, redvest_options)
    if new_folder_id == None or new_resources_id == None: return 1

    # Only make individual section folders if field set to true
    alias_map = None
    section_ids = None
    check_stop_script()
    if redvest_options["individual-sections"]:
        # Read parts
        parts_dict = util.parse_options("parts.json")['parts']
        if parts_dict == None: return 1

        # Make individual section folders
        print("Making individual section folders...")
        section_ids = make_section_folders(service, new_folder_id,
                                           parts_dict.keys())

        # Invert parts_dict to create map of alias's -> folder
        alias_map = util.make_alias_map(parts_dict)

    # Write each chart to the new redvest folder
    for index, chart in enumerate(redvest_options["chartz"]):
        write_song(service, chart, chart_ids[index], new_folder_id,
                   new_resources_id, section_ids, alias_map)

    print(
        f'Successfully created new folder "{redvest_options["folder-name"]}"!')
    return 0
def download_parts():
    service = util.build_service()
    options = util.parse_options("folder_creator_options.json")
    if options == None: return

    # Ensure that there are parts to download
    if len(options["download-parts"]) == 0:
        print(f'ERROR: No parts specified.')
        return

    # Get the current parts id
    print("Verifying DigitalLibrary format...")
    library_id = util.get_digital_library(service).get("library_id")
    if library_id == None: return 1

    curr_parts_id = util.get_separated_folders(service, library_id)["sec_curr"]
    if curr_parts_id == None: return 1

    for part in options["download-parts"]:
        check_stop_script()
        print(f'Downloading files for part "{part}"')
        pdf_tools.download_part_files(
            service, curr_parts_id, part,
            os.path.join(options["folder-dir"], "parts"), options["verbose"])

    print("Finished downloading parts")
    return 0
def folder_creator(max_workers=10):
    options = parse_options("folder_creator_options.json")
    if options == None: return 1

    with concurrent.futures.ThreadPoolExecutor(max_workers) as threadPool:
        futures = {
            threadPool.submit(create_part_folder, part, options): part
            for part in options['folder-parts']
        }
        for future in concurrent.futures.as_completed(futures):
            pass

    thread_print("Finished generating folders")

    return 0
def validate_folder_files():
    options = parse_options("folder_creator_options.json")
    if options == None: return 1

    for part in options["folder-parts"]:
        check_stop_script()

        # Validate part files
        title_map = pdf_tools.validate_part(part, options)
        if not title_map: continue

        # Generate sample table of contents
        if options["toc"]["generate-on-validation"]:
            validate_toc(part, title_map, options)

    print("Finished validating folders and parts")
    return 0
Beispiel #5
0
    def __init__(self, parent, *args, **kwargs):
        ttk.Frame.__init__(self, parent, *args, **kwargs)

        # Parse move_chartz options
        self.options = parse_options("move_chartz_options.json")

        # Move chartz selection
        self.new_chartz = Multiselect(self,
                                      input=self.options['chartz'],
                                      title='Chartz to Move',
                                      key1='name',
                                      key2='to',
                                      header='Chart Name',
                                      addText='Add Chart',
                                      orient='vertical',
                                      height=10,
                                      archive=True)
        self.new_chartz.grid(row=0,
                             column=0,
                             columnspan=2,
                             sticky=(N, E, S, W),
                             padx=20,
                             pady=10)

        # Run script/Close buttons
        close_button = ttk.Button(self,
                                  text='Close',
                                  command=lambda: parent.master.destroy())
        bind_button(close_button)
        run_script_button = ttk.Button(self,
                                       text='Move Chartz',
                                       command=self.run_script)
        bind_button(run_script_button)

        close_button.grid(row=1, column=0, sticky=(S, W), padx=20, pady=10)
        run_script_button.grid(row=1,
                               column=1,
                               sticky=(S, E),
                               padx=20,
                               pady=10)

        # Allow resizing
        self.rowconfigure(1, weight="1")
        self.columnconfigure(1, weight="1")
Beispiel #6
0
def main(argv):
    script = None

    # Parse command line inputs
    try:
        opts, args = getopt(argv, "hs:", ["script=", "help"])
    except GetoptError:
        print_help()
        sys.exit(2)
    for opt, arg, in opts:
        if opt in ["-h", "--help"]:
            print_help()
            sys.exit()
        elif opt in ["-s", "--script"]:
            if arg in SCRIPT_DICT:
                script = SCRIPT_DICT[arg]
            else:
                print_help()
                sys.exit()

    # If a script is specified on the command line - run it!
    if script:
        script()
        return

    # Search for application data directory, if running as executable
    data_dir = None
    if is_frozen():
        data_dir = user_data_dir('LSJUMB Librarianz Scripts', 'LSJUMB',
                                 VERSION)
        res_options = parse_options("res_paths.json", from_=data_dir)
        res_options['res-path'] = data_dir
        make_application_data(data_dir, VERSION != res_options.get('version'))
        res_options['version'] = VERSION
        write_options(res_options, "res_paths.json")
        write_options(res_options, "res_paths.json")

    # Run Main Application
    root = tk.Tk()
    MainMenu(root, data_dir)
    root.mainloop()
    def __init__(self, parent, *args, **kwargs):
        ttk.Frame.__init__(self, parent, *args, **kwargs)

        # Parse redvest options
        self.options = parse_options("redvest_options.json")

        # Parent folder selection
        self.parent_entry = LabledEntry(
            self,
            title='Redvest Subdirectory Folder',
            label='Enter Subdirectory Folder Name',
            defaultEntry=self.options['parent-name'],
            info='Directory Structure: Redvest -> Subdirectory -> Session')
        self.parent_entry.grid(row=0,
                               column=0,
                               columnspan=2,
                               sticky=(N, S, E, W),
                               padx=20,
                               pady=10)

        # Folder name selection
        self.folder_entry = LabledEntry(
            self,
            title='Create New Redvest Session Folder',
            label='New Folder Name',
            defaultEntry=self.options['folder-name'])
        self.folder_entry.grid(row=1,
                               column=0,
                               columnspan=2,
                               sticky=(N, E, S, W),
                               padx=20,
                               pady=10)

        # Select Chartz multiselect
        self.select_chartz = Multiselect(self,
                                         input=self.options['chartz'],
                                         title='Select Chartz for Redvest',
                                         header='Chart Name',
                                         addText='Add Chart',
                                         height=7)
        self.select_chartz.grid(row=2,
                                column=0,
                                columnspan=2,
                                sticky=(N, E, S, W),
                                padx=20,
                                pady=10)

        # Individual Sections
        sep_sec_frame = ttk.LabelFrame(self, text='Separated Section Parts')

        self.sep_sec = BooleanVar()
        self.sep_sec.set(self.options['individual-sections'])
        sep_sec_checkbox = ttk.Checkbutton(
            sep_sec_frame,
            text='Include Separated Section Parts',
            variable=self.sep_sec)
        sep_sec_checkbox.grid(row=0, column=0, padx=10, pady=5)
        sep_sec_frame.rowconfigure(0, weight='1')
        sep_sec_frame.columnconfigure(0, weight='1')

        sep_sec_frame.grid(row=3,
                           column=0,
                           columnspan=2,
                           sticky=(N, E, S, W),
                           padx=20,
                           pady=10)

        # Run script/Close buttons
        close_button = ttk.Button(self,
                                  text='Close',
                                  command=lambda: parent.master.destroy())
        bind_button(close_button)
        run_script_button = ttk.Button(self,
                                       text='Create Redvest Folder',
                                       command=self.run_script)
        bind_button(run_script_button)

        close_button.grid(row=4, column=0, sticky=(S, W), padx=20, pady=10)
        run_script_button.grid(row=4,
                               column=1,
                               sticky=(S, E),
                               padx=20,
                               pady=10)

        # Make resizeable
        for i in range(5):
            self.rowconfigure(i, weight='1')
        self.columnconfigure(1, weight='1')
def upload_files():
    # Build service
    service = util.build_service()

    # Read options
    alias_map = util.make_alias_map(util.parse_options("parts.json")['parts'])
    options = util.parse_options("upload_options.json")
    if options == None: return 1
    check_stop_script()

    # Get list of files that need to be uploaded
    files = util.get_dir_files(options["resources-directory"],
                               options["supported-file-types"])
    check_stop_script()

    # Verify all needed folders exist and retrieve their ids
    print("Verifying DigitalLibrary format...")
    lib_ids = util.get_digital_library(service)
    library_id = lib_ids.get("library_id")
    if library_id == None: return 1
    check_stop_script()

    separated_ids = util.get_separated_folders(service, library_id)
    if separated_ids == None: return 1
    check_stop_script()

    # Cache will store folder + parts folder ids and a list of files
    cache = {}

    # 0 = update only, 1 = new files only, 2 = update and add new files
    mode = options["mode"]

    # Create new folders (if in proper mode)
    if mode != 0:
        for chart_info in options["new-chartz"]:
            check_stop_script()
            chart_dest = chart_info["to"]
            new_chart_dest_key = "current_id" if chart_dest == 0 else "past_id" if chart_dest == 1 else "future_id" if chart_dest == 2 else "archive_id"
            chart_id, parts_id, audio_id = lib_management.create_chart_structure(
                service, lib_ids.get(new_chart_dest_key), chart_info["name"])
            if chart_id:
                cache[chart_info["name"]] = {
                    "chart_id": chart_id,
                    "parts_id": parts_id,
                    "audio_id": audio_id,
                    "loc": chart_info["to"],
                    "files": []
                }

    # Operate on files
    for file in files:
        # Check to see if we should exit
        check_stop_script()

        # Populate cache
        lib_management.populate_cache(service, lib_ids.get("current_id"),
                                      lib_ids.get("past_id"),
                                      lib_ids.get("future_id"),
                                      lib_ids.get("archive_id"),
                                      util.parse_file(file, alias_map)[0],
                                      cache, options)
        updated = None
        added = None

        # Update file
        if mode != 1:
            updated = lib_management.update_file(service, file, alias_map,
                                                 cache, options)

        # Add file
        if mode != 0 and not updated:
            added = lib_management.add_file(service, file, separated_ids,
                                            alias_map, cache, options)

        # print output
        if updated == True:
            print(f'Successfully updated "{file}"')
        elif added == True:
            print(f'Successfully added "{file}"')
        elif updated == False:
            print(f'ERROR: Unable to update "{file}"')

    print("Finished uploading files")
    return 0
Beispiel #9
0
    def __init__(self, parent, *args, **kwargs):
        ttk.Frame.__init__(self, parent, *args, **kwargs)

        # Parse upload files options
        self.options = parse_options("upload_options.json")

        # Directory selection       
        self.select_directory = SelectDirectory(self, path=self.options["resources-directory"], title='Select Resources Folder')
        self.select_directory.grid(row=0, column=0, columnspan=2, sticky=(N, E, S, W), padx=20, pady=10)

        # Mode selection + title match checkbox
        self.mode = IntVar()
        self.mode.set(self.options["mode"])
        self.title_match = BooleanVar()
        self.title_match.set(self.options["require-titles-match"])
        mode_frame = ttk.Labelframe(self, text='Select Mode')
        update = ttk.Radiobutton(mode_frame, text='Update Files', variable=self.mode, value=0)
        add = ttk.Radiobutton(mode_frame, text='Add Files', variable=self.mode, value=1)
        update_and_add = ttk.Radiobutton(mode_frame, text='Add and Update', variable=self.mode, value=2)
        title_match_checkbox = ttk.Checkbutton(mode_frame, text='Enforce Matching Titles', variable=self.title_match)

        mode_frame.grid(row=1, column=0, columnspan=2, sticky=(N, E, S, W), padx=20, pady=10)
        update.grid(row=0, column=0)
        add.grid(row=0, column=1)
        update_and_add.grid(row=0, column=2)
        title_match_checkbox.grid(row=0, column=3, padx=20)

        # New chartz selection
        self.new_chartz = Multiselect(self, input=self.options['new-chartz'],
                                        title='Create New Chartz',
                                        key1='name', 
                                        key2='to',
                                        header='Chart Name',
                                        addText='Add New Chart',
                                        height=3,
                                        archive=True)
        self.new_chartz.grid(row=2, column=0, columnspan=2, sticky=(N, E, S, W), padx=20, pady=10)

        # File extensions selection
        self.file_extensions = Multiselect(self, input=self.options["supported-file-types"],
                                            title='Supported File Types',
                                            header='File Type',
                                            addText='Add File Type',
                                            warn=True,
                                            height=6)
        self.file_extensions.grid(row=3, column=0, columnspan=2, sticky=(N, E, S, W), padx=20, pady=10)

        # Run script/Close buttons
        close_button = ttk.Button(self, text='Close', command=lambda: parent.master.destroy())
        bind_button(close_button)
        run_script_button = ttk.Button(self, text='Upload Files', command=self.run_script)
        bind_button(run_script_button)

        close_button.grid(row=4, column=0, sticky=(S, W), padx=20, pady=10)
        run_script_button.grid(row=4, column=1, sticky=(S, E), padx=20, pady=10)

        # Allow resizing
        for row in range(5):
            self.rowconfigure(row, weight="1")
        self.columnconfigure(0, weight="1")
        for col in range(4):
            mode_frame.columnconfigure(col, weight="1", minsize="80")
    def __init__(self, parent, mode, *args, **kwargs):
        # Initialize superclass
        title = kwargs.get('title') or 'Select Font'
        ttk.LabelFrame.__init__(self, parent, text=title)

        # Initializes props
        name = kwargs.get('name') or 'Entry'

        # Supported fonts
        fonts_dict = parse_options("supported_fonts.json")
        supported_fonts: List = fonts_dict['default']
        if fonts_dict.get('more'):
            more: List = fonts_dict['more']
            more.sort()
            supported_fonts.extend(more)


        # Leftmost entry is either a text entry or a font select, depending on mode
        left_label_text = kwargs.get('leftLabel') or f'{name} Text:'
        self.left_entry_text = StringVar()
        if mode == 0:
            left_label = ttk.Label(self, text=left_label_text)
            left_label.grid(row=0, column=0, sticky=S, padx=10, pady=2)

            self.left_entry_text.set(kwargs.get('leftEntry') or '')
            left_entry = ttk.Entry(self, textvariable=self.left_entry_text)
            left_entry.grid(row=1, column=0, sticky=N, padx=10, pady=2)
        elif mode == 1:
            left_label = ttk.Label(self, text=left_label_text)
            left_label.grid(row=0, column=0, sticky=S, padx=10, pady=2)

            self.left_entry_text.set(kwargs.get('leftEntry') or 'Courier')
            left_combobox = ttk.Combobox(self, textvariable=self.left_entry_text)
            left_combobox['values'] = supported_fonts
            left_combobox.state(['readonly'])
            left_combobox.grid(row=1, column=0, sticky=N, padx=10, pady=2)
        

        # Middle entry is alwas a font select
        middle_label = ttk.Label(self, text=kwargs.get('middleLabel') or f'{name} Font:')
        middle_label.grid(row=0, column=1 - (mode > 1), sticky=S, padx=10, pady=2)

        self.middle_entry_text = StringVar()
        self.middle_entry_text.set(kwargs.get('middleEntry') or 'Courier')
        middle_combobox = ttk.Combobox(self, textvariable=self.middle_entry_text)
        middle_combobox['values'] = supported_fonts
        middle_combobox.state(['readonly'])
        middle_combobox.grid(row=1, column=1 - (mode > 1), sticky=N, padx=10, pady=2)

        # Right entry is always a size selection
        validate_fn = (self.register(validate_numerical_entry(False)), '%P')

        right_label = ttk.Label(self, text=kwargs.get('rightLabel') or 'Font Size:')
        right_label.grid(row=0, column=2 - (mode > 1), sticky=S, padx=10, pady=2)

        self.right_entry_val = StringVar()
        self.right_entry_val.set(kwargs.get('rightEntry') or 12)
        right_spinbox = ttk.Spinbox(self, from_=6, to=36, increment=2, textvariable=self.right_entry_val, width=3, validate='key', validatecommand=validate_fn)
        right_spinbox.bind('<FocusOut>', lambda _: self.right_entry_val.set(kwargs.get('rightLabel') or 12) if not len(self.right_entry_val.get()) else '')
        right_spinbox.grid(row=1, column=2 - (mode > 1), sticky=N, padx=10, pady=2)
        self.bind('<Button-1>', lambda e: e.widget.focus_set())

        # Make resizeable
        for col in range(3 - (mode > 1)):
            self.columnconfigure(col, weight='1')
        self.rowconfigure(0, weight='1')
        self.rowconfigure(1, weight='1')
    def __init__(self, parent, *args, **kwargs):
        ttk.Frame.__init__(self, parent, *args, **kwargs)

        self.options = parse_options('parts.json')
        self.DELIMETERS = (":", "|")
        parts_frame = ttk.Labelframe(self, text='Configure Part Mappings')

        # Add info label
        info = ttk.Label(
            parts_frame,
            justify='center',
            text=
            f'Each line of text is a part alias configuration.\nThe part name is followed by "{self.DELIMETERS[0]}", and aliases are delimited by "{self.DELIMETERS[1]}".\nFor example, if you wish for files "All Right Now - Toobz" and\n"All Right Now - Tööbz" to be mapped to the same folder,\nyou would enter "Toobz{self.DELIMETERS[0]} Toobz {self.DELIMETERS[1]} Tööbz"'
        )
        info.grid(row=0, column=0, padx=10, pady=5)

        # Add text input area
        dummy_frame = ttk.Frame(parts_frame)

        self.parts_text = CustomText(dummy_frame,
                                     width=70,
                                     height=15,
                                     wrap='none',
                                     font=('TkDefaultFont'),
                                     undo=True)
        self.parts_text.grid(row=0, column=0, sticky=(N, E, S, W))
        self.parts_text.tag_configure('delimeter-0-good',
                                      font=('TkFixedFont'),
                                      foreground='green')
        self.parts_text.tag_configure('delimeter-0-bad',
                                      font=('TkFixedFont'),
                                      foreground='red')
        self.parts_text.tag_configure('delimeter-1-good',
                                      font=('TkFixedFont'),
                                      foreground='blue')
        self.parts_text.tag_configure('delimeter-1-bad',
                                      font=('TkFixedFont'),
                                      foreground='red')
        self.parts_text.bind('<<TextModified>>', self.tag_delimeters)

        scrollx = ttk.Scrollbar(dummy_frame,
                                orient='horizontal',
                                command=self.parts_text.xview)
        scrolly = ttk.Scrollbar(dummy_frame,
                                orient='vertical',
                                command=self.parts_text.yview)
        self.parts_text['xscrollcommand'] = scrollx.set
        self.parts_text['yscrollcommand'] = scrolly.set
        scrollx.grid(row=1, column=0, sticky=(E, W, N))
        scrolly.grid(row=0, column=1, sticky=(N, S, W))

        parts_frame.grid(row=0,
                         column=0,
                         columnspan=2,
                         sticky=(N, E, S, W),
                         padx=20,
                         pady=10)

        dummy_frame.grid(row=1, column=0, sticky=(N, E, S, W), padx=10, pady=5)
        dummy_frame.rowconfigure(0, weight='1')
        dummy_frame.columnconfigure(0, weight='1')

        # Populate text
        self.populate_parts(self.options['parts'])

        # Make Text Area Resizeable
        parts_frame.columnconfigure(0, weight='1')
        parts_frame.rowconfigure(1, weight='1')

        # Add exclusion selection
        self.exclusions = Multiselect(
            self,
            input=self.options['exclude'],
            title='Parts to Exclude from Live Digital Library',
            header='Part Name',
            addText='Add Part',
            warn=True,
            height=5)
        self.exclusions.grid(row=1,
                             column=0,
                             columnspan=2,
                             padx=20,
                             pady=10,
                             sticky=(N, E, S, W))

        # Run script/Close buttons
        close_button = ttk.Button(self,
                                  text='Close',
                                  command=lambda: parent.master.destroy())
        bind_button(close_button)
        run_script_button = ttk.Button(self,
                                       text='Remake Shortcuts',
                                       command=self.run_script)
        bind_button(run_script_button)

        close_button.grid(row=2, column=0, sticky=(S, W), padx=20, pady=10)
        run_script_button.grid(row=2,
                               column=1,
                               sticky=(S, E),
                               padx=20,
                               pady=10)

        # Allow resizing
        self.rowconfigure(0, weight="1")
        self.rowconfigure(1, weight="1")
        self.columnconfigure(1, weight="1")
    def __init__(self, parent, *args, **kwargs):
        ttk.Frame.__init__(self, parent, *args, **kwargs)

        # Parse folder creator options
        self.options = parse_options("folder_creator_options.json")

        # Target Directory selection
        self.select_directory = SelectDirectory(self, path=self.options["folder-dir"], title='Select Target Directory')
        self.select_directory.grid(row=0, column=0, columnspan=3, sticky=(N, E, S, W), padx=20, pady=10)

        # Folder Name Selection
        self.folder_name_entry = LabledEntry(self, title='Enter Output Folder Name', label='Output Name', defaultEntry=self.options['folder-name'])
        self.folder_name_entry.grid(row=1, column=0, sticky=(N, S, W, E), padx=20, pady=10)

        # Verbose Output Selection
        verbose_frame = ttk.LabelFrame(self, text='Console Logging')

        self.verbose = BooleanVar()
        self.verbose.set(self.options['verbose'])
        verbose_checkbox = ttk.Checkbutton(verbose_frame, text='Verbose Logging', variable=self.verbose)
        verbose_checkbox.grid(row=0, column=0, padx=10, pady=5)
        verbose_frame.rowconfigure(0, weight='1')
        verbose_frame.columnconfigure(0, weight='1')

        verbose_frame.grid(row=1, column=1, sticky=(N, E, S, W), padx=20, pady=10)

        # Workflows
        workflow_frame = ttk.Frame(self)

        # Download Files Workflow
        dl_workflow = FolderCreatorWorkflow(parent=workflow_frame,
                                            description="Downloads files from the Digial Library onto your local machine at the target directory specified above",
                                            scriptButtonName="Download Files",
                                            scriptCallback=self.runDownloadScript,
                                            optionsCallback=lambda: self.open_options(0))
        dl_workflow.grid(row=0, column=0, sticky=(N, E, S, W), padx=0, pady=5)

        # Validate Folders Workflow
        validate_workflow = FolderCreatorWorkflow(parent=workflow_frame,
                                                description="Validates the folder structure at the target directory, and optionally outputs a sample table of contents",
                                                scriptButtonName='Validate Folder',
                                                scriptCallback=self.runValidateScript,
                                                optionsCallback=lambda: self.open_options(1))
        validate_workflow.grid(row=0, column=1, sticky=(N, E, S, W), padx=20, pady=5)

        # Create Folders workflow
        create_folders = FolderCreatorWorkflow(parent=workflow_frame,
                                                description="Writes the folders to the Output folder in the target directory\n\nThis takes about 2-5 minutes",
                                                scriptButtonName='Generate Folders',
                                                scriptCallback=self.runFolderCreatorScript,
                                                optionsCallback=lambda: self.open_options(2))
        create_folders.grid(row=0, column=2, sticky=(N, E, S, W), padx=0, pady=5)

        # Make Workflow Frame resizeable
        workflow_frame.grid(row=2, column=0, columnspan=3, sticky=(N, E, S, W), padx=20, pady=10)
        workflow_frame.rowconfigure(0, weight='1')
        for i in range(3): workflow_frame.columnconfigure(i, weight='1')
        
        # Run script/Close buttons
        close_button = ttk.Button(self, text='Close', command=lambda: parent.master.destroy())
        bind_button(close_button)

        close_button.grid(row=3, column=0, sticky=(S, W), padx=20, pady=10)

        # Make resizeable
        for i in range(4):
            self.rowconfigure(i, weight='1')
        self.columnconfigure(1, weight='1')