#!/usr/bin/env python3 # StepMania 5 Song package generator # (c) 2015 Taeyeon Mori # # This program tries to create a .smzip ready to drop into SM5/Packages from downloaded .zips containing songs import zipfile import os import tempfile import posixpath def zip_has_file(f, filename): try: f.getinfo(filename) except KeyError: return False return True def colorful(text, color): return "\033[%sm%s\033[0m" % (color, text) def run(filename, *, delete_orig=False, replace=False, rename_bak=False): with zipfile.ZipFile(filename) as f: if zip_has_file(f, "Songs/"): print("==> '%s' already a valid StepMania song package" % colorful(filename, 36)) return True else: print("==> '%s' is not a valid StepMania song package" % colorful(filename, 36)) if any(( zip_has_file(f, "Announcers/"), zip_has_file(f, "Characters/"), zip_has_file(f, "Data/"), zip_has_file(f, "Noteskins/"), zip_has_file(f, "Themes/"))): print("===> However, it seems to be a different type of SM Package.") return False if replace: newname = filename oldname = ".".join(filename, "bak") os.rename(filename, oldname) print("===> Original was renamed to '%s'" % colorful(oldname, 35)) else: newname = ".".join((os.path.splitext(filename)[0], "smzip")) if newname == filename: newname = ".".join((os.path.splitext(filename)[0], "new", "smzip")) oldname = filename if os.path.exists(newname): print("===> Target filename exists: '%s'" % colorful(newname, 35)) return False print("===> Repacking into StepMania Package: '%s'" % colorful(newname, 35)) with tempfile.TemporaryDirectory() as tmp: with zipfile.ZipFile(newname, "w", zipfile.ZIP_DEFLATE) as out: dirs = [] for info in f.infolist(): print("\r====> Processing '%s'" % colorful(info.filename, 32), end="\033[0K") file = f.extract(info, path=tmp) out.write(file, posixpath.join("Songs", info.filename)) if os.path.isfile(file): os.unlink(file) else: dirs.append(file) for directory in reversed(dirs): os.rmdir(directory) print("\r\033[2K", end="") if delete_orig: print("===> Deleting Original Archive.") os.unlink(oldname) elif rename_bak and not replace: xoldname = ".".join((oldname, "bak")) os.rename(oldname, xoldname) print("===> Original was renamed to '%s'" % colorful(xoldname, 35)) print("===> Done.") return True if __name__ == "__main__": import argparse parser = argparse.ArgumentParser() parser.add_argument("-delete", action="store_true", help="Delete original files") parser.add_argument("-replace", action="store_true", help="Use the original filename for the new archive and add .bak to the original one") parser.add_argument("-rename", action="store_true", help="Rename original files to *.bak") parser.add_argument("files", nargs="+", help="The files to process") args = parser.parse_args() print("=> Running sm-song-package") print("=> (c) 2015 Taeyeon Mori") for file in args.files: run(file, delete_orig=args.delete, replace=args.replace, rename_bak=args.rename) print("=> Done.")