mirror of
https://github.com/9001/copyparty.git
synced 2025-10-23 04:52:21 +00:00
Compare commits
20 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
0a8e759fe6 | ||
|
d70981cdd1 | ||
|
e08c03b886 | ||
|
56086e8984 | ||
|
1aa9033022 | ||
|
076e103d53 | ||
|
38c00ea8fc | ||
|
415757af43 | ||
|
e72ed8c0ed | ||
|
32f9c6b5bb | ||
|
6251584ef6 | ||
|
f3e413bc28 | ||
|
6f6cc8f3f8 | ||
|
8b081e9e69 | ||
|
c8a510d10e | ||
|
6f834f6679 | ||
|
cf2d6650ac | ||
|
cd52dea488 | ||
|
6ea75df05d | ||
|
4846e1e8d6 |
14
README.md
14
README.md
@@ -62,6 +62,14 @@ download [copyparty-sfx.py](https://github.com/9001/copyparty/releases/latest/do
|
||||
|
||||
running the sfx without arguments (for example doubleclicking it on Windows) will give everyone full access to the current folder; see `-h` for help if you want accounts and volumes etc
|
||||
|
||||
some recommended options:
|
||||
* `-e2dsa` enables general file indexing, see [search configuration](#search-configuration)
|
||||
* `-e2ts` enables audio metadata indexing (needs either FFprobe or mutagen), see [optional dependencies](#optional-dependencies)
|
||||
* `-v /mnt/music:/music:r:afoo -a foo:bar` shares `/mnt/music` as `/music`, `r`eadable by anyone, with user `foo` as `a`dmin (read/write), password `bar`
|
||||
* replace `:r:afoo` with `:rfoo` to only make the folder readable by `foo` and nobody else
|
||||
* in addition to `r`ead and `a`dmin, `w`rite makes a folder write-only, so cannot list/access files in it
|
||||
* `--ls '**,*,ln,p,r'` to crash on startup if any of the volumes contain a symlink which point outside the volume, as that could give users unintended access
|
||||
|
||||
you may also want these, especially on servers:
|
||||
* [contrib/systemd/copyparty.service](contrib/systemd/copyparty.service) to run copyparty as a systemd service
|
||||
* [contrib/nginx/copyparty.conf](contrib/nginx/copyparty.conf) to reverse-proxy behind nginx (for better https)
|
||||
@@ -101,7 +109,7 @@ summary: all planned features work! now please enjoy the bloatening
|
||||
* ☑ FUSE client (read-only)
|
||||
* browser
|
||||
* ☑ tree-view
|
||||
* ☑ media player
|
||||
* ☑ audio player
|
||||
* ☑ thumbnails
|
||||
* ☑ images using Pillow
|
||||
* ☑ videos using FFmpeg
|
||||
@@ -163,7 +171,7 @@ the browser has the following hotkeys
|
||||
* `0..9` jump to 10%..90%
|
||||
* `U/O` skip 10sec back/forward
|
||||
* `J/L` prev/next song
|
||||
* `J` also starts playing the folder
|
||||
* `M` play/pause (also starts playing the folder)
|
||||
* in the grid view:
|
||||
* `S` toggle multiselect
|
||||
* `A/D` zoom
|
||||
@@ -301,7 +309,7 @@ the same arguments can be set as volume flags, in addition to `d2d` and `d2t` fo
|
||||
* `-v ~/music::r:cd2t` disables all `-e2t*` (tags), does not affect `-e2d*`
|
||||
|
||||
note:
|
||||
* `e2tsr` is probably always overkill, since `e2ds`/`e2dsa` would pick up any file modifications and cause `e2ts` to reindex those
|
||||
* `e2tsr` is probably always overkill, since `e2ds`/`e2dsa` would pick up any file modifications and `e2ts` would then reindex those
|
||||
* the rescan button in the admin panel has no effect unless the volume has `-e2ds` or higher
|
||||
|
||||
you can choose to only index filename/path/size/last-modified (and not the hash of the file contents) by setting `--no-hash` or the volume-flag `cdhash`, this has the following consequences:
|
||||
|
@@ -1,3 +1,8 @@
|
||||
# when running copyparty behind a reverse-proxy,
|
||||
# make sure that copyparty allows at least as many clients as the proxy does,
|
||||
# so run copyparty with -nc 512 if your nginx has the default limits
|
||||
# (worker_processes 1, worker_connections 512)
|
||||
|
||||
upstream cpp {
|
||||
server 127.0.0.1:3923;
|
||||
keepalive 120;
|
||||
|
@@ -1,8 +1,8 @@
|
||||
# coding: utf-8
|
||||
|
||||
VERSION = (0, 11, 14)
|
||||
VERSION = (0, 11, 17)
|
||||
CODENAME = "the grid"
|
||||
BUILD_DT = (2021, 6, 14)
|
||||
BUILD_DT = (2021, 6, 17)
|
||||
|
||||
S_VERSION = ".".join(map(str, VERSION))
|
||||
S_BUILD_DT = "{0:04d}-{1:02d}-{2:02d}".format(*BUILD_DT)
|
||||
|
@@ -339,29 +339,32 @@ class ThumbSrv(object):
|
||||
interval = self.args.th_clean
|
||||
while True:
|
||||
time.sleep(interval)
|
||||
ndirs = 0
|
||||
for vol, histpath in self.asrv.vfs.histtab.items():
|
||||
if histpath.startswith(vol):
|
||||
self.log("\033[Jcln {}/\033[A".format(histpath))
|
||||
else:
|
||||
self.log("\033[Jcln {} ({})/\033[A".format(histpath, vol))
|
||||
|
||||
self.clean(histpath)
|
||||
ndirs += self.clean(histpath)
|
||||
|
||||
self.log("\033[Jcln ok")
|
||||
self.log("\033[Jcln ok; rm {} dirs".format(ndirs))
|
||||
|
||||
def clean(self, histpath):
|
||||
# self.log("cln {}".format(histpath))
|
||||
thumbpath = os.path.join(histpath, "th")
|
||||
# self.log("cln {}".format(thumbpath))
|
||||
maxage = self.args.th_maxage
|
||||
now = time.time()
|
||||
prev_b64 = None
|
||||
prev_fp = None
|
||||
try:
|
||||
ents = os.listdir(histpath)
|
||||
ents = os.listdir(thumbpath)
|
||||
except:
|
||||
return
|
||||
return 0
|
||||
|
||||
ndirs = 0
|
||||
for f in sorted(ents):
|
||||
fp = os.path.join(histpath, f)
|
||||
fp = os.path.join(thumbpath, f)
|
||||
cmp = fp.lower().replace("\\", "/")
|
||||
|
||||
# "top" or b64 prefix/full (a folder)
|
||||
@@ -376,10 +379,11 @@ class ThumbSrv(object):
|
||||
break
|
||||
|
||||
if safe:
|
||||
ndirs += 1
|
||||
self.log("rm -rf [{}]".format(fp))
|
||||
shutil.rmtree(fp, ignore_errors=True)
|
||||
else:
|
||||
self.clean(fp)
|
||||
ndirs += self.clean(fp)
|
||||
continue
|
||||
|
||||
# thumb file
|
||||
@@ -401,3 +405,5 @@ class ThumbSrv(object):
|
||||
|
||||
prev_b64 = b64
|
||||
prev_fp = fp
|
||||
|
||||
return ndirs
|
||||
|
@@ -53,6 +53,7 @@ body {
|
||||
#files tbody a {
|
||||
display: block;
|
||||
padding: .3em 0;
|
||||
scroll-margin-top: 45vh;
|
||||
}
|
||||
#files tbody div a {
|
||||
color: #f5a;
|
||||
@@ -68,7 +69,6 @@ a, #files tbody div a:last-child {
|
||||
text-decoration: underline;
|
||||
}
|
||||
#files thead {
|
||||
background: #333;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
}
|
||||
@@ -76,29 +76,30 @@ a, #files tbody div a:last-child {
|
||||
color: #999;
|
||||
font-weight: normal;
|
||||
}
|
||||
#files tr:hover {
|
||||
#files tr:hover td {
|
||||
background: #1c1c1c;
|
||||
}
|
||||
#files thead th {
|
||||
padding: .5em 1.3em .3em 1.3em;
|
||||
padding: .5em .3em .3em .3em;
|
||||
border-right: 2px solid #3c3c3c;
|
||||
border-bottom: 2px solid #444;
|
||||
background: #333;
|
||||
cursor: pointer;
|
||||
}
|
||||
#files thead th+th {
|
||||
border-left: 2px solid #2a2a2a;
|
||||
}
|
||||
#files thead th:last-child {
|
||||
background: #444;
|
||||
border-radius: .7em .7em 0 0;
|
||||
border-right: none;
|
||||
}
|
||||
#files thead th:first-child {
|
||||
#files tbody {
|
||||
background: #222;
|
||||
}
|
||||
#files tbody,
|
||||
#files thead th:nth-child(2) {
|
||||
background: #222;
|
||||
border-radius: 0 .7em 0 0;
|
||||
}
|
||||
#files td {
|
||||
margin: 0;
|
||||
padding: 0 .5em;
|
||||
border-bottom: 1px solid #111;
|
||||
border-left: 1px solid #2c2c2c;
|
||||
}
|
||||
#files td+td+td {
|
||||
max-width: 30em;
|
||||
@@ -185,7 +186,7 @@ a, #files tbody div a:last-child {
|
||||
margin: -.2em;
|
||||
}
|
||||
#files tbody a.play.act {
|
||||
color: #840;
|
||||
color: #720;
|
||||
text-shadow: 0 0 .3em #b80;
|
||||
}
|
||||
#files tbody tr.sel td,
|
||||
@@ -483,20 +484,48 @@ html.light #ggrid a.sel {
|
||||
margin: .5em;
|
||||
}
|
||||
.opview input[type=text] {
|
||||
color: #fff;
|
||||
background: #383838;
|
||||
color: #fff;
|
||||
border: none;
|
||||
box-shadow: 0 0 .3em #222;
|
||||
border-bottom: 1px solid #fc5;
|
||||
border-radius: .2em;
|
||||
padding: .2em .3em;
|
||||
}
|
||||
.opview input.err {
|
||||
background: #a20;
|
||||
border-color: #f00;
|
||||
box-shadow: 0 0 .7em #f00;
|
||||
text-shadow: 1px 1px 0 #500;
|
||||
outline: none;
|
||||
}
|
||||
input[type="checkbox"]+label {
|
||||
color: #f5a;
|
||||
}
|
||||
input[type="checkbox"]:checked+label {
|
||||
color: #fc5;
|
||||
}
|
||||
input.eq_gain {
|
||||
width: 3em;
|
||||
text-align: center;
|
||||
margin: 0 .6em;
|
||||
}
|
||||
#audio_eq table {
|
||||
border-collapse: collapse;
|
||||
}
|
||||
#audio_eq td {
|
||||
text-align: center;
|
||||
}
|
||||
#audio_eq a.eq_step {
|
||||
font-size: 1.5em;
|
||||
display: block;
|
||||
padding: 0;
|
||||
}
|
||||
#au_eq {
|
||||
display: block;
|
||||
margin-top: .5em;
|
||||
padding: 1.3em .3em;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -563,6 +592,7 @@ input[type="checkbox"]:checked+label {
|
||||
}
|
||||
#wrap {
|
||||
margin-top: 2em;
|
||||
min-height: 90vh;
|
||||
}
|
||||
#tree {
|
||||
display: none;
|
||||
@@ -575,6 +605,12 @@ input[type="checkbox"]:checked+label {
|
||||
overscroll-behavior-y: none;
|
||||
scrollbar-color: #eb0 #333;
|
||||
}
|
||||
#treeh {
|
||||
background: #333;
|
||||
position: sticky;
|
||||
z-index: 1;
|
||||
top: 0;
|
||||
}
|
||||
#thx_ff {
|
||||
padding: 5em 0;
|
||||
}
|
||||
@@ -600,6 +636,7 @@ input[type="checkbox"]:checked+label {
|
||||
box-shadow: 0 .1em .2em #222 inset;
|
||||
border-radius: .3em;
|
||||
margin: .2em;
|
||||
white-space: pre;
|
||||
position: relative;
|
||||
top: -.2em;
|
||||
}
|
||||
@@ -667,34 +704,20 @@ input[type="checkbox"]:checked+label {
|
||||
font-size: 2em;
|
||||
white-space: nowrap;
|
||||
}
|
||||
#files th:hover .cfg,
|
||||
#files th.min .cfg {
|
||||
#files th:hover .cfg {
|
||||
display: block;
|
||||
width: 1em;
|
||||
border-radius: .2em;
|
||||
margin: -1.3em auto 0 auto;
|
||||
background: #444;
|
||||
}
|
||||
#files th.min .cfg {
|
||||
margin: -.6em;
|
||||
}
|
||||
#files>thead>tr>th.min span {
|
||||
position: absolute;
|
||||
transform: rotate(270deg);
|
||||
background: linear-gradient(90deg, rgba(68,68,68,0), rgba(68,68,68,0.5) 70%, #444);
|
||||
margin-left: -4.6em;
|
||||
padding: .4em;
|
||||
top: 5.4em;
|
||||
width: 8em;
|
||||
text-align: right;
|
||||
letter-spacing: .04em;
|
||||
#files>thead>tr>th.min,
|
||||
#files td.min {
|
||||
display: none;
|
||||
}
|
||||
#files td:nth-child(2n) {
|
||||
color: #f5a;
|
||||
}
|
||||
#files td.min a {
|
||||
display: none;
|
||||
}
|
||||
#files tr.play td,
|
||||
#files tr.play div a {
|
||||
background: #fc4;
|
||||
@@ -709,18 +732,28 @@ input[type="checkbox"]:checked+label {
|
||||
color: #300;
|
||||
background: #fea;
|
||||
}
|
||||
#op_cfg {
|
||||
.opwide {
|
||||
max-width: none;
|
||||
margin-right: 1.5em;
|
||||
}
|
||||
#op_cfg>div>a {
|
||||
.opwide>div {
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
border-left: .2em solid #444;
|
||||
margin-left: .5em;
|
||||
padding-left: .5em;
|
||||
}
|
||||
.opwide>div.fill {
|
||||
display: block;
|
||||
}
|
||||
.opwide>div>div>a {
|
||||
line-height: 2em;
|
||||
}
|
||||
#op_cfg>div>span {
|
||||
#op_cfg>div>div>span {
|
||||
display: inline-block;
|
||||
padding: .2em .4em;
|
||||
}
|
||||
#op_cfg h3 {
|
||||
.opbox h3 {
|
||||
margin: .8em 0 0 .6em;
|
||||
padding: 0;
|
||||
border-bottom: 1px solid #555;
|
||||
@@ -918,13 +951,14 @@ html.light #files {
|
||||
}
|
||||
html.light #files thead th {
|
||||
background: #eee;
|
||||
border-radius: 0;
|
||||
border-right: 1px solid #ccc;
|
||||
border-bottom: 1px solid #ccc;
|
||||
}
|
||||
html.light #files tr td {
|
||||
border-top: 1px solid #ddd;
|
||||
html.light #files thead th {
|
||||
border-left: 1px solid #f7f7f7;
|
||||
}
|
||||
html.light #files td {
|
||||
border-bottom: 1px solid #f7f7f7;
|
||||
border-color: #ddd #fff #fff #ddd;
|
||||
}
|
||||
html.light #files tbody tr:last-child td {
|
||||
border-bottom: .2em solid #ccc;
|
||||
@@ -932,25 +966,25 @@ html.light #files tbody tr:last-child td {
|
||||
html.light #files td:nth-child(2n) {
|
||||
color: #d38;
|
||||
}
|
||||
html.light #files tr:hover td {
|
||||
background: #fff;
|
||||
html.light #files tr.play td:nth-child(2n) {
|
||||
color: #c16;
|
||||
}
|
||||
html.light #files tbody a.play {
|
||||
color: #c0f;
|
||||
}
|
||||
html.light tr.play td {
|
||||
html.light #files tr.play td {
|
||||
background: #fc5;
|
||||
border-color: #eb1;
|
||||
}
|
||||
html.light #files tr:hover td {
|
||||
background: #fff;
|
||||
}
|
||||
html.light tr.play a {
|
||||
color: #406;
|
||||
}
|
||||
html.light #files th:hover .cfg,
|
||||
html.light #files th.min .cfg {
|
||||
html.light #files th:hover .cfg {
|
||||
background: #ccc;
|
||||
}
|
||||
html.light #files > thead > tr > th.min span {
|
||||
background: linear-gradient(90deg, rgba(204,204,204,0), rgba(204,204,204,0.5) 70%, #ccc);
|
||||
}
|
||||
html.light #blocked {
|
||||
background: #eee;
|
||||
}
|
||||
@@ -960,7 +994,21 @@ html.light #blk_abrt a {
|
||||
box-shadow: 0 .2em .4em #ddd;
|
||||
}
|
||||
html.light #widget a {
|
||||
color: #fc5;
|
||||
color: #06a;
|
||||
}
|
||||
html.light #wtoggle,
|
||||
html.light #widgeti {
|
||||
background: #eee;
|
||||
}
|
||||
html.light #wtoggle {
|
||||
box-shadow: 0 0 .5em #bbb;
|
||||
}
|
||||
html.light #widget.open {
|
||||
border-top: .2em solid #f7f7f7;
|
||||
}
|
||||
html.light #wzip,
|
||||
html.light #wnp {
|
||||
border-color: #ccc;
|
||||
}
|
||||
html.light #files tr.sel:hover td {
|
||||
background: #c37;
|
||||
@@ -977,6 +1025,9 @@ html.light #files tr.sel a.play.act {
|
||||
html.light input[type="checkbox"] + label {
|
||||
color: #333;
|
||||
}
|
||||
html.light .opwide>div {
|
||||
border-color: #ddd;
|
||||
}
|
||||
html.light .opview input[type="text"] {
|
||||
background: #fff;
|
||||
color: #333;
|
||||
@@ -1021,6 +1072,9 @@ html.light #files tr.sel a:hover {
|
||||
color: #000;
|
||||
background: #fff;
|
||||
}
|
||||
html.light #treeh {
|
||||
background: #eee;
|
||||
}
|
||||
html.light #tree {
|
||||
scrollbar-color: #a70 #ddd;
|
||||
}
|
||||
|
@@ -26,6 +26,7 @@
|
||||
<a href="#" data-perm="write" data-dest="mkdir" data-desc="mkdir: create a new directory">📂</a>
|
||||
<a href="#" data-perm="read write" data-dest="new_md" data-desc="new-md: create a new markdown document">📝</a>
|
||||
<a href="#" data-perm="write" data-dest="msg" data-desc="msg: send a message to the server log">📟</a>
|
||||
<a href="#" data-dest="player" data-desc="media player options">🎺</a>
|
||||
<a href="#" data-dest="cfg" data-desc="configuration options">⚙️</a>
|
||||
<div id="opdesc"></div>
|
||||
</div>
|
||||
@@ -39,22 +40,25 @@
|
||||
<div id="srch_q"></div>
|
||||
</div>
|
||||
|
||||
<div id="op_player" class="opview opbox opwide"></div>
|
||||
|
||||
{%- include 'upload.html' %}
|
||||
|
||||
<div id="op_cfg" class="opview opbox">
|
||||
<h3>switches</h3>
|
||||
<div id="op_cfg" class="opview opbox opwide">
|
||||
<div>
|
||||
<a id="tooltips" class="tgl btn" href="#">tooltips</a>
|
||||
<a id="lightmode" class="tgl btn" href="#">lightmode</a>
|
||||
<a id="griden" class="tgl btn" href="#">the grid</a>
|
||||
<a id="thumbs" class="tgl btn" href="#">thumbs</a>
|
||||
<h3>switches</h3>
|
||||
<div>
|
||||
<a id="tooltips" class="tgl btn" href="#">ℹ️ tooltips</a>
|
||||
<a id="lightmode" class="tgl btn" href="#">☀️ lightmode</a>
|
||||
<a id="griden" class="tgl btn" href="#">田 the grid</a>
|
||||
<a id="thumbs" class="tgl btn" href="#">🖼️ thumbs</a>
|
||||
</div>
|
||||
</div>
|
||||
{%- if have_zip %}
|
||||
<h3>folder download</h3>
|
||||
<div id="arc_fmt"></div>
|
||||
<div><h3>folder download</h3><div id="arc_fmt"></div></div>
|
||||
{%- endif %}
|
||||
<h3>key notation</h3>
|
||||
<div id="key_notation"></div>
|
||||
<div><h3>key notation</h3><div id="key_notation"></div></div>
|
||||
<div class="fill"><h3>hidden columns</h3><div id="hcols"></div></div>
|
||||
</div>
|
||||
|
||||
<h1 id="path">
|
||||
@@ -65,10 +69,12 @@
|
||||
</h1>
|
||||
|
||||
<div id="tree">
|
||||
<a href="#" id="detree">🍞...</a>
|
||||
<a href="#" class="btn" step="2" id="twobytwo">+</a>
|
||||
<a href="#" class="btn" step="-2" id="twig">–</a>
|
||||
<a href="#" class="tgl btn" id="dyntree">a</a>
|
||||
<div id="treeh">
|
||||
<a href="#" id="detree">🍞...</a>
|
||||
<a href="#" class="btn" step="2" id="twobytwo">+</a>
|
||||
<a href="#" class="btn" step="-2" id="twig">–</a>
|
||||
<a href="#" class="tgl btn" id="dyntree">a</a>
|
||||
</div>
|
||||
<ul id="treeul"></ul>
|
||||
<div id="thx_ff"> </div>
|
||||
</div>
|
||||
|
@@ -42,6 +42,39 @@ var have_webp = null;
|
||||
})();
|
||||
|
||||
|
||||
var mpl = (function () {
|
||||
ebi('op_player').innerHTML = (
|
||||
'<div><h3>playback mode</h3><div id="pb_mode">' +
|
||||
'<a href="#" class="tgl btn">🔁 loop-folder</a>' +
|
||||
'<a href="#" class="tgl btn">📂 next-folder</a>' +
|
||||
'</div></div>' +
|
||||
|
||||
'<div><h3>audio equalizer</h3><div id="audio_eq"></div></div>');
|
||||
|
||||
var r = {
|
||||
"pb_mode": sread('pb_mode') || 'loop-folder'
|
||||
};
|
||||
|
||||
function draw_pb_mode() {
|
||||
var btns = QSA('#pb_mode>a');
|
||||
for (var a = 0, aa = btns.length; a < aa; a++) {
|
||||
clmod(btns[a], 'on', btns[a].textContent.indexOf(r.pb_mode) != -1);
|
||||
btns[a].onclick = set_pb_mode;
|
||||
}
|
||||
}
|
||||
draw_pb_mode();
|
||||
|
||||
function set_pb_mode(e) {
|
||||
ev(e);
|
||||
r.pb_mode = this.textContent.split(' ').slice(-1)[0];
|
||||
swrite('pb_mode', r.pb_mode);
|
||||
draw_pb_mode();
|
||||
}
|
||||
|
||||
return r;
|
||||
})();
|
||||
|
||||
|
||||
// extract songs + add play column
|
||||
function MPlayer() {
|
||||
this.id = Date.now();
|
||||
@@ -162,8 +195,9 @@ var widget = (function () {
|
||||
m = ck + 'np: ';
|
||||
|
||||
for (var a = 1, aa = th.length; a < aa; a++) {
|
||||
var tk = a == 1 ? '' : th[a].getAttribute('name').split('/').slice(-1)[0];
|
||||
var tv = tr[a].getAttribute('html') || tr[a].textContent;
|
||||
var tv = tr[a].textContent,
|
||||
tk = a == 1 ? '' : th[a].getAttribute('name').split('/').slice(-1)[0];
|
||||
|
||||
m += tk + '(' + cv + tv + ck + ') // ';
|
||||
}
|
||||
|
||||
@@ -407,23 +441,26 @@ function song_skip(n) {
|
||||
if (tid !== null)
|
||||
play(mp.order.indexOf(tid) + n);
|
||||
else
|
||||
play(mp.order[0]);
|
||||
play(mp.order[n == -1 ? mp.order.length - 1 : 0]);
|
||||
}
|
||||
|
||||
|
||||
function playpause(e) {
|
||||
ev(e);
|
||||
if (mp.au) {
|
||||
if (mp.au.paused)
|
||||
mp.au.play();
|
||||
else
|
||||
mp.au.pause();
|
||||
}
|
||||
else
|
||||
play(0);
|
||||
};
|
||||
|
||||
|
||||
// hook up the widget buttons
|
||||
(function () {
|
||||
ebi('bplay').onclick = function (e) {
|
||||
ev(e);
|
||||
if (mp.au) {
|
||||
if (mp.au.paused)
|
||||
mp.au.play();
|
||||
else
|
||||
mp.au.pause();
|
||||
}
|
||||
else
|
||||
play(0);
|
||||
};
|
||||
ebi('bplay').onclick = playpause;
|
||||
ebi('bprev').onclick = function (e) {
|
||||
ev(e);
|
||||
song_skip(-1);
|
||||
@@ -508,6 +545,219 @@ try {
|
||||
catch (ex) { }
|
||||
|
||||
|
||||
var audio_eq = (function () {
|
||||
var r = {
|
||||
"en": false,
|
||||
"bands": [31.25, 62.5, 125, 250, 500, 1000, 2000, 4000, 8000, 16000],
|
||||
"gains": [4, 3, 2, 1, 0, 0, 1, 2, 3, 4],
|
||||
"filters": [],
|
||||
"amp": 0,
|
||||
"last_au": null
|
||||
};
|
||||
|
||||
var cfg = [ // hz, q, g
|
||||
[31.25 * 0.88, 0, 1.4], // shelf
|
||||
[31.25 * 1.04, 0.7, 0.96], // peak
|
||||
[62.5, 0.7, 1],
|
||||
[125, 0.8, 1],
|
||||
[250, 0.9, 1.03],
|
||||
[500, 0.9, 1.1],
|
||||
[1000, 0.9, 1.1],
|
||||
[2000, 0.9, 1.105],
|
||||
[4000, 0.88, 1.05],
|
||||
[8000 * 1.006, 0.73, 1.24],
|
||||
[16000 * 0.89, 0.7, 1.26], // peak
|
||||
[16000 * 1.13, 0.82, 1.09], // peak
|
||||
[16000 * 1.205, 0, 1.9] // shelf
|
||||
];
|
||||
|
||||
try {
|
||||
r.amp = fcfg_get('au_eq_amp', r.amp);
|
||||
var gains = jread('au_eq_gain', r.gains);
|
||||
if (r.gains.length == gains.length)
|
||||
r.gains = gains;
|
||||
}
|
||||
catch (ex) { }
|
||||
|
||||
r.draw = function () {
|
||||
jwrite('au_eq_gain', r.gains);
|
||||
swrite('au_eq_amp', r.amp);
|
||||
|
||||
var txt = QSA('input.eq_gain');
|
||||
for (var a = 0; a < r.bands.length; a++)
|
||||
txt[a].value = r.gains[a];
|
||||
|
||||
QS('input.eq_gain[band="amp"]').value = r.amp;
|
||||
};
|
||||
|
||||
r.apply = function () {
|
||||
r.draw();
|
||||
|
||||
var Ctx = window.AudioContext || window.webkitAudioContext;
|
||||
if (!Ctx)
|
||||
bcfg_set('au_eq', false);
|
||||
|
||||
if (!Ctx || !mp.au)
|
||||
return;
|
||||
|
||||
if (!r.en && !mp.ac)
|
||||
return;
|
||||
|
||||
if (mp.ac) {
|
||||
for (var a = 0; a < r.filters.length; a++)
|
||||
r.filters[a].disconnect();
|
||||
|
||||
mp.acs.disconnect();
|
||||
}
|
||||
|
||||
if (!mp.ac || mp.au != r.last_au) {
|
||||
if (mp.ac)
|
||||
mp.ac.close();
|
||||
|
||||
r.last_au = mp.au;
|
||||
mp.ac = new Ctx();
|
||||
mp.acs = mp.ac.createMediaElementSource(mp.au);
|
||||
}
|
||||
|
||||
r.filters = [];
|
||||
|
||||
if (!r.en) {
|
||||
mp.acs.connect(mp.ac.destination);
|
||||
return;
|
||||
}
|
||||
|
||||
var max = 0;
|
||||
for (var a = 0; a < r.gains.length; a++)
|
||||
if (max < r.gains[a])
|
||||
max = r.gains[a];
|
||||
|
||||
var gains = []
|
||||
for (var a = 0; a < r.gains.length; a++)
|
||||
gains.push(r.gains[a] - max);
|
||||
|
||||
var t = gains[gains.length - 1];
|
||||
gains.push(t);
|
||||
gains.push(t);
|
||||
gains.unshift(gains[0]);
|
||||
|
||||
for (var a = 0; a < cfg.length; a++) {
|
||||
var fi = mp.ac.createBiquadFilter();
|
||||
fi.frequency.value = cfg[a][0];
|
||||
fi.gain.value = cfg[a][2] * gains[a];
|
||||
fi.Q.value = cfg[a][1];
|
||||
fi.type = a == 0 ? 'lowshelf' : a == cfg.length - 1 ? 'highshelf' : 'peaking';
|
||||
r.filters.push(fi);
|
||||
}
|
||||
|
||||
// pregain, keep first in chain
|
||||
fi = mp.ac.createGain();
|
||||
fi.gain.value = r.amp + 0.94; // +.137 dB measured; now -.25 dB and almost bitperfect
|
||||
r.filters.push(fi);
|
||||
|
||||
for (var a = r.filters.length - 1; a >= 0; a--)
|
||||
r.filters[a].connect(a > 0 ? r.filters[a - 1] : mp.ac.destination);
|
||||
|
||||
mp.acs.connect(r.filters[r.filters.length - 1]);
|
||||
}
|
||||
|
||||
function eq_step(e) {
|
||||
ev(e);
|
||||
var band = parseInt(this.getAttribute('band')),
|
||||
step = parseFloat(this.getAttribute('step'));
|
||||
|
||||
if (isNaN(band))
|
||||
r.amp = Math.round((r.amp + step * 0.2) * 100) / 100;
|
||||
else
|
||||
r.gains[band] += step;
|
||||
|
||||
r.apply();
|
||||
}
|
||||
|
||||
function adj_band(that, step) {
|
||||
var err = false;
|
||||
try {
|
||||
var band = parseInt(that.getAttribute('band')),
|
||||
vs = that.value,
|
||||
v = parseFloat(vs);
|
||||
|
||||
if (isNaN(v) || v + '' != vs)
|
||||
throw 42;
|
||||
|
||||
if (isNaN(band))
|
||||
r.amp = Math.round((v + step * 0.2) * 100) / 100;
|
||||
else
|
||||
r.gains[band] = v + step;
|
||||
|
||||
r.apply();
|
||||
}
|
||||
catch (ex) {
|
||||
err = true;
|
||||
}
|
||||
clmod(that, 'err', err);
|
||||
}
|
||||
|
||||
function eq_mod(e) {
|
||||
ev(e);
|
||||
adj_band(this, 0);
|
||||
}
|
||||
|
||||
function eq_keydown(e) {
|
||||
var step = e.key == 'ArrowUp' ? 0.25 : e.key == 'ArrowDown' ? -0.25 : 0;
|
||||
if (step != 0)
|
||||
adj_band(this, step);
|
||||
}
|
||||
|
||||
var html = ['<table><tr><td rowspan="4">',
|
||||
'<a id="au_eq" class="tgl btn" href="#">enable</a></td>'],
|
||||
h2 = [], h3 = [], h4 = [];
|
||||
|
||||
var vs = [];
|
||||
for (var a = 0; a < r.bands.length; a++) {
|
||||
var hz = r.bands[a];
|
||||
if (hz >= 1000)
|
||||
hz = (hz / 1000) + 'k';
|
||||
|
||||
hz = (hz + '').split('.')[0];
|
||||
vs.push([a, hz, r.gains[a]]);
|
||||
}
|
||||
vs.push(["amp", "boost", r.amp]);
|
||||
|
||||
for (var a = 0; a < vs.length; a++) {
|
||||
var b = vs[a][0];
|
||||
html.push('<td><a href="#" class="eq_step" step="0.5" band="' + b + '">+</a></td>');
|
||||
h2.push('<td>' + vs[a][1] + '</td>');
|
||||
h4.push('<td><a href="#" class="eq_step" step="-0.5" band="' + b + '">–</a></td>');
|
||||
h3.push('<td><input type="text" class="eq_gain" band="' + b + '" value="' + vs[a][2] + '" /></td>');
|
||||
}
|
||||
html = html.join('\n') + '</tr><tr>';
|
||||
html += h2.join('\n') + '</tr><tr>';
|
||||
html += h3.join('\n') + '</tr><tr>';
|
||||
html += h4.join('\n') + '</tr><table>';
|
||||
ebi('audio_eq').innerHTML = html;
|
||||
|
||||
var stp = QSA('a.eq_step');
|
||||
for (var a = 0, aa = stp.length; a < aa; a++)
|
||||
stp[a].onclick = eq_step;
|
||||
|
||||
var txt = QSA('input.eq_gain');
|
||||
for (var a = 0; a < txt.length; a++) {
|
||||
txt[a].oninput = eq_mod;
|
||||
txt[a].onkeydown = eq_keydown;
|
||||
}
|
||||
|
||||
r.en = bcfg_get('au_eq', false);
|
||||
ebi('au_eq').onclick = function (e) {
|
||||
ev(e);
|
||||
r.en = !r.en;
|
||||
bcfg_set('au_eq', r.en);
|
||||
r.apply();
|
||||
};
|
||||
|
||||
r.draw();
|
||||
return r;
|
||||
})();
|
||||
|
||||
|
||||
// plays the tid'th audio file on the page
|
||||
function play(tid, seek, call_depth) {
|
||||
if (mp.order.length == 0)
|
||||
@@ -517,11 +767,25 @@ function play(tid, seek, call_depth) {
|
||||
if ((tn + '').indexOf('f-') === 0)
|
||||
tn = mp.order.indexOf(tn);
|
||||
|
||||
while (tn >= mp.order.length)
|
||||
tn -= mp.order.length;
|
||||
if (tn >= mp.order.length) {
|
||||
if (mpl.pb_mode == 'loop-folder') {
|
||||
tn = 0;
|
||||
}
|
||||
else if (mpl.pb_mode == 'next-folder') {
|
||||
treectl.ls_cb = function () { song_skip(1); };
|
||||
return tree_neigh(1);
|
||||
}
|
||||
}
|
||||
|
||||
while (tn < 0)
|
||||
tn += mp.order.length;
|
||||
if (tn < 0) {
|
||||
if (mpl.pb_mode == 'loop-folder') {
|
||||
tn = mp.order.length - 1;
|
||||
}
|
||||
else if (mpl.pb_mode == 'next-folder') {
|
||||
treectl.ls_cb = function () { song_skip(-1); };
|
||||
return tree_neigh(-1);
|
||||
}
|
||||
}
|
||||
|
||||
tid = mp.order[tn];
|
||||
|
||||
@@ -568,6 +832,8 @@ function play(tid, seek, call_depth) {
|
||||
mp.au = mp.au_native;
|
||||
}
|
||||
|
||||
audio_eq.apply();
|
||||
|
||||
mp.au.tid = tid;
|
||||
mp.au.src = url;
|
||||
mp.au.volume = mp.expvol();
|
||||
@@ -989,6 +1255,9 @@ document.onkeydown = function (e) {
|
||||
if (n !== 0)
|
||||
return song_skip(n);
|
||||
|
||||
if (k == 'KeyM')
|
||||
return playpause();
|
||||
|
||||
n = k == 'KeyU' ? -10 : k == 'KeyO' ? 10 : 0;
|
||||
if (n !== 0)
|
||||
return mp.au ? seek_au_sec(mp.au.currentTime + n) : true;
|
||||
@@ -1276,7 +1545,8 @@ document.onkeydown = function (e) {
|
||||
|
||||
var treectl = (function () {
|
||||
var treectl = {
|
||||
"hidden": false
|
||||
"hidden": false,
|
||||
"ls_cb": null
|
||||
},
|
||||
entreed = false,
|
||||
fixedpos = false,
|
||||
@@ -1376,6 +1646,11 @@ var treectl = (function () {
|
||||
onscroll();
|
||||
}
|
||||
|
||||
treectl.goto = function (url, push) {
|
||||
get_tree("", url, true);
|
||||
reqls(url, push);
|
||||
}
|
||||
|
||||
function get_tree(top, dst, rst) {
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.top = top;
|
||||
@@ -1570,6 +1845,12 @@ var treectl = (function () {
|
||||
msel.render();
|
||||
reload_tree();
|
||||
reload_browser();
|
||||
|
||||
var fun = treectl.ls_cb;
|
||||
if (fun) {
|
||||
treectl.ls_cb = null;
|
||||
fun();
|
||||
}
|
||||
}
|
||||
|
||||
function parsetree(res, top) {
|
||||
@@ -1634,9 +1915,7 @@ var treectl = (function () {
|
||||
return;
|
||||
|
||||
var url = new URL(e.state, "https://" + document.location.host);
|
||||
url = url.pathname;
|
||||
get_tree("", url, true);
|
||||
reqls(url);
|
||||
treectl.goto(url.pathname);
|
||||
};
|
||||
|
||||
if (window.history && history.pushState) {
|
||||
@@ -1761,17 +2040,34 @@ var filecols = (function () {
|
||||
var add_btns = function () {
|
||||
var ths = QSA('#files th>span');
|
||||
for (var a = 0, aa = ths.length; a < aa; a++) {
|
||||
var th = ths[a].parentElement,
|
||||
is_hidden = has(hidden, ths[a].textContent);
|
||||
|
||||
th.innerHTML = '<div class="cfg"><a href="#">' +
|
||||
(is_hidden ? '+' : '-') + '</a></div>' + ths[a].outerHTML;
|
||||
|
||||
var th = ths[a].parentElement;
|
||||
th.innerHTML = '<div class="cfg"><a href="#">-</a></div>' + ths[a].outerHTML;
|
||||
th.getElementsByTagName('a')[0].onclick = ev_row_tgl;
|
||||
}
|
||||
};
|
||||
|
||||
function hcols_click(e) {
|
||||
ev(e);
|
||||
var t = e.target;
|
||||
if (t.tagName != 'A')
|
||||
return;
|
||||
|
||||
toggle(t.textContent);
|
||||
}
|
||||
|
||||
var set_style = function () {
|
||||
hidden.sort();
|
||||
|
||||
var html = [],
|
||||
hcols = ebi('hcols');
|
||||
|
||||
for (var a = 0; a < hidden.length; a++) {
|
||||
html.push('<a href="#" class="btn">' + esc(hidden[a]) + '</a>');
|
||||
}
|
||||
hcols.previousSibling.style.display = html.length ? 'block' : 'none';
|
||||
hcols.innerHTML = html.join('\n');
|
||||
hcols.onclick = hcols_click;
|
||||
|
||||
add_btns();
|
||||
|
||||
var ohidden = [],
|
||||
@@ -1796,22 +2092,8 @@ var filecols = (function () {
|
||||
var cls = has(ohidden, a) ? 'min' : '',
|
||||
tds = QSA('#files>tbody>tr>td:nth-child(' + (a + 1) + ')');
|
||||
|
||||
for (var b = 0, bb = tds.length; b < bb; b++) {
|
||||
for (var b = 0, bb = tds.length; b < bb; b++)
|
||||
tds[b].setAttribute('class', cls);
|
||||
if (a < 2)
|
||||
continue;
|
||||
|
||||
if (cls) {
|
||||
if (!tds[b].hasAttribute('html')) {
|
||||
tds[b].setAttribute('html', tds[b].innerHTML);
|
||||
tds[b].innerHTML = '...';
|
||||
}
|
||||
}
|
||||
else if (tds[b].hasAttribute('html')) {
|
||||
tds[b].innerHTML = tds[b].getAttribute('html');
|
||||
tds[b].removeAttribute('html');
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
set_style();
|
||||
@@ -1830,15 +2112,13 @@ var filecols = (function () {
|
||||
try {
|
||||
var ci = find_file_col('dur'),
|
||||
i = ci[0],
|
||||
min = ci[1],
|
||||
rows = ebi('files').tBodies[0].rows;
|
||||
|
||||
if (!min)
|
||||
for (var a = 0, aa = rows.length; a < aa; a++) {
|
||||
var c = rows[a].cells[i];
|
||||
if (c && c.textContent)
|
||||
c.textContent = s2ms(c.textContent);
|
||||
}
|
||||
for (var a = 0, aa = rows.length; a < aa; a++) {
|
||||
var c = rows[a].cells[i];
|
||||
if (c && c.textContent)
|
||||
c.textContent = s2ms(c.textContent);
|
||||
}
|
||||
}
|
||||
catch (ex) { }
|
||||
|
||||
|
61
copyparty/web/dbg-audio.js
Normal file
61
copyparty/web/dbg-audio.js
Normal file
@@ -0,0 +1,61 @@
|
||||
var ofun = audio_eq.apply.bind(audio_eq);
|
||||
audio_eq.apply = function () {
|
||||
var ac1 = mp.ac;
|
||||
ofun();
|
||||
var ac = mp.ac,
|
||||
w = 2048,
|
||||
h = 256;
|
||||
|
||||
if (!audio_eq.filters.length) {
|
||||
audio_eq.ana = null;
|
||||
return;
|
||||
}
|
||||
|
||||
var can = ebi('fft_can');
|
||||
if (!can) {
|
||||
can = mknod('canvas');
|
||||
can.setAttribute('id', 'fft_can');
|
||||
can.style.cssText = 'position:absolute;left:0;bottom:5em;width:' + w + 'px;height:' + h + 'px;z-index:9001';
|
||||
document.body.appendChild(can);
|
||||
can.width = w;
|
||||
can.height = h;
|
||||
}
|
||||
var cc = can.getContext('2d');
|
||||
if (!ac)
|
||||
return;
|
||||
|
||||
var ana = ac.createAnalyser();
|
||||
ana.smoothingTimeConstant = 0;
|
||||
ana.fftSize = 8192;
|
||||
|
||||
audio_eq.filters[0].connect(ana);
|
||||
audio_eq.ana = ana;
|
||||
|
||||
var buf = new Uint8Array(ana.frequencyBinCount),
|
||||
colw = can.width / buf.length;
|
||||
|
||||
cc.fillStyle = '#fc0';
|
||||
function draw() {
|
||||
if (ana == audio_eq.ana)
|
||||
requestAnimationFrame(draw);
|
||||
|
||||
ana.getByteFrequencyData(buf);
|
||||
|
||||
cc.clearRect(0, 0, can.width, can.height);
|
||||
|
||||
/*var x = 0, w = 1;
|
||||
for (var a = 0; a < buf.length; a++) {
|
||||
cc.fillRect(x, h - buf[a], w, h);
|
||||
x += w;
|
||||
}*/
|
||||
var mul = Math.pow(w, 4) / buf.length;
|
||||
for (var x = 0; x < w; x++) {
|
||||
var a = Math.floor(Math.pow(x, 4) / mul),
|
||||
v = buf[a];
|
||||
|
||||
cc.fillRect(x, h - v, 1, v);
|
||||
}
|
||||
}
|
||||
draw();
|
||||
};
|
||||
audio_eq.apply();
|
95
docs/biquad.html
Normal file
95
docs/biquad.html
Normal file
@@ -0,0 +1,95 @@
|
||||
<!DOCTYPE html><html><head></head><body><script>
|
||||
|
||||
setTimeout(location.reload.bind(location), 700);
|
||||
document.documentElement.scrollLeft = 0;
|
||||
|
||||
var can = document.createElement('canvas'),
|
||||
cc = can.getContext('2d'),
|
||||
w = 2048,
|
||||
h = 1024;
|
||||
|
||||
w = 2048;
|
||||
|
||||
can.width = w;
|
||||
can.height = h;
|
||||
document.body.appendChild(can);
|
||||
can.style.cssText = 'width:' + w + 'px;height:' + h + 'px';
|
||||
|
||||
cc.fillStyle = '#000';
|
||||
cc.fillRect(0, 0, w, h);
|
||||
|
||||
var cfg = [ // hz, q, g
|
||||
[31.25 * 0.88, 0, 1.4], // shelf
|
||||
[31.25 * 1.04, 0.7, 0.96], // peak
|
||||
[62.5, 0.7, 1],
|
||||
[125, 0.8, 1],
|
||||
[250, 0.9, 1.03],
|
||||
[500, 0.9, 1.1],
|
||||
[1000, 0.9, 1.1],
|
||||
[2000, 0.9, 1.105],
|
||||
[4000, 0.88, 1.05],
|
||||
[8000 * 1.006, 0.73, 1.24],
|
||||
//[16000 * 1.00, 0.5, 1.75], // peak.v1
|
||||
//[16000 * 1.19, 0, 1.8] // shelf.v1
|
||||
[16000 * 0.89, 0.7, 1.26], // peak
|
||||
[16000 * 1.13, 0.82, 1.09], // peak
|
||||
[16000 * 1.205, 0, 1.9] // shelf
|
||||
];
|
||||
|
||||
var freqs = new Float32Array(22000),
|
||||
sum = new Float32Array(freqs.length),
|
||||
ac = new AudioContext(),
|
||||
step = w / freqs.length,
|
||||
colors = [
|
||||
'rgba(255, 0, 0, 0.7)',
|
||||
'rgba(0, 224, 0, 0.7)',
|
||||
'rgba(0, 64, 255, 0.7)'
|
||||
];
|
||||
|
||||
var order = [];
|
||||
|
||||
for (var a = 0; a < cfg.length; a += 2)
|
||||
order.push(a);
|
||||
|
||||
for (var a = 1; a < cfg.length; a += 2)
|
||||
order.push(a);
|
||||
|
||||
for (var ia = 0; ia < order.length; ia++) {
|
||||
var a = order[ia],
|
||||
fi = ac.createBiquadFilter(),
|
||||
mag = new Float32Array(freqs.length),
|
||||
phase = new Float32Array(freqs.length);
|
||||
|
||||
for (var b = 0; b < freqs.length; b++)
|
||||
freqs[b] = b;
|
||||
|
||||
fi.type = a == 0 ? 'lowshelf' : a == cfg.length - 1 ? 'highshelf' : 'peaking';
|
||||
fi.frequency.value = cfg[a][0];
|
||||
fi.Q.value = cfg[a][1];
|
||||
fi.gain.value = 1;
|
||||
|
||||
fi.getFrequencyResponse(freqs, mag, phase);
|
||||
cc.fillStyle = colors[a % colors.length];
|
||||
for (var b = 0; b < sum.length; b++) {
|
||||
mag[b] -= 1;
|
||||
sum[b] += mag[b] * cfg[a][2];
|
||||
var y = h - (mag[b] * h * 3);
|
||||
cc.fillRect(b * step, y, step, h - y);
|
||||
cc.fillRect(b * step - 1, y - 1, 3, 3);
|
||||
}
|
||||
}
|
||||
|
||||
var min = 999999, max = 0;
|
||||
for (var a = 0; a < sum.length; a++) {
|
||||
min = Math.min(min, sum[a]);
|
||||
max = Math.max(max, sum[a]);
|
||||
}
|
||||
cc.fillStyle = 'rgba(255,255,255,1)';
|
||||
for (var a = 0; a < sum.length; a++) {
|
||||
var v = (sum[a] - min) / (max - min);
|
||||
cc.fillRect(a * step, 0, step, v * h / 2);
|
||||
}
|
||||
|
||||
cc.fillRect(0, 460, w, 1);
|
||||
|
||||
</script></body></html>
|
32
docs/tcp-debug.sh
Normal file
32
docs/tcp-debug.sh
Normal file
@@ -0,0 +1,32 @@
|
||||
(cd ~/dev/copyparty && strace -Tttyyvfs 256 -o strace.strace python3 -um copyparty -i 127.0.0.1 --http-only --stackmon /dev/shm/cpps,10 ) 2>&1 | tee /dev/stderr > ~/log-copyparty-$(date +%Y-%m%d-%H%M%S).txt
|
||||
|
||||
14/Jun/2021:16:34:02 1623688447.212405 death
|
||||
14/Jun/2021:16:35:02 1623688502.420860 back
|
||||
|
||||
tcpdump -nni lo -w /home/ed/lo.pcap
|
||||
|
||||
# 16:35:25.324662 IP 127.0.0.1.48632 > 127.0.0.1.3920: Flags [F.], seq 849, ack 544, win 359, options [nop,nop,TS val 809396796 ecr 809396796], length 0
|
||||
|
||||
tcpdump -nnr /home/ed/lo.pcap | awk '/ > 127.0.0.1.3920: /{sub(/ > .*/,"");sub(/.*\./,"");print}' | sort -n | uniq | while IFS= read -r port; do echo; tcpdump -nnr /home/ed/lo.pcap 2>/dev/null | grep -E "\.$port( > |: F)" | sed -r 's/ > .*, /, /'; done | grep -E '^16:35:0.*length [^0]' -C50
|
||||
|
||||
16:34:02.441732 IP 127.0.0.1.48638, length 0
|
||||
16:34:02.441738 IP 127.0.0.1.3920, length 0
|
||||
16:34:02.441744 IP 127.0.0.1.48638, length 0
|
||||
16:34:02.441756 IP 127.0.0.1.48638, length 791
|
||||
16:34:02.441759 IP 127.0.0.1.3920, length 0
|
||||
16:35:02.445529 IP 127.0.0.1.48638, length 0
|
||||
16:35:02.489194 IP 127.0.0.1.3920, length 0
|
||||
16:35:02.515595 IP 127.0.0.1.3920, length 216
|
||||
16:35:02.515600 IP 127.0.0.1.48638, length 0
|
||||
|
||||
grep 48638 "$(find ~ -maxdepth 1 -name log-copyparty-\*.txt | sort | tail -n 1)"
|
||||
|
||||
1623688502.510380 48638 rh
|
||||
1623688502.511291 48638 Unrecv direct ...
|
||||
1623688502.511827 48638 rh = 791
|
||||
16:35:02.518 127.0.0.1 48638 shut(8): [Errno 107] Socket not connected
|
||||
Exception in thread httpsrv-0.1-48638:
|
||||
|
||||
grep 48638 ~/dev/copyparty/strace.strace
|
||||
14561 16:35:02.506310 <... accept4 resumed> {sa_family=AF_INET, sin_port=htons(48638), sin_addr=inet_addr("127.0.0.1")}, [16], SOCK_CLOEXEC) = 8<TCP:[127.0.0.1:3920->127.0.0.1:48638]> <0.000012>
|
||||
15230 16:35:02.510725 write(1<pipe:[256639555]>, "1623688502.510380 48638 rh\n", 27 <unfinished ...>
|
@@ -167,7 +167,7 @@ find .. -type f \( -name .DS_Store -or -name ._.DS_Store \) -delete
|
||||
find .. -type f -name ._\* | while IFS= read -r f; do cmp <(printf '\x00\x05\x16') <(head -c 3 -- "$f") && rm -f -- "$f"; done
|
||||
|
||||
echo use smol web deps
|
||||
rm -f copyparty/web/deps/*.full.* copyparty/web/Makefile
|
||||
rm -f copyparty/web/deps/*.full.* copyparty/web/dbg-* copyparty/web/Makefile
|
||||
|
||||
# it's fine dw
|
||||
grep -lE '\.full\.(js|css)' copyparty/web/* |
|
||||
|
Reference in New Issue
Block a user