mirror of
https://github.com/9001/copyparty.git
synced 2026-01-12 15:52:39 -07:00
Merge branch '9001:hovudstraum' into hovudstraum
This commit is contained in:
commit
3d228d9a6e
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -43,6 +43,7 @@ scripts/docker/*.err
|
|||
|
||||
# nix build output link
|
||||
result
|
||||
result-*
|
||||
|
||||
# IDEA config
|
||||
.idea/
|
||||
|
|
|
|||
|
|
@ -2924,6 +2924,11 @@ if [cfssl](https://github.com/cloudflare/cfssl/releases/latest) is installed, co
|
|||
* this will be a self-signed certificate so you must install your `ca.pem` into all your browsers/devices
|
||||
* if you want to avoid the hassle of distributing certs manually, please consider using a reverse proxy
|
||||
|
||||
to install cfssl on windows:
|
||||
* [download](https://github.com/cloudflare/cfssl/releases/latest) `cfssl_windows_amd64.exe`, `cfssljson_windows_amd64.exe`, `cfssl-certinfo_windows_amd64.exe`
|
||||
* rename them to `cfssl.exe`, `cfssljson.exe`, `cfssl-certinfo.exe`
|
||||
* put them in PATH, for example inside `c:\windows\system32`
|
||||
|
||||
|
||||
# recovering from crashes
|
||||
|
||||
|
|
|
|||
|
|
@ -34,7 +34,10 @@ MOUNT_BASE = b"/run/media/egon/"
|
|||
|
||||
def main():
|
||||
try:
|
||||
label = sys.argv[1].split(":usb-eject:")[1].split(":")[0]
|
||||
msg = sys.argv[1]
|
||||
if msg.startswith("upload-queue-empty;"):
|
||||
return
|
||||
label = msg.split(":usb-eject:")[1].split(":")[0]
|
||||
mp = MOUNT_BASE + unquote(label)
|
||||
# print("ejecting [%s]... " % (mp,), end="")
|
||||
mp = os.path.abspath(os.path.realpath(mp))
|
||||
|
|
|
|||
|
|
@ -62,6 +62,9 @@ def do_stuff(inf):
|
|||
log = inf["log"]
|
||||
|
||||
url = inf["txt"]
|
||||
if url.startswith("upload-queue-empty;"):
|
||||
return
|
||||
|
||||
if "://" not in url:
|
||||
url = "https://" + url
|
||||
|
||||
|
|
|
|||
|
|
@ -47,6 +47,9 @@ while you're in the /inc folder (or any folder below there)
|
|||
def main():
|
||||
inf = json.loads(sys.argv[1])
|
||||
url = inf["txt"]
|
||||
if url.startswith("upload-queue-empty;"):
|
||||
return
|
||||
|
||||
if "://" not in url:
|
||||
url = "https://" + url
|
||||
|
||||
|
|
|
|||
|
|
@ -67,18 +67,64 @@
|
|||
# additional dependencies
|
||||
extraPythonPackages ? (_p: [ ]),
|
||||
|
||||
# to build stable + unstable with the same file
|
||||
stable ? true,
|
||||
|
||||
# for commit date, only used when stable = false
|
||||
copypartyFlake ? null,
|
||||
|
||||
nix-gitignore,
|
||||
}:
|
||||
|
||||
let
|
||||
pinData = lib.importJSON ./pin.json;
|
||||
runtimeDeps = ([ util-linux ] ++ extraPackages ++ lib.optional withMediaProcessing ffmpeg);
|
||||
inherit (copypartyFlake) lastModifiedDate;
|
||||
# ex: "1970" "01" "01"
|
||||
dateStringsZeroPrefixed = {
|
||||
year = builtins.substring 0 4 lastModifiedDate;
|
||||
month = builtins.substring 4 2 lastModifiedDate;
|
||||
day = builtins.substring 6 2 lastModifiedDate;
|
||||
};
|
||||
# ex: "1970" "1" "1"
|
||||
dateStringsShort = builtins.mapAttrs (_: val: toString (lib.toIntBase10 val)) dateStringsZeroPrefixed;
|
||||
unstableVersion =
|
||||
if copypartyFlake == null then
|
||||
"${pinData.version}-unstable"
|
||||
else
|
||||
with dateStringsZeroPrefixed; "${pinData.version}-unstable-${year}-${month}-${day}"
|
||||
;
|
||||
version = if stable then pinData.version else unstableVersion;
|
||||
stableSrc = fetchurl {
|
||||
inherit (pinData) url hash;
|
||||
};
|
||||
root = ../../../..;
|
||||
unstableSrc = nix-gitignore.gitignoreSource [] root;
|
||||
src = if stable then stableSrc else unstableSrc;
|
||||
rev = copypartyFlake.shortRev or copypartyFlake.dirtyShortRev or "unknown";
|
||||
unstableCodename = "unstable" + (lib.optionalString (copypartyFlake != null) "-${rev}");
|
||||
in
|
||||
buildPythonApplication {
|
||||
pname = "copyparty";
|
||||
inherit (pinData) version;
|
||||
src = fetchurl {
|
||||
inherit (pinData) url hash;
|
||||
};
|
||||
inherit version src;
|
||||
postPatch = lib.optionalString (!stable) ''
|
||||
old_src="$(mktemp -d)"
|
||||
tar -C "$old_src" -xf ${stableSrc}
|
||||
declare -a folders
|
||||
folders=("$old_src"/*)
|
||||
count_folders="''${#folders[@]}"
|
||||
if [[ $count_folders != 1 ]]; then
|
||||
declare -p folders
|
||||
echo "Expected 1 folder, found $count_folders" >&2
|
||||
exit 1
|
||||
fi
|
||||
old_src_folder="''${folders[0]}"
|
||||
cp -r "$old_src_folder"/copyparty/web/deps copyparty/web/deps
|
||||
sed -i 's/^CODENAME =.*$/CODENAME = "${unstableCodename}"/' copyparty/__version__.py
|
||||
${lib.optionalString (copypartyFlake != null) (with dateStringsShort; ''
|
||||
sed -i 's/^BUILD_DT =.*$/BUILD_DT = (${year}, ${month}, ${day})/' copyparty/__version__.py
|
||||
'')}
|
||||
'';
|
||||
dependencies =
|
||||
[
|
||||
jinja2
|
||||
|
|
|
|||
|
|
@ -1,8 +1,28 @@
|
|||
final: prev: {
|
||||
copyparty = final.python3.pkgs.callPackage ./copyparty {
|
||||
ffmpeg = final.ffmpeg-full;
|
||||
final: prev:
|
||||
let
|
||||
fullAttrs = {
|
||||
withHashedPasswords = true;
|
||||
withCertgen = true;
|
||||
withThumbnails = true;
|
||||
withFastThumbnails = true;
|
||||
withMediaProcessing = true;
|
||||
withBasicAudioMetadata = true;
|
||||
withZeroMQ = true;
|
||||
withFTP = true;
|
||||
withFTPS = true;
|
||||
withTFTP = true;
|
||||
withSMB = true;
|
||||
withMagic = true;
|
||||
};
|
||||
|
||||
call = attrs: final.python3.pkgs.callPackage ./copyparty ({ ffmpeg = final.ffmpeg-full; } // attrs);
|
||||
in
|
||||
{
|
||||
copyparty = call { stable = true; };
|
||||
copyparty-unstable = call { stable = false; };
|
||||
copyparty-full = call (fullAttrs // { stable = true; });
|
||||
copyparty-unstable-full = call (fullAttrs // { stable = false; });
|
||||
|
||||
python3 = prev.python3.override {
|
||||
packageOverrides = pyFinal: pyPrev: {
|
||||
partftpy = pyFinal.callPackage ./partftpy { };
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import calendar
|
|||
import errno
|
||||
import json
|
||||
import os
|
||||
import shutil
|
||||
import time
|
||||
|
||||
from .__init__ import ANYWIN
|
||||
|
|
@ -19,6 +20,19 @@ else:
|
|||
VF = {"mv_re_t": 0, "rm_re_t": 0}
|
||||
|
||||
|
||||
def _sp_err(exe, what, rc, so, se, sin):
|
||||
try:
|
||||
zs = shutil.which(exe)
|
||||
except:
|
||||
zs = "<?>"
|
||||
try:
|
||||
zi = os.path.getsize(zs)
|
||||
except:
|
||||
zi = 0
|
||||
t = "failed to %s; error %s using %s (%s):\n STDOUT: %s\n STDERR: %s\n STDIN: %s\n"
|
||||
raise Exception(t % (what, rc, zs, zi, so, se, sin.decode("utf-8")))
|
||||
|
||||
|
||||
def ensure_cert(log: "RootLogger", args) -> None:
|
||||
"""
|
||||
the default cert (and the entire TLS support) is only here to enable the
|
||||
|
|
@ -107,13 +121,13 @@ def _gen_ca(log: "RootLogger", args):
|
|||
cmd = "cfssl gencert -initca -"
|
||||
rc, so, se = runcmd(cmd.split(), 30, sin=sin)
|
||||
if rc:
|
||||
raise Exception("failed to create ca-cert: {}, {}".format(rc, se), 3)
|
||||
_sp_err("cfssl", "create ca-cert", rc, so, se, sin)
|
||||
|
||||
cmd = "cfssljson -bare ca"
|
||||
sin = so.encode("utf-8")
|
||||
rc, so, se = runcmd(cmd.split(), 10, sin=sin, cwd=args.crt_dir)
|
||||
if rc:
|
||||
raise Exception("failed to translate ca-cert: {}, {}".format(rc, se), 3)
|
||||
_sp_err("cfssljson", "translate ca-cert", rc, so, se, sin)
|
||||
|
||||
bname = os.path.join(args.crt_dir, "ca")
|
||||
try:
|
||||
|
|
@ -201,13 +215,13 @@ def _gen_srv(log: "RootLogger", args, netdevs: dict[str, Netdev]):
|
|||
acmd = cmd.split() + ["-hostname=" + ",".join(names), "-"]
|
||||
rc, so, se = runcmd(acmd, 30, sin=sin, cwd=args.crt_dir)
|
||||
if rc:
|
||||
raise Exception("failed to create cert: {}, {}".format(rc, se))
|
||||
_sp_err("cfssl", "create cert", rc, so, se, sin)
|
||||
|
||||
cmd = "cfssljson -bare srv"
|
||||
sin = so.encode("utf-8")
|
||||
rc, so, se = runcmd(cmd.split(), 10, sin=sin, cwd=args.crt_dir)
|
||||
if rc:
|
||||
raise Exception("failed to translate cert: {}, {}".format(rc, se))
|
||||
_sp_err("cfssljson", "translate cert", rc, so, se, sin)
|
||||
|
||||
bname = os.path.join(args.crt_dir, "srv")
|
||||
try:
|
||||
|
|
|
|||
|
|
@ -2449,7 +2449,7 @@ function mpause(e) {
|
|||
return true;
|
||||
|
||||
dist *= -1;
|
||||
mp.setvol(mp.vol + dist / 500);
|
||||
mp.setvol(Math.round((mp.vol + dist / 500) * 100) / 100 );
|
||||
vbar.draw();
|
||||
ev(e);
|
||||
};
|
||||
|
|
@ -3019,9 +3019,6 @@ function play(tid, is_ev, seek) {
|
|||
}
|
||||
|
||||
if (tn >= mp.order.length) {
|
||||
if (mpl.pb_mode == 'stop')
|
||||
return;
|
||||
|
||||
if (mpl.pb_mode == 'loop' || ebi('unsearch')) {
|
||||
tn = 0;
|
||||
}
|
||||
|
|
@ -3029,6 +3026,7 @@ function play(tid, is_ev, seek) {
|
|||
treectl.ls_cb = next_song;
|
||||
return tree_neigh(1);
|
||||
}
|
||||
else return;
|
||||
}
|
||||
|
||||
if (tn < 0) {
|
||||
|
|
@ -3039,6 +3037,7 @@ function play(tid, is_ev, seek) {
|
|||
treectl.ls_cb = last_song;
|
||||
return tree_neigh(-1);
|
||||
}
|
||||
else return;
|
||||
}
|
||||
|
||||
tid = mp.order[tn];
|
||||
|
|
|
|||
|
|
@ -2271,11 +2271,17 @@ function up2k_init(subtle) {
|
|||
busy = {},
|
||||
nbusy = 0,
|
||||
init = 0,
|
||||
ninit = 0,
|
||||
hashtab = {},
|
||||
mem = (MOBILE ? 128 : 256) * 1024 * 1024;
|
||||
|
||||
if (!hws_ok)
|
||||
init = setTimeout(function() {
|
||||
init = setInterval(function() {
|
||||
if (ninit < hws_ok) {
|
||||
ninit = hws_ok;
|
||||
return toast.inf(10, 'initializing webworkers ({0}/{1})'.format(hws_ok, hws.length), "iwwt");
|
||||
}
|
||||
clearInterval(init);
|
||||
hws_ng = true;
|
||||
toast.warn(30, 'webworkers failed to start\n\nwill be a bit slower due to\nhashing on main-thread');
|
||||
apop(st.busy.hash, t);
|
||||
|
|
@ -2325,12 +2331,17 @@ function up2k_init(subtle) {
|
|||
}
|
||||
|
||||
function onmsg(d) {
|
||||
if (hws_ng)
|
||||
return;
|
||||
|
||||
d = d.data;
|
||||
var k = d[0];
|
||||
|
||||
if (k == "pong")
|
||||
if (++hws_ok == hws.length) {
|
||||
clearTimeout(init);
|
||||
clearInterval(init);
|
||||
if (toast.tag == 'iwwt')
|
||||
toast.hide();
|
||||
go_next();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@
|
|||
[/] # create a volume at "/" (the webroot), which will
|
||||
/w # share /w (the docker data volume)
|
||||
accs:
|
||||
rw: * # everyone gets read-access, but
|
||||
r: * # everyone gets read-access, but
|
||||
rwmda: @su # the group "su" gets read-write-move-delete-admin
|
||||
|
||||
|
||||
|
|
|
|||
25
flake.nix
25
flake.nix
|
|
@ -12,7 +12,8 @@
|
|||
}:
|
||||
{
|
||||
nixosModules.default = ./contrib/nixos/modules/copyparty.nix;
|
||||
overlays.default = import ./contrib/package/nix/overlay.nix;
|
||||
overlays.default = final: prev:
|
||||
(import ./contrib/package/nix/overlay.nix final prev) // { copypartyFlake = self; };
|
||||
}
|
||||
// flake-utils.lib.eachDefaultSystem (
|
||||
system:
|
||||
|
|
@ -22,26 +23,26 @@
|
|||
config = {
|
||||
allowAliases = false;
|
||||
};
|
||||
overlays = [ self.overlays.default ];
|
||||
overlays = [
|
||||
self.overlays.default
|
||||
];
|
||||
};
|
||||
in
|
||||
{
|
||||
# check that copyparty builds with all optionals turned on
|
||||
checks.copyparty-full = self.packages.${system}.copyparty.override {
|
||||
withHashedPasswords = true;
|
||||
withCertgen = true;
|
||||
withThumbnails = true;
|
||||
withFastThumbnails = true;
|
||||
withMediaProcessing = true;
|
||||
withBasicAudioMetadata = true;
|
||||
withZeroMQ = true;
|
||||
withFTPS = true;
|
||||
withSMB = true;
|
||||
checks = {
|
||||
inherit (pkgs)
|
||||
copyparty-full
|
||||
copyparty-unstable-full
|
||||
;
|
||||
};
|
||||
|
||||
packages = {
|
||||
inherit (pkgs)
|
||||
copyparty
|
||||
copyparty-full
|
||||
copyparty-unstable
|
||||
copyparty-unstable-full
|
||||
;
|
||||
default = self.packages.${system}.copyparty;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,6 +1,12 @@
|
|||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
command -v gfind >/dev/null &&
|
||||
command -v gsed >/dev/null &&
|
||||
command -v gsort >/dev/null && {
|
||||
sed() { gsed "$@"; }
|
||||
}
|
||||
|
||||
[ -e make-sfx.sh ] || cd scripts
|
||||
[ -e make-sfx.sh ] && [ -e deps-docker ] || {
|
||||
echo cd into the scripts folder first
|
||||
|
|
|
|||
|
|
@ -37,7 +37,12 @@ def cnv(src):
|
|||
hostname = str(socket.gethostname()).split(".")[0]
|
||||
|
||||
yield '<!DOCTYPE html>'
|
||||
yield '<html style="background:#222;color:#fff"><body>'
|
||||
yield '<html><body><style>'
|
||||
yield 'html{background:#222;color:#fff;line-height:1.25em}'
|
||||
yield 'h3{margin:0;padding:0}'
|
||||
yield 'a{color:#fc5;text-decoration:none;scroll-margin-top:3em}'
|
||||
yield 'a:active,a:target{background:#fc5;color:#000;box-shadow:0 0 0 .12em #fc5}'
|
||||
yield '</style>'
|
||||
skip_sfx = False
|
||||
in_sfx = 0
|
||||
in_salt = 0
|
||||
|
|
@ -104,6 +109,15 @@ def cnv(src):
|
|||
ln = re.sub(r">[0-9]{1,2}\.[0-9]<", ">dynamic<", ln)
|
||||
if t != ln:
|
||||
in_th_ram_max = 0
|
||||
m = re.search(r"^# (.* help page)(.*)", ln)
|
||||
if m:
|
||||
zs1, zs2 = m.groups()
|
||||
zs3 = zs1.replace(" ", "-")
|
||||
ln = '<h3># <a id="%s" href="#%s">%s</a>%s</h3></a>' % (zs3, zs3, zs1, zs2)
|
||||
m = re.search(r"^ (-{1,2})([^ ,]+)(.*)", ln)
|
||||
if m:
|
||||
zs1, zs2, zs3 = m.groups()
|
||||
ln = ' <a href="#g-%s" id="g-%s">%s%s</a>%s' % (zs2, zs2, zs1, zs2, zs3)
|
||||
|
||||
ln = ln.replace(">/home/ed/", ">~/")
|
||||
if ln.startswith("0" * 20):
|
||||
|
|
|
|||
|
|
@ -1,6 +1,12 @@
|
|||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
command -v gfind >/dev/null &&
|
||||
command -v gsed >/dev/null &&
|
||||
command -v gsort >/dev/null && {
|
||||
head() { ghead "$@"; }
|
||||
}
|
||||
|
||||
( ( HLPTXT=CAT && cat || xsel -ob ) | sed -r '
|
||||
s`/home/ed/`~/`;
|
||||
s/uuid:[0-9a-f-]{36}/autogenerated/;
|
||||
|
|
|
|||
Loading…
Reference in a new issue