194 lines
8.0 KiB
Python
194 lines
8.0 KiB
Python
import json
|
|
from pathlib import Path
|
|
import shutil
|
|
from PIL import Image
|
|
from data.path_constant import ANDROID_ASSETS, DOWNLOAD_DIR, NETWORK_DIR
|
|
from data.special_list import BOMTOON
|
|
|
|
class WebtoonConverter:
|
|
def __init__(self, webtoon_path: Path):
|
|
self.webtoon_path = webtoon_path
|
|
self.webtoon_path_network = NETWORK_DIR / webtoon_path.name
|
|
self.thumbnail = ''
|
|
self.img_extensions = {'.png', '.jpg', '.jpeg', '.webp'}
|
|
|
|
def do_convert(self):
|
|
if self.webtoon_path.is_dir() and self.has_new_episode():
|
|
print(self.webtoon_path)
|
|
self.copy_information()
|
|
for item_path in self.webtoon_path.iterdir():
|
|
if item_path.is_dir():
|
|
episode_path = item_path
|
|
if self.is_new_episode(episode_path) and self.is_not_empty(episode_path):
|
|
print(f"new episode: {episode_path}")
|
|
if self.webtoon_path.name not in BOMTOON:
|
|
self.delete_over_width_image(episode_path)
|
|
self.concat_images(episode_path)
|
|
elif item_path.name == self.thumbnail:
|
|
thumbnail_path = item_path
|
|
self.copy_thumbnail(thumbnail_path)
|
|
|
|
|
|
def has_new_episode(self) -> bool:
|
|
self.webtoon_path_network.mkdir(parents=True, exist_ok=True)
|
|
return self._count_episodes(self.webtoon_path) > self._count_episodes(self.webtoon_path_network)
|
|
|
|
def _count_episodes(self, path: Path):
|
|
episodes = [d for d in path.iterdir() if d.is_dir()]
|
|
return len(episodes)
|
|
|
|
def copy_information(self):
|
|
info_path_local = self.webtoon_path / 'information.json'
|
|
info_path_network = self.webtoon_path_network / 'information.json'
|
|
|
|
self.updateTag(info_path_local)
|
|
|
|
copy_necessary = True
|
|
if info_path_network.exists():
|
|
with open(info_path_local, "r", encoding='utf-8') as json_file:
|
|
local_information = json.load(json_file)
|
|
with open(info_path_network, "r", encoding='utf-8') as json_file:
|
|
network_information = json.load(json_file)
|
|
|
|
self.thumbnail = local_information["thumbnail"]
|
|
|
|
if (
|
|
local_information["title"] == network_information["title"] and
|
|
local_information["author"] == network_information["author"] and
|
|
local_information["tag"] == network_information["tag"] and
|
|
local_information["description"] == network_information["description"] and
|
|
local_information["thumbnail"] == network_information["thumbnail"]
|
|
):
|
|
copy_necessary = False
|
|
|
|
if (copy_necessary):
|
|
try:
|
|
shutil.copyfile(info_path_local, info_path_network)
|
|
print(f"File '{info_path_local}' copied to '{info_path_network}'.")
|
|
except FileNotFoundError:
|
|
print(f"Source file '{info_path_local}' not found.")
|
|
|
|
def updateTag(self, path: Path):
|
|
update_necessary = False
|
|
if path.exists():
|
|
with open(path, "r", encoding='utf-8') as json_file:
|
|
existing_information = json.load(json_file)
|
|
tag = existing_information["tag"]
|
|
print(tag)
|
|
if '冒險' in tag and tag != '冒險':
|
|
tag = '冒險'
|
|
update_necessary = True
|
|
elif '愛情' in tag and tag != '愛情':
|
|
tag = '愛情'
|
|
update_necessary = True
|
|
elif 'BL' in tag and tag != 'BL':
|
|
tag = 'BL'
|
|
update_necessary = True
|
|
elif '武俠' in tag:
|
|
tag = '冒險'
|
|
update_necessary = True
|
|
elif '大人系' in tag:
|
|
tag = '愛情'
|
|
update_necessary = True
|
|
elif '驚悚' in tag:
|
|
tag = '劇情'
|
|
update_necessary = True
|
|
elif '奇幻' in tag:
|
|
tag = '劇情'
|
|
update_necessary = True
|
|
elif '宮廷' in tag:
|
|
tag = '劇情'
|
|
update_necessary = True
|
|
elif '懸疑' in tag:
|
|
tag = '劇情'
|
|
update_necessary = True
|
|
|
|
if update_necessary:
|
|
information = {
|
|
"title": existing_information["title"],
|
|
"author": existing_information["author"],
|
|
"tag": tag,
|
|
"description": existing_information["description"],
|
|
"thumbnail": existing_information["thumbnail"]
|
|
}
|
|
|
|
with open(path, 'w', encoding='utf-8') as json_file:
|
|
json.dump(information, json_file, ensure_ascii=False, indent=2)
|
|
print(f"{path} is saved.")
|
|
|
|
def copy_thumbnail(self, thumbnail_path: Path):
|
|
assets_path = ANDROID_ASSETS / thumbnail_path.name
|
|
if (not assets_path.exists()):
|
|
try:
|
|
shutil.copyfile(thumbnail_path, assets_path)
|
|
print(f"File '{thumbnail_path}' copied to '{assets_path}'.")
|
|
except FileNotFoundError:
|
|
print(f"Source file '{thumbnail_path}' not found.")
|
|
|
|
def delete_over_width_image(self, episode_path: Path):
|
|
if self.webtoon_path.name != "地下城見聞錄[UO]":
|
|
for img_path in episode_path.iterdir():
|
|
if self._is_image_800(img_path):
|
|
img_path.unlink()
|
|
print(f"delete {img_path}")
|
|
|
|
def delete_bomtoon_000(self, episode_path: Path):
|
|
for img_path in episode_path.iterdir():
|
|
if img_path.name == "000.webp":
|
|
img_path.unlink()
|
|
print(f"delete {img_path}")
|
|
|
|
|
|
def _is_image_800(self, image_path: Path) -> bool:
|
|
try:
|
|
with Image.open(image_path) as img:
|
|
return img.width >= 800 and img.width < 1080
|
|
except Exception as e:
|
|
print(f"Error opening image {image_path}: {e}")
|
|
return False
|
|
|
|
def is_new_episode(self, episode_path: Path) -> bool:
|
|
episode_path_network = self.webtoon_path_network / episode_path.name
|
|
return not episode_path_network.exists()
|
|
|
|
def is_not_empty(self, episode_path: Path) -> bool:
|
|
return any(episode_path.iterdir())
|
|
|
|
|
|
def concat_images(self, episode_path: Path):
|
|
episode_path_network = self.webtoon_path_network / episode_path.name
|
|
episode_path_network.mkdir(parents=True, exist_ok=True)
|
|
|
|
result_images = []
|
|
total_height = 0
|
|
result_index = 1
|
|
|
|
for img_path in episode_path.iterdir():
|
|
if img_path.suffix.lower() in self.img_extensions:
|
|
|
|
with open(img_path, 'rb') as img_file:
|
|
img = Image.open(img_file)
|
|
img.load()
|
|
if total_height + img.height > 20000:
|
|
self.save_concatenated_image(result_images, episode_path_network, result_index)
|
|
result_index += 1
|
|
result_images = []
|
|
total_height = 0
|
|
|
|
result_images.append(img)
|
|
total_height += img.height
|
|
if result_images:
|
|
self.save_concatenated_image(result_images, episode_path_network, result_index)
|
|
|
|
def save_concatenated_image(self, images: list, output_episode_path: Path, index: int):
|
|
img_width = images[0].width # Assuming all images have the same width
|
|
total_height = sum(img.height for img in images)
|
|
result_image = Image.new('RGB', (img_width, total_height))
|
|
y_offset = 0
|
|
for img in images:
|
|
result_image.paste(img, (0, y_offset))
|
|
y_offset += img.height
|
|
|
|
output_file = output_episode_path / f"{index}.jpg"
|
|
print(f"saving '{output_file}'")
|
|
result_image.save(output_file) |