import json from pathlib import Path import shutil from PIL import Image from data.path_constant import ANDROID_ASSETS, DOWNLOAD_DIR, NETWORK_DIR class WebtoonConverter: def __init__(self, webtoon_path: Path): self.webtoon_path = webtoon_path self.webtoon_path_network = NETWORK_DIR / webtoon_path.name 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): print(f"new episode: {episode_path}") self.delete_over_width_image(episode_path) self.concat_images(episode_path) elif item_path.suffix.lower() in self.img_extensions: 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) 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_name"] == network_information["thumbnail_name"] ): 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_name": existing_information["thumbnail_name"] } 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): for img_path in episode_path.iterdir(): if self._is_image_800(img_path): 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 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 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 > 28800: 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)