Example #1
0
def get_files(parent: str) -> Union[list, List[str]]:
    """Get the members of the given folder."""
    try:
        files: List[str] = Str(parent).listdir()
    except OSError as err:
        if errors.osraise(errors.ENOENT, errors.ENOTDIR, err=err):
            raise
        print(err)
        return []

    hidden: bool = x.OPTS.hidden
    exclude: Set[str] = set(x.OPTS.exclude)
    only: Set[str] = set(x.OPTS.only)
    done: Set[str] = set(get_files_from_cache())
    use: bool = x.OPTS.use_cache

    for member in files.copy():
        if any([
                Str(member).isdir(),
                all([not hidden, Str(member).ishidden()]),
                all([
                    bool(exclude),
                    any(Str(member).endsext(_) for _ in exclude)
                ]),
                all([
                    bool(only), not any(Str(member).endsext(_) for _ in only)
                ]),
                all([use, Str(member).sha256() in done]),
        ]):
            files.remove(member)

    return files
Example #2
0
def save_to_cache_as_done(file: str) -> None:
    """Save the hash of the given file to the cache."""
    try:
        with open(consts.FILE_CACHE, "a", encoding=U8, errors=XML) as cache:
            cache.write(Str(file).sha256() + "\n")
    except OSError as err:
        if errors.osraise(errors.ENOENT, err=err):
            raise
Example #3
0
 def attrs(self) -> int:
     """Retrieve file attributes from the given string."""
     try:
         return os.stat(self.abs()).st_file_attributes
     except OSError as err:
         if errors.osraise(errors.ENOENT, err=err):
             raise
         return int(False)
Example #4
0
def get_files_from_cache() -> Union[list, List[str]]:
    """Get hashes from the cache."""
    try:
        with open(consts.FILE_CACHE, "r", encoding=U8) as cache:
            return [hash_.strip() for hash_ in cache.readlines()]
    except OSError as err:
        if errors.osraise(errors.ENOENT, err=err):
            raise
        return []
Example #5
0
def fcleaner(*containers: Dict[str, str]) -> None:
    """Delete files that to be deleted on exit."""
    for container in containers:
        for output in container.values():
            try:
                os.remove(Str(output).abs())
            except OSError as err:
                if errors.osraise(errors.ENOENT, err=err):
                    raise
                continue
Example #6
0
def dcleaner(*containers: List[str]) -> None:  # avsub: N2204
    """Delete folders that to be deleted on exit."""
    for container in containers:
        for folder in container:
            try:
                if folder is not None:
                    os.rmdir(Str(folder).abs())
            except OSError as err:
                if errors.osraise(errors.ENOENT, errors.ENOTEMPTY, err=err):
                    raise
                continue
Example #7
0
def create_startup_program() -> bool:
    """Create a startup program to auto check for updates."""
    if Str(consts.FILE_STARTUP).isfile() and not x.OPTS.fix_startup:
        return True
    try:
        with open(consts.FILE_STARTUP, "w", encoding=U8) as bat:
            bat.write("avsub\n" "pause\n")
    except OSError as err:
        if errors.osraise(errors.ENOENT, err=err):
            raise
        return False
    return True
Example #8
0
def logger() -> int:
    """Print results to the terminal and then save them to a file."""
    log: List[str] = []
    status: int = 0

    for member in x.SUCCEEDED:
        msg: Template = Template("[+] Job completed: '$member'")
        print(msg.substitute(member=Str(member).base()))
        log.append(msg.substitute(member=Str(member).abs()))
    for member in x.DEL_ON_EXIT:
        if member in x.FATAL_FFMPEG:  # avsub: C2203
            continue
        msg = Template("[-] Not completed: '$member'")
        print(msg.substitute(member=Str(member).base()))
        log.append(msg.substitute(member=Str(member).abs()))
        status = 2
    for member in x.NOT_PROCESSED:
        msg = Template("[ ] Not processed: '$member'")
        print(msg.substitute(member=Str(member).base()))
        log.append(msg.substitute(member=Str(member).abs()))
        status = 2
    for member in x.FATAL_FFMPEG:
        msg = Template("[F] Fatal, FFmpeg: '$member'")
        print(msg.substitute(member=Str(member).base()))
        log.append(msg.substitute(member=Str(member).abs()))
        status = 3

    if x.OPTS.log:
        try:
            with open(x.LOG_FILE, "a", encoding=U8, errors=XML) as file:
                date_format: str = "%m/%d/%Y - %H:%M:%S"
                date: str = datetime.now().strftime(date_format)
                line: str = Str("=").line(col=len(date))
                file.write(f"{line}\n{date}\n{line}\n")
                log.reverse()  # avsub: C2200
                for message in log:
                    file.write(message + "\n")
        except OSError as err:
            if errors.osraise(errors.ENOENT, err=err):
                raise
            print("[!] Logging error:", err)
        else:
            print("[*] Results saved:", f"'{file.name}'")

    return status
Example #9
0
def main() -> None:
    """Main function."""
    SigHandler(consts.SIGNALS).capture(stop)
    checker()

    fff: ffmpeg.FFmpeg = ffmpeg.FFmpeg()
    fff.build()  # Start creating the ultimate FFmpeg command

    try:
        x.THE_TEMP = Str(x.OPTS.temp).abs()
        x.OUTS = Str(x.THE_TEMP).join("Outs")  # avsub: F2400
        dmaker(x.THE_TEMP, x.OUTS, consts.DIR_CONFS, consts.DIR_LOGS)
        x.A_TEMP = tempfile.mkdtemp(prefix="avsub-", dir=x.OUTS)
        x.DEL_ON_EXIT_TEMP_FOLDER.append(x.A_TEMP)
    except OSError as err:  # avsub: F2210,F2220
        if errors.osraise(errors.EEXIST, errors.ENOENT, err=err):
            raise
        print(err)
        print("[F] Required folders could not be created")
        sys.exit(3)
    else:
        x.LOG_FILE = Str(consts.DIR_LOGS).join(f"{x.A_TEMP}.log")

    if OS.nt and create_startup_program():  # avsub: N2400
        reg: registry.Registry = registry.Registry()
        reg.set()
        del reg

    # MANUAL OPERATION?
    if Str(x.OPTS.input).isfile():
        files: List[str] = [Str(x.OPTS.input).abs()]
        # HARDSUB MANUAL OPERATION?
        if x.OPTS.embed:
            # Note: New TEMP subtitle to -almost- avoid the escaping nonsense
            tempsub: str = Str(x.A_TEMP).join(x.A_TEMP)
            x.DEL_ON_EXIT_TEMP.update({tempsub: tempsub})

            try:
                shutil.copyfile(Str(x.OPTS.embed).abs(), tempsub)
            except OSError as err:
                if errors.osraise(errors.ENOENT, err=err):
                    raise
                print(err)
                print("[F] Required TEMP subtitle file could not be created")
                dcleaner(x.DEL_ON_EXIT_TEMP_FOLDER)
                sys.exit(3)

            # Add a new level of escaping for TEMP subtitle pathname
            sub_escaped: str = tempsub.replace("\\", "/").replace(":", "\\\\:")
            fff.build_hardsub(subpath=sub_escaped)
    # AUTOMATIC OPERATION?
    else:
        print("[*] Getting files...")
        files = get_files(parent=x.OPTS.input)
        if not files:
            print("[-] Exiting, no files to process with current options")
            dcleaner(x.DEL_ON_EXIT_TEMP_FOLDER)
            sys.exit(2)

    print("[*] Getting ready to start...")
    mark_as_not_processed(parent=x.A_TEMP, files=files)

    x.FULL_CLEAN_AFTER_STOP = True
    ffmpeg.execute(fff.cmd, files=files)