Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
43a23bf733 | ||
|
|
92bb00c6d2 | ||
|
|
b0b97a2648 | ||
|
|
2c452fe323 | ||
|
|
ad73d0c77d |
12
README.md
12
README.md
@@ -59,7 +59,7 @@ you may also want these, especially on servers:
|
||||
* server indexing
|
||||
* ☑ locate files by contents
|
||||
* ☑ search by name/path/date/size
|
||||
* ✖ search by ID3-tags etc.
|
||||
* ☑ search by ID3-tags etc.
|
||||
* markdown
|
||||
* ☑ viewer
|
||||
* ☑ editor (sure why not)
|
||||
@@ -82,6 +82,8 @@ path/name queries are space-separated, AND'ed together, and words are negated wi
|
||||
* path: `shibayan -bossa` finds all files where one of the folders contain `shibayan` but filters out any results where `bossa` exists somewhere in the path
|
||||
* name: `demetori styx` gives you [good stuff](https://www.youtube.com/watch?v=zGh0g14ZJ8I&list=PL3A147BD151EE5218&index=9)
|
||||
|
||||
add `-e2ts` to also scan/index tags from music files:
|
||||
|
||||
|
||||
## search configuration
|
||||
|
||||
@@ -144,9 +146,13 @@ copyparty returns a truncated sha512sum of your PUT/POST as base64; you can gene
|
||||
|
||||
# dependencies
|
||||
|
||||
* `jinja2`
|
||||
* `jinja2` (is built into the SFX)
|
||||
|
||||
optional, will eventually enable thumbnails:
|
||||
**optional,** enables music tags:
|
||||
* either `mutagen` (fast, pure-python, skips a few tags, makes copyparty GPL? idk)
|
||||
* or `FFprobe` (20x slower, more accurate, possibly dangerous depending on your distro and users)
|
||||
|
||||
**optional,** will eventually enable thumbnails:
|
||||
* `Pillow` (requires py2.7 or py3.5+)
|
||||
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# coding: utf-8
|
||||
|
||||
VERSION = (0, 9, 0)
|
||||
VERSION = (0, 9, 1)
|
||||
CODENAME = "the strongest music server"
|
||||
BUILD_DT = (2021, 3, 2)
|
||||
BUILD_DT = (2021, 3, 3)
|
||||
|
||||
S_VERSION = ".".join(map(str, VERSION))
|
||||
S_BUILD_DT = "{0:04d}-{1:02d}-{2:02d}".format(*BUILD_DT)
|
||||
|
||||
@@ -428,6 +428,7 @@ class HttpCli(object):
|
||||
body["ptop"] = vfs.realpath
|
||||
body["prel"] = rem
|
||||
body["addr"] = self.ip
|
||||
body["vcfg"] = vfs.flags
|
||||
|
||||
x = self.conn.hsrv.broker.put(True, "up2k.handle_json", body)
|
||||
response = x.get()
|
||||
@@ -1271,7 +1272,8 @@ class HttpCli(object):
|
||||
|
||||
w = r[0][:16]
|
||||
tags = {}
|
||||
for k, v in icur.execute("select k, v from mt where w = ?", (w,)):
|
||||
q = "select k, v from mt where w = ? and k != 'x'"
|
||||
for k, v in icur.execute(q, (w,)):
|
||||
taglist[k] = True
|
||||
tags[k] = v
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ class U2idx(object):
|
||||
fsize = body["size"]
|
||||
fhash = body["hash"]
|
||||
wark = up2k_wark_from_hashlist(self.args.salt, fsize, fhash)
|
||||
return self.run_query(vols, "w = ?", [wark], "", [])
|
||||
return self.run_query(vols, "w = ?", [wark], "", [])[0]
|
||||
|
||||
def get_cur(self, ptop):
|
||||
cur = self.cur.get(ptop)
|
||||
@@ -115,7 +115,7 @@ class U2idx(object):
|
||||
w = hit["w"]
|
||||
del hit["w"]
|
||||
tags = {}
|
||||
q = "select k, v from mt where w = ?"
|
||||
q = "select k, v from mt where w = ? and k != 'x'"
|
||||
for k, v in cur.execute(q, (w,)):
|
||||
taglist[k] = True
|
||||
tags[k] = v
|
||||
@@ -124,7 +124,7 @@ class U2idx(object):
|
||||
|
||||
ret.extend(sret)
|
||||
|
||||
return ret, taglist.keys()
|
||||
return ret, list(taglist.keys())
|
||||
|
||||
|
||||
def _open(ptop):
|
||||
|
||||
@@ -138,6 +138,16 @@ class Up2k(object):
|
||||
vols = auth.vfs.all_vols.values()
|
||||
t0 = time.time()
|
||||
|
||||
live_vols = []
|
||||
for vol in vols:
|
||||
try:
|
||||
os.listdir(vol.realpath)
|
||||
live_vols.append(vol)
|
||||
except:
|
||||
self.log("\033[31mcannot access " + vol.realpath)
|
||||
|
||||
vols = live_vols
|
||||
|
||||
# e2ds(a) volumes first,
|
||||
# also covers tags where e2ts is set
|
||||
for vol in vols:
|
||||
@@ -444,12 +454,9 @@ class Up2k(object):
|
||||
def _open_db(self, db_path):
|
||||
existed = os.path.exists(db_path)
|
||||
cur = self._orz(db_path)
|
||||
try:
|
||||
ver = self._read_ver(cur)
|
||||
except:
|
||||
ver = None
|
||||
if not existed:
|
||||
return self._create_db(db_path, cur)
|
||||
ver = self._read_ver(cur)
|
||||
if not existed and ver is None:
|
||||
return self._create_db(db_path, cur)
|
||||
|
||||
orig_ver = ver
|
||||
if not ver or ver < 3:
|
||||
@@ -571,6 +578,10 @@ class Up2k(object):
|
||||
return self._orz(db_path)
|
||||
|
||||
def handle_json(self, cj):
|
||||
if not self.register_vpath(cj["ptop"], cj["vcfg"]):
|
||||
if cj["ptop"] not in self.registry:
|
||||
raise Pebkac(410, "location unavailable")
|
||||
|
||||
cj["name"] = sanitize_fn(cj["name"])
|
||||
cj["poke"] = time.time()
|
||||
wark = self._get_wark(cj)
|
||||
@@ -580,10 +591,9 @@ class Up2k(object):
|
||||
cur = self.cur.get(cj["ptop"], None)
|
||||
reg = self.registry[cj["ptop"]]
|
||||
if cur:
|
||||
cur = cur.execute(
|
||||
r"select * from up where substr(w,1,16) = ? and w = ?",
|
||||
(wark[:16], wark,),
|
||||
)
|
||||
q = r"select * from up where substr(w,1,16) = ? and w = ?"
|
||||
argv = (wark[:16], wark)
|
||||
cur = cur.execute(q, argv)
|
||||
for _, dtime, dsize, dp_dir, dp_fn in cur:
|
||||
if dp_dir.startswith("//") or dp_fn.startswith("//"):
|
||||
dp_dir, dp_fn = self.w8dec(dp_dir, dp_fn)
|
||||
|
||||
@@ -121,6 +121,8 @@ a,
|
||||
#files tbody tr:last-child td {
|
||||
padding-bottom: 1.3em;
|
||||
border-bottom: .5em solid #444;
|
||||
}
|
||||
#files tbody tr td:last-child {
|
||||
white-space: nowrap;
|
||||
}
|
||||
#files thead th[style] {
|
||||
|
||||
@@ -606,7 +606,7 @@ function autoplay_blocked() {
|
||||
}
|
||||
ebi('srch_form').innerHTML = html.join('\n');
|
||||
|
||||
var o = document.querySelectorAll('#op_search input[type="text"]');
|
||||
var o = document.querySelectorAll('#op_search input');
|
||||
for (var a = 0; a < o.length; a++) {
|
||||
o[a].oninput = ev_search_input;
|
||||
}
|
||||
@@ -615,8 +615,11 @@ function autoplay_blocked() {
|
||||
|
||||
function ev_search_input() {
|
||||
var v = this.value;
|
||||
var chk = ebi(this.getAttribute('id').slice(0, -1) + 'c');
|
||||
chk.checked = ((v + '').length > 0);
|
||||
var id = this.getAttribute('id');
|
||||
if (id.slice(-1) == 'v') {
|
||||
var chk = ebi(id.slice(0, -1) + 'c');
|
||||
chk.checked = ((v + '').length > 0);
|
||||
}
|
||||
clearTimeout(search_timeout);
|
||||
search_timeout = setTimeout(do_search, 100);
|
||||
}
|
||||
@@ -1158,7 +1161,6 @@ function reload_browser(not_mp) {
|
||||
hsz = sz.replace(/\B(?=(\d{3})+(?!\d))/g, " ");
|
||||
|
||||
oo[a].textContent = hsz;
|
||||
oo[a].setAttribute("sortv", sz);
|
||||
}
|
||||
|
||||
if (!not_mp) {
|
||||
|
||||
@@ -99,22 +99,33 @@ function sortTable(table, col) {
|
||||
th[a].className = th[a].className.replace(/ *sort-?1 */, " ");
|
||||
th[col].className += ' sort' + reverse;
|
||||
var stype = th[col].getAttribute('sort');
|
||||
tr = tr.sort(function (a, b) {
|
||||
if (!a.cells[col])
|
||||
var vl = [];
|
||||
for (var a = 0; a < tr.length; a++) {
|
||||
var cell = tr[a].cells[col];
|
||||
if (!cell) {
|
||||
vl.push([null, a]);
|
||||
continue;
|
||||
}
|
||||
var v = cell.getAttribute('sortv') || cell.textContent.trim();
|
||||
if (stype == 'int') {
|
||||
v = parseInt(v.replace(/[, ]/g, '')) || 0;
|
||||
}
|
||||
vl.push([v, a]);
|
||||
}
|
||||
vl.sort(function (a, b) {
|
||||
a = a[0];
|
||||
b = b[0];
|
||||
if (a === null)
|
||||
return -1;
|
||||
if (!b.cells[col])
|
||||
if (b === null)
|
||||
return 1;
|
||||
|
||||
var v1 = a.cells[col].getAttribute('sortv') || a.cells[col].textContent.trim();
|
||||
var v2 = b.cells[col].getAttribute('sortv') || b.cells[col].textContent.trim();
|
||||
if (stype == 'int') {
|
||||
v1 = parseInt(v1.replace(/,/g, '')) || 0;
|
||||
v2 = parseInt(v2.replace(/,/g, '')) || 0;
|
||||
return reverse * (v1 - v2);
|
||||
return reverse * (a - b);
|
||||
}
|
||||
return reverse * (v1.localeCompare(v2));
|
||||
return reverse * (a.localeCompare(b));
|
||||
});
|
||||
for (i = 0; i < tr.length; ++i) tb.appendChild(tr[i]);
|
||||
for (i = 0; i < tr.length; ++i) tb.appendChild(tr[vl[i][1]]);
|
||||
}
|
||||
function makeSortable(table) {
|
||||
var th = table.tHead, i;
|
||||
|
||||
Reference in New Issue
Block a user