initial commit
This commit is contained in:
546
src/logic/cli.py
Normal file
546
src/logic/cli.py
Normal file
@@ -0,0 +1,546 @@
|
||||
import os
|
||||
import re
|
||||
import shutil
|
||||
import subprocess
|
||||
import time
|
||||
import zipfile
|
||||
import jaro
|
||||
from src.data.komga import KomgaAPI
|
||||
from komgapi.schemas.Series import Series
|
||||
from src.data.mangadex import MangadexAPI
|
||||
from src.data.cache import ListCache
|
||||
from src.data.Feeds.nyaasi import Nyaa
|
||||
from src.logic.download import Download
|
||||
from komconfig import KomConfig
|
||||
import loguru
|
||||
import sys
|
||||
|
||||
config = KomConfig()
|
||||
|
||||
logs = loguru.logger
|
||||
logs.remove()
|
||||
logs.add("komgrabber.log", level="INFO")
|
||||
Komga = KomgaAPI()
|
||||
md = MangadexAPI()
|
||||
|
||||
|
||||
LINE_CLEAR = "\x1b[2K" # <-- ANSI sequence
|
||||
failed_items = []
|
||||
|
||||
|
||||
class utils:
|
||||
def __init__(self) -> None:
|
||||
self.dl = Download("/home/alexander/Downloads/torrents/Manga_test/")
|
||||
self.file = None
|
||||
self.serie = ""
|
||||
self.serie_id = ""
|
||||
self.series_data: Series = None
|
||||
self.volumes = []
|
||||
self.download_path = config.komgrabber.download_location
|
||||
if "~" in self.download_path:
|
||||
self.download_path = os.path.expanduser(self.download_path)
|
||||
# self.allSeries = Komga.getAllSeries()
|
||||
pass
|
||||
|
||||
def download(self, feed_url: str):
|
||||
def __chapter_check(title: str) -> bool:
|
||||
if title.endswith(".cbz") or title.endswith(".cbr"):
|
||||
if not re.search(r"(v\d{1,3}(-\d{1,3})?)|(Vol\. \d{1,3})", title):
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def __epub_check(title: str) -> bool:
|
||||
if title.endswith(".epub"):
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
file: str
|
||||
file = self.dl.get_file(feed_url)
|
||||
if __chapter_check(file):
|
||||
print(f"Skipping {file}, reason: no volume number, likely a chapter")
|
||||
return False
|
||||
if __epub_check(file):
|
||||
print(f"Skipping {file}, reason: epub file")
|
||||
return False
|
||||
|
||||
self.file = file
|
||||
|
||||
print(f"Filename: {file}")
|
||||
file_move = False
|
||||
if file.endswith(".cbz") or file.endswith(".cbr"):
|
||||
new_folder = f"{self.download_path}{self.serie}"
|
||||
os.makedirs(new_folder, exist_ok=True)
|
||||
file_move = True
|
||||
|
||||
state = self.dl.add_torrent(feed_url.split("/")[-1])
|
||||
if state is False:
|
||||
print("Error adding torrent")
|
||||
return False
|
||||
|
||||
gid = self.dl.api.get_downloads()[0].gid
|
||||
# check if the download is complete usin the gid
|
||||
dl_complete = True
|
||||
check_done = False
|
||||
while not self.dl.api.get_downloads(gids=[gid])[0].seeder:
|
||||
# while not self.dl.api.get_downloads()[0].seeder:
|
||||
progress = self.dl.check_progress()
|
||||
progress = "{:.2f}".format(progress)
|
||||
eta = self.dl.api.get_downloads()[0].eta_string()
|
||||
print(end=LINE_CLEAR)
|
||||
print("Progress: ", progress, "ETA: ", eta, end="\r")
|
||||
# if progress remains the same for 30 seconds, stop the download
|
||||
progress = self.dl.check_progress()
|
||||
time.sleep(30)
|
||||
n_progress = self.dl.check_progress()
|
||||
if not check_done:
|
||||
local_files = os.listdir(f"{self.download_path}")
|
||||
for f in local_files:
|
||||
# print(f)
|
||||
if os.path.isdir(f"{self.download_path}/{f}"):
|
||||
local_files.extend(
|
||||
[
|
||||
f"{self.download_path}/{f}/{file}"
|
||||
for file in os.listdir(f"{self.download_path}/{f}")
|
||||
]
|
||||
)
|
||||
local_files = [
|
||||
file
|
||||
for file in local_files
|
||||
if file.endswith(".cbz") or file.endswith(".cbr")
|
||||
]
|
||||
local_volumes = Komga.getVolumes(self.series_data.id)
|
||||
# if not local_files:
|
||||
# dl_complete=False
|
||||
# break
|
||||
local_files_volumes = []
|
||||
for file in local_files:
|
||||
vol_regex = r"(v\d{1,3}(-\d{1,3})?)|(Vol\. \d{1,3})"
|
||||
# if the file does not match the naming convention, skip it
|
||||
if re.search(vol_regex, file):
|
||||
match = re.search(vol_regex, file)
|
||||
if match:
|
||||
vol = match.group(0).replace("v", "").replace("Vol. ", "")
|
||||
if "-" in vol:
|
||||
local_files_volumes.extend(
|
||||
[int(volume) for volume in vol.split("-")]
|
||||
)
|
||||
continue
|
||||
vol = int(vol)
|
||||
local_files_volumes.append(vol)
|
||||
print(f"Grabbed volumes: {local_files_volumes}")
|
||||
print(f"Komga volumes: {local_volumes}")
|
||||
if local_files_volumes == []:
|
||||
pass
|
||||
# check íf any local_file_volumes are not in local_volumes
|
||||
if all([vol in local_volumes for vol in local_files_volumes]):
|
||||
print("all volumes downloaded, stopping...")
|
||||
dl_complete = False
|
||||
break
|
||||
else:
|
||||
print("not all volumes downloaded, continuing...")
|
||||
check_done = True
|
||||
if progress == n_progress:
|
||||
print("Progress has not changed for 30 seconds, stopping the download")
|
||||
self.dl.api.get_downloads()[0].remove(force=True)
|
||||
dl_complete = False
|
||||
break
|
||||
else:
|
||||
pass
|
||||
# stop the download, remove the torrent files
|
||||
try:
|
||||
self.dl.api.get_downloads()[0].remove(force=True)
|
||||
except:
|
||||
pass
|
||||
self.dl.remove_torrents()
|
||||
print(end=LINE_CLEAR)
|
||||
print("Download complete")
|
||||
# self.dl.download(feed_url, file_rename=True)
|
||||
if not dl_complete:
|
||||
# remove everything from the download folder
|
||||
data = os.listdir(f"{self.download_path}")
|
||||
for file in data:
|
||||
try:
|
||||
os.remove(f"{self.download_path}{file}")
|
||||
except IsADirectoryError:
|
||||
shutil.rmtree(f"{self.download_path}{file}")
|
||||
|
||||
if dl_complete is True:
|
||||
# for dfile in os.listdir(f'{self.download_path}{file}'):
|
||||
# if __chapter_check(dfile):
|
||||
# os.remove(f'{self.download_path}{file}{dfile}')
|
||||
try:
|
||||
if file_move is True:
|
||||
shutil.move(
|
||||
f"{self.download_path}{file}",
|
||||
f"{new_folder}/{file}",
|
||||
)
|
||||
except Exception as e:
|
||||
print(e)
|
||||
return False
|
||||
return True
|
||||
return False
|
||||
|
||||
def tag_files(self, folder: str, interactive: bool = False):
|
||||
"""Tag all files in the specified folder.
|
||||
|
||||
Args:
|
||||
----
|
||||
- folder (str): the path to the folder containing the files to tag
|
||||
- interactive (bool, optional): if set to True, the shell will pause and await user input instead of not writing data to file. Defaults to False.
|
||||
"""
|
||||
|
||||
def is_valid_cbz(file_path) -> bool:
|
||||
try:
|
||||
with zipfile.ZipFile(file_path, "r") as cbz_file:
|
||||
# Check if the file is a valid ZIP archive
|
||||
if cbz_file.testzip() is not None:
|
||||
return False
|
||||
|
||||
# Check if the CBZ file contains at least one image file
|
||||
for file_info in cbz_file.infolist():
|
||||
if (
|
||||
not file_info.is_dir()
|
||||
and file_info.filename.lower().endswith(
|
||||
(".jpg", ".jpeg", ".png")
|
||||
)
|
||||
):
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
except (zipfile.BadZipFile, FileNotFoundError):
|
||||
return False
|
||||
|
||||
for file in os.listdir(f"{folder}"):
|
||||
print(f"Checking {file}")
|
||||
# if file is a not cbz file, skip
|
||||
if not file.endswith(".cbz"):
|
||||
print(f"Skipping {file}")
|
||||
continue
|
||||
|
||||
try:
|
||||
# if not is_valid_cbz(f"{folder}/{file}"):
|
||||
# print(f"removing {file}, not a valid cbz file")
|
||||
# os.remove(f"{folder}/{file}")
|
||||
# continue
|
||||
print(f"Tagging {file}")
|
||||
regex = r"v(\d{2,3}) #(\d{2,3})"
|
||||
match = re.search(regex, file)
|
||||
if not match:
|
||||
print(f"Skipping {file}, no match")
|
||||
os.remove(f"{folder}/{file}")
|
||||
continue
|
||||
if interactive:
|
||||
subprocess.call(
|
||||
f'comictagger -s -t cr -f -o "{folder}/{file}" --nosummary --overwrite -i',
|
||||
shell=True,
|
||||
)
|
||||
subprocess.call(
|
||||
f'comictagger -s -t cr -f -o "{folder}/{file}" --nosummary --overwrite',
|
||||
shell=True,
|
||||
)
|
||||
print(f"Tagged {file}")
|
||||
except Exception as e:
|
||||
print(e)
|
||||
continue
|
||||
|
||||
def rename_folder_and_files(self, file: str, komga_data, remove=False):
|
||||
logs.info(f"Renaming {file}")
|
||||
# rename the folder to the komga name
|
||||
series_id = komga_data.id
|
||||
series_name = komga_data.name
|
||||
new_folder = f"{self.download_path}{series_name}"
|
||||
try:
|
||||
os.rename(f"{self.download_path}{file}", new_folder)
|
||||
except Exception as e:
|
||||
print(e)
|
||||
try:
|
||||
files = os.listdir(new_folder)
|
||||
except NotADirectoryError:
|
||||
return
|
||||
volumes = []
|
||||
for file in files:
|
||||
if not (file.endswith(".cbz") or file.endswith(".cbr")):
|
||||
print(f"Skipping {file}, not a comicarchive file")
|
||||
continue
|
||||
ext = file.split(".")[-1]
|
||||
|
||||
# match = re.search(r"v\d{2,4}(-\d{2,4})*", file)
|
||||
match = re.search(r"v\d{2,4} ", file)
|
||||
|
||||
if match:
|
||||
# print(match)
|
||||
split_start = match.start()
|
||||
split_end = match.end()
|
||||
# Split the filename between split_start and split_end
|
||||
volume = file[split_start:split_end]
|
||||
# Split the filename at the split index, but keep the "v" and digits in the title
|
||||
title = file[:split_start].strip()
|
||||
# add the volume number to the title as a suffix #nr
|
||||
title = f"{title} {volume} #{volume.replace('v', '')}".strip().replace(
|
||||
" ", " "
|
||||
)
|
||||
# print(title)
|
||||
# rename the file
|
||||
os.rename(f"{new_folder}/{file}", f"{new_folder}/{title}.{ext}")
|
||||
volumes.append(int(volume.replace("v", "")))
|
||||
logs.info(f"Renamed {file} to {title}")
|
||||
if remove:
|
||||
print("removing files that are already in komga")
|
||||
# search komga_name in series
|
||||
# get all volumes of the serie
|
||||
local_volumes = Komga.getVolumes(series_id=series_id)
|
||||
# remove the volumes that are already in komga
|
||||
self.remove_if_alr_in_db(local_volumes, volumes, series_name)
|
||||
self.tag_files(new_folder)
|
||||
|
||||
def process_serie(self, data: Series):
|
||||
"""Pprocess a single serie based on its title.
|
||||
The process is as follows:
|
||||
1. get all volumes of the serie from komga using the api
|
||||
2. get all feed entries from nyaa.si using the api
|
||||
3. compare the volumes from komga with the volumes from nyaa.si
|
||||
3.1 if the volumes from nyaa.si are greater than the volumes from komga, add the entry to the download list.
|
||||
|
||||
Args:
|
||||
----
|
||||
- data (dict): a dict containing the title of the serie at ["title"] and the id of the serie at ["id"]
|
||||
|
||||
|
||||
Returns:
|
||||
-------
|
||||
- list[dict]: a list of dictionaries containing the entries to download
|
||||
"""
|
||||
serie = data.name
|
||||
series_id = data.id
|
||||
vols = Komga.getVolumes(series_id=series_id, unpaged=True)
|
||||
feed_titles = Nyaa.search(keyword=serie, category=3, subcategory=1)
|
||||
print(feed_titles)
|
||||
f_d = []
|
||||
if feed_titles == []:
|
||||
failed_items.append(serie)
|
||||
added_max_vols = vols if vols else [0]
|
||||
# #print(len(added_max_vols))
|
||||
for entry in feed_titles:
|
||||
if entry.seeders > 0:
|
||||
if (
|
||||
serie.lower() in entry.name.lower()
|
||||
or jaro.jaro_metric(entry.name.lower(), serie.lower()) > 0.7
|
||||
):
|
||||
volumes = entry["volumes"]
|
||||
if isinstance(volumes, list):
|
||||
volumes = volumes[
|
||||
::-1
|
||||
] # reverse the list to get the highest volume number quickly
|
||||
for vol in volumes:
|
||||
if vol not in added_max_vols:
|
||||
f_d.append(entry)
|
||||
added_max_vols.append(vol)
|
||||
break
|
||||
|
||||
return f_d
|
||||
|
||||
def media_grabber(self, serie: Series):
|
||||
result = self.process_serie(serie)
|
||||
logs.info(f"Found {len(result)} new volumes for {serie.name}")
|
||||
logs.info(f"Data: {result}")
|
||||
print(
|
||||
f"current volumes: {Komga.getVolumes(series_id=serie.id, unpaged=True)}, new volumes: {result}"
|
||||
)
|
||||
|
||||
# print(result)
|
||||
if len(result) != 0:
|
||||
for entry in result:
|
||||
# print(entry["link"])
|
||||
if self.download(entry["link"]) is True:
|
||||
print("renaming...")
|
||||
self.rename_folder_and_files(
|
||||
self.file, komga_data=serie, remove=True
|
||||
)
|
||||
# self.move_to_komga(serie=entry)
|
||||
print("done")
|
||||
return True
|
||||
else:
|
||||
# remove the folder
|
||||
try:
|
||||
folders = os.listdir(self.download_path)
|
||||
for folder in folders:
|
||||
os.remove(f"{self.download_path}{folder}")
|
||||
except Exception as e:
|
||||
print(e)
|
||||
|
||||
return False
|
||||
|
||||
def remove_if_alr_in_db(
|
||||
self, present_volumes: list, downloaded_volumes: list, folder: str
|
||||
):
|
||||
"""Delete any file from the folder that is already in the database, or does not conform to the naming convention.
|
||||
|
||||
Args:
|
||||
----
|
||||
present_volumes (list): a list of volumes that are already in the database, retrieved from komga api
|
||||
downloaded_volumes (list): the list of volumes that are downloaded from the corresponding feed/api
|
||||
folder (str): relative path to the folder containing the downloaded files
|
||||
"""
|
||||
print(f"present_volumes: {present_volumes}")
|
||||
print(f"downloaded_volumes: {downloaded_volumes}")
|
||||
content_folder = f"{self.download_path}{folder}"
|
||||
content_files = [file for file in os.listdir(content_folder)]
|
||||
print(f"content_files: {content_files}")
|
||||
duplicates = [any(file in content_files for file in present_volumes)]
|
||||
for file in os.listdir(content_folder):
|
||||
if "#" not in file:
|
||||
try:
|
||||
os.remove(os.path.join(content_folder, file))
|
||||
if IsADirectoryError:
|
||||
shutil.rmtree(os.path.join(content_folder, file))
|
||||
if FileNotFoundError:
|
||||
continue
|
||||
except Exception as e:
|
||||
# print(e)
|
||||
continue
|
||||
# print(f"removed {file}, Reason: not a valid file")
|
||||
content_files.remove(file)
|
||||
for vol in present_volumes:
|
||||
if vol < 10:
|
||||
vol = f"0{vol}"
|
||||
for file in content_files:
|
||||
if str(vol) in file:
|
||||
# print(f"removing {vol}")
|
||||
try:
|
||||
os.remove(os.path.join(content_folder, file))
|
||||
except:
|
||||
print(f"could not remove {vol}")
|
||||
|
||||
def move_to_komga(self, serie: tuple[str, str] = None):
|
||||
komga_path = f"{config.komga.media_path}{self.serie}"
|
||||
# print(f"komga_path: {komga_path}")
|
||||
# print("moving to komga")
|
||||
# move files to komga
|
||||
for file in os.listdir(f"{self.download_path}{self.serie}"):
|
||||
file_path = os.path.join(f"{self.download_path}{self.serie}", file)
|
||||
final_path = os.path.join(komga_path, file)
|
||||
|
||||
shutil.move(file_path, final_path)
|
||||
|
||||
print(f"moved {file} to {komga_path}")
|
||||
# delete empty folder
|
||||
try:
|
||||
os.rmdir(f"{self.download_path}{self.serie}")
|
||||
logs.info(f"moved {self.serie} to komga")
|
||||
except:
|
||||
print(f"could not remove {self.serie}")
|
||||
logs.error(f"could not remove {self.serie}")
|
||||
return self
|
||||
|
||||
def search_for_new_volumes(self):
|
||||
series = Komga.series_controller.getAllSeries(
|
||||
body={
|
||||
"condition": {
|
||||
"seriesStatus": {
|
||||
"operator": "is",
|
||||
"value": "HIATUS",
|
||||
"value": "ENDED",
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
shutil.rmtree(self.download_path)
|
||||
os.mkdir(self.download_path)
|
||||
|
||||
for serie in series:
|
||||
position = series.index(serie)
|
||||
print("Working on serie", position, "of ", len(series))
|
||||
logs.info(f"searching for new volumes for {serie.name}")
|
||||
print(serie.name)
|
||||
self.series_data = serie
|
||||
self.serie = serie.name
|
||||
self.serie_id = serie.id
|
||||
|
||||
if self.media_grabber(serie) is True:
|
||||
self.move_to_komga(serie)
|
||||
time.sleep(5)
|
||||
# print("done", serie.name)
|
||||
return self
|
||||
|
||||
def add_missing_to_db(self):
|
||||
database_series = ListCache("mangacache.db").get_all_series("name")
|
||||
database_series = [serie[0] for serie in database_series]
|
||||
database_set = set(database_series)
|
||||
# print(database_series)
|
||||
komga_series = Komga.series_controller.getAllSeries()
|
||||
|
||||
db_added = []
|
||||
for serie in komga_series:
|
||||
if serie.id not in database_set:
|
||||
# print(serie.id)
|
||||
db_added.append(serie)
|
||||
ListCache("mangacache.db").add_series(
|
||||
serie.id, serie.name, serie.metadata.status
|
||||
)
|
||||
else:
|
||||
print(f"{serie.id} already in db")
|
||||
print("added to db:", len(db_added))
|
||||
|
||||
# print(f"{serie[1]} has status {komga_series}")
|
||||
|
||||
@DeprecationWarning
|
||||
def get_md_metadata(self, id: str):
|
||||
data = md.get_metadata(id, lang="en")
|
||||
db_data = ListCache("mangacache.db").get_series_by_id(id, "mangadex_id")
|
||||
|
||||
def automated(self, series_data: tuple[str, str]):
|
||||
"""_summary_.
|
||||
|
||||
Args:
|
||||
----
|
||||
series_data (list[tuple[str,str]]): _description_
|
||||
"""
|
||||
if self.media_grabber(series_data) is True:
|
||||
self.move_to_komga(series_data)
|
||||
time.sleep(5)
|
||||
|
||||
|
||||
def parallel_execution(series: list[tuple[str, str, str]]):
|
||||
"""_summary_.
|
||||
|
||||
Args:
|
||||
----
|
||||
series (list[tuple[str,str,str]]): _description_
|
||||
"""
|
||||
th = utils()
|
||||
for serie in series:
|
||||
th.automated(serie)
|
||||
|
||||
|
||||
@DeprecationWarning
|
||||
def update_state():
|
||||
database_series = ListCache("mangacache.db").get_all_series()
|
||||
database_series = [serie for serie in database_series if serie[3] != "ENDED"]
|
||||
|
||||
for serie in database_series:
|
||||
komga_series = Komga.getSeriesStatus(serie)
|
||||
if komga_series == "ONGOING":
|
||||
continue
|
||||
else:
|
||||
ListCache("mangacache.db").update_database(
|
||||
komga_id=serie[2], complete=komga_series
|
||||
)
|
||||
|
||||
|
||||
def avail_check():
|
||||
komga_avail = True
|
||||
|
||||
return (True, komga_avail)
|
||||
|
||||
|
||||
def main():
|
||||
utils().search_for_new_volumes()
|
||||
# update_state()
|
||||
print("Failed series:\n", failed_items)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
utils().search_for_new_volumes()
|
||||
231
src/logic/constants.py
Normal file
231
src/logic/constants.py
Normal file
@@ -0,0 +1,231 @@
|
||||
LINK_TRANSFORM = {"al":"https://anilist.co/manga/",
|
||||
"ap":"https://www.anime-planet.com/manga/",
|
||||
"bw":"https://bookwalker.jp/",
|
||||
"kt":"https://kitsu.io/manga/",
|
||||
"mu":"https://www.mangaupdates.com/series.html?id=",
|
||||
"mal":"https://myanimelist.net/manga/"}
|
||||
|
||||
|
||||
LANG_CODES = [
|
||||
"ab",
|
||||
"aa",
|
||||
"af",
|
||||
"ak",
|
||||
"sq",
|
||||
"am",
|
||||
"ar",
|
||||
"an",
|
||||
"hy",
|
||||
"as",
|
||||
"av",
|
||||
"ae",
|
||||
"ay",
|
||||
"az",
|
||||
"bm",
|
||||
"ba",
|
||||
"eu",
|
||||
"be",
|
||||
"bn",
|
||||
"bi",
|
||||
"bs",
|
||||
"br",
|
||||
"bg",
|
||||
"my",
|
||||
"ca",
|
||||
"ch",
|
||||
"ce",
|
||||
"ny",
|
||||
"zh",
|
||||
"cu",
|
||||
"cv",
|
||||
"kw",
|
||||
"co",
|
||||
"cr",
|
||||
"hr",
|
||||
"cs",
|
||||
"da",
|
||||
"dv",
|
||||
"nl",
|
||||
"dz",
|
||||
"en",
|
||||
"eo",
|
||||
"et",
|
||||
"ee",
|
||||
"fo",
|
||||
"fj",
|
||||
"fi",
|
||||
"fr",
|
||||
"fy",
|
||||
"ff",
|
||||
"gd",
|
||||
"gl",
|
||||
"lg",
|
||||
"ka",
|
||||
"de",
|
||||
"el",
|
||||
"kl",
|
||||
"gn",
|
||||
"gu",
|
||||
"ht",
|
||||
"ha",
|
||||
"he",
|
||||
"hz",
|
||||
"hi",
|
||||
"ho",
|
||||
"hu",
|
||||
"is",
|
||||
"io",
|
||||
"ig",
|
||||
"id",
|
||||
"ia",
|
||||
"ie",
|
||||
"iu",
|
||||
"ik",
|
||||
"ga",
|
||||
"it",
|
||||
"ja",
|
||||
"jv",
|
||||
"kn",
|
||||
"kr",
|
||||
"ks",
|
||||
"kk",
|
||||
"km",
|
||||
"ki",
|
||||
"rw",
|
||||
"ky",
|
||||
"kv",
|
||||
"kg",
|
||||
"ko",
|
||||
"kj",
|
||||
"ku",
|
||||
"lo",
|
||||
"la",
|
||||
"lv",
|
||||
"li",
|
||||
"ln",
|
||||
"lt",
|
||||
"lu",
|
||||
"lb",
|
||||
"mk",
|
||||
"mg",
|
||||
"ms",
|
||||
"ml",
|
||||
"mt",
|
||||
"gv",
|
||||
"mi",
|
||||
"mr",
|
||||
"mh",
|
||||
"mn",
|
||||
"na",
|
||||
"nv",
|
||||
"nd",
|
||||
"nr",
|
||||
"ng",
|
||||
"ne",
|
||||
"no",
|
||||
"nb",
|
||||
"nn",
|
||||
"ii",
|
||||
"oc",
|
||||
"oj",
|
||||
"or",
|
||||
"om",
|
||||
"os",
|
||||
"pi",
|
||||
"ps",
|
||||
"fa",
|
||||
"pl",
|
||||
"pt",
|
||||
"pa",
|
||||
"qu",
|
||||
"ro",
|
||||
"rm",
|
||||
"rn",
|
||||
"ru",
|
||||
"se",
|
||||
"sm",
|
||||
"sg",
|
||||
"sa",
|
||||
"sc",
|
||||
"sr",
|
||||
"sn",
|
||||
"sd",
|
||||
"si",
|
||||
"sk",
|
||||
"sl",
|
||||
"so",
|
||||
"st",
|
||||
"es",
|
||||
"su",
|
||||
"sw",
|
||||
"ss",
|
||||
"sv",
|
||||
"tl",
|
||||
"ty",
|
||||
"tg",
|
||||
"ta",
|
||||
"tt",
|
||||
"te",
|
||||
"th",
|
||||
"bo",
|
||||
"ti",
|
||||
"to",
|
||||
"ts",
|
||||
"tn",
|
||||
"tr",
|
||||
"tk",
|
||||
"tw",
|
||||
"ug",
|
||||
"uk",
|
||||
"ur",
|
||||
"uz",
|
||||
"ve",
|
||||
"vi",
|
||||
"vo",
|
||||
"wa",
|
||||
"cy",
|
||||
"wo",
|
||||
"xh",
|
||||
"yi",
|
||||
"yo",
|
||||
"za",
|
||||
"zu",
|
||||
]
|
||||
READING_DIRECTIONS = ["Left to Right", "Right to Left", "Vertical", "Webtoon"]
|
||||
READING_DIRECTONS_KOMGA = ["LEFT_TO_RIGHT", "RIGHT_TO_LEFT", "VERTICAL", "WEBTOON"]
|
||||
READING_DIR_TRANSLATION = {
|
||||
READING_DIRECTIONS[0]: READING_DIRECTONS_KOMGA[0],
|
||||
READING_DIRECTIONS[1]: READING_DIRECTONS_KOMGA[1],
|
||||
READING_DIRECTIONS[2]: READING_DIRECTONS_KOMGA[2],
|
||||
READING_DIRECTIONS[3]: READING_DIRECTONS_KOMGA[3],
|
||||
}
|
||||
|
||||
|
||||
METADATA_PROVIDERS = ["MangaDex", "ComicVine", "AniList", "MyAnimeList", "Comics.org"]
|
||||
SERIES_STATUS = ["---", "Ongoing", "Ended", "Hiatus", "Abandoned"]
|
||||
SERIES_STATUS_KOMGA = ["UNKNOWN", "ONGOING", "ENDED", "HIATUS", "ABANDONED"]
|
||||
SERIES_STATUS_TRANSLATION = {
|
||||
SERIES_STATUS[0]: SERIES_STATUS_KOMGA[0],
|
||||
SERIES_STATUS[1]: SERIES_STATUS_KOMGA[1],
|
||||
SERIES_STATUS[2]: SERIES_STATUS_KOMGA[2],
|
||||
SERIES_STATUS[3]: SERIES_STATUS_KOMGA[3],
|
||||
SERIES_STATUS[4]: SERIES_STATUS_KOMGA[4],
|
||||
}
|
||||
|
||||
def translate_series_status(status: str) -> str:
|
||||
if status in SERIES_STATUS_TRANSLATION.keys():
|
||||
return SERIES_STATUS_TRANSLATION[status]
|
||||
else:
|
||||
#get the key from the value
|
||||
for key, value in SERIES_STATUS_TRANSLATION.items():
|
||||
if value == status:
|
||||
return key
|
||||
|
||||
def translate_reading_direction(direction: str) -> str:
|
||||
if direction in READING_DIR_TRANSLATION.keys():
|
||||
return READING_DIR_TRANSLATION[direction]
|
||||
else:
|
||||
#get the key from the value
|
||||
for key, value in READING_DIR_TRANSLATION.items():
|
||||
if value == direction:
|
||||
return key
|
||||
0
src/logic/data.py
Normal file
0
src/logic/data.py
Normal file
16
src/logic/detect_chapters.py
Normal file
16
src/logic/detect_chapters.py
Normal file
@@ -0,0 +1,16 @@
|
||||
import os
|
||||
import re
|
||||
|
||||
|
||||
def detect_chapters(src: str = "/home/alexander/Downloads/torrents/manga/"):
|
||||
for folder in os.listdir(src):
|
||||
if os.path.isdir(f"{src}/{folder}"):
|
||||
files = os.listdir(f"{src}/{folder}")
|
||||
for file in files:
|
||||
# check for regex "v(d) #(d)" in the file name
|
||||
regex = re.compile(r"^.* v(\d+) #(\d+(?:-\d+)?)\.cbz$")
|
||||
if regex.search(file):
|
||||
print(f"File {file} is a Volume")
|
||||
else:
|
||||
print(f"Deleting chapter {file}")
|
||||
os.remove(f"{src}/{folder}/{file}")
|
||||
99
src/logic/download.py
Normal file
99
src/logic/download.py
Normal file
@@ -0,0 +1,99 @@
|
||||
import sys
|
||||
import os
|
||||
import time
|
||||
import bencodepy
|
||||
from .rename import rename
|
||||
from aria2p import Client
|
||||
|
||||
from aria2p import API
|
||||
|
||||
class Download:
|
||||
""" Download a file from a url and start the download using aria2"""
|
||||
def __init__(self, download_location) -> None:
|
||||
self.download_location=download_location
|
||||
self.filename=None
|
||||
self.torrent_file=None
|
||||
self.progress=0
|
||||
self.canceled=False
|
||||
self.aria2_running=self.check_aria2()
|
||||
self.api = API(
|
||||
client=Client(
|
||||
host="http://localhost",
|
||||
port=6800,
|
||||
secret="",
|
||||
timeout=60,
|
||||
)
|
||||
)
|
||||
self.api.set_global_options({"dir": self.download_location})
|
||||
if not self.aria2_running:
|
||||
print("Aria2 is not running")
|
||||
sys.exit()
|
||||
def check_aria2(self):
|
||||
#check if aria2 is running
|
||||
if os.system("ps -A | grep aria2c") == 0:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
|
||||
def check_progress(self):
|
||||
try:
|
||||
current_progress=self.api.get_downloads()[0].progress
|
||||
except:
|
||||
return self.progress+0.01
|
||||
if current_progress > self.progress:
|
||||
self.progress=current_progress
|
||||
return current_progress
|
||||
|
||||
def get_file(self, url, series_name=None):
|
||||
#get the file name from the url
|
||||
#use wget to download the file to the download location
|
||||
name=url.split('/')[-1]
|
||||
dl_url=f'{self.download_location}{name}'
|
||||
while self.get_filename(dl_url) is None:
|
||||
if not os.path.exists(dl_url):
|
||||
os.system(f'wget -P {self.download_location} {url}')
|
||||
filename = self.get_filename(dl_url)
|
||||
self.torrent_file=url.split('/')[-1]
|
||||
self.filename=filename
|
||||
return filename
|
||||
|
||||
|
||||
|
||||
def remove_torrents(self):
|
||||
tr_files=[file for file in os.listdir(self.download_location) if ".torrent" in file]
|
||||
for file in tr_files:
|
||||
os.remove(f'{self.download_location}{file}')
|
||||
|
||||
def add_torrent(self, torr_name):
|
||||
try:
|
||||
self.api.add_torrent(f'{self.download_location}{torr_name}')
|
||||
print("Torrent added")
|
||||
except Exception as e:
|
||||
print(f"Error adding torrent: {e}")
|
||||
return False
|
||||
|
||||
|
||||
|
||||
def rename_download(self):
|
||||
filename=self.filename.replace(".aria2", "")
|
||||
foldername=filename.replace(".cbz", "") if ".cbz" in filename else filename
|
||||
print(f'Filename: {filename}')
|
||||
print(f'Foldername: {foldername}')
|
||||
if not os.path.exists(f'{self.download_location}{foldername}'):
|
||||
os.mkdir(f'{self.download_location}{foldername}')
|
||||
os.rename(f'{self.download_location}{filename}', f'{self.download_location}{foldername}/{filename}')
|
||||
#rename the file
|
||||
rename(f'{self.download_location}{foldername}')
|
||||
|
||||
def get_filename(self, torrent_file):
|
||||
try:
|
||||
with open(torrent_file, 'rb') as f:
|
||||
torrent = bencodepy.decode(f.read())
|
||||
#self.filename=torrent[b'info'][b'name'].decode('utf-8')
|
||||
return torrent[b'info'][b'name'].decode('utf-8')
|
||||
except FileNotFoundError:
|
||||
return None
|
||||
|
||||
|
||||
53
src/logic/manual.py
Normal file
53
src/logic/manual.py
Normal file
@@ -0,0 +1,53 @@
|
||||
import os
|
||||
import re
|
||||
|
||||
|
||||
def _vol_list() -> list[int]:
|
||||
path = "/home/alexander/Downloads/torrents/Manga_test/"
|
||||
# get all files in the dir and subdirs
|
||||
files = os.listdir(path)
|
||||
|
||||
for f in files:
|
||||
print(f)
|
||||
if os.path.isdir(f"{path}/{f}"):
|
||||
print("is dir")
|
||||
files.extend([f"{path}/{f}/{file}" for file in os.listdir(f"{path}/{f}")])
|
||||
|
||||
return files
|
||||
|
||||
|
||||
def isdircheck(path: str) -> bool:
|
||||
if os.path.isdir(path):
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
def __chapter_check(title: str) -> bool:
|
||||
if title.endswith(".cbz") or title.endswith(".cbr"):
|
||||
if not re.search(r"(v\d{1,3}(-\d{1,3})?)|(Vol\. \d{1,3})", title):
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
def check_folder(folder):
|
||||
files = os.listdir(folder)
|
||||
for file in files:
|
||||
if os.path.isdir(f"{folder}/{file}"):
|
||||
print(f"{file} is a dir")
|
||||
check_folder(f"{folder}/{file}")
|
||||
else:
|
||||
print(f"{file} is a file")
|
||||
if __chapter_check(file):
|
||||
print(f"{file} is a chapter")
|
||||
os.remove(f"{folder}/{file}")
|
||||
else:
|
||||
print(f"{file} is a volume")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
# # print(__chapter_check("Even Given the Worthless 'Appraiser' Class, I'm Actually the Strongest v01-09+073 (2023) (Digital) (danke-Empire).cbz"))
|
||||
# __vol_list()
|
||||
# # print(isdircheck("/home/alexander/Downloads/torrents/Manga_test/Peter Grill and the Philosopher's Time (Digital)/"))
|
||||
check_folder("/home/alexander/Downloads/torrents/Manga_test/")
|
||||
42
src/logic/move.py
Normal file
42
src/logic/move.py
Normal file
@@ -0,0 +1,42 @@
|
||||
import os
|
||||
import shutil
|
||||
|
||||
|
||||
def move(src, dest: str = "/mnt/Media/Manga"):
|
||||
"""Move the files in a folder to another folder.
|
||||
Args:
|
||||
----
|
||||
- dest (str): the string to the destination folder
|
||||
"""
|
||||
# Get the files in the folder
|
||||
# +move the folders from src to disc, if folder already exists, only move new files
|
||||
folders = os.listdir(src)
|
||||
for folder in folders:
|
||||
if not os.path.exists(f"{dest}/{folder}"):
|
||||
print(f"Moving {folder} to {dest}")
|
||||
shutil.move(f"{src}/{folder}", dest)
|
||||
else:
|
||||
files = os.listdir(f"{src}/{folder}")
|
||||
for file in files:
|
||||
if not os.path.exists(f"{dest}/{folder}/{file}"):
|
||||
print(f"Moving {file} to {dest}/{folder}")
|
||||
shutil.move(f"{src}/{folder}/{file}", f"{dest}/{folder}")
|
||||
# Remove empty folders
|
||||
remove_empty_folders(src)
|
||||
|
||||
|
||||
def remove_empty_folders(src):
|
||||
"""Remove empty folders from a directory.
|
||||
Args:
|
||||
----
|
||||
- src (str): the string to the source folder
|
||||
"""
|
||||
folders = os.listdir(src)
|
||||
for folder in folders:
|
||||
if os.path.isfile(f"{src}/{folder}"):
|
||||
continue
|
||||
if not os.listdir(f"{src}/{folder}"):
|
||||
print(f"Removing {folder}")
|
||||
os.rmdir(f"{src}/{folder}")
|
||||
else:
|
||||
remove_empty_folders(f"{src}/{folder}")
|
||||
45
src/logic/move_test.py
Normal file
45
src/logic/move_test.py
Normal file
@@ -0,0 +1,45 @@
|
||||
import os
|
||||
import re
|
||||
|
||||
folder_path = "/home/alexander/Downloads/torrents/Manga_test/"
|
||||
|
||||
|
||||
def rename(folder):
|
||||
"""Rename the files in a folder according to the template.
|
||||
Template: [Name] v[nr] #[nr].ext (e.g. "The Flash v1 #1.cbz").
|
||||
|
||||
Args:
|
||||
----
|
||||
- folder (str): the string to the folder
|
||||
"""
|
||||
# Get the files in the folder
|
||||
files = os.listdir(folder)
|
||||
for file in files:
|
||||
if not file.endswith(".cbz"):
|
||||
print(f"Skipping {file}, not a cbz file")
|
||||
continue
|
||||
ext = file.split(".")[-1]
|
||||
|
||||
match = re.search(r"v\d{2,4} ", file)
|
||||
if match:
|
||||
print(match)
|
||||
split_start = match.start()
|
||||
split_end = match.end()
|
||||
# Split the filename between split_start and split_end
|
||||
volume = file[split_start:split_end]
|
||||
# Split the filename at the split index, but keep the "v" and digits in the title
|
||||
title = file[:split_start].strip()
|
||||
# add the volume number to the title as a suffix #nr
|
||||
title = f"{title} {volume} #{volume.replace('v','')}"
|
||||
print(title)
|
||||
# rename the file
|
||||
os.rename(f"{folder}/{file}", f"{folder}/{title}.{ext}")
|
||||
|
||||
|
||||
for folder in os.listdir(folder_path):
|
||||
if os.path.isdir(f"{folder_path}/{folder}"):
|
||||
rename(f"{folder_path}/{folder}")
|
||||
print(f"Renamed {folder}")
|
||||
else:
|
||||
print(f"{folder} is not a folder")
|
||||
continue
|
||||
7
src/logic/pickles.py
Normal file
7
src/logic/pickles.py
Normal file
@@ -0,0 +1,7 @@
|
||||
import pickle
|
||||
|
||||
def make_pickle(obj):
|
||||
return pickle.dumps(obj)
|
||||
|
||||
def load_pickle(pickled_obj):
|
||||
return pickle.loads(pickled_obj)
|
||||
51
src/logic/rename.py
Normal file
51
src/logic/rename.py
Normal file
@@ -0,0 +1,51 @@
|
||||
# Rename the downloaded files according to the template
|
||||
# Template: [Name] v[nr] #[nr].ext (e.g. "The Flash v1 #1.cbz")
|
||||
|
||||
import os
|
||||
import re
|
||||
|
||||
|
||||
def rename(folder: str = "/home/alexander/Downloads/torrents/manga/") -> None:
|
||||
"""Rename the files in a folder according to the template.
|
||||
Template: [Name] v[nr] #[nr].ext (e.g. "The Flash v1 #1.cbz").
|
||||
|
||||
Args:
|
||||
----
|
||||
- folder (str): the string to the folder
|
||||
"""
|
||||
# Get the files in the folder
|
||||
files = os.listdir(folder)
|
||||
print(files)
|
||||
for file in files:
|
||||
if os.path.isdir(f"{folder}/{file}"):
|
||||
rename(f"{folder}/{file}")
|
||||
if not file.endswith(".cbz"):
|
||||
print(f"Skipping {file}, not a cbz file")
|
||||
continue
|
||||
ext = file.split(".")[-1]
|
||||
|
||||
match = re.search(r"v\d{2,4}", file)
|
||||
if match:
|
||||
split_start = match.start()
|
||||
split_end = match.end()
|
||||
# Split the filename between split_start and split_end
|
||||
volume = file[split_start:split_end]
|
||||
# Split the filename at the split index, but keep the "v" and digits in the title
|
||||
title = file[:split_start].strip()
|
||||
# add the volume number to the title as a suffix #nr
|
||||
title = f"{title} {volume} #{volume.replace('v', '')}"
|
||||
print(title)
|
||||
# rename the file
|
||||
os.rename(f"{folder}/{file}", f"{folder}/{title}.{ext}")
|
||||
|
||||
|
||||
# rename the folder
|
||||
def rename_recursive(folder: str) -> None:
|
||||
# get all directories in the folder and apply the rename function to them
|
||||
for root, dirs, _files in os.walk(folder):
|
||||
for dir in dirs:
|
||||
rename(f"{root}/{dir}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
rename_recursive("/home/alexander/Downloads/torrents/manga/")
|
||||
27
src/logic/tag.py
Normal file
27
src/logic/tag.py
Normal file
@@ -0,0 +1,27 @@
|
||||
import os
|
||||
from pathlib import Path
|
||||
import subprocess
|
||||
|
||||
|
||||
def tag_folder(
|
||||
folder: Path = Path("/home/alexander/Downloads/torrents/manga/"),
|
||||
) -> None:
|
||||
"""Tag the files in a folder according to the template.
|
||||
Template: [Name] v[nr] #[nr].ext (e.g. "The Flash v1 #1.cbz").
|
||||
|
||||
Args:
|
||||
----
|
||||
- folder (Path): the string to the folder
|
||||
"""
|
||||
# Get the files in the folder
|
||||
files = os.listdir(folder)
|
||||
for file in files:
|
||||
if os.path.isdir(f"{folder}/{file}"):
|
||||
tag_folder(f"{folder}/{file}")
|
||||
if not file.endswith(".cbz"):
|
||||
continue
|
||||
print("Trying to tag file", file)
|
||||
subprocess.call(
|
||||
f'comictagger -s -t cr -f -o "{folder}/{file}" --nosummary --overwrite -i',
|
||||
shell=True,
|
||||
)
|
||||
190
src/logic/testing.py
Normal file
190
src/logic/testing.py
Normal file
@@ -0,0 +1,190 @@
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
|
||||
# import a library to open zip files
|
||||
import zipfile
|
||||
|
||||
from jellyfish import jaro_similarity
|
||||
|
||||
from APIs import KomgaAPI, MangadexAPI, NyaaFeed
|
||||
from APIs.cache import ListCache
|
||||
|
||||
Komga = KomgaAPI()
|
||||
|
||||
config = json.load(open("config.json"))
|
||||
|
||||
|
||||
cat = NyaaFeed()
|
||||
|
||||
|
||||
# with open("compare1.json") as f:
|
||||
# data = json.load(f)
|
||||
|
||||
# with open("compare2.json") as f:
|
||||
# data2 = json.load(f)
|
||||
|
||||
|
||||
def compare(data1, data2):
|
||||
# compare the two data sets and return a list of differences
|
||||
differences = []
|
||||
for key in data1:
|
||||
if key in data2:
|
||||
if data1[key] != data2[key]:
|
||||
differences.append(key)
|
||||
else:
|
||||
differences.append(key)
|
||||
|
||||
return differences
|
||||
|
||||
|
||||
# diffs=compare(data, data2)
|
||||
|
||||
# #get the differences from the first data set
|
||||
# for diff in diffs:
|
||||
# print(diff, data[diff])
|
||||
|
||||
# #get the differences from the second data set
|
||||
# for diff in diffs:
|
||||
# print(diff, data2[diff])
|
||||
|
||||
|
||||
def check_presence_of_xml_file(filename: str):
|
||||
with zipfile.ZipFile(filename, "r") as zip_ref:
|
||||
return "ComicInfo.xml" in zip_ref.namelist()
|
||||
|
||||
|
||||
def create_xml_file(filename: str):
|
||||
with zipfile.ZipFile(filename, "r") as zip_ref:
|
||||
return zip_ref.read("ComicInfo.xml")
|
||||
|
||||
|
||||
def rename_files(komga_data: str):
|
||||
"""Rename the files in the folder to the komga name with the volume number.
|
||||
|
||||
Args:
|
||||
----
|
||||
file (str): pth to the folder
|
||||
komga_data (str): series name
|
||||
"""
|
||||
# rename the folder to the komga name
|
||||
new_folder = f'{config["download_location"]}/{komga_data}'
|
||||
try:
|
||||
files = os.listdir(new_folder)
|
||||
except FileNotFoundError:
|
||||
return
|
||||
for file in files:
|
||||
if not (file.endswith(".cbz") or file.endswith(".cbr")):
|
||||
print(f"Skipping {file}, not a cbz file")
|
||||
continue
|
||||
ext = file.split(".")[-1]
|
||||
|
||||
match = re.search(r"v\d{2,4}(-\d{2,4})*", file)
|
||||
if match:
|
||||
print(match.group(0))
|
||||
vol = match.group(0).replace("v", "")
|
||||
title = file.split(match.group(0))[0]
|
||||
title = title.lstrip().rstrip()
|
||||
new_filename = f"{title} v{vol} #{vol}.{ext}"
|
||||
print(new_filename)
|
||||
os.rename(f"{new_folder}/{file}", f"{new_folder}/{new_filename}")
|
||||
# try:
|
||||
# os.rename(f"{new_folder}/{file}", f"{new_folder}/{filename} v{vol} #{vol}.{ext}")
|
||||
# except FileNotFoundError:
|
||||
# print(f"File not found: {file}")
|
||||
# split_index = match.start()
|
||||
# #split the title after the split_index
|
||||
# title=f"{file[:split_index]}{file[:split_index+len(match.group(0)):]}"
|
||||
# print(title)
|
||||
# volumes = match.group(0).split("-")
|
||||
# volumes = [volume.replace("v", "") for volume in volumes]
|
||||
# volume_data="-".join(volumes)
|
||||
|
||||
# # print(volume)
|
||||
# # volumes.append(int(volume))
|
||||
# # #add the volume number to the title as a suffix #nr
|
||||
# title=f"{title} #{volume_data}"
|
||||
# #rename the file
|
||||
# os.rename(f"{new_folder}/{file}", f"{new_folder}/{title}.{ext}")
|
||||
|
||||
|
||||
def __chapter_check(title: str) -> bool:
|
||||
if title.endswith(".cbz") or title.endswith(".cbr"):
|
||||
if not re.search(r"(v\d{1,3}(-\d{1,3})?)|(Vol\. \d{1,3})", title):
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
def check_folder(folder):
|
||||
files = os.listdir(folder)
|
||||
for file in files:
|
||||
if os.path.isdir(f"{folder}/{file}"):
|
||||
print(f"{file} is a dir")
|
||||
check_folder(f"{folder}/{file}")
|
||||
else:
|
||||
print(f"{file} is a file")
|
||||
if __chapter_check(file):
|
||||
print(f"{file} is a chapter")
|
||||
os.remove(f"{folder}/{file}")
|
||||
else:
|
||||
print(f"{file} is a volume")
|
||||
|
||||
|
||||
def add_ids():
|
||||
def __determine_similarity(search_string: str, given_string: str) -> float:
|
||||
return jaro_similarity(search_string, given_string)
|
||||
|
||||
database = ListCache("mangacache.db")
|
||||
Ma = MangadexAPI()
|
||||
result = database.query_all_missing_id_type("mangadex")
|
||||
print(len(result))
|
||||
max_sim = 0
|
||||
manga_id = None
|
||||
for series in result:
|
||||
title = series[1]
|
||||
mangadex_id = Ma.get_manga_id(title)
|
||||
if type(mangadex_id) == tuple:
|
||||
print("result is a tuple")
|
||||
similarity = __determine_similarity(mangadex_id["title"], title)
|
||||
if similarity > max_sim:
|
||||
max_sim = similarity
|
||||
manga_id = mangadex_id["id"]
|
||||
for alt_title in mangadex_id["alternate_titles"]:
|
||||
similarity = __determine_similarity(alt_title, title)
|
||||
if similarity > max_sim:
|
||||
max_sim = similarity
|
||||
manga_id = mangadex_id["id"]
|
||||
# print(mangadex_id)
|
||||
elif type(mangadex_id) == list:
|
||||
print("result is a list")
|
||||
# print(mangadex_id)
|
||||
for res_title in mangadex_id:
|
||||
similarity = __determine_similarity(res_title["title"], title)
|
||||
if similarity > max_sim:
|
||||
max_sim = similarity
|
||||
manga_id = res_title["id"]
|
||||
for alt_title in res_title["alternate_titles"]:
|
||||
similarity = __determine_similarity(alt_title, title)
|
||||
if similarity > max_sim:
|
||||
max_sim = similarity
|
||||
manga_id = res_title["id"]
|
||||
else:
|
||||
print(mangadex_id)
|
||||
print(manga_id)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
# series_names=Komga.get_all_series()
|
||||
# for series in series_names:
|
||||
# print(series[0])
|
||||
# rename_files(series[0])
|
||||
folders = os.listdir(config["download_location"])
|
||||
for folder in folders:
|
||||
print(folder)
|
||||
check_folder(f'{config["download_location"]}/{folder}')
|
||||
rename_files(f'{config["download_location"]}/{folder}')
|
||||
|
||||
# rename_files(komga_data="Hell's Paradise - Jigokuraku")
|
||||
|
||||
# add_ids()
|
||||
28
src/logic/threads.py
Normal file
28
src/logic/threads.py
Normal file
@@ -0,0 +1,28 @@
|
||||
from gui import SeriesSelectDialog
|
||||
from PySide6 import QtWidgets, QtCore, QtGui
|
||||
#import thread capabilties
|
||||
from PySide6.QtCore import QThread, Signal
|
||||
|
||||
|
||||
|
||||
class SeriesThread(QThread):
|
||||
"""Thread to get the series from the api.
|
||||
"""
|
||||
#signal to send the series data to the main thread
|
||||
series = Signal(list)
|
||||
def __init__(self, api, series_name) -> None:
|
||||
super().__init__()
|
||||
self.api = api
|
||||
self.series_name = series_name
|
||||
|
||||
def run(self):
|
||||
#display the SeriesSelectDialog
|
||||
print("running thread")
|
||||
dialog = QtWidgets.QDialog()
|
||||
ui = SeriesSelectDialog(self.series_name, self.api)
|
||||
ui.setupUi(dialog)
|
||||
dialog.show()
|
||||
dialog.exec()
|
||||
|
||||
#send the data back to the main thread
|
||||
self.series.emit(ui.data)
|
||||
Reference in New Issue
Block a user