diff --git a/bin/hooks/reloc-by-ext.py b/bin/hooks/reloc-by-ext.py index cdae1734..b25d3c35 100644 --- a/bin/hooks/reloc-by-ext.py +++ b/bin/hooks/reloc-by-ext.py @@ -2,11 +2,12 @@ import json import os +import re import sys _ = r""" -relocate/redirect incoming uploads according to file extension +relocate/redirect incoming uploads according to file extension or name example usage as global config: --xbu j,c1,bin/hooks/reloc-by-ext.py @@ -52,11 +53,19 @@ def main(): try: fn, ext = fn.rsplit(".", 1) except: - # no file extension; abort - return + # no file extension; pretend it's "bin" + ext = "bin" ext = ext.lower() + # this function must end by printing the action to perform; + # that's handled by the print(json.dumps(... at the bottom + # + # the action can contain the following keys: + # "vp" is the folder URL to move the upload to, + # "ap" is the filesystem-path to move it to (but "vp" is safer), + # "fn" overrides the final filename to use + ## ## some example actions to take; pick one by ## selecting it inside the print at the end: @@ -80,11 +89,37 @@ def main(): elif ext in MUSIC.split(): by_category = {"vp": "/just/tunes"} else: - by_category = {} + by_category = {} # no action - # now choose the effect to apply; can be any of these: + # now choose the default effect to apply; can be any of these: # into_subfolder into_toplevel into_sibling by_category - effect = into_subfolder + effect = {"vp": "/junk"} + + ## + ## but we can keep going, adding more speicifc rules + ## which can take precedence, replacing the fallback + ## effect we just specified: + ## + + fn = fn.lower() # lowercase filename to make this easier + + if "screenshot" in fn: + effect = {"vp": "/ss"} + if "mpv_" in fn: + effect = {"vp": "/anishots"} + elif "debian" in fn or "biebian" in fn: + effect = {"vp": "/linux-ISOs"} + elif re.search(r"ep(isode |\.)?[0-9]", fn): + effect = {"vp": "/podcasts"} + + # regex lets you grab a part of the matching + # text and use that in the upload path: + m = re.search(r"\b(op|ed)([^a-z]|$)", fn) + if m: + # the regex matched; use "anime-op" or "anime-ed" + effect = {"vp": "/anime-" + m[1]} + + # aaand DO IT print(json.dumps({"reloc": effect})) diff --git a/copyparty/up2k.py b/copyparty/up2k.py index 8e29160e..4bb5b01c 100644 --- a/copyparty/up2k.py +++ b/copyparty/up2k.py @@ -2564,7 +2564,10 @@ class Up2k(object): return ret - def _handle_json(self, cj: dict[str, Any]) -> dict[str, Any]: + def _handle_json(self, cj: dict[str, Any], depth: int = 1) -> dict[str, Any]: + if depth > 16: + raise Pebkac(500, "too many xbu relocs, giving up") + ptop = cj["ptop"] if not self.register_vpath(ptop, cj["vcfg"]): if ptop not in self.registry: @@ -2794,12 +2797,16 @@ class Up2k(object): if hr.get("reloc"): x = pathmod(self.asrv.vfs, dst, vp, hr["reloc"]) if x: + zvfs = vfs pdir, _, job["name"], (vfs, rem) = x dst = os.path.join(pdir, job["name"]) + job["vcfg"] = vfs.flags job["ptop"] = vfs.realpath job["vtop"] = vfs.vpath job["prel"] = rem - bos.makedirs(pdir) + if zvfs.vpath != vfs.vpath: + self.log("xbu reloc %d..." % (depth,), 6) + return self._handle_json(job, depth + 1) job["name"] = self._untaken(pdir, job, now) @@ -2880,7 +2887,9 @@ class Up2k(object): lut.add(k) try: - self._new_upload(job) + ret = self._new_upload(job, vfs, depth) + if ret: + return ret # xbu recursed except: self.registry[job["ptop"]].pop(job["wark"], None) raise @@ -4176,22 +4185,17 @@ class Up2k(object): return ret - def _new_upload(self, job: dict[str, Any]) -> None: + def _new_upload(self, job: dict[str, Any], vfs: VFS, depth: int) -> dict[str, str]: pdir = djoin(job["ptop"], job["prel"]) if not job["size"]: try: inf = bos.stat(djoin(pdir, job["name"])) if stat.S_ISREG(inf.st_mode): job["lmod"] = inf.st_size - return + return {} except: pass - self.registry[job["ptop"]][job["wark"]] = job - job["name"] = self._untaken(pdir, job, job["t0"]) - # if len(job["name"].split(".")) > 8: - # raise Exception("aaa") - xbu = self.flags[job["ptop"]].get("xbu") ap_chk = djoin(pdir, job["name"]) vp_chk = djoin(job["vtop"], job["prel"], job["name"]) @@ -4220,10 +4224,18 @@ class Up2k(object): if hr.get("reloc"): x = pathmod(self.asrv.vfs, ap_chk, vp_chk, hr["reloc"]) if x: + zvfs = vfs pdir, _, job["name"], (vfs, rem) = x + job["vcfg"] = vfs.flags job["ptop"] = vfs.realpath job["vtop"] = vfs.vpath job["prel"] = rem + if zvfs.vpath != vfs.vpath: + self.log("xbu reloc %d..." % (depth,), 6) + return self._handle_json(job, depth + 1) + + job["name"] = self._untaken(pdir, job, job["t0"]) + self.registry[job["ptop"]][job["wark"]] = job tnam = job["name"] + ".PARTIAL" if self.args.dotpart: @@ -4233,7 +4245,7 @@ class Up2k(object): job["tnam"] = tnam if not job["hash"]: del self.registry[job["ptop"]][job["wark"]] - return + return {} if self.args.plain_ip: dip = job["addr"].replace(":", ".") @@ -4293,6 +4305,8 @@ class Up2k(object): if not job["hash"]: self._finish_upload(job["ptop"], job["wark"]) + return {} + def _snapshot(self) -> None: slp = self.args.snap_wri if not slp or self.args.no_snap: