animelib3: Fix some Special related things, don't overwrite everything, don't leave empty folder when crashing while doing the magic
	
		
	
				
					
				
			
							parent
							
								
									d5b890a46a
								
							
						
					
					
						commit
						ca2a91262e
					
				
				 1 changed files with 164 additions and 38 deletions
			
			
		@ -1,52 +1,178 @@ | 
				
			|||||||
#!/usr/bin/env python3 | 
					#!/usr/bin/env python3 | 
				
			||||||
 | 
					# (c) 2016 Taeyeon Mori | 
				
			||||||
 | 
					# Inferior in capabilities to animeimport.py/animelib, but has better default heuristics | 
				
			||||||
 | 
					# Needs to be integrated with the former. (Not to mention this is a hackjob >.>) | 
				
			||||||
 | 
					
 | 
				
			||||||
import os | 
					import os | 
				
			||||||
import sys | 
					import sys | 
				
			||||||
import re | 
					import re | 
				
			||||||
import shutil | 
					import shutil | 
				
			||||||
 | 
					import tempfile | 
				
			||||||
 | 
					import itertools | 
				
			||||||
 | 
					import argparse | 
				
			||||||
 | 
					
 | 
				
			||||||
epb_re=re.compile(r'((NC)?(OP|ED)|S[Pp]?|EX)\s*\d+|Special|[Ii]ntroduction') | 
					 | 
				
			||||||
epc_re=re.compile(r'Hi10|\d+p|\d+x\d+|[Vv]\d+|[\[\(][0-9A-Fa-f]{8}[\)\]]') | 
					 | 
				
			||||||
ep_re=re.compile(r'[^\[](?:[Ee][Pp]?)?[_\s]*(\d+)[^\d\]]') | 
					 | 
				
			||||||
stuff_re=re.compile(r'\[[^\]]+\]|\([^\)]+\)') | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
for x in os.listdir(): | 
					epc_re=re.compile(r'Hi10|10[Bb][Ii][Tt]|\d+p|\d+x\d+|[Vv]\d+|[\[\(][0-9A-Fa-f]{8}[\)\]]|S(eason)?[_\s]*\d+') # Clean out unrelated numbers things | 
				
			||||||
    if os.path.isdir(x) and not x.startswith("."): | 
					 | 
				
			||||||
        print("Clean", x) | 
					 | 
				
			||||||
        shutil.rmtree(x) | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					epb_re=re.compile(r'((NC|TV)?(OP|ED)|S(P|p(ecial)?)|EX)[_\s]*\d+|[Ii]ntroduction') # Episode Blacklist | 
				
			||||||
 | 
					ep_re=re.compile(r'[^\[](?:[Ee][Pp]?)?[_\s]*[^\d.](\d+)[^\d\].]') # Episode Number | 
				
			||||||
 | 
					
 | 
				
			||||||
root=sys.argv[1] if len(sys.argv)>1 else "../Downloads" | 
					stuff_re=re.compile(r'\[[^\]]+\]|\([^\)]+\)') # Remove all metadata | 
				
			||||||
 | 
					esp_re=re.compile(r'S(?:P|p(?:ecial)?)?\s*(\d+)(?!.+\d+)') # Special Number | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Functions | 
				
			||||||
 | 
					def makeabs(path, anchor): | 
				
			||||||
 | 
					    return path if os.path.isabs(path) else os.path.join(anchor if os.path.isabs(anchor) else os.path.abspath(anchor), path) | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def abslink(link, anchor=None): | 
				
			||||||
 | 
					    return os.path.normpath(makeabs(os.readlink(link), anchor if anchor else os.path.dirname(link))) | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def compute_link_dir_sync(src_dir, dst_dir): | 
				
			||||||
 | 
					    src_content = {x.name: x for x in os.scandir(src_dir)} | 
				
			||||||
 | 
					    dst_content = {x.name: x for x in os.scandir(dst_dir)} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ok = set() | 
				
			||||||
 | 
					    need_update = set() | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for name, src_file in src_content.items(): | 
				
			||||||
 | 
					        if name in dst_content: | 
				
			||||||
 | 
					            dst_file = dst_content[name] | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if abslink(src_file.path, dst_dir) == abslink(dst_file.path): | 
				
			||||||
 | 
					                ok.add(name) | 
				
			||||||
 | 
					            else: | 
				
			||||||
 | 
					                need_update.add(name) | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    need_del = set(dst_content.keys()) - set(src_content.keys()) | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return ok, need_update, need_del | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Commandline | 
				
			||||||
 | 
					parser = argparse.ArgumentParser() | 
				
			||||||
 | 
					parser.add_argument("repo", default=None, nargs="?") | 
				
			||||||
 | 
					parser.add_argument("--library", default=".library") | 
				
			||||||
 | 
					parser.add_argument("-v", action="store_true", dest="verbose") | 
				
			||||||
 | 
					args = parser.parse_args() | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Load settings | 
				
			||||||
fix = {} | 
					fix = {} | 
				
			||||||
with open(".library") as f: | 
					root = os.path.abspath(args.repo or "../Downloads") | 
				
			||||||
    root = f.readline().strip() | 
					os.chdir(os.path.dirname(args.library)) | 
				
			||||||
    for line in f: | 
					
 | 
				
			||||||
        if "|" in line: | 
					if os.path.exists(args.library): | 
				
			||||||
            k, v = line.rstrip("\n").rsplit("|", 2) | 
					    if args.repo: | 
				
			||||||
            fix[k] = v | 
					        print("Error: Cannot use 'repo' argument when updating a library (%s)" % args.library) | 
				
			||||||
 | 
					        sys.exit(2) | 
				
			||||||
 | 
					
 | 
				
			||||||
for name in os.listdir(root): | 
					    with open(args.library) as f: | 
				
			||||||
    dir = os.path.join(root, name) | 
					        root = f.readline().strip() | 
				
			||||||
    if not os.path.isdir(dir): | 
					        if "=>" in root: | 
				
			||||||
        print("not a directory %s" % dir) | 
					            root, cwd = root.split("=>", 1) | 
				
			||||||
        continue | 
					            root = os.path.abspath(root) | 
				
			||||||
    if name in fix: | 
					            os.chdir(cwd) | 
				
			||||||
        series_name = fix[name] | 
					        for line in f: | 
				
			||||||
    else: | 
					            if "|" in line: | 
				
			||||||
        series_name = stuff_re.sub("", name).replace("_", " ").replace(".", " ").strip() | 
					                k, v = line.rstrip("\n").rsplit("|", 2) | 
				
			||||||
    print("Series: %s" % series_name) | 
					                fix[k] = v | 
				
			||||||
    os.mkdir(series_name) | 
					
 | 
				
			||||||
    for f in sorted(os.scandir(dir), key=lambda x: x.name): | 
					print("Library %s: Using repo at '%s', got %i fixes" % (args.library, root, len(fix))) | 
				
			||||||
        if not f.is_file() or f.name.endswith(".part"): | 
					
 | 
				
			||||||
            continue | 
					
 | 
				
			||||||
        cn = epc_re.sub("", f.name) | 
					with tempfile.TemporaryDirectory(prefix=".temp-", dir=os.getcwd()) as temp: | 
				
			||||||
        m = ep_re.search(cn) | 
					    print("=== Analyzing Repo ===") | 
				
			||||||
        if m and not epb_re.search(cn): | 
					    # Do work in temporary directory | 
				
			||||||
            new_name = "%s - E%s" % (series_name, m.group(1)) | 
					    for name in os.listdir(root): | 
				
			||||||
 | 
					        path = os.path.join(root, name) | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if os.path.isdir(path): | 
				
			||||||
 | 
					            if name in fix: | 
				
			||||||
 | 
					                series_name = fix[name] | 
				
			||||||
 | 
					            else: | 
				
			||||||
 | 
					                series_name = stuff_re.sub("", name).replace("_", " ").replace(".", " ").strip() | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            print("Series: %s" % series_name) | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            os.mkdir(os.path.join(temp, series_name)) | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            for f in sorted(os.scandir(path), key=lambda x: x.name): | 
				
			||||||
 | 
					                if not f.is_file() or f.name.endswith(".part"): | 
				
			||||||
 | 
					                    continue | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                cn = epc_re.sub("", f.name) | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                m = ep_re.search(cn) | 
				
			||||||
 | 
					                if m and not epb_re.search(cn): | 
				
			||||||
 | 
					                    new_name = "%s - E%s" % (series_name, m.group(1)) | 
				
			||||||
 | 
					                else: | 
				
			||||||
 | 
					                    cn = stuff_re.sub("", os.path.splitext(f.name)[0]).replace("_", " ").replace(".", " ").strip() | 
				
			||||||
 | 
					                    m = esp_re.search(cn) | 
				
			||||||
 | 
					                    if m: | 
				
			||||||
 | 
					                        new_name = "%s - S%s" % (series_name, m.group(1)) | 
				
			||||||
 | 
					                    else: | 
				
			||||||
 | 
					                        new_name = cn | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if args.verbose: | 
				
			||||||
 | 
					                    print("    %s (from %s)" % (new_name, f.name)) | 
				
			||||||
 | 
					                os.symlink(os.path.join("..", os.path.relpath(path), f.name), os.path.join(temp, series_name, new_name + os.path.splitext(f.name)[1])) | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        elif os.path.isfile(path) and name[-4] == "." and name[-3:] in {"mkv", "mp4"}: | 
				
			||||||
 | 
					            if name in fix: | 
				
			||||||
 | 
					                title = fix[name] | 
				
			||||||
 | 
					            else: | 
				
			||||||
 | 
					                title = stuff_re.sub("", name[:-4]).replace("_", " ").replace(".", " ").strip() | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            print("Movie: %s" % title) | 
				
			||||||
 | 
					            if args.verbose: | 
				
			||||||
 | 
					                print("    From %s" % name) | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            os.mkdir(os.path.join(temp, title)) | 
				
			||||||
 | 
					            os.symlink(os.path.join("..", os.path.relpath(path)), os.path.join(temp, title, title + name[-4:])) | 
				
			||||||
 | 
					
 | 
				
			||||||
        else: | 
					        else: | 
				
			||||||
            new_name = stuff_re.sub("", os.path.splitext(f.name)[0]).replace("_", " ").strip() | 
					            print("Warning: Ignoring unknown file: %s" % name) | 
				
			||||||
        print("    %s (from %s)" % (new_name, f.name)) | 
					
 | 
				
			||||||
        os.symlink(os.path.join("..", os.path.relpath(dir), f.name), os.path.join(series_name, new_name + "." + os.path.splitext(f.name)[1])) | 
					    print("=== Updating Library ===") | 
				
			||||||
 | 
					    # Replace old one | 
				
			||||||
 | 
					    for x in os.listdir(): | 
				
			||||||
 | 
					        if x.startswith("."): | 
				
			||||||
 | 
					            continue | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        tempx = os.path.join(temp, x) | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if os.path.isdir(x): | 
				
			||||||
 | 
					            if os.path.isdir(tempx): | 
				
			||||||
 | 
					                ok, need_update, need_del = compute_link_dir_sync(tempx, x) | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if need_update or need_del: | 
				
			||||||
 | 
					                    print("Update", x) | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    for name in need_update: | 
				
			||||||
 | 
					                        if args.verbose: | 
				
			||||||
 | 
					                            print("    Update", name) | 
				
			||||||
 | 
					                        os.rename(os.path.join(tempx, name), os.path.join(x, name)) | 
				
			||||||
 | 
					                    for name in need_del: | 
				
			||||||
 | 
					                        if args.verbose: | 
				
			||||||
 | 
					                            print("    Remove", name) | 
				
			||||||
 | 
					                        os.unlink(os.path.join(x, name)) | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                else: | 
				
			||||||
 | 
					                    print("Keep", x) | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                shutil.rmtree(tempx) | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            else: | 
				
			||||||
 | 
					                print("Remove", x) | 
				
			||||||
 | 
					                shutil.rmtree(x) | 
				
			||||||
 | 
					     | 
				
			||||||
 | 
					    for x in os.listdir(temp): | 
				
			||||||
 | 
					        print("Add", x) | 
				
			||||||
 | 
					        os.rename(os.path.join(temp, x), x) | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					print("=== Done ===") | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
					Loading…
					
					
				
		Reference in new issue