mirror of
https://github.com/9001/copyparty.git
synced 2025-08-17 09:02:15 -06:00
general-purpose file parsing
This commit is contained in:
parent
c0e6df4b63
commit
0fcfe79994
|
@ -299,6 +299,10 @@ copyparty can invoke external programs to collect additional metadata for files
|
||||||
* `-mtp key=f,t5,~/bin/audio-key.py` uses `~/bin/audio-key.py` to get the `key` tag, replacing any existing metadata tag (`f,`), aborting if it takes longer than 5sec (`t5,`)
|
* `-mtp key=f,t5,~/bin/audio-key.py` uses `~/bin/audio-key.py` to get the `key` tag, replacing any existing metadata tag (`f,`), aborting if it takes longer than 5sec (`t5,`)
|
||||||
* `-v ~/music::r:cmtp=.bpm=~/bin/audio-bpm.py:cmtp=key=f,t5,~/bin/audio-key.py` both as a per-volume config wow this is getting ugly
|
* `-v ~/music::r:cmtp=.bpm=~/bin/audio-bpm.py:cmtp=key=f,t5,~/bin/audio-key.py` both as a per-volume config wow this is getting ugly
|
||||||
|
|
||||||
|
*but wait, there's more!* `-mtp` can be used for non-audio files as well using the `a` flag: `ay` only do audio files, `an` audio files are skipped, or `ad` always do it (d as in dontcare)
|
||||||
|
|
||||||
|
* `-mtp ext=an,~/bin/file-ext.py` runs `~/bin/file-ext.py` to get the `ext` tag only if file is not audio (`an`)
|
||||||
|
|
||||||
|
|
||||||
## complete examples
|
## complete examples
|
||||||
|
|
||||||
|
|
9
bin/mtag/file-ext.py
Normal file
9
bin/mtag/file-ext.py
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
import sys
|
||||||
|
|
||||||
|
"""
|
||||||
|
example that just prints the file extension
|
||||||
|
"""
|
||||||
|
|
||||||
|
print(sys.argv[1].split(".")[-1])
|
|
@ -674,7 +674,7 @@ class HttpCli(object):
|
||||||
self.log("failed to utime ({}, {})".format(path, times))
|
self.log("failed to utime ({}, {})".format(path, times))
|
||||||
|
|
||||||
spd = self._spd(post_sz)
|
spd = self._spd(post_sz)
|
||||||
self.log("{} thank".format(spd))
|
self.log("binpost {} thank".format(spd))
|
||||||
self.reply(b"thank")
|
self.reply(b"thank")
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
|
@ -511,6 +511,7 @@ class Up2k(object):
|
||||||
|
|
||||||
def _run_all_mtp(self):
|
def _run_all_mtp(self):
|
||||||
t0 = time.time()
|
t0 = time.time()
|
||||||
|
self.mtp_audio = {}
|
||||||
self.mtp_force = {}
|
self.mtp_force = {}
|
||||||
self.mtp_parsers = {}
|
self.mtp_parsers = {}
|
||||||
for ptop, flags in self.flags.items():
|
for ptop, flags in self.flags.items():
|
||||||
|
@ -527,8 +528,9 @@ class Up2k(object):
|
||||||
|
|
||||||
entags = self.entags[ptop]
|
entags = self.entags[ptop]
|
||||||
|
|
||||||
force = {}
|
audio = {} # [r]equire [n]ot [d]ontcare
|
||||||
timeout = {}
|
force = {} # bool
|
||||||
|
timeout = {} # int
|
||||||
parsers = {}
|
parsers = {}
|
||||||
for parser in self.flags[ptop]["mtp"]:
|
for parser in self.flags[ptop]["mtp"]:
|
||||||
orig = parser
|
orig = parser
|
||||||
|
@ -536,6 +538,8 @@ class Up2k(object):
|
||||||
if tag not in entags:
|
if tag not in entags:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
audio[tag] = "y"
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
bp = os.path.expanduser(parser)
|
bp = os.path.expanduser(parser)
|
||||||
|
@ -549,6 +553,10 @@ class Up2k(object):
|
||||||
arg, parser = parser.split(",", 1)
|
arg, parser = parser.split(",", 1)
|
||||||
arg = arg.lower()
|
arg = arg.lower()
|
||||||
|
|
||||||
|
if arg.startswith("a"):
|
||||||
|
audio[tag] = arg[1:]
|
||||||
|
continue
|
||||||
|
|
||||||
if arg == "f":
|
if arg == "f":
|
||||||
force[tag] = True
|
force[tag] = True
|
||||||
continue
|
continue
|
||||||
|
@ -563,6 +571,8 @@ class Up2k(object):
|
||||||
self.log("invalid argument: " + orig, 1)
|
self.log("invalid argument: " + orig, 1)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
# todo audio/force => parser attributes
|
||||||
|
self.mtp_audio[ptop] = audio
|
||||||
self.mtp_force[ptop] = force
|
self.mtp_force[ptop] = force
|
||||||
self.mtp_parsers[ptop] = parsers
|
self.mtp_parsers[ptop] = parsers
|
||||||
|
|
||||||
|
@ -596,8 +606,8 @@ class Up2k(object):
|
||||||
have = cur.execute(q, (w,)).fetchall()
|
have = cur.execute(q, (w,)).fetchall()
|
||||||
have = [x[0] for x in have]
|
have = [x[0] for x in have]
|
||||||
|
|
||||||
if ".dur" not in have and ".dur" in entags:
|
parsers = self._get_parsers(ptop, have)
|
||||||
# skip non-audio
|
if not parsers:
|
||||||
to_delete[w] = True
|
to_delete[w] = True
|
||||||
n_left -= 1
|
n_left -= 1
|
||||||
continue
|
continue
|
||||||
|
@ -605,10 +615,7 @@ class Up2k(object):
|
||||||
if w in in_progress:
|
if w in in_progress:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
task_parsers = {
|
jobs.append([parsers, None, w, abspath])
|
||||||
k: v for k, v in parsers.items() if k in force or k not in have
|
|
||||||
}
|
|
||||||
jobs.append([task_parsers, None, w, abspath])
|
|
||||||
in_progress[w] = True
|
in_progress[w] = True
|
||||||
|
|
||||||
done = self._flush_mpool(wcur)
|
done = self._flush_mpool(wcur)
|
||||||
|
@ -667,6 +674,26 @@ class Up2k(object):
|
||||||
wcur.close()
|
wcur.close()
|
||||||
cur.close()
|
cur.close()
|
||||||
|
|
||||||
|
def _get_parsers(self, ptop, have):
|
||||||
|
audio = self.mtp_audio[ptop]
|
||||||
|
force = self.mtp_force[ptop]
|
||||||
|
entags = self.entags[ptop]
|
||||||
|
parsers = {}
|
||||||
|
for k, v in self.mtp_parsers[ptop].items():
|
||||||
|
if ".dur" in entags:
|
||||||
|
if ".dur" in have:
|
||||||
|
# is audio, require non-audio?
|
||||||
|
if audio[k] == "n":
|
||||||
|
continue
|
||||||
|
# is not audio, require audio?
|
||||||
|
elif audio[k] == "y":
|
||||||
|
continue
|
||||||
|
|
||||||
|
parsers[k] = v
|
||||||
|
|
||||||
|
parsers = {k: v for k, v in parsers.items() if k in force or k not in have}
|
||||||
|
return parsers
|
||||||
|
|
||||||
def _start_mpool(self):
|
def _start_mpool(self):
|
||||||
# mp.pool.ThreadPool and concurrent.futures.ThreadPoolExecutor
|
# mp.pool.ThreadPool and concurrent.futures.ThreadPoolExecutor
|
||||||
# both do crazy runahead so lets reinvent another wheel
|
# both do crazy runahead so lets reinvent another wheel
|
||||||
|
@ -1308,13 +1335,9 @@ class Up2k(object):
|
||||||
abspath = os.path.join(ptop, rd, fn)
|
abspath = os.path.join(ptop, rd, fn)
|
||||||
tags = self.mtag.get(abspath)
|
tags = self.mtag.get(abspath)
|
||||||
ntags1 = len(tags)
|
ntags1 = len(tags)
|
||||||
if self.mtp_parsers.get(ptop, {}):
|
parsers = self._get_parsers(ptop, tags)
|
||||||
parser = {
|
if parsers:
|
||||||
k: v
|
tags.update(self.mtag.get_bin(parsers, abspath))
|
||||||
for k, v in self.mtp_parsers[ptop].items()
|
|
||||||
if k in self.mtp_force[ptop] or k not in tags
|
|
||||||
}
|
|
||||||
tags.update(self.mtag.get_bin(parser, abspath))
|
|
||||||
|
|
||||||
with self.mutex:
|
with self.mutex:
|
||||||
cur = self.cur[ptop]
|
cur = self.cur[ptop]
|
||||||
|
|
Loading…
Reference in a new issue