211 lines
6.1 KiB
Python
Executable File
211 lines
6.1 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
|
|
"""
|
|
WARNING -- DANGEROUS PLUGIN --
|
|
if someone is able to upload files to a copyparty which is
|
|
running this plugin, they can execute malware on your machine
|
|
so please keep this on a LAN and protect it with a password
|
|
|
|
here is a MUCH BETTER ALTERNATIVE (which also works on Windows):
|
|
https://github.com/steinuil/kameloso
|
|
|
|
----------------------------------------------------------------------
|
|
|
|
use copyparty as a chromecast replacement:
|
|
* post a URL and it will open in the default browser
|
|
* upload a file and it will open in the default application
|
|
* the `key` command simulates keyboard input
|
|
* the `x` command executes other xdotool commands
|
|
* the `c` command executes arbitrary unix commands
|
|
|
|
the android app makes it a breeze to post pics and links:
|
|
https://github.com/9001/party-up/releases
|
|
|
|
iOS devices can use the web-UI or the shortcut instead:
|
|
https://github.com/9001/copyparty#ios-shortcuts
|
|
|
|
example copyparty config to use this;
|
|
lets the user "kevin" with password "hunter2" use this plugin:
|
|
-a kevin:hunter2 --urlform save,get -v.::w,kevin:c,e2d,e2t,mte=+a1:c,mtp=a1=ad,kn,c0,bin/mtag/very-bad-idea.py
|
|
|
|
recommended deps:
|
|
apt install xdotool libnotify-bin mpv
|
|
python3 -m pip install --user -U streamlink yt-dlp
|
|
https://github.com/9001/copyparty/blob/hovudstraum/contrib/plugins/meadup.js
|
|
|
|
and you probably want `twitter-unmute.user.js` from the res folder
|
|
|
|
|
|
-----------------------------------------------------------------------
|
|
-- startup script:
|
|
-----------------------------------------------------------------------
|
|
|
|
#!/bin/bash
|
|
set -e
|
|
|
|
# create qr code
|
|
ip=$(ip r | awk '/^default/{print$(NF-2)}'); echo http://$ip:3923/ | qrencode -o - -s 4 >/dev/shm/cpp-qr.png
|
|
/usr/bin/feh -x /dev/shm/cpp-qr.png &
|
|
|
|
# reposition and make topmost (with janky raspbian support)
|
|
( sleep 0.5
|
|
xdotool search --name cpp-qr.png windowactivate --sync windowmove 1780 0
|
|
wmctrl -r :ACTIVE: -b toggle,above || true
|
|
|
|
ps aux | grep -E 'sleep[ ]7\.27' ||
|
|
while true; do
|
|
w=$(xdotool getactivewindow)
|
|
xdotool search --name cpp-qr.png windowactivate windowraise windowfocus
|
|
xdotool windowactivate $w
|
|
xdotool windowfocus $w
|
|
sleep 7.27 || break
|
|
done &
|
|
xeyes # distraction window to prevent ^w from closing the qr-code
|
|
) &
|
|
|
|
# bail if copyparty is already running
|
|
ps aux | grep -E '[3] copy[p]arty' && exit 0
|
|
|
|
# dumb chrome wrapper to allow autoplay
|
|
cat >/usr/local/bin/chromium-browser <<'EOF'
|
|
#!/bin/bash
|
|
set -e
|
|
/usr/bin/chromium-browser --autoplay-policy=no-user-gesture-required "$@"
|
|
EOF
|
|
chmod 755 /usr/local/bin/chromium-browser
|
|
|
|
# start the server
|
|
# note 1: replace hunter2 with a better password to access the server
|
|
# note 2: replace `-v.::rw` with `-v.::w` to disallow retrieving uploaded stuff
|
|
cd ~/Downloads; python3 copyparty-sfx.py -a kevin:hunter2 --urlform save,get -v.::rw,kevin:c,e2d,e2t,mte=+a1:c,mtp=a1=ad,kn,very-bad-idea.py
|
|
|
|
"""
|
|
|
|
|
|
import os
|
|
import sys
|
|
import time
|
|
import shutil
|
|
import subprocess as sp
|
|
from urllib.parse import unquote_to_bytes as unquote
|
|
from urllib.parse import quote
|
|
|
|
have_mpv = shutil.which("mpv")
|
|
have_vlc = shutil.which("vlc")
|
|
|
|
|
|
def main():
|
|
if len(sys.argv) > 2 and sys.argv[1] == "x":
|
|
# invoked on commandline for testing;
|
|
# python3 very-bad-idea.py x msg=https://youtu.be/dQw4w9WgXcQ
|
|
txt = " ".join(sys.argv[2:])
|
|
txt = quote(txt.replace(" ", "+"))
|
|
return open_post(txt.encode("utf-8"))
|
|
|
|
fp = os.path.abspath(sys.argv[1])
|
|
with open(fp, "rb") as f:
|
|
txt = f.read(4096)
|
|
|
|
if txt.startswith(b"msg="):
|
|
open_post(txt)
|
|
else:
|
|
open_url(fp)
|
|
|
|
|
|
def open_post(txt):
|
|
txt = unquote(txt.replace(b"+", b" ")).decode("utf-8")[4:]
|
|
try:
|
|
k, v = txt.split(" ", 1)
|
|
except:
|
|
return open_url(txt)
|
|
|
|
if k == "key":
|
|
sp.call(["xdotool", "key"] + v.split(" "))
|
|
elif k == "x":
|
|
sp.call(["xdotool"] + v.split(" "))
|
|
elif k == "c":
|
|
env = os.environ.copy()
|
|
while " " in v:
|
|
v1, v2 = v.split(" ", 1)
|
|
if "=" not in v1:
|
|
break
|
|
|
|
ek, ev = v1.split("=", 1)
|
|
env[ek] = ev
|
|
v = v2
|
|
|
|
sp.call(v.split(" "), env=env)
|
|
else:
|
|
open_url(txt)
|
|
|
|
|
|
def open_url(txt):
|
|
ext = txt.rsplit(".")[-1].lower()
|
|
sp.call(["notify-send", "--", txt])
|
|
if ext not in ["jpg", "jpeg", "png", "gif", "webp"]:
|
|
# sp.call(["wmctrl", "-c", ":ACTIVE:"]) # closes the active window correctly
|
|
sp.call(["killall", "vlc"])
|
|
sp.call(["killall", "mpv"])
|
|
sp.call(["killall", "feh"])
|
|
time.sleep(0.5)
|
|
for _ in range(20):
|
|
sp.call(["xdotool", "key", "ctrl+w"]) # closes the open tab correctly
|
|
# else:
|
|
# sp.call(["xdotool", "getactivewindow", "windowminimize"]) # minimizes the focused windo
|
|
|
|
# mpv is probably smart enough to use streamlink automatically
|
|
if try_mpv(txt):
|
|
print("mpv got it")
|
|
return
|
|
|
|
# or maybe streamlink would be a good choice to open this
|
|
if try_streamlink(txt):
|
|
print("streamlink got it")
|
|
return
|
|
|
|
# nope,
|
|
# close any error messages:
|
|
sp.call(["xdotool", "search", "--name", "Error", "windowclose"])
|
|
# sp.call(["xdotool", "key", "ctrl+alt+d"]) # doesnt work at all
|
|
# sp.call(["xdotool", "keydown", "--delay", "100", "ctrl+alt+d"])
|
|
# sp.call(["xdotool", "keyup", "ctrl+alt+d"])
|
|
sp.call(["xdg-open", txt])
|
|
|
|
|
|
def try_mpv(url):
|
|
t0 = time.time()
|
|
try:
|
|
print("trying mpv...")
|
|
sp.check_call(["mpv", "--fs", url])
|
|
return True
|
|
except:
|
|
# if it ran for 15 sec it probably succeeded and terminated
|
|
t = time.time()
|
|
return t - t0 > 15
|
|
|
|
|
|
def try_streamlink(url):
|
|
t0 = time.time()
|
|
try:
|
|
import streamlink
|
|
|
|
print("trying streamlink...")
|
|
streamlink.Streamlink().resolve_url(url)
|
|
|
|
if have_mpv:
|
|
args = "-m streamlink -p mpv -a --fs"
|
|
else:
|
|
args = "-m streamlink"
|
|
|
|
cmd = [sys.executable] + args.split() + [url, "best"]
|
|
t0 = time.time()
|
|
sp.check_call(cmd)
|
|
return True
|
|
except:
|
|
# if it ran for 10 sec it probably succeeded and terminated
|
|
t = time.time()
|
|
return t - t0 > 10
|
|
|
|
|
|
main()
|