From ca73445114bf2471d3eef0322fb73f04cf0e8eb0 Mon Sep 17 00:00:00 2001 From: Soap Date: Tue, 7 Oct 2025 23:44:04 +0000 Subject: [PATCH] Initial yt-dlp hook --- copyparty/cfg/hooks/ytdlp.py | 100 +++++++++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 copyparty/cfg/hooks/ytdlp.py diff --git a/copyparty/cfg/hooks/ytdlp.py b/copyparty/cfg/hooks/ytdlp.py new file mode 100644 index 0000000..dcbc235 --- /dev/null +++ b/copyparty/cfg/hooks/ytdlp.py @@ -0,0 +1,100 @@ +#!/usr/bin/env python3 + +import os +import sys +import json +import subprocess as sp + +""" +Experimental YT-DLP hook for copyparty. Based on wget.py hook +To-Dos: Youtube videos won't work without cookies, so how do I pass them?? + +""" + +_ = r""" +use copyparty as a file downloader by POSTing URLs as +application/x-www-form-urlencoded (for example using the +📟 message-to-server-log in the web-ui) + +example usage as global config: + --xm aw,f,j,t3600,bin/hooks/ytdlp.py + +parameters explained, + xm = execute on message-to-server-log + aw = only users with write-access can use this + f = fork; don't delay other hooks while this is running + j = provide message information as json (not just the text) + c3 = mute all output + t3600 = timeout and abort download after 1 hour + +example usage as a volflag (per-volume config): + -v srv/inc:inc:r:rw,ed:c,xm=aw,f,j,t3600,bin/hooks/ytdlp.py + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + (share filesystem-path srv/inc as volume /inc, + readable by everyone, read-write for user 'ed', + running this plugin on all messages with the params explained above) + +example usage as a volflag in a copyparty config file: + [/inc] + srv/inc + accs: + r: * + rw: ed + flags: + xm: aw,f,j,t3600,bin/hooks/ytdlp.py + +the volflag examples only kicks in if you send the message +while you're in the /inc folder (or any folder below there) +""" + + +def main(): + inf = json.loads(sys.argv[1]) + url = inf["txt"] + if "://" not in url: + url = "https://" + url + + proto = url.split("://")[0].lower() + if proto not in ("http", "https", "ftp", "ftps"): + raise Exception("bad proto {}".format(proto)) + + os.chdir(inf["ap"]) + + name = url.split("?")[0].split("/")[-1] + tfn = "-- DOWNLOADING " + name + print(f"{tfn}\n", end="") + open(tfn, "wb").close() + + cmd = [ + "yt-dlp", + "-f", "bv*+ba/b", + "--downloader", "aria2c", + "--downloader-args", "-j 16 -x 8 -s 16 -k 1M", + url + ] + + if '.' in (name[-3], name[-4]) and name[-3:] != 'php': + cmd += ["-o", name] + + print(" ".join(cmd) + "\n", end="") + + + try: + result = sp.run(cmd, stdout=sp.PIPE, stderr=sp.PIPE, text=True) + print("STDOUT:\n" + result.stdout) + print("STDERR:\n" + result.stderr) + result.check_returncode() + + except sp.CalledProcessError as e: + t = "-- FAILED TO DOWNLOAD " + name + print(f"{t}\n", end="") + open(t, "wb").close() + print(f"Error: {e}") + print("STDOUT:\n" + e.stdout) + print("STDERR:\n" + e.stderr) + os.unlink(tfn) + + +if __name__ == "__main__": + main()