many changes
This commit is contained in:
@@ -1,15 +1,18 @@
|
||||
import os
|
||||
import re
|
||||
from komconfig import KomConfig
|
||||
from pathlib import Path
|
||||
import shutil
|
||||
import subprocess
|
||||
import jaro
|
||||
import loguru
|
||||
import sys
|
||||
import time
|
||||
from komgapi import komgapi
|
||||
from pathlib import Path
|
||||
|
||||
import jaro
|
||||
import loguru
|
||||
from komcache import KomCache
|
||||
from komconfig import KomConfig
|
||||
from komconfig.config import Library
|
||||
from komgapi import komgapi
|
||||
from komgapi.schemas import Series
|
||||
|
||||
cfg = KomConfig()
|
||||
|
||||
@@ -21,7 +24,7 @@ config = KomConfig()
|
||||
komga = komgapi(cfg.komga.user, cfg.komga.password, cfg.komga.url)
|
||||
|
||||
|
||||
def rename(folder: Path = config.komgrabber.download_location) -> None:
|
||||
def rename(folder: Path = config.komgrabber.tag_location) -> None:
|
||||
"""Rename the files in a folder according to the template.
|
||||
Template: [Name] v[nr] #[nr].ext (e.g. "The Flash v1 #1.cbz").
|
||||
|
||||
@@ -61,14 +64,14 @@ def rename_recursive(folder: str) -> None:
|
||||
rename(Path(f"{root}/{dir}"))
|
||||
|
||||
|
||||
def tag_folder(folder: Path = config.komgrabber.download_location) -> None:
|
||||
def tag_folder(folder: Path = config.komgrabber.tag_location) -> None:
|
||||
"""
|
||||
Recursively tags all the .cbz files in the folder using ComicTagger
|
||||
|
||||
Parameters
|
||||
----------
|
||||
folder : Path, optional
|
||||
The path that will be used to tag, by default Path(config.komgrabber.download_location)
|
||||
The path that will be used to tag, by default Path(config.komgrabber.tag_location)
|
||||
"""
|
||||
# Get the files in the folder
|
||||
if "~" in str(folder):
|
||||
@@ -88,7 +91,7 @@ def tag_folder(folder: Path = config.komgrabber.download_location) -> None:
|
||||
)
|
||||
|
||||
|
||||
def move(src: Path, dest: Path = Path(config.komga.media_path)) -> None:
|
||||
def move(src: Path, library_path: str) -> None:
|
||||
"""
|
||||
Moves the files from the source folder to the destination folder.
|
||||
If the folder already exists in the destination, only move the new files.
|
||||
@@ -97,12 +100,13 @@ def move(src: Path, dest: Path = Path(config.komga.media_path)) -> None:
|
||||
----------
|
||||
src : Path
|
||||
The source folder
|
||||
dest : Path, optional
|
||||
The destination folder used by Komga, by default Path(config.komga.media_path)
|
||||
dest : str
|
||||
The destination folder used by Komga for the library, set in config file, defaults to "Manga"
|
||||
"""
|
||||
# Get the files in the folder
|
||||
# +move the folders from src to disc, if folder already exists, only move new files
|
||||
|
||||
dest = Path(config.komga.media_path, library_path)
|
||||
folders = os.listdir(src)
|
||||
for folder in folders:
|
||||
if not os.path.exists(f"{dest}/{folder}"):
|
||||
@@ -116,6 +120,9 @@ def move(src: Path, dest: Path = Path(config.komga.media_path)) -> None:
|
||||
else:
|
||||
files = os.listdir(f"{src}/{folder}")
|
||||
for file in files:
|
||||
if file.startswith("."):
|
||||
log.debug(f"Skipping hidden file {file}")
|
||||
continue
|
||||
if not os.path.exists(f"{dest}/{folder}/{file}"):
|
||||
log.info(f"Moving {file} to {dest}/{folder}")
|
||||
shutil.move(f"{src}/{folder}/{file}", f"{dest}/{folder}")
|
||||
@@ -123,7 +130,7 @@ def move(src: Path, dest: Path = Path(config.komga.media_path)) -> None:
|
||||
remove_empty_folders(src)
|
||||
|
||||
|
||||
def remove_empty_folders(src):
|
||||
def remove_empty_folders(src: Path):
|
||||
"""
|
||||
Recursively removes empty folders in the source folder
|
||||
|
||||
@@ -140,36 +147,67 @@ def remove_empty_folders(src):
|
||||
log.info(f"Removing {folder}")
|
||||
os.rmdir(f"{src}/{folder}")
|
||||
else:
|
||||
remove_empty_folders(f"{src}/{folder}")
|
||||
newPath = Path(f"{src}/{folder}")
|
||||
remove_empty_folders(newPath)
|
||||
|
||||
|
||||
def detect_chapters(src: Path = config.komgrabber.download_location) -> None:
|
||||
def detect_chapters(
|
||||
src: Path = config.komgrabber.tag_location, valid_extension: str = "cbz|epub"
|
||||
) -> None:
|
||||
"""
|
||||
Detects and deletes any non-volume file in the source folder
|
||||
|
||||
Parameters
|
||||
----------
|
||||
src : Path, optional
|
||||
The Path to be checked, by default Path(config.komgrabber.download_location)
|
||||
The Path to be checked, by default Path(config.komgrabber.tag_location)
|
||||
"""
|
||||
log.info(f"Checking {src} for chapters")
|
||||
|
||||
regex = re.compile(rf"^.* v(\d+) #(\d+(?:-\d+)?)\.({valid_extension})$")
|
||||
for folder in os.listdir(src):
|
||||
if os.path.isdir(f"{src}/{folder}"):
|
||||
files = os.listdir(f"{src}/{folder}")
|
||||
for file in files:
|
||||
if os.path.isdir(f"{src}/{folder}/{file}"):
|
||||
folder_files = os.listdir(f"{src}/{folder}/{file}")
|
||||
for folder_file in folder_files:
|
||||
# check for regex "v(d) #(d)" in the file name
|
||||
if regex.search(folder_file):
|
||||
log.debug(f"File {folder_file} is a Volume")
|
||||
else:
|
||||
log.info(f"Deleting chapter {folder_file}")
|
||||
if os.path.isfile(f"{src}/{folder}/{file}/{folder_file}"):
|
||||
os.remove(f"{src}/{folder}/{file}/{folder_file}")
|
||||
else:
|
||||
shutil.rmtree(f"{src}/{folder}/{file}/{folder_file}")
|
||||
# check for regex "v(d) #(d)" in the file name
|
||||
regex = re.compile(r"^.* v(\d+) #(\d+(?:-\d+)?)\.cbz$")
|
||||
if regex.search(file):
|
||||
log.debug(f"File {file} is a Volume")
|
||||
else:
|
||||
log.debug(f"Deleting chapter {file}")
|
||||
if os.path.isdir(f"{src}/{folder}/{file}"):
|
||||
shutil.rmtree(f"{src}/{folder}/{file}")
|
||||
else:
|
||||
log.info(f"Deleting chapter {file}")
|
||||
if os.path.isfile(f"{src}/{folder}/{file}"):
|
||||
os.remove(f"{src}/{folder}/{file}")
|
||||
else:
|
||||
if os.path.isdir(f"{src}/{folder}/{file}"):
|
||||
for subfile in os.listdir(f"{src}/{folder}/{file}"):
|
||||
if regex.search(subfile):
|
||||
log.debug(f"File {subfile} is a Volume")
|
||||
else:
|
||||
log.info(f"Deleting chapter {subfile}")
|
||||
if os.path.isfile(
|
||||
f"{src}/{folder}/{file}/{subfile}"
|
||||
):
|
||||
os.remove(f"{src}/{folder}/{file}/{subfile}")
|
||||
else:
|
||||
shutil.rmtree(
|
||||
f"{src}/{folder}/{file}/{subfile}"
|
||||
)
|
||||
else:
|
||||
shutil.rmtree(f"{src}/{folder}/{file}")
|
||||
|
||||
|
||||
def folder_similarity(folder1, folder2) -> float:
|
||||
def folder_similarity(folder1: str, folder2: str) -> float:
|
||||
"""
|
||||
Calculate the similarity between two folder names using Jaro-Winkler distance.
|
||||
|
||||
@@ -184,7 +222,9 @@ def folder_similarity(folder1, folder2) -> float:
|
||||
return similarity
|
||||
|
||||
|
||||
def rename_folder(src=config.komgrabber.download_location, series=None) -> bool:
|
||||
def rename_folder(
|
||||
src: Path = config.komgrabber.tag_location, series: Series = None
|
||||
) -> bool:
|
||||
renamer_regex = r"(\s*\([^)]*\))+$"
|
||||
for folder in os.listdir(src):
|
||||
if os.path.isdir(f"{src}/{folder}"):
|
||||
@@ -235,11 +275,16 @@ def calculate_new_volumes(
|
||||
present_volumes: list[int], new_volumes: list[int]
|
||||
) -> list[int]:
|
||||
if len(new_volumes) == 1:
|
||||
if max(new_volumes) > max(present_volumes):
|
||||
if len(present_volumes) == 0:
|
||||
return new_volumes
|
||||
if max(new_volumes) > max(present_volumes):
|
||||
# return any new volume that is not in present volumes
|
||||
return [v for v in new_volumes if v not in present_volumes]
|
||||
else:
|
||||
return []
|
||||
else:
|
||||
if len(present_volumes) == 0:
|
||||
return new_volumes
|
||||
new_volumes = sorted(new_volumes)
|
||||
new_volumes = [i for i in new_volumes if i > max(present_volumes)]
|
||||
if len(new_volumes) == 0:
|
||||
@@ -283,3 +328,138 @@ def get_series_update_date(series_name: str) -> str:
|
||||
args=(series_name,),
|
||||
)
|
||||
print(update_date)
|
||||
|
||||
|
||||
def process_manga(download_path: Path, library: Library, serie: Series) -> None:
|
||||
"""Process the downloaded manga: rename files, detect chapters, tag, rename folder, and move to library."""
|
||||
|
||||
rename(download_path)
|
||||
if not config.komgrabber.get_chapters:
|
||||
detect_chapters(download_path, "|".join(library.valid_extensions))
|
||||
tag_folder(download_path)
|
||||
if rename_folder(series=serie, src=download_path):
|
||||
move(
|
||||
download_path,
|
||||
library.media_path,
|
||||
)
|
||||
|
||||
|
||||
def process_novel(
|
||||
download_path: Path, library: Library, serie: Series, copy: bool = False
|
||||
) -> None:
|
||||
"""Process the downloaded novel: rename files, tag, rename folder, and move to library."""
|
||||
|
||||
# rename the folder to the series name
|
||||
folder = os.listdir(download_path)[0]
|
||||
series_name = serie.name
|
||||
# remove all files that are not valid extensions
|
||||
valid_extensions = library.valid_extensions
|
||||
# flatten subfolders and subsubfolders
|
||||
for root, dirs, files in os.walk(f"{download_path}/{folder}"):
|
||||
for dir in dirs:
|
||||
for file in os.listdir(f"{root}/{dir}"):
|
||||
if file.startswith("."):
|
||||
log.debug(f"Skipping hidden file {file}")
|
||||
continue
|
||||
log.info(f"Moving {file} to {download_path}/{folder}")
|
||||
shutil.move(f"{root}/{dir}/{file}", f"{download_path}/{folder}")
|
||||
os.rmdir(f"{root}/{dir}")
|
||||
|
||||
# removing invalid extensions
|
||||
for file in os.listdir(f"{download_path}/{folder}"):
|
||||
if not any(file.endswith(ext) for ext in valid_extensions):
|
||||
log.info(f"Removing {file} as it is not a valid extension")
|
||||
if os.path.isfile(f"{download_path}/{folder}/{file}"):
|
||||
os.remove(f"{download_path}/{folder}/{file}")
|
||||
else:
|
||||
shutil.rmtree(f"{download_path}/{folder}/{file}")
|
||||
|
||||
# rename files to remove all [] and text within
|
||||
for file in os.listdir(f"{download_path}/{folder}"):
|
||||
filename = file.split(".")[0]
|
||||
|
||||
if f"{series_name} - Volume" in filename:
|
||||
log.debug(f"Skipping {file}, already renamed")
|
||||
continue
|
||||
# extract the volume number, may be a float, either v1, v1.5, v01, v01.5, vol.1, vol.01, vol.1.5, vol.01.5, Vol.1, Vol.01, Vol.1.5, Vol.01.5, Volume 1, Volume 01, Volume 1.5, Volume 01.5
|
||||
regex_volume_pattern = r"(v|vol\.|Vol\.|Volume\s)(\d+(\.\d+)?)"
|
||||
match = re.search(regex_volume_pattern, file, re.IGNORECASE)
|
||||
# from the match, get the volume number
|
||||
volume = match.group(2) if match else None
|
||||
|
||||
# rename the file to series name v(volume).ext
|
||||
ext = file.split(".")[-1]
|
||||
# if volume is not null and less than 10, pad with a 0
|
||||
if volume and float(volume) < 10:
|
||||
volume = f"0{volume}"
|
||||
if volume and "00" in volume:
|
||||
volume = volume.replace("00", "0")
|
||||
fixed = (
|
||||
f"{series_name} - Volume {volume}.{ext}"
|
||||
if volume
|
||||
else f"{series_name}.{ext}"
|
||||
)
|
||||
log.debug(f"Renaming {file} to {fixed}")
|
||||
os.rename(
|
||||
f"{download_path}/{folder}/{file}", f"{download_path}/{folder}/{fixed}"
|
||||
)
|
||||
# flatten subfolders
|
||||
|
||||
os.rename(f"{download_path}/{folder}", f"{download_path}/{series_name}")
|
||||
dest = Path(config.komga.media_path, library.media_path)
|
||||
folders = os.listdir(download_path)
|
||||
log.info(f"Moving {folders} to {dest}")
|
||||
for folder in folders:
|
||||
log.info(f"Processing folder {folder}")
|
||||
time.sleep(1)
|
||||
if not os.path.exists(f"{dest}/{folder}"):
|
||||
log.info(f"Moving {folder} to {dest}")
|
||||
os.mkdir(f"{dest}/{folder}")
|
||||
files = os.listdir(f"{download_path}/{folder}")
|
||||
for file in files:
|
||||
time.sleep(1)
|
||||
log.debug(f"Moving {file} to {dest}/{folder}")
|
||||
if copy:
|
||||
# copy file to komgrabber tag location
|
||||
copy_location = config.komgrabber.copy_location
|
||||
if not os.path.exists(f"{copy_location}"):
|
||||
os.mkdir(f"{copy_location}")
|
||||
shutil.copy(
|
||||
f"{download_path}/{folder}/{file}",
|
||||
f"{copy_location}/{file}",
|
||||
)
|
||||
log.debug(
|
||||
f"Copied from {download_path}/{folder}/{file} to {copy_location}/{file}"
|
||||
)
|
||||
shutil.move(f"{download_path}/{folder}/{file}", f"{dest}/{folder}")
|
||||
# shutil.move(f"{src}/{folder}", dest)
|
||||
else:
|
||||
files = os.listdir(f"{download_path}/{folder}")
|
||||
for file in files:
|
||||
time.sleep(1)
|
||||
log.debug(f"Processing file {file}")
|
||||
if file.startswith("."):
|
||||
log.debug(f"Skipping hidden file {file}")
|
||||
continue
|
||||
if not os.path.exists(f"{dest}/{folder}/{file}"):
|
||||
log.debug(f"Moving {file} to {dest}/{folder}")
|
||||
if copy:
|
||||
# copy file to komgrabber tag location
|
||||
copy_location = config.komgrabber.copy_location
|
||||
if not os.path.exists(f"{copy_location}/{folder}"):
|
||||
os.mkdir(f"{copy_location}")
|
||||
shutil.copy(
|
||||
f"{download_path}/{folder}/{file}",
|
||||
f"{copy_location}/{file}",
|
||||
)
|
||||
log.debug(
|
||||
f"Copied from {download_path}/{folder}/{file} to {copy_location}/{file}"
|
||||
)
|
||||
shutil.move(f"{download_path}/{folder}/{file}", f"{dest}/{folder}")
|
||||
|
||||
log.info("Finished moving files, removing empty folders")
|
||||
remove_empty_folders(download_path)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
print(folder_similarity("Dr. STONE (2018-2023) (Digital) (1r0n)", "Dr. STONE"))
|
||||
|
||||
Reference in New Issue
Block a user