main 함수 리팩토링

comicinfo.xml 에 경로가 포함되어도 읽을 수 있게 수정
--fix-arc-path 옵션 추가 : root 로 몰아버린다.
This commit is contained in:
2026-06-30 20:42:35 +09:00
parent edb41ab16c
commit c54fa70012
2 changed files with 115 additions and 116 deletions

1
.gitignore vendored
View File

@@ -9,3 +9,4 @@ __pycache__/
metadata_1.json metadata_1.json
metadata_mi.json metadata_mi.json
main.spec main.spec
.vscode/settings.json

228
main.py
View File

@@ -39,6 +39,7 @@ def main(argc, argv):
parser.add_argument('--print', dest='bPrint', action='store_true', help='comicinfo.xml 출력') parser.add_argument('--print', dest='bPrint', action='store_true', help='comicinfo.xml 출력')
parser.add_argument('--metadata', dest='bMetadata', action='store_true', help='.metadata 파일로부터 ComicInfo.xml 생성 및 CBZ에 추가') parser.add_argument('--metadata', dest='bMetadata', action='store_true', help='.metadata 파일로부터 ComicInfo.xml 생성 및 CBZ에 추가')
parser.add_argument('--verbose', dest='bVerbose', action='store_true', help='상세 로그 출력') parser.add_argument('--verbose', dest='bVerbose', action='store_true', help='상세 로그 출력')
parser.add_argument('--fix-arc-path', dest='bFixArcPath', action='store_true', help='CBZ 아카이브의 내부 폴더 구조를 제거합니다.')
parser.add_argument('-v', '--version', action='version', version='ComicInfoXMLConv 1.0') parser.add_argument('-v', '--version', action='version', version='ComicInfoXMLConv 1.0')
args = parser.parse_args(argv[1:]) # argv[0]은 스크립트 이름 제외 args = parser.parse_args(argv[1:]) # argv[0]은 스크립트 이름 제외
@@ -52,68 +53,13 @@ def main(argc, argv):
# 태그 파싱 # 태그 파싱
if args.info_tags is not None and len(args.info_tags) > 0: if args.info_tags is not None and len(args.info_tags) > 0:
util.DbgOut(f"입력된 태그: {args.info_tags}", True) util.DbgOut(f"입력된 태그: {args.info_tags}", True)
listTags = args.info_tags.split(',') # listTags = args.info_tags.split(',') # This variable is not used
util.DbgOut(f"태그 리스트: {listTags}", True) # util.DbgOut(f"태그 리스트: {listTags}", True)
# 단일 파일 처리 (--in 옵션) # 단일 파일 처리 (--in 옵션)
if True == util.IsExistsPath(args.arc_file): if True == util.IsExistsPath(args.arc_file):
util.DbgOut(f"대상 파일: {args.arc_file}", True) util.DbgOut(f"대상 파일: {args.arc_file}", True)
process_archive_file(args.arc_file, args)
# Path 변수 확장
arc_title = ExpandPathVars(args.info_title, args.arc_file)
arc_writer = ExpandPathVars(args.info_writer, args.arc_file)
arc_series = ExpandPathVars(args.info_series, args.arc_file)
arc_volume = ExpandPathVars(args.info_volume, args.arc_file)
arc_number = ExpandPathVars(args.info_number, args.arc_file)
arc_tags = args.info_tags.split(',') if args.info_tags else []
# .metadata 옵션이 활성화된 경우
if True == args.bMetadata:
ProcessMetadataToCBZ(args.arc_file, args.bPrint,
arc_volume, arc_number, args.info_count,
arc_title, arc_writer, arc_series,
arc_tags if arc_tags else None)
return
listArcContents = util.GetZipContentList(args.arc_file)
if True == any(item.lower() == "comicinfo.xml" for item in listArcContents):
util.DbgOut(f"comicinfo.xml 발견됨: {args.arc_file}", True)
comicinfo_xml_bytes = util.GetZippedFileByte(args.arc_file, "ComicInfo.xml")
if None != comicinfo_xml_bytes:
modified = ModComicInfoXML(comicinfo_xml_bytes, arc_title, arc_writer, arc_series, arc_tags,
info_number=arc_number, info_volume=arc_volume, info_count=args.info_count)
if True == args.bPrint:
if modified is not None:
print(modified.decode('utf-8'))
else:
print(comicinfo_xml_bytes.decode('utf-8'))
elif modified is not None:
util.AddFileToZip(args.arc_file, "ComicInfo.xml", modified)
util.DbgOut(f"ComicInfo.xml 업데이트됨: {args.arc_file}", True)
else:
util.DbgOut(f"comicinfo.xml 없음: {args.arc_file}", True)
if arc_volume or arc_number or arc_title or arc_writer or arc_series or arc_tags or args.info_count:
new_xml = CreateComicInfoXML(
info_title=arc_title if arc_title else "",
info_writer=arc_writer if arc_writer else "",
info_series=arc_series if arc_series else "",
tags=arc_tags if arc_tags else [],
pages=[],
volume=arc_volume if arc_volume else "",
number=arc_number if arc_number else "",
count=int(args.info_count) if args.info_count is not None else -1
)
if new_xml:
if True == args.bPrint:
print(new_xml)
else:
util.AddFileToZip(args.arc_file, "ComicInfo.xml", new_xml.encode('utf-8'))
util.DbgOut(f"ComicInfo.xml 생성됨: {args.arc_file}", True)
return return
# 폴더 처리 (--root 옵션) - 하위 폴더 포함, CBZ 파일만 처리 # 폴더 처리 (--root 옵션) - 하위 폴더 포함, CBZ 파일만 처리
@@ -127,66 +73,76 @@ def main(argc, argv):
continue continue
util.DbgOut(f"파일 발견: {strFullPath}", True) util.DbgOut(f"파일 발견: {strFullPath}", True)
process_archive_file(strFullPath, args)
# Path 변수 확장 (파일마다 달라짐)
arc_title = ExpandPathVars(args.info_title, strFullPath)
arc_writer = ExpandPathVars(args.info_writer, strFullPath)
arc_series = ExpandPathVars(args.info_series, strFullPath)
arc_volume = ExpandPathVars(args.info_volume, strFullPath)
arc_number = ExpandPathVars(args.info_number, strFullPath)
arc_tags = args.info_tags.split(',') if args.info_tags else []
# .metadata 옵션이 활성화된 경우
if True == args.bMetadata:
ProcessMetadataToCBZ(strFullPath, args.bPrint,
arc_volume, arc_number, args.info_count,
arc_title, arc_writer, arc_series,
arc_tags if arc_tags else None)
continue
listArcContents = util.GetZipContentList(strFullPath)
if True == any(item.lower() == "comicinfo.xml" for item in listArcContents):
util.DbgOut(f"comicinfo.xml 발견됨: {strFullPath}", True)
comicinfo_xml_bytes = util.GetZippedFileByte(strFullPath, "ComicInfo.xml")
if None != comicinfo_xml_bytes:
modified = ModComicInfoXML(comicinfo_xml_bytes, arc_title, arc_writer, arc_series, arc_tags,
info_number=arc_number, info_volume=arc_volume, info_count=args.info_count)
if True == args.bPrint:
if modified is not None:
print(modified.decode('utf-8'))
else:
print(comicinfo_xml_bytes.decode('utf-8'))
elif modified is not None:
util.AddFileToZip(strFullPath, "ComicInfo.xml", modified)
util.DbgOut(f"ComicInfo.xml 업데이트됨: {strFullPath}", True)
else:
util.DbgOut(f"comicinfo.xml 없음: {strFullPath}", True)
if arc_volume or arc_number or arc_title or arc_writer or arc_series or arc_tags or args.info_count:
new_xml = CreateComicInfoXML(
info_title=arc_title if arc_title else "",
info_writer=arc_writer if arc_writer else "",
info_series=arc_series if arc_series else "",
tags=arc_tags if arc_tags else [],
pages=[],
volume=arc_volume if arc_volume else "",
number=arc_number if arc_number else "",
count=int(args.info_count) if args.info_count is not None else -1
)
if new_xml:
if True == args.bPrint:
print(new_xml)
else:
util.AddFileToZip(strFullPath, "ComicInfo.xml", new_xml.encode('utf-8'))
util.DbgOut(f"ComicInfo.xml 생성됨: {strFullPath}", True)
return return
# def process_archive_file(archive_path: str, args: argparse.Namespace):
"""지정된 아카이브 파일에 대해 ComicInfo.xml을 처리합니다."""
# --fix-arc-path 옵션 처리
if args.bFixArcPath:
if FlattenZipArchive(archive_path):
util.DbgOut(f"아카이브 폴더 구조 제거 완료: {archive_path}", True)
# Path 변수 확장
arc_title = ExpandPathVars(args.info_title, archive_path)
arc_writer = ExpandPathVars(args.info_writer, archive_path)
arc_series = ExpandPathVars(args.info_series, archive_path)
arc_volume = ExpandPathVars(args.info_volume, archive_path)
arc_number = ExpandPathVars(args.info_number, archive_path)
arc_tags = args.info_tags.split(',') if args.info_tags else []
# .metadata 옵션이 활성화된 경우
if args.bMetadata:
ProcessMetadataToCBZ(archive_path, args.bPrint,
arc_volume, arc_number, args.info_count,
arc_title, arc_writer, arc_series,
arc_tags if arc_tags else None)
return
listArcContents = util.GetZipContentList(archive_path)
comicinfo_path_in_zip = None
for item in listArcContents:
# os.path.basename은 '/' 또는 '\' 구분자를 사용하여 경로의 마지막 부분을 반환합니다.
if os.path.basename(item.lower()) == "comicinfo.xml":
comicinfo_path_in_zip = item
break
has_comicinfo = comicinfo_path_in_zip is not None
if has_comicinfo:
util.DbgOut(f"comicinfo.xml 발견됨: {archive_path} (경로: {comicinfo_path_in_zip})", True)
comicinfo_xml_bytes = util.GetZippedFileByte(archive_path, comicinfo_path_in_zip)
if comicinfo_xml_bytes:
modified = ModComicInfoXML(comicinfo_xml_bytes, arc_title, arc_writer, arc_series, arc_tags,
info_number=arc_number, info_volume=arc_volume, info_count=args.info_count)
if args.bPrint:
output = modified.decode('utf-8') if modified else comicinfo_xml_bytes.decode('utf-8')
print(output)
elif modified:
util.AddFileToZip(archive_path, comicinfo_path_in_zip, modified)
util.DbgOut(f"ComicInfo.xml 업데이트됨: {archive_path} (경로: {comicinfo_path_in_zip})", True)
else:
util.DbgOut(f"comicinfo.xml 없음: {archive_path}", True)
if arc_volume or arc_number or arc_title or arc_writer or arc_series or arc_tags or args.info_count:
new_xml = CreateComicInfoXML(
info_title=arc_title or "",
info_writer=arc_writer or "",
info_series=arc_series or "",
tags=arc_tags,
pages=[],
volume=arc_volume or "",
number=arc_number or "",
count=int(args.info_count) if args.info_count is not None else -1
)
if new_xml:
if args.bPrint:
print(new_xml)
else:
util.AddFileToZip(archive_path, "ComicInfo.xml", new_xml.encode('utf-8'))
util.DbgOut(f"ComicInfo.xml 생성됨: {archive_path}", True)
def ExpandPathVars(text: str | None, filepath: str) -> str | None: def ExpandPathVars(text: str | None, filepath: str) -> str | None:
"""Replace path template variables (<filename>, <parentfolder>, etc.) with actual values. """Replace path template variables (<filename>, <parentfolder>, etc.) with actual values.
After variable expansion, if the result has a :s/pattern/replacement/ suffix, After variable expansion, if the result has a :s/pattern/replacement/ suffix,
@@ -235,6 +191,48 @@ def ExpandPathVars(text: str | None, filepath: str) -> str | None:
return result return result
def FlattenZipArchive(zip_path: str) -> bool:
"""
ZIP 아카이브의 내부 폴더 구조를 제거합니다.
모든 파일을 루트 디렉토리로 이동시킵니다.
Args:
zip_path: ZIP 파일 경로
Returns:
구조가 변경되었으면 True, 아니면 False
"""
try:
needs_flattening = False
with util.zipfile.ZipFile(zip_path, 'r') as zin:
for item in zin.infolist():
if '/' in item.filename or '\\' in item.filename:
needs_flattening = True
break
if not needs_flattening:
return False
temp_zip = zip_path + '.tmp'
with util.zipfile.ZipFile(zip_path, 'r') as zin:
with util.zipfile.ZipFile(temp_zip, 'w') as zout:
for item in zin.infolist():
if item.is_dir():
continue
data = zin.read(item.filename)
new_name = os.path.basename(item.filename)
zout.writestr(new_name, data)
util.shutil.move(temp_zip, zip_path)
return True
except Exception as e:
util.DbgOut(f"아카이브 구조 변경 중 오류 발생: {e}", True)
if 'temp_zip' in locals() and os.path.exists(temp_zip):
os.remove(temp_zip)
return False
def ResolveRegexTransform(text: str | None, current_value: str | None) -> str | None: def ResolveRegexTransform(text: str | None, current_value: str | None) -> str | None:
"""Apply regex substitution if text uses s/pattern/replacement/ syntax. """Apply regex substitution if text uses s/pattern/replacement/ syntax.