示例#1
0
文件: main.py 项目: snemetz/tvnamer
def confirm(question, options, default="y"):
    """Takes a question (string), list of options and a default value (used
    when user simply hits enter).
    Asks until valid option is entered.
    """
    # Highlight default option with [ ]
    options_str = []
    for x in options:
        if x == default:
            x = "[%s]" % x
        if x != '':
            options_str.append(x)
    options_str = "/".join(options_str)

    while True:
        p(question)
        p("(%s) " % (options_str), end="")
        try:
            ans = raw_input().strip()
        except KeyboardInterrupt as errormsg:
            p("\n", errormsg)
            raise UserAbort(errormsg)

        if ans in options:
            return ans
        elif ans == '':
            return default
示例#2
0
    def populate_from_tvdb(self,
                           tvdb_instance,
                           force_name=None,
                           series_id=None):
        # mypy: ignore # type: (tvdb_api.Tvdb, Optional[Any], Optional[Any]) -> None
        """Queries the tvdb_api.Tvdb instance for episode name and corrected
        series name.
        If series cannot be found, it will warn the user. If the episode is not
        found, it will use the corrected show name and not set an episode name.
        If the site is unreachable, it will warn the user. If the user aborts
        it will catch tvdb_api's user abort error and raise tvnamer's
        """

        # FIXME: MOve this into each subclass - too much hasattr/isinstance
        try:
            if series_id is None:
                show = tvdb_instance[force_name or self.seriesname]
            else:
                series_id = int(series_id)
                tvdb_instance._getShowData(series_id, Config['language'])
                show = tvdb_instance[series_id]
        except tvdb_api.tvdb_error as errormsg:
            raise DataRetrievalError("Error with www.thetvdb.com: %s" %
                                     errormsg)
        except tvdb_api.tvdb_shownotfound:
            # No such series found.
            raise ShowNotFound("Show %s not found on www.thetvdb.com" %
                               self.seriesname)
        except tvdb_api.tvdb_userabort as error:
            raise UserAbort("%s" % error)
        else:
            # Series was found, use corrected series name
            self.seriesname = _replace_output_series_name(show['seriesName'])

        if isinstance(self, DatedEpisodeInfo):
            # Date-based episode
            epnames = []
            for cepno in self.episodenumbers:
                try:
                    sr = show.aired_on(cepno)
                    if len(sr) > 1:
                        # filter out specials if multiple episodes aired on the day
                        sr = [s for s in sr if s['seasonnumber'] != '0']

                    if len(sr) > 1:
                        raise EpisodeNotFound(
                            "Ambigious air date %s, there were %s episodes on that day"
                            % (cepno, len(sr)))
                    epnames.append(sr[0]['episodeName'])
                except tvdb_api.tvdb_episodenotfound:
                    raise EpisodeNotFound(
                        "Episode that aired on %s could not be found" %
                        (cepno))
            self.episodename = epnames  # Optional[List[str]]
            return

        if not hasattr(self, "seasonnumber") or self.seasonnumber is None:
            # Series without concept of seasons have all episodes in season 1
            seasonnumber = 1
        else:
            seasonnumber = self.seasonnumber

        epnames = []
        for cepno in self.episodenumbers:
            try:
                episodeinfo = show[seasonnumber][cepno]

            except tvdb_api.tvdb_seasonnotfound:
                raise SeasonNotFound(
                    "Season %s of show %s could not be found" %
                    (seasonnumber, self.seriesname))

            except tvdb_api.tvdb_episodenotfound:
                # Try to search by absolute number
                sr = show.search(cepno, "absoluteNumber")
                if len(sr) > 1:
                    # For multiple results try and make sure there is a direct match
                    unsure = True
                    for e in sr:
                        if int(e['absoluteNumber']) == cepno:
                            epnames.append(e['episodeName'])
                            unsure = False
                    # If unsure error out
                    if unsure:
                        raise EpisodeNotFound(
                            "No episode actually matches %s, found %s results instead"
                            % (cepno, len(sr)))
                elif len(sr) == 1:
                    epnames.append(sr[0]['episodeName'])
                else:
                    raise EpisodeNotFound(
                        "Episode %s of show %s, season %s could not be found (also tried searching by absolute episode number)"
                        % (cepno, self.seriesname, seasonnumber))

            except tvdb_api.tvdb_attributenotfound:
                raise EpisodeNameNotFound(
                    "Could not find episode name for %s" % cepno)
            else:
                epnames.append(episodeinfo['episodeName'])

        self.episodename = epnames
示例#3
0
文件: main.py 项目: snemetz/tvnamer
def processFile(tvdb_instance, episode):
    """Gets episode name, prompts user for input
    """
    p("#" * 20)
    p("# Processing file: %s" % episode.fullfilename)

    if len(Config['input_filename_replacements']) > 0:
        replaced = applyCustomInputReplacements(episode.fullfilename)
        p("# With custom replacements: %s" % (replaced))

    # Use force_name option. Done after input_filename_replacements so
    # it can be used to skip the replacements easily
    if Config['force_name'] is not None:
        episode.seriesname = Config['force_name']

    p("# Detected series: %s (%s)" %
      (episode.seriesname, episode.number_string()))

    try:
        episode.populateFromTvdb(tvdb_instance,
                                 force_name=Config['force_name'],
                                 series_id=Config['series_id'])
    except (DataRetrievalError, ShowNotFound) as errormsg:
        if Config['always_rename'] and Config['skip_file_on_error'] is True:
            if Config['skip_behaviour'] == 'exit':
                warn("Exiting due to error: %s" % errormsg)
                raise SkipBehaviourAbort()
            warn("Skipping file due to error: %s" % errormsg)
            return
        else:
            warn(errormsg)
    except (SeasonNotFound, EpisodeNotFound, EpisodeNameNotFound) as errormsg:
        # Show was found, so use corrected series name
        if Config['always_rename'] and Config['skip_file_on_error']:
            if Config['skip_behaviour'] == 'exit':
                warn("Exiting due to error: %s" % errormsg)
                raise SkipBehaviourAbort()
            warn("Skipping file due to error: %s" % errormsg)
            return

        warn(errormsg)

    cnamer = Renamer(episode.fullpath)

    shouldRename = False

    if Config["move_files_only"]:

        newName = episode.fullfilename
        shouldRename = True

    else:
        newName = episode.generateFilename()
        if newName == episode.fullfilename:
            p("#" * 20)
            p("Existing filename is correct: %s" % episode.fullfilename)
            p("#" * 20)

            shouldRename = True

        else:
            p("#" * 20)
            p("Old filename: %s" % episode.fullfilename)

            if len(Config['output_filename_replacements']) > 0:
                # Show filename without replacements
                p("Before custom output replacements: %s" %
                  (episode.generateFilename(preview_orig_filename=False)))

            p("New filename: %s" % newName)

            if Config['always_rename']:
                doRenameFile(cnamer, newName)
                if Config['move_files_enable']:
                    if Config['move_files_destination_is_filepath']:
                        doMoveFile(cnamer=cnamer,
                                   destFilepath=getMoveDestination(episode))
                    else:
                        doMoveFile(cnamer=cnamer,
                                   destDir=getMoveDestination(episode))
                return

            elif Config['dry_run']:
                p("%s will be renamed to %s" % (episode.fullfilename, newName))
                if Config['move_files_enable']:
                    p("%s will be moved to %s" %
                      (newName, getMoveDestination(episode)))
                return

            ans = confirm("Rename?", options=['y', 'n', 'a', 'q'], default='y')

            if ans == "a":
                p("Always renaming")
                Config['always_rename'] = True
                shouldRename = True
            elif ans == "q":
                p("Quitting")
                raise UserAbort("User exited with q")
            elif ans == "y":
                p("Renaming")
                shouldRename = True
            elif ans == "n":
                p("Skipping")
            else:
                p("Invalid input, skipping")

            if shouldRename:
                doRenameFile(cnamer, newName)

    if shouldRename and Config['move_files_enable']:
        newPath = getMoveDestination(episode)
        if Config['dry_run']:
            p("%s will be moved to %s" %
              (newName, getMoveDestination(episode)))
            return

        if Config['move_files_destination_is_filepath']:
            doMoveFile(cnamer=cnamer,
                       destFilepath=newPath,
                       getPathPreview=True)
        else:
            doMoveFile(cnamer=cnamer, destDir=newPath, getPathPreview=True)

        if not Config['batch'] and Config['move_files_confirmation']:
            ans = confirm("Move file?", options=['y', 'n', 'q'], default='y')
        else:
            ans = 'y'

        if ans == 'y':
            p("Moving file")
            doMoveFile(cnamer, newPath)
        elif ans == 'q':
            p("Quitting")
            raise UserAbort("user exited with q")
示例#4
0
def process_file(tvdb_instance, episode):
    # type: (tvdb_api.Tvdb, BaseInfo) -> None
    """Gets episode name, prompts user for input
    """
    print("#" * 20)
    print("# Processing file: %s" % episode.fullfilename)

    if len(Config["input_filename_replacements"]) > 0:
        replaced = _apply_replacements_input(episode.fullfilename)
        print("# With custom replacements: %s" % (replaced))

    # Use force_name option. Done after input_filename_replacements so
    # it can be used to skip the replacements easily
    if Config["force_name"] is not None:
        episode.seriesname = Config["force_name"]

    print("# Detected series: %s (%s)" %
          (episode.seriesname, episode.number_string()))

    try:
        episode.populate_from_tvdb(
            tvdb_instance,
            force_name=Config["force_name"],
            series_id=Config["series_id"],
        )
    except (DataRetrievalError, ShowNotFound) as errormsg:
        if Config["always_rename"] and Config["skip_file_on_error"] is True:
            if Config["skip_behaviour"] == "exit":
                warn("Exiting due to error: %s" % errormsg)
                raise SkipBehaviourAbort()
            warn("Skipping file due to error: %s" % errormsg)
            return
        else:
            warn("%s" % (errormsg))
    except (SeasonNotFound, EpisodeNotFound, EpisodeNameNotFound) as errormsg:
        # Show was found, so use corrected series name
        if Config["always_rename"] and Config["skip_file_on_error"]:
            if Config["skip_behaviour"] == "exit":
                warn("Exiting due to error: %s" % errormsg)
                raise SkipBehaviourAbort()
            warn("Skipping file due to error: %s" % errormsg)
            return

        warn("%s" % (errormsg))

    cnamer = Renamer(episode.fullpath)

    should_rename = False

    if Config["move_files_only"]:

        new_name = episode.fullfilename
        should_rename = True

    else:
        new_name = episode.generate_filename()
        if new_name == episode.fullfilename:
            print("#" * 20)
            print("Existing filename is correct: %s" % episode.fullfilename)
            print("#" * 20)

            should_rename = True

        else:
            print("#" * 20)
            print("Old filename: %s" % episode.fullfilename)

            if len(Config["output_filename_replacements"]) > 0:
                # Show filename without replacements
                print("Before custom output replacements: %s" %
                      (episode.generate_filename(preview_orig_filename=False)))

            print("New filename: %s" % new_name)

            if Config["dry_run"]:
                print("%s will be renamed to %s" %
                      (episode.fullfilename, new_name))
                if Config["move_files_enable"]:
                    print("%s will be moved to %s" %
                          (new_name, get_move_destination(episode)))
                return
            elif Config["always_rename"]:
                do_rename_file(cnamer, new_name)
                if Config["move_files_enable"]:
                    if Config["move_files_destination_is_filepath"]:
                        do_move_file(
                            cnamer=cnamer,
                            dest_filepath=get_move_destination(episode))
                    else:
                        do_move_file(cnamer=cnamer,
                                     dest_dir=get_move_destination(episode))
                return

            ans = confirm("Rename?", options=["y", "n", "a", "q"], default="y")

            if ans == "a":
                print("Always renaming")
                Config["always_rename"] = True
                should_rename = True
            elif ans == "q":
                print("Quitting")
                raise UserAbort("User exited with q")
            elif ans == "y":
                print("Renaming")
                should_rename = True
            elif ans == "n":
                print("Skipping")
            else:
                print("Invalid input, skipping")

            if should_rename:
                do_rename_file(cnamer, new_name)

    if should_rename and Config["move_files_enable"]:
        new_path = get_move_destination(episode)
        if Config["dry_run"]:
            print("%s will be moved to %s" %
                  (new_name, get_move_destination(episode)))
            return

        if Config["move_files_destination_is_filepath"]:
            do_move_file(cnamer=cnamer,
                         dest_filepath=new_path,
                         get_path_preview=True)
        else:
            do_move_file(cnamer=cnamer,
                         dest_dir=new_path,
                         get_path_preview=True)

        if not Config["batch"] and Config["move_files_confirmation"]:
            ans = confirm("Move file?", options=["y", "n", "q"], default="y")
        else:
            ans = "y"

        if ans == "y":
            print("Moving file")
            do_move_file(cnamer, new_path)
        elif ans == "q":
            print("Quitting")
            raise UserAbort("user exited with q")