mirror of
https://github.com/9001/copyparty.git
synced 2025-11-05 14:23:17 +00:00
Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
adbb6c449e | ||
|
|
3993605324 | ||
|
|
0ae574ec2c | ||
|
|
c56ded828c | ||
|
|
02c7061945 | ||
|
|
9209e44cd3 | ||
|
|
ebed37394e | ||
|
|
4c7a2a7ec3 | ||
|
|
0a25a88a34 |
@@ -451,6 +451,8 @@ note:
|
|||||||
|
|
||||||
if you add/remove a tag from `mte` you will need to run with `-e2tsr` once to rebuild the database, otherwise only new files will be affected
|
if you add/remove a tag from `mte` you will need to run with `-e2tsr` once to rebuild the database, otherwise only new files will be affected
|
||||||
|
|
||||||
|
but instead of using `-mte`, `-mth` is a better way to hide tags in the browser: these tags will not be displayed by default, but they still get indexed and become searchable, and users can choose to unhide them in the settings pane
|
||||||
|
|
||||||
`-mtm` can be used to add or redefine a metadata mapping, say you have media files with `foo` and `bar` tags and you want them to display as `qux` in the browser (preferring `foo` if both are present), then do `-mtm qux=foo,bar` and now you can `-mte artist,title,qux`
|
`-mtm` can be used to add or redefine a metadata mapping, say you have media files with `foo` and `bar` tags and you want them to display as `qux` in the browser (preferring `foo` if both are present), then do `-mtm qux=foo,bar` and now you can `-mte artist,title,qux`
|
||||||
|
|
||||||
tags that start with a `.` such as `.bpm` and `.dur`(ation) indicate numeric value
|
tags that start with a `.` such as `.bpm` and `.dur`(ation) indicate numeric value
|
||||||
|
|||||||
@@ -341,7 +341,9 @@ def run_argparse(argv, formatter):
|
|||||||
ap2.add_argument("--no-mtag-ff", action="store_true", help="never use FFprobe as tag reader")
|
ap2.add_argument("--no-mtag-ff", action="store_true", help="never use FFprobe as tag reader")
|
||||||
ap2.add_argument("-mtm", metavar="M=t,t,t", type=u, action="append", help="add/replace metadata mapping")
|
ap2.add_argument("-mtm", metavar="M=t,t,t", type=u, action="append", help="add/replace metadata mapping")
|
||||||
ap2.add_argument("-mte", metavar="M,M,M", type=u, help="tags to index/display (comma-sep.)",
|
ap2.add_argument("-mte", metavar="M,M,M", type=u, help="tags to index/display (comma-sep.)",
|
||||||
default="circle,album,.tn,artist,title,.bpm,key,.dur,.q,.vq,.aq,ac,vc,res,.fps")
|
default="circle,album,.tn,artist,title,.bpm,key,.dur,.q,.vq,.aq,vc,ac,res,.fps")
|
||||||
|
ap2.add_argument("-mth", metavar="M,M,M", type=u, help="tags to hide by default (comma-sep.)",
|
||||||
|
default=".vq,.aq,vc,ac,res,.fps")
|
||||||
ap2.add_argument("-mtp", metavar="M=[f,]bin", type=u, action="append", help="read tag M using bin")
|
ap2.add_argument("-mtp", metavar="M=[f,]bin", type=u, action="append", help="read tag M using bin")
|
||||||
|
|
||||||
ap2 = ap.add_argument_group('appearance options')
|
ap2 = ap.add_argument_group('appearance options')
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
# coding: utf-8
|
# coding: utf-8
|
||||||
|
|
||||||
VERSION = (0, 12, 7)
|
VERSION = (0, 12, 10)
|
||||||
CODENAME = "fil\033[33med"
|
CODENAME = "fil\033[33med"
|
||||||
BUILD_DT = (2021, 7, 31)
|
BUILD_DT = (2021, 8, 2)
|
||||||
|
|
||||||
S_VERSION = ".".join(map(str, VERSION))
|
S_VERSION = ".".join(map(str, VERSION))
|
||||||
S_BUILD_DT = "{0:04d}-{1:02d}-{2:02d}".format(*BUILD_DT)
|
S_BUILD_DT = "{0:04d}-{1:02d}-{2:02d}".format(*BUILD_DT)
|
||||||
|
|||||||
@@ -624,9 +624,11 @@ class AuthSrv(object):
|
|||||||
if k1 in vol.flags:
|
if k1 in vol.flags:
|
||||||
vol.flags[k2] = True
|
vol.flags[k2] = True
|
||||||
|
|
||||||
# default tag-list if unset
|
# default tag cfgs if unset
|
||||||
if "mte" not in vol.flags:
|
if "mte" not in vol.flags:
|
||||||
vol.flags["mte"] = self.args.mte
|
vol.flags["mte"] = self.args.mte
|
||||||
|
if "mth" not in vol.flags:
|
||||||
|
vol.flags["mth"] = self.args.mth
|
||||||
|
|
||||||
# append parsers from argv to volume-flags
|
# append parsers from argv to volume-flags
|
||||||
self._read_volflag(vol.flags, "mtp", self.args.mtp, True)
|
self._read_volflag(vol.flags, "mtp", self.args.mtp, True)
|
||||||
|
|||||||
@@ -1755,7 +1755,7 @@ class HttpCli(object):
|
|||||||
"acct": self.uname,
|
"acct": self.uname,
|
||||||
"perms": json.dumps(perms),
|
"perms": json.dumps(perms),
|
||||||
"taglist": [],
|
"taglist": [],
|
||||||
"tag_order": [],
|
"def_hcols": [],
|
||||||
"have_up2k_idx": ("e2d" in vn.flags),
|
"have_up2k_idx": ("e2d" in vn.flags),
|
||||||
"have_tags_idx": ("e2t" in vn.flags),
|
"have_tags_idx": ("e2t" in vn.flags),
|
||||||
"have_mv": (not self.args.no_mv),
|
"have_mv": (not self.args.no_mv),
|
||||||
@@ -1952,8 +1952,8 @@ class HttpCli(object):
|
|||||||
j2a["logues"] = logues
|
j2a["logues"] = logues
|
||||||
j2a["taglist"] = taglist
|
j2a["taglist"] = taglist
|
||||||
|
|
||||||
if "mte" in vn.flags:
|
if "mth" in vn.flags:
|
||||||
j2a["tag_order"] = json.dumps(vn.flags["mte"].split(","))
|
j2a["def_hcols"] = vn.flags["mth"].split(",")
|
||||||
|
|
||||||
if self.args.css_browser:
|
if self.args.css_browser:
|
||||||
j2a["css"] = self.args.css_browser
|
j2a["css"] = self.args.css_browser
|
||||||
|
|||||||
@@ -433,6 +433,14 @@ class MTag(object):
|
|||||||
]:
|
]:
|
||||||
try:
|
try:
|
||||||
v = getattr(md.info, attr)
|
v = getattr(md.info, attr)
|
||||||
|
except:
|
||||||
|
if k != "ac":
|
||||||
|
continue
|
||||||
|
|
||||||
|
try:
|
||||||
|
v = str(md.info).split(".")[1]
|
||||||
|
if v.startswith("ogg"):
|
||||||
|
v = v[3:]
|
||||||
except:
|
except:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
|||||||
@@ -1068,6 +1068,46 @@ html.light #ggrid a:hover {
|
|||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
#rui {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: calc(100% - 2em);
|
||||||
|
height: auto;
|
||||||
|
overflow: auto;
|
||||||
|
max-height: calc(100% - 2em);
|
||||||
|
border-bottom: .5em solid #999;
|
||||||
|
background: #333;
|
||||||
|
padding: 1em;
|
||||||
|
z-index: 765;
|
||||||
|
}
|
||||||
|
html.light #rui {
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
#rui div+div {
|
||||||
|
margin-top: 1em;
|
||||||
|
}
|
||||||
|
#rui table {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
#rui td {
|
||||||
|
padding: .2em .5em;
|
||||||
|
}
|
||||||
|
#rui td+td,
|
||||||
|
#rui td input {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
#rui input[readonly] {
|
||||||
|
color: #fff;
|
||||||
|
background: #444;
|
||||||
|
border: 1px solid #777;
|
||||||
|
padding: .2em .25em;
|
||||||
|
}
|
||||||
|
#rui h1 {
|
||||||
|
margin: 0 0 .3em 0;
|
||||||
|
padding: 0;
|
||||||
|
font-size: 1.5em;
|
||||||
|
}
|
||||||
#pvol,
|
#pvol,
|
||||||
#barbuf,
|
#barbuf,
|
||||||
#barpos,
|
#barpos,
|
||||||
|
|||||||
@@ -125,7 +125,7 @@
|
|||||||
<script>
|
<script>
|
||||||
var acct = "{{ acct }}",
|
var acct = "{{ acct }}",
|
||||||
perms = {{ perms }},
|
perms = {{ perms }},
|
||||||
tag_order_cfg = {{ tag_order }},
|
def_hcols = {{ def_hcols|tojson }},
|
||||||
have_up2k_idx = {{ have_up2k_idx|tojson }},
|
have_up2k_idx = {{ have_up2k_idx|tojson }},
|
||||||
have_tags_idx = {{ have_tags_idx|tojson }},
|
have_tags_idx = {{ have_tags_idx|tojson }},
|
||||||
have_mv = {{ have_mv|tojson }},
|
have_mv = {{ have_mv|tojson }},
|
||||||
|
|||||||
@@ -522,15 +522,14 @@ var mp = new MPlayer();
|
|||||||
makeSortable(ebi('files'), mp.read_order.bind(mp));
|
makeSortable(ebi('files'), mp.read_order.bind(mp));
|
||||||
|
|
||||||
|
|
||||||
function get_np() {
|
function ft2dict(tr) {
|
||||||
var th = ebi('files').tHead.rows[0].cells,
|
var th = ebi('files').tHead.rows[0].cells,
|
||||||
tr = QS('#files tr.play').cells,
|
|
||||||
rv = [],
|
rv = [],
|
||||||
ra = [],
|
ra = [],
|
||||||
rt = {};
|
rt = {};
|
||||||
|
|
||||||
for (var a = 1, aa = th.length; a < aa; a++) {
|
for (var a = 1, aa = th.length; a < aa; a++) {
|
||||||
var tv = tr[a].textContent,
|
var tv = tr.cells[a].textContent,
|
||||||
tk = a == 1 ? 'file' : th[a].getAttribute('name').split('/').slice(-1)[0],
|
tk = a == 1 ? 'file' : th[a].getAttribute('name').split('/').slice(-1)[0],
|
||||||
vis = th[a].className.indexOf('min') === -1;
|
vis = th[a].className.indexOf('min') === -1;
|
||||||
|
|
||||||
@@ -541,6 +540,12 @@ function get_np() {
|
|||||||
rt[tk] = tv;
|
rt[tk] = tv;
|
||||||
}
|
}
|
||||||
return [rt, rv, ra];
|
return [rt, rv, ra];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function get_np() {
|
||||||
|
var tr = QS('#files tr.play');
|
||||||
|
return ft2dict(tr);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -1499,11 +1504,68 @@ var fileman = (function () {
|
|||||||
base = vsp[0],
|
base = vsp[0],
|
||||||
ofn = uricom_dec(vsp[1])[0];
|
ofn = uricom_dec(vsp[1])[0];
|
||||||
|
|
||||||
var fn = prompt('new filename:', ofn);
|
var rui = ebi('rui');
|
||||||
if (!fn || fn == ofn)
|
if (!rui) {
|
||||||
return toast.warn(1, 'rename aborted');
|
rui = mknod('div');
|
||||||
|
rui.setAttribute('id', 'rui');
|
||||||
|
document.body.appendChild(rui);
|
||||||
|
}
|
||||||
|
var html = [
|
||||||
|
'<h1>rename file</h1>',
|
||||||
|
'<div><table>',
|
||||||
|
'<tr><td>old:</td><td><input type="text" id="rn_old" readonly /></td></tr>',
|
||||||
|
'<tr><td>new:</td><td><input type="text" id="rn_new" /></td></tr>',
|
||||||
|
'</table></div>',
|
||||||
|
'<div>',
|
||||||
|
'<button id="rn_dec">url-decode</button>',
|
||||||
|
'|',
|
||||||
|
'<button id="rn_reset">↺ reset</button>',
|
||||||
|
'<button id="rn_cancel">❌ cancel</button>',
|
||||||
|
'<button id="rn_apply">✅ apply rename</button>',
|
||||||
|
'</div>',
|
||||||
|
'<div><table>'
|
||||||
|
];
|
||||||
|
|
||||||
var dst = base + uricom_enc(fn, false);
|
var vars = ft2dict(ebi(sel[0].id).closest('tr')),
|
||||||
|
keys = vars[1].concat(vars[2]);
|
||||||
|
|
||||||
|
vars = vars[0];
|
||||||
|
for (var a = 0; a < keys.length; a++)
|
||||||
|
html.push('<tr><td>' + esc(keys[a]) + '</td><td><input type="text" readonly value="' + esc(vars[keys[a]]) + '" /></td></tr>');
|
||||||
|
|
||||||
|
html.push('</table></div>');
|
||||||
|
rui.innerHTML = html.join('\n');
|
||||||
|
var iold = ebi('rn_old'),
|
||||||
|
inew = ebi('rn_new');
|
||||||
|
|
||||||
|
function rn_reset() {
|
||||||
|
inew.value = iold.value;
|
||||||
|
inew.focus();
|
||||||
|
inew.setSelectionRange(0, inew.value.lastIndexOf('.'), "forward");
|
||||||
|
}
|
||||||
|
function rn_cancel() {
|
||||||
|
rui.parentNode.removeChild(rui);
|
||||||
|
}
|
||||||
|
|
||||||
|
inew.onkeydown = function (e) {
|
||||||
|
if (e.key == 'Escape')
|
||||||
|
return rn_cancel();
|
||||||
|
|
||||||
|
if (e.key == 'Enter')
|
||||||
|
return rn_apply();
|
||||||
|
};
|
||||||
|
ebi('rn_cancel').onclick = rn_cancel;
|
||||||
|
ebi('rn_reset').onclick = rn_reset;
|
||||||
|
ebi('rn_apply').onclick = rn_apply;
|
||||||
|
ebi('rn_dec').onclick = function () {
|
||||||
|
inew.value = uricom_dec(inew.value)[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
iold.value = ofn;
|
||||||
|
rn_reset();
|
||||||
|
|
||||||
|
function rn_apply() {
|
||||||
|
var dst = base + uricom_enc(inew.value, false);
|
||||||
|
|
||||||
function rename_cb() {
|
function rename_cb() {
|
||||||
if (this.readyState != XMLHttpRequest.DONE)
|
if (this.readyState != XMLHttpRequest.DONE)
|
||||||
@@ -1516,12 +1578,14 @@ var fileman = (function () {
|
|||||||
}
|
}
|
||||||
toast.ok(2, 'rename OK');
|
toast.ok(2, 'rename OK');
|
||||||
treectl.goto(get_evpath());
|
treectl.goto(get_evpath());
|
||||||
|
rn_cancel();
|
||||||
}
|
}
|
||||||
var xhr = new XMLHttpRequest();
|
var xhr = new XMLHttpRequest();
|
||||||
xhr.open('GET', src + '?move=' + dst, true);
|
xhr.open('GET', src + '?move=' + dst, true);
|
||||||
xhr.onreadystatechange = rename_cb;
|
xhr.onreadystatechange = rename_cb;
|
||||||
xhr.send();
|
xhr.send();
|
||||||
};
|
};
|
||||||
|
};
|
||||||
|
|
||||||
r.delete = function (e) {
|
r.delete = function (e) {
|
||||||
ev(e);
|
ev(e);
|
||||||
@@ -1627,12 +1691,12 @@ var fileman = (function () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (exists.length)
|
if (exists.length)
|
||||||
alert('these ' + exists.length + ' items cannot be pasted here (names already exist):\n\n' + exists.join('\n'));
|
alert('these ' + exists.length + ' items cannot be pasted here (names already exist):\n\n' + uricom_adec(exists).join('\n'));
|
||||||
|
|
||||||
if (!req.length)
|
if (!req.length)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!confirm('paste these ' + req.length + ' items here?\n\n' + req.join('\n')))
|
if (!confirm('paste these ' + req.length + ' items here?\n\n' + uricom_adec(req).join('\n')))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
function paster() {
|
function paster() {
|
||||||
@@ -1645,7 +1709,7 @@ var fileman = (function () {
|
|||||||
r.tx(srcdir);
|
r.tx(srcdir);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
toast.inf(0, 'pasting ' + (req.length + 1) + ' items\n\n' + vp);
|
toast.inf(0, 'pasting ' + (req.length + 1) + ' items\n\n' + uricom_dec(vp)[0]);
|
||||||
|
|
||||||
var dst = get_evpath() + vp.split('/').slice(-1)[0];
|
var dst = get_evpath() + vp.split('/').slice(-1)[0];
|
||||||
|
|
||||||
@@ -2976,6 +3040,21 @@ var filecols = (function () {
|
|||||||
"hz": "sample rate"
|
"hz": "sample rate"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (JSON.stringify(def_hcols) != sread('hfilecols')) {
|
||||||
|
console.log("applying default hidden-cols");
|
||||||
|
jwrite('hfilecols', def_hcols);
|
||||||
|
for (var a = 0; a < def_hcols.length; a++) {
|
||||||
|
var t = def_hcols[a];
|
||||||
|
t = t.slice(0, 1).toUpperCase() + t.slice(1);
|
||||||
|
if (t.startsWith("."))
|
||||||
|
t = t.slice(1);
|
||||||
|
|
||||||
|
if (hidden.indexOf(t) == -1)
|
||||||
|
hidden.push(t);
|
||||||
|
}
|
||||||
|
jwrite("filecols", hidden);
|
||||||
|
}
|
||||||
|
|
||||||
var add_btns = function () {
|
var add_btns = function () {
|
||||||
var ths = QSA('#files th>span');
|
var ths = QSA('#files th>span');
|
||||||
for (var a = 0, aa = ths.length; a < aa; a++) {
|
for (var a = 0, aa = ths.length; a < aa; a++) {
|
||||||
|
|||||||
@@ -398,6 +398,15 @@ function uricom_dec(txt) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function uricom_adec(arr) {
|
||||||
|
var ret = [];
|
||||||
|
for (var a = 0; a < arr.length; a++)
|
||||||
|
ret.push(uricom_dec(arr[a])[0]);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
function get_evpath() {
|
function get_evpath() {
|
||||||
var ret = document.location.pathname;
|
var ret = document.location.pathname;
|
||||||
|
|
||||||
|
|||||||
@@ -79,6 +79,10 @@ command -v gdate && date() { gdate "$@"; }; while true; do t=$(date +%s.%N); (ti
|
|||||||
# get all up2k search result URLs
|
# get all up2k search result URLs
|
||||||
var t=[]; var b=document.location.href.split('#')[0].slice(0, -1); document.querySelectorAll('#u2tab .prog a').forEach((x) => {t.push(b+encodeURI(x.getAttribute("href")))}); console.log(t.join("\n"));
|
var t=[]; var b=document.location.href.split('#')[0].slice(0, -1); document.querySelectorAll('#u2tab .prog a').forEach((x) => {t.push(b+encodeURI(x.getAttribute("href")))}); console.log(t.join("\n"));
|
||||||
|
|
||||||
|
# rename all selected songs to <leading-track-number> + <Title> + <extension>
|
||||||
|
var sel=msel.getsel(), ci=find_file_col('Title')[0], re=[]; for (var a=0; a<sel.length; a++) { var url=sel[a].vp, tag=ebi(sel[a].id).closest('tr').querySelectorAll('td')[ci].textContent, name=uricom_dec(vsplit(url)[1])[0], m=/^([0-9]+[\. -]+)?.*(\.[^\.]+$)/.exec(name), name2=(m[1]||'')+tag+m[2], url2=vsplit(url)[0]+uricom_enc(name2,false); if (url!=url2) re.push([url, url2]); }
|
||||||
|
console.log(JSON.stringify(re, null, ' '));
|
||||||
|
function f() { if (!re.length) return treectl.goto(get_evpath()); var [u1,u2] = re.shift(); fetch(u1+'?move='+u2).then((rsp) => {if (rsp.ok) f(); }); }; f();
|
||||||
|
|
||||||
##
|
##
|
||||||
## bash oneliners
|
## bash oneliners
|
||||||
|
|||||||
@@ -268,7 +268,7 @@ zdir="$tmpdir/cpp-mksfx"
|
|||||||
mkdir -p "$zdir"
|
mkdir -p "$zdir"
|
||||||
echo a > "$zdir/$stamp"
|
echo a > "$zdir/$stamp"
|
||||||
nf=$(ls -1 "$zdir"/arc.* | wc -l)
|
nf=$(ls -1 "$zdir"/arc.* | wc -l)
|
||||||
[ $nf -ge 10 ] && [ ! $repack ] && use_zdir=1 || use_zdir=
|
[ $nf -ge 2 ] && [ ! $repack ] && use_zdir=1 || use_zdir=
|
||||||
|
|
||||||
[ $use_zdir ] || {
|
[ $use_zdir ] || {
|
||||||
echo "$nf alts += 1"
|
echo "$nf alts += 1"
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ class Cfg(Namespace):
|
|||||||
nih=True,
|
nih=True,
|
||||||
mtp=[],
|
mtp=[],
|
||||||
mte="a",
|
mte="a",
|
||||||
|
mth="",
|
||||||
hist=None,
|
hist=None,
|
||||||
no_hash=False,
|
no_hash=False,
|
||||||
css_browser=None,
|
css_browser=None,
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ class Cfg(Namespace):
|
|||||||
ex2 = {
|
ex2 = {
|
||||||
"mtp": [],
|
"mtp": [],
|
||||||
"mte": "a",
|
"mte": "a",
|
||||||
|
"mth": "",
|
||||||
"hist": None,
|
"hist": None,
|
||||||
"no_hash": False,
|
"no_hash": False,
|
||||||
"css_browser": None,
|
"css_browser": None,
|
||||||
|
|||||||
Reference in New Issue
Block a user