option to show upload timestamps in directory listing;

enable with -mte +.ip_at
or volflag mte=+.ip_at

worst-case performance impact: 18%
This commit is contained in:
ed 2023-10-17 17:51:27 +00:00
parent 2048b7538e
commit 4b5a0787ab
6 changed files with 83 additions and 28 deletions

View file

@ -27,6 +27,8 @@ from .authsrv import expand_config_file, re_vol, split_cfg_ln, upgrade_cfg_fmt
from .cfg import flagcats, onedash
from .svchub import SvcHub
from .util import (
DEF_MTE,
DEF_MTH,
IMPLICATIONS,
JINJA_VER,
PYFTPD_VER,
@ -1132,10 +1134,8 @@ def add_db_metadata(ap):
ap2.add_argument("--mtag-v", action="store_true", help="verbose tag scanning; print errors from mtp subprocesses and such")
ap2.add_argument("--mtag-vv", action="store_true", help="debug mtp settings and mutagen/ffprobe parsers")
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,vc,ac,fmt,res,.fps,ahash,vhash,up_ip,.up_at")
ap2.add_argument("-mth", metavar="M,M,M", type=u, help="tags to hide by default (comma-sep.)",
default=".vq,.aq,vc,ac,fmt,res,.fps")
ap2.add_argument("-mte", metavar="M,M,M", type=u, help="tags to index/display (comma-sep.); either an entire replacement list, or add/remove stuff on the default-list with +foo or /bar", default=DEF_MTE)
ap2.add_argument("-mth", metavar="M,M,M", type=u, help="tags to hide by default (comma-sep.); assign/add/remove same as -mte", default=DEF_MTH)
ap2.add_argument("-mtp", metavar="M=[f,]BIN", type=u, action="append", help="read tag M using program BIN to parse the file")

View file

@ -21,11 +21,13 @@ from .util import (
META_NOBOTS,
SQLITE_VER,
UNPLICATIONS,
ODict,
Pebkac,
absreal,
afsenc,
get_df,
humansize,
odfusion,
relchk,
statdir,
uncyg,
@ -1477,13 +1479,14 @@ class AuthSrv(object):
# default tag cfgs if unset
if "mte" not in vol.flags:
vol.flags["mte"] = self.args.mte
elif vol.flags["mte"].startswith("+"):
vol.flags["mte"] = ",".join(
x for x in [self.args.mte, vol.flags["mte"][1:]] if x
)
vol.flags["mte"] = self.args.mte.copy()
else:
vol.flags["mte"] = odfusion(self.args.mte, vol.flags["mte"])
if "mth" not in vol.flags:
vol.flags["mth"] = self.args.mth
vol.flags["mth"] = self.args.mth.copy()
else:
vol.flags["mth"] = odfusion(self.args.mth, vol.flags["mth"])
# append additive args from argv to volflags
hooks = "xbu xau xiu xbr xar xbd xad xm xban".split()
@ -1584,12 +1587,12 @@ class AuthSrv(object):
if local:
local_only_mtp[a] = True
local_mte = {}
for a in vol.flags.get("mte", "").split(","):
local_mte = ODict()
for a in vol.flags.get("mte", {}).keys():
local = True
all_mte[a] = True
local_mte[a] = True
for b in self.args.mte.split(","):
for b in self.args.mte.keys():
if not a or not b:
continue

View file

@ -40,6 +40,7 @@ from .util import (
HTTPCODE,
META_NOBOTS,
MultipartParser,
ODict,
Pebkac,
UnrecvEOF,
absreal,
@ -1971,8 +1972,7 @@ class HttpCli(object):
self.log("q#: {} ({:.2f}s)".format(msg, idx.p_dur))
order = []
cfg = self.args.mte.split(",")
for t in cfg:
for t in self.args.mte:
if t in taglist:
order.append(t)
for t in taglist:
@ -4051,6 +4051,9 @@ class HttpCli(object):
ap = vn.canonical(rem)
return self.tx_file(ap) # is no-cache
mte = vn.flags.get("mte", {})
add_up_at = ".up_at" in mte
is_admin = self.can_admin
tagset: set[str] = set()
for fe in files:
fn = fe["name"]
@ -4078,24 +4081,38 @@ class HttpCli(object):
self.log(t.format(rd, fn, min_ex()))
break
fe["tags"] = {k: v for k, v in r}
tags = {k: v for k, v in r}
if self.can_admin:
if is_admin:
q = "select ip, at from up where rd=? and fn=?"
try:
zs1, zs2 = icur.execute(q, erd_efn).fetchone()
fe["tags"]["up_ip"] = zs1
fe["tags"][".up_at"] = zs2
if zs1:
tags["up_ip"] = zs1
if zs2:
tags[".up_at"] = zs2
except:
pass
elif add_up_at:
q = "select at from up where rd=? and fn=?"
try:
(zs1,) = icur.execute(q, erd_efn).fetchone()
if zs1:
tags[".up_at"] = zs1
except:
pass
_ = [tagset.add(k) for k in fe["tags"]]
_ = [tagset.add(k) for k in tags]
fe["tags"] = tags
if icur:
mte = vn.flags.get("mte") or "up_ip,.up_at"
taglist = [k for k in mte.split(",") if k in tagset]
lmte = list(mte)
if self.can_admin:
lmte += ["up_ip", ".up_at"]
taglist = [k for k in lmte if k in tagset]
for fe in dirs:
fe["tags"] = {}
fe["tags"] = ODict()
else:
taglist = list(tagset)
@ -4142,7 +4159,7 @@ class HttpCli(object):
j2a["txt_ext"] = self.args.textfiles.replace(",", " ")
if "mth" in vn.flags:
j2a["def_hcols"] = vn.flags["mth"].split(",")
j2a["def_hcols"] = list(vn.flags["mth"])
html = self.j2s(tpl, **j2a)
self.reply(html.encode("utf-8", "replace"))

View file

@ -39,13 +39,17 @@ from .util import (
FFMPEG_URL,
VERSIONS,
Daemon,
DEF_MTE,
DEF_MTH,
Garda,
HLog,
HMaccas,
ODict,
alltrace,
ansi_re,
min_ex,
mp,
odfusion,
pybin,
start_log_thrs,
start_stackmon,
@ -433,6 +437,12 @@ class SvcHub(object):
zs = al.xff_src.replace(" ", "").replace(".", "\\.").replace(",", "|")
al.xff_re = re.compile("^(?:" + zs + ")")
mte = ODict.fromkeys(DEF_MTE.split(","), True)
al.mte = odfusion(mte, al.mte)
mth = ODict.fromkeys(DEF_MTH.split(","), True)
al.mth = odfusion(mth, al.mth)
return True
def _setlimits(self) -> None:

View file

@ -642,10 +642,7 @@ class Up2k(object):
if self.stop:
break
en: set[str] = set()
if "mte" in vol.flags:
en = set(vol.flags["mte"].split(","))
en = set(vol.flags.get("mte", {}))
self.entags[vol.realpath] = en
if "e2d" in vol.flags:

View file

@ -36,6 +36,14 @@ from .__version__ import S_BUILD_DT, S_VERSION
from .stolen import surrogateescape
if sys.version_info >= (3, 7) or (
sys.version_info >= (3, 6) and platform.python_implementation() == "CPython"
):
ODict = dict
else:
from collections import OrderedDict as ODict
def _ens(want: str) -> tuple[int, ...]:
ret: list[int] = []
for v in want.split():
@ -261,6 +269,11 @@ EXTS["vnd.mozilla.apng"] = "png"
MAGIC_MAP = {"jpeg": "jpg"}
DEF_MTE = "circle,album,.tn,artist,title,.bpm,key,.dur,.q,.vq,.aq,vc,ac,fmt,res,.fps,ahash,vhash"
DEF_MTH = ".vq,.aq,vc,ac,fmt,res,.fps"
REKOBO_KEY = {
v: ln.split(" ", 1)[0]
for ln in """
@ -1774,6 +1787,21 @@ def exclude_dotfiles(filepaths: list[str]) -> list[str]:
return [x for x in filepaths if not x.split("/")[-1].startswith(".")]
def odfusion(base: ODict[str, bool], oth: str) -> ODict[str, bool]:
# merge an "ordered set" (just a dict really) with another list of keys
ret = base.copy()
if oth.startswith("+"):
for k in oth[1:].split(","):
ret[k] = True
elif oth[:1] in ("-", "/"):
for k in oth[1:].split(","):
ret.pop(k, None)
else:
ret = ODict.fromkeys(oth.split(","), True)
return ret
def ipnorm(ip: str) -> str:
if ":" in ip:
# assume /64 clients; drop 4 groups