mirror of
				https://github.com/9001/copyparty.git
				synced 2025-10-31 03:53:31 +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 | ||||
|  | ||||
| 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` | ||||
|  | ||||
| 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("-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.)", | ||||
|         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 = ap.add_argument_group('appearance options') | ||||
|   | ||||
| @@ -1,8 +1,8 @@ | ||||
| # coding: utf-8 | ||||
|  | ||||
| VERSION = (0, 12, 7) | ||||
| VERSION = (0, 12, 10) | ||||
| CODENAME = "fil\033[33med" | ||||
| BUILD_DT = (2021, 7, 31) | ||||
| BUILD_DT = (2021, 8, 2) | ||||
|  | ||||
| S_VERSION = ".".join(map(str, VERSION)) | ||||
| S_BUILD_DT = "{0:04d}-{1:02d}-{2:02d}".format(*BUILD_DT) | ||||
|   | ||||
| @@ -624,9 +624,11 @@ class AuthSrv(object): | ||||
|                 if k1 in vol.flags: | ||||
|                     vol.flags[k2] = True | ||||
|  | ||||
|             # default tag-list if unset | ||||
|             # default tag cfgs if unset | ||||
|             if "mte" not in vol.flags: | ||||
|                 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 | ||||
|             self._read_volflag(vol.flags, "mtp", self.args.mtp, True) | ||||
|   | ||||
| @@ -1755,7 +1755,7 @@ class HttpCli(object): | ||||
|             "acct": self.uname, | ||||
|             "perms": json.dumps(perms), | ||||
|             "taglist": [], | ||||
|             "tag_order": [], | ||||
|             "def_hcols": [], | ||||
|             "have_up2k_idx": ("e2d" in vn.flags), | ||||
|             "have_tags_idx": ("e2t" in vn.flags), | ||||
|             "have_mv": (not self.args.no_mv), | ||||
| @@ -1952,8 +1952,8 @@ class HttpCli(object): | ||||
|         j2a["logues"] = logues | ||||
|         j2a["taglist"] = taglist | ||||
|  | ||||
|         if "mte" in vn.flags: | ||||
|             j2a["tag_order"] = json.dumps(vn.flags["mte"].split(",")) | ||||
|         if "mth" in vn.flags: | ||||
|             j2a["def_hcols"] = vn.flags["mth"].split(",") | ||||
|  | ||||
|         if self.args.css_browser: | ||||
|             j2a["css"] = self.args.css_browser | ||||
|   | ||||
| @@ -434,7 +434,15 @@ class MTag(object): | ||||
|             try: | ||||
|                 v = getattr(md.info, attr) | ||||
|             except: | ||||
|                 continue | ||||
|                 if k != "ac": | ||||
|                     continue | ||||
|  | ||||
|                 try: | ||||
|                     v = str(md.info).split(".")[1] | ||||
|                     if v.startswith("ogg"): | ||||
|                         v = v[3:] | ||||
|                 except: | ||||
|                     continue | ||||
|  | ||||
|             if not v: | ||||
|                 continue | ||||
|   | ||||
| @@ -1068,6 +1068,46 @@ html.light #ggrid a:hover { | ||||
| 	margin: 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, | ||||
| #barbuf, | ||||
| #barpos, | ||||
|   | ||||
| @@ -125,7 +125,7 @@ | ||||
| 	<script> | ||||
| 		var acct = "{{ acct }}", | ||||
| 			perms = {{ perms }}, | ||||
| 			tag_order_cfg = {{ tag_order }}, | ||||
| 			def_hcols = {{ def_hcols|tojson }}, | ||||
| 			have_up2k_idx = {{ have_up2k_idx|tojson }}, | ||||
| 			have_tags_idx = {{ have_tags_idx|tojson }}, | ||||
| 			have_mv = {{ have_mv|tojson }}, | ||||
|   | ||||
| @@ -522,15 +522,14 @@ var mp = new MPlayer(); | ||||
| makeSortable(ebi('files'), mp.read_order.bind(mp)); | ||||
|  | ||||
|  | ||||
| function get_np() { | ||||
| function ft2dict(tr) { | ||||
| 	var th = ebi('files').tHead.rows[0].cells, | ||||
| 		tr = QS('#files tr.play').cells, | ||||
| 		rv = [], | ||||
| 		ra = [], | ||||
| 		rt = {}; | ||||
|  | ||||
| 	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], | ||||
| 			vis = th[a].className.indexOf('min') === -1; | ||||
|  | ||||
| @@ -541,6 +540,12 @@ function get_np() { | ||||
| 		rt[tk] = tv; | ||||
| 	} | ||||
| 	return [rt, rv, ra]; | ||||
| } | ||||
|  | ||||
|  | ||||
| function get_np() { | ||||
| 	var tr = QS('#files tr.play'); | ||||
| 	return ft2dict(tr); | ||||
| }; | ||||
|  | ||||
|  | ||||
| @@ -1499,28 +1504,87 @@ var fileman = (function () { | ||||
| 			base = vsp[0], | ||||
| 			ofn = uricom_dec(vsp[1])[0]; | ||||
|  | ||||
| 		var fn = prompt('new filename:', ofn); | ||||
| 		if (!fn || fn == ofn) | ||||
| 			return toast.warn(1, 'rename aborted'); | ||||
|  | ||||
| 		var dst = base + uricom_enc(fn, false); | ||||
|  | ||||
| 		function rename_cb() { | ||||
| 			if (this.readyState != XMLHttpRequest.DONE) | ||||
| 				return; | ||||
|  | ||||
| 			if (this.status !== 200) { | ||||
| 				var msg = this.responseText; | ||||
| 				toast.err(9, 'rename failed:\n' + msg); | ||||
| 				return; | ||||
| 			} | ||||
| 			toast.ok(2, 'rename OK'); | ||||
| 			treectl.goto(get_evpath()); | ||||
| 		var rui = ebi('rui'); | ||||
| 		if (!rui) { | ||||
| 			rui = mknod('div'); | ||||
| 			rui.setAttribute('id', 'rui'); | ||||
| 			document.body.appendChild(rui); | ||||
| 		} | ||||
| 		var xhr = new XMLHttpRequest(); | ||||
| 		xhr.open('GET', src + '?move=' + dst, true); | ||||
| 		xhr.onreadystatechange = rename_cb; | ||||
| 		xhr.send(); | ||||
| 		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 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() { | ||||
| 				if (this.readyState != XMLHttpRequest.DONE) | ||||
| 					return; | ||||
|  | ||||
| 				if (this.status !== 200) { | ||||
| 					var msg = this.responseText; | ||||
| 					toast.err(9, 'rename failed:\n' + msg); | ||||
| 					return; | ||||
| 				} | ||||
| 				toast.ok(2, 'rename OK'); | ||||
| 				treectl.goto(get_evpath()); | ||||
| 				rn_cancel(); | ||||
| 			} | ||||
| 			var xhr = new XMLHttpRequest(); | ||||
| 			xhr.open('GET', src + '?move=' + dst, true); | ||||
| 			xhr.onreadystatechange = rename_cb; | ||||
| 			xhr.send(); | ||||
| 		}; | ||||
| 	}; | ||||
|  | ||||
| 	r.delete = function (e) { | ||||
| @@ -1627,12 +1691,12 @@ var fileman = (function () { | ||||
| 		} | ||||
|  | ||||
| 		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) | ||||
| 			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; | ||||
|  | ||||
| 		function paster() { | ||||
| @@ -1645,7 +1709,7 @@ var fileman = (function () { | ||||
| 				r.tx(srcdir); | ||||
| 				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]; | ||||
|  | ||||
| @@ -2976,6 +3040,21 @@ var filecols = (function () { | ||||
| 			"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 ths = QSA('#files th>span'); | ||||
| 		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() { | ||||
|     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 | ||||
| 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 | ||||
|   | ||||
| @@ -268,7 +268,7 @@ zdir="$tmpdir/cpp-mksfx" | ||||
| mkdir -p "$zdir" | ||||
| echo a > "$zdir/$stamp" | ||||
| 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 ] || { | ||||
| 	echo "$nf alts += 1" | ||||
|   | ||||
| @@ -43,6 +43,7 @@ class Cfg(Namespace): | ||||
|             nih=True, | ||||
|             mtp=[], | ||||
|             mte="a", | ||||
|             mth="", | ||||
|             hist=None, | ||||
|             no_hash=False, | ||||
|             css_browser=None, | ||||
|   | ||||
| @@ -21,6 +21,7 @@ class Cfg(Namespace): | ||||
|         ex2 = { | ||||
|             "mtp": [], | ||||
|             "mte": "a", | ||||
|             "mth": "", | ||||
|             "hist": None, | ||||
|             "no_hash": False, | ||||
|             "css_browser": None, | ||||
|   | ||||
		Reference in New Issue
	
	Block a user