🧱 massive revamp

This commit is contained in:
sakamoto
2024-08-09 13:45:59 -05:00
parent 46f24cd349
commit 978f13ebed
2 changed files with 114 additions and 122 deletions
+80 -122
View File
@@ -1,140 +1,98 @@
# Created on iPad.
# Comic to PDF Converter
from utils import Sorter
from utils import src, dest, verbose
from utils import log
# version 1.0
import os
import img2pdf
import tempfile
import patoolib
import shutil
import os, re, argparse, tqdm, img2pdf, pathlib, tempfile, patoolib
from tqdm import tqdm
from send2trash import send2trash
parser = argparse.ArgumentParser(
description="Converts comic book zipfiles to PDF.",
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
)
parser.add_argument("-src", help="location of file(s) to convert")
parser.add_argument("-dest", help="destination of converted files")
parser.add_argument(
"-t",
"--trash-old",
action="store_true",
help="places converted cbz and cbr to the trash",
)
parser.add_argument(
"-d",
"--delete-old",
action="store_true",
help="delete cbz and cbr that are converted",
)
args = parser.parse_args()
src = args.src
dest = args.dest
delete_old = args.delete_old
trash_old = args.trash_old
print(f"The source file is: {args.source}")
print(f"The destination file is: {args.dest}")
class Comic2PDF:
def __init__(self, src, dest):
# huh? this needs to be fixed. I can't read it
# horrible use of OOP
src = self.check_src(src, dest)
dest = self.check_dest(src, dest)
def __init__(self, src, dest, verbose=False, use_tempfile=False):
self.sort = Sorter()
self.src = src
self.dest = dest
self.dest_temp_dir = os.path.join(dest, "tmp")
self.define_temp = (
tempfile.TemporaryDirectory() if use_tempfile else self.dest_temp_dir
)
self.temp_dir = (
self.define_temp.name
if isinstance(self.define_temp, tempfile.TemporaryDirectory)
else self.define_temp
)
os.makedirs(self.dest, exist_ok=True)
os.makedirs(self.dest_temp_dir, exist_ok=True)
os.makedirs(self.temp_dir, exist_ok=True)
log.info(f"Source: {self.src}")
log.info(f"Destination: {self.dest}")
log.debug(f"Temp Dir: {self.temp_dir}")
log.debug(f"Dest Temp Dir: {self.dest_temp_dir}")
def __del__(self):
delete_it = True
try:
if delete_it:
log.debug(f"Deleting: {self.dest_temp_dir}")
shutil.rmtree(self.dest_temp_dir)
except Exception as e:
log.error(e)
def run(self):
if os.path.isfile(self.src):
self.extract(self.src)
self.convert(self.src)
if src.endswith(".cbz") or src.endswith(".cbr"):
self.convert_single_file(src, dest)
else:
self.batch_convert(src, dest)
scanned_folder = self.scan(self.src)
log.debug(f"scanned folder: {scanned_folder}")
for root, dirs, files in os.walk(self.src):
for file in files:
log.info("="*30)
self.__del__()
os.makedirs(self.temp_dir)
self.extract(file)
self.convert(file)
def check_src(self, src, dest):
if (src is None and dest is None) or (src is None and dest is not None):
# src = os.path.realpath(__file__)
src = os.getcwd()
src = os.path.dirname(src)
return src
else:
return src
def scan(self, dir):
log.info(f"Scanning {dir}")
def check_dest(self, src, dest):
if dest is None and src is None:
# dest = os.path.realpath(__file__)
dest = os.getcwd()
dest = os.path.dirname(dest)
return dest
elif dest is None and src is not None:
if src.endswith(".cbz") or src.endswith(".cbr"):
dest = pathlib.Path(src).parents[0]
else:
dest = pathlib.Path(src)
return dest
else:
return dest
files_in_folder = []
def scan_folder(self, src):
filesIn_folder = []
for root, dirs, files in os.walk(src):
for root, dirs, files in os.walk(dir):
for name in files:
if name.endswith((".png", ".jpg", ".jpeg", ".cbz", ".cbr")):
filesIn_folder.append(os.path.join(root, name))
files_in_folder.append(os.path.join(root, name))
filesIn_folder.sort(key=natural_keys)
return filesIn_folder
files_in_folder.sort(key=self.sort.natural_keys)
log.info(f"Found {len(files_in_folder)} files.")
return files_in_folder
def convert_to_pdf(self, src, dest, name):
def extract(self, file):
log.info(f"Extracting... {file}")
path_file = os.path.join(self.src, file)
patoolib.extract_archive(path_file, outdir=self.temp_dir, verbosity=-1)
log.info("Extraction Complete")
def convert(self, file):
log.info("Converting to pdf...")
imgs = []
imgs = self.scan_folder(src)
pdf_path = f"{dest}/{name}.pdf"
imgs = self.scan(self.temp_dir)
basename = os.path.basename(file)
name = os.path.splitext(basename)[0]
pdf_path = os.path.join(self.dest, f"{name}.pdf")
with open(pdf_path, "wb") as f:
f.write(img2pdf.convert(imgs))
def convert_single_file(self, src, dest):
with tempfile.TemporaryDirectory() as temp_dict:
folder_parents = pathlib.Path(temp_dict)
name = pathlib.Path(src).stem
patoolib.extract_archive(src, outdir=temp_dict)
list_folderInside = next(os.walk(folder_parents))[1]
log.info("Conversion complete")
try:
storage = f"{temp_dict}/{list_folderInside[0]}"
except:
storage = f"{temp_dict}/"
self.convert_to_pdf(src=storage, dest=dest, name=name)
if trash_old is True:
send2trash(f"{src}")
if delete_old is True:
os.remove(f"{src}")
def batch_convert(self, src, dest):
for root, dir, files in os.walk(src):
pstat = [f for f in files if f.endswith(".cbr") or f.endswith(".cbz")]
pbar = tqdm(total=len(pstat))
queue = 0
for name in files:
if name.endswith(".cbz") or name.endswith(".cbr"):
pbar.set_description(f"Converting {name}")
self.convert_single_file(os.path.join(root, name), dest)
pbar.update(1)
queue += 1
else:
pass
break
# exported from the internet;
# sorts folder name to human order
def atoi(text):
return int(text) if text.isdigit() else text
def natural_keys(text):
return [atoi(c) for c in re.split(r"(d )", text)]
Comic2PDF(src, dest)
if __name__ == "__main__":
comic2pdf = Comic2PDF(src, dest, verbose)
comic2pdf.run()
+34
View File
@@ -0,0 +1,34 @@
import re
import argparse
import logging
parser = argparse.ArgumentParser(
description="A comic archive to pdf converter.",
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
)
parser.add_argument("source", type=str, help="source of file/folder with .cbz or .cbr format")
parser.add_argument(
"destination", type=str, help="ouptput of the converted files"
)
parser.add_argument("-v", "--verbose", action="store_true", help="debug mode")
args = parser.parse_args()
src = args.source
dest = args.destination
verbose = args.verbose
if verbose:
logging.basicConfig(level=logging.DEBUG, format="[%(levelname)s] - %(message)s")
else:
logging.basicConfig(level=logging.INFO, format="[%(levelname)s] - %(message)s")
log = logging.getLogger()
# got this from the internet
class Sorter:
def atoi(self, text):
return int(text) if text.isdigit() else text
def natural_keys(self, text):
return [self.atoi(c) for c in re.split(r"(d )", text)]