Esempio n. 1
0
def get_activation_bytes(checksum: str) -> Optional[str]:

    if not is_rcrack_enabled():
        return None

    logging.debug(f"Getting activation on {checksum}")
    has_rtc = len([x for x in listdir(RCRACK_DIR) if x.endswith(".rtc")]) > 0
    rcrack_command = ["./rcrack", "." if has_rtc else "*.rt", "-h", checksum]

    rcrack_process = Popen(rcrack_command,
                           stdout=PIPE,
                           stderr=PIPE,
                           cwd=RCRACK_DIR)
    rcrack_result = rcrack_process.communicate()[0]

    if isinstance(rcrack_result, bytes):
        rcrack_result = rcrack_result.decode("utf-8")

    rcrack_result = [
        x.strip() for x in rcrack_result.split(linesep) if len(x.strip()) > 0
    ][-1]

    rcrack_result = rcrack_result[re_search(r"hex:", rcrack_result).end(
    ):].strip()

    logging.debug(f"Activation for {checksum} is {rcrack_result}")

    return rcrack_result
Esempio n. 2
0
 def prepare_file(self, selected_file: str) -> str:
     new_file = os.path.join(self.get_temp_dir(), str(uuid4()))
     logging.debug(
         f"Starting download of {selected_file} from {self._host}")
     self._oc.get_file(selected_file, new_file)
     logging.debug(
         f"Finished download of {selected_file} from {self._host}")
     return new_file
Esempio n. 3
0
 def run(self) -> None:
     logging.debug(
         f"Starting interruptable thread with {self.__time_out}s as timeout"
     )
     if not hasattr(self, "__run"):
         self.__run = AtomicType(init_value=True)
     while self.__run.get():
         run_result = self.one_run()
         if (run_result is None) or (not run_result):
             time.sleep(self.__time_out)
Esempio n. 4
0
    def __mkdir_recursive(self, path_parts: List[str]) -> Optional[str]:

        logging.debug(
            f"Trying to create directory {os.path.join(*path_parts)}")

        for i in range(1, len(path_parts) + 1, 1):
            try:
                self._oc.mkdir(os.path.join(*path_parts[:i]))
            except owncloud.owncloud.HTTPResponseError as e:
                if e.status_code != 405:
                    return None

        return os.path.join(*path_parts)
Esempio n. 5
0
def simple_conversion(audiobook: AudioBook,
                      target_path: str,
                      output_format: str = "mp3"):
    try:
        logging.info(f"Converting {audiobook}")
        temporary_out_name = f"{target_path}.conv"
        ffmpeg_result, (stdout, stderr) = ffmpeg(
            input_file=audiobook.get_input_file(),
            output_file=temporary_out_name,
            quality_level=2,
            output_format=output_format,
            activation_bytes=audiobook.get_activation_bytes())

        logging.info(f"Job for book {audiobook} exited good: {ffmpeg_result}")
        if ffmpeg_result:
            if audiobook.get_cover() is not None:
                logging.debug(
                    f"Adding cover to {audiobook} -> {audiobook.get_cover()}")
                add_cover(temporary_out_name, audiobook.get_cover())
            rename(temporary_out_name, target_path)
            return target_path
        else:
            error_name = f"/tmp/error_{uuid.uuid4()}.json"
            with open(error_name, "w") as f_err:
                if isinstance(stdout, bytes):
                    stdout = stdout.decode("utf-8")
                else:
                    stdout = str(stdout)
                if isinstance(stderr, bytes):
                    stderr = stderr.decode("utf-8")
                else:
                    stderr = str(stderr)
                json.dump({"stdout": stdout, "stderr": stderr}, f_err)
            logging.notify("FFMPEG had an error during conversion",
                           extra={
                               "notification_title": "FFMPEG-ERROR",
                               "attach": error_name
                           })
            remove(temporary_out_name)
            remove(error_name)
    except:
        pass
    return None
Esempio n. 6
0
    def one_run(self) -> bool:
        all_files = self.get_file_list(current_element=self._watch_folder, recursive=self._recursive)
        all_files = [x for x in all_files if
                     x.lower().endswith(".aax") or x.lower().endswith(".mp3") or x.lower().endswith(".aaxc")]
        if len(all_files) <= 0:
            return False
        work_file = self.prepare_file(selected_file=all_files[0])
        audiobook = get_audiobook_by_file(work_file)
        if audiobook is None:
            self.broken_input(selected_file=all_files[0], work_file=work_file)
            logging.notify(f"Audiobook conversion of {os.path.basename(all_files[0])} failed. "
                           f"Has been awarded 'broken' :(")
            return True
        if self.audiobook_already_exists(audiobook=audiobook, target_folder=self._target_folder) is None:
            logging.info(f"Audiobook {audiobook} already exists. Deleting and carrying on")
            self.cleanup(audiobook=audiobook, final_file=None, selected_file=all_files[0])
            return True
        cover = audiobook.get_cover()

        _extra = {"notification_title": "Conversion started"}
        if cover is not None:
            _extra["attach"] = cover

        logging.notify(message=f"Conversion of {audiobook} initiated", extra=_extra)
        try:
            _ = audiobook.get_activation_bytes(create_if_missing=True)
        except TypeError:
            pass
        converted_file = simple_conversion(audiobook=audiobook, target_path=f"{work_file}.mp3")
        logging.debug(message=f"Conversion of {audiobook} finished. Saved to \"{converted_file}\"")
        if not self.finalize_file(final_file=converted_file, audiobook=audiobook, target_folder=self._target_folder):
            logging.info(f"Finalization of {audiobook} failed")
            logging.notify(message=f"Conversion of {audiobook} failed",
                           extra={"notification_title": "Conversion failed"})
            self.stale_input(selected_input=all_files[0])
        else:
            logging.info(f"Finalization of {audiobook} succeeded. Going to clean up")
            logging.success(message=f"Conversion and upload of {audiobook} secceded",
                            extra={"notification_title": "Conversion successful"})
            self.cleanup(audiobook=audiobook, final_file=converted_file, selected_file=all_files[0])
        return True
Esempio n. 7
0
def ffmpeg(input_file: str,
           output_file: str,
           activation_bytes: Optional[str] = None,
           quality_level: int = 2,
           output_format: str = None) -> Tuple[bool, Tuple[AnyStr, AnyStr]]:
    if not isfile(input_file) or isfile(output_file):
        return False, ("", "")
    ffmpeg_process = [FFMPEG_COMMAND]
    if activation_bytes is not None:
        ffmpeg_process += ["-activation_bytes", activation_bytes]
    ffmpeg_process += ["-i", input_file]
    ffmpeg_process = ffmpeg_process + ["-q:a", quality_level, "-vn"]
    if isinstance(output_format, str):
        ffmpeg_process = ffmpeg_process + ["-f", output_format]
    ffmpeg_process = ffmpeg_process + [output_file]
    logging.debug(
        f"Executing ffmpeg process {' '.join(str(x) for x in ffmpeg_process)}")
    ffmpeg_process = Popen([str(x) for x in ffmpeg_process],
                           stdout=PIPE,
                           stderr=PIPE)
    stdout, stderr = ffmpeg_process.communicate()
    return ffmpeg_process.returncode == 0, (stdout, stderr)
Esempio n. 8
0
 def generate_activation_bytes(self) -> str:
     logging.debug(f"Generating activation bytes for {self}")
     self.set_activation_bytes(get_activation_bytes(self.get_checksum()))
     return self.get_activation_bytes()