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