Compare commits

...

18 Commits

Author SHA1 Message Date
ed
fff45552da v1.17.0 2025-04-26 21:49:09 +00:00
ed
95157d02c9 ie11 can't sandbox; add minimal fallback 2025-04-26 20:14:23 +00:00
ed
3090c74832 ie11: fix debounce-untint;
css 'unset' appeared in chr41, ff27

dom.closest appeared in chr41, ff35
2025-04-26 19:57:59 +00:00
ed
4195762d2a playlist: when lacking perms, s/edit/view/ 2025-04-26 19:28:12 +00:00
ed
dc3b7a2720 reduce --th-ram-max floor;
helps avoid oom in a vm with 512 MiB ram
2025-04-26 19:06:32 +00:00
ed
ad200f2b97 add ui for creating playlists 2025-04-26 00:19:41 +00:00
ed
897f9d328d audioplayer: load and play m3u8 playlists 2025-04-25 22:33:00 +00:00
ed
efbe34f29d readme: mention basic-auth behavior 2025-04-25 18:57:12 +00:00
ed
dbfc899d79 pw-hash tweaks (#159):
* do not take lock on shares-db / sessions-db when running with
   `--ah-gen` or `--ah-cli` (allows a 2nd instance for that purpose)

* add options to print effective salt for ah/fk/dk; useful for nixos
   and other usecases where config is derived or otherwise opaque
2025-04-25 18:12:35 +00:00
ed
74fb4b0cb8 fix --u2j helptext:
* mention potential hdd-bottleneck from big values
* most browsers enforce a max-value of 6 (c354a38b)
* chunk-stitching (132a8350) made this less important;
   still beneficial, but only to a point
2025-04-24 20:51:45 +00:00
ed
68e7000275 update pkgs to 1.16.21 2025-04-20 19:19:35 +00:00
ed
38c2dcce3e v1.16.21 2025-04-20 18:36:32 +00:00
ed
5b3a5fe76b show warning on ctrl-a in lazyloaded folders 2025-04-20 13:33:01 +00:00
ed
d5a9bd80b2 docker: hide healthcheck from logs 2025-04-20 12:26:56 +00:00
ed
71c5565949 add button to loop/repeat music; closes #156 2025-04-20 11:45:48 +00:00
ed
db33d68d42 zip-download: eagerly 64bit data-descriptors; closes #155
this avoids a false-positive in the info-zip unzip zipbomb detector.

unfortunately,

* now impossible to extract large (4 GiB) zipfiles using old software
   (WinXP, macos 10.12)

* now less viable to stream download-as-zip into a zipfile unpacker
   (please use download-as-tar for that purpose)

context:

the zipfile specification (APPNOTE.TXT) is slightly ambiguous as to when
data-descriptor (0x504b0708) filesize-fields change from 32bit to 64bit;
both copyparty and libarchive independently made the same interpretation
that this is only when the local header is zip64, AND the size-fields
are both 0xFFFFFFFF. This makes sense because the data descriptor is
only necessary when that particular file-to-be-added exceeds 4 GiB,
and/or when the crc32 is not known ahead of time.

another interpretation, seen in an early version of the patchset
to fix CVE-2019-13232 (zip-bombs) in the info-zip unzip command,
believes the only requirement is that the local header is zip64.

in many linux distributions, the unzip command would thus fail on
zipfiles created by copyparty, since they (by default) satisfy
the three requirements to hit the zipbomb false-positive:

* total filesize exceeds 4 GiB, and...
* a mix of regular (32bit) and zip64 entries, and...
* streaming-mode zipfile (not made with ?zip=crc)

this issue no longer exists in a more recent version of that patchset,
https://github.com/madler/unzip/commit/af0d07f95809653b
but this fix has not yet made it into most linux distros
2025-04-17 18:52:47 +00:00
ed
e1c20c7a18 readme: mention bootable flashdrive / cdrom 2025-04-17 18:45:50 +00:00
ed
d3f1b45ce3 update pkgs to 1.16.20 2025-04-13 22:32:06 +00:00
15 changed files with 377 additions and 53 deletions

View File

@@ -50,6 +50,8 @@ turn almost any device into a file server with resumable uploads/downloads using
* [rss feeds](#rss-feeds) - monitor a folder with your RSS reader
* [recent uploads](#recent-uploads) - list all recent uploads
* [media player](#media-player) - plays almost every audio format there is
* [playlists](#playlists) - create and play [m3u8](https://en.wikipedia.org/wiki/M3U) playlists
* [creating a playlist](#creating-a-playlist) - with a standalone mediaplayer or copyparty
* [audio equalizer](#audio-equalizer) - and [dynamic range compressor](https://en.wikipedia.org/wiki/Dynamic_range_compression)
* [fix unreliable playback on android](#fix-unreliable-playback-on-android) - due to phone / app settings
* [markdown viewer](#markdown-viewer) - and there are *two* editors
@@ -147,6 +149,7 @@ just run **[copyparty-sfx.py](https://github.com/9001/copyparty/releases/latest/
* or if you are on android, [install copyparty in termux](#install-on-android)
* or maybe you have a [synology nas / dsm](./docs/synology-dsm.md)
* or if your computer is messed up and nothing else works, [try the pyz](#zipapp)
* or if your OS is dead, give the [bootable flashdrive / cd-rom](https://a.ocv.me/pub/stuff/edcd001/enterprise-edition/) a spin
* or if you don't trust copyparty yet and want to isolate it a little, then...
* ...maybe [prisonparty](./bin/prisonparty.sh) to create a tiny [chroot](https://wiki.archlinux.org/title/Chroot) (very portable),
* ...or [bubbleparty](./bin/bubbleparty.sh) to wrap it in [bubblewrap](https://github.com/containers/bubblewrap) (much better)
@@ -250,6 +253,7 @@ also see [comparison to similar software](./docs/versus.md)
* ☑ file manager (cut/paste, delete, [batch-rename](#batch-rename))
* ☑ audio player (with [OS media controls](https://user-images.githubusercontent.com/241032/215347492-b4250797-6c90-4e09-9a4c-721edf2fb15c.png) and opus/mp3 transcoding)
* ☑ play video files as audio (converted on server)
* ☑ create and play [m3u8 playlists](#playlists)
* ☑ image gallery with webm player
* ☑ textfile browser with syntax hilighting
* ☑ [thumbnails](#thumbnails)
@@ -302,6 +306,8 @@ project goals / philosophy
* adaptable, malleable, hackable
* no build steps; modify the js/python without needing node.js or anything like that
becoming rich is specifically *not* a motivation, but if you wanna donate then see my [github profile](https://github.com/9001) regarding donations for my FOSS stuff in general (also THANKS!)
## notes
@@ -730,6 +736,7 @@ select which type of archive you want in the `[⚙️] config` tab:
* `up2k.db` and `dir.txt` is always excluded
* bsdtar supports streaming unzipping: `curl foo?zip | bsdtar -xv`
* good, because copyparty's zip is faster than tar on small files
* but `?tar` is better for large files, especially if the total exceeds 4 GiB
* `zip_crc` will take longer to download since the server has to read each file twice
* this is only to support MS-DOS PKZIP v2.04g (october 1993) and older
* how are you accessing copyparty actually
@@ -1034,11 +1041,13 @@ click the `play` link next to an audio file, or copy the link target to [share i
open the `[🎺]` media-player-settings tab to configure it,
* "switches":
* `[🔁]` repeats one single song forever
* `[🔀]` shuffles the files inside each folder
* `[preload]` starts loading the next track when it's about to end, reduces the silence between songs
* `[full]` does a full preload by downloading the entire next file; good for unreliable connections, bad for slow connections
* `[~s]` toggles the seekbar waveform display
* `[/np]` enables buttons to copy the now-playing info as an irc message
* `[📻]` enables buttons to create an [m3u playlist](#playlists) with the selected songs
* `[os-ctl]` makes it possible to control audio playback from the lockscreen of your device (enables [mediasession](https://developer.mozilla.org/en-US/docs/Web/API/MediaSession))
* `[seek]` allows seeking with lockscreen controls (buggy on some devices)
* `[art]` shows album art on the lockscreen
@@ -1057,11 +1066,39 @@ open the `[🎺]` media-player-settings tab to configure it,
* "transcode to":
* `[opus]` produces an `opus` whenever transcoding is necessary (the best choice on Android and PCs)
* `[awo]` is `opus` in a `weba` file, good for iPhones (iOS 17.5 and newer) but Apple is still fixing some state-confusion bugs as of iOS 18.2.1
* `[caf]` is `opus` in a `caf` file, good for iPhones (iOS 11 through 17), technically unsupported by Apple but works for the mos tpart
* `[caf]` is `opus` in a `caf` file, good for iPhones (iOS 11 through 17), technically unsupported by Apple but works for the most part
* `[mp3]` -- the myth, the legend, the undying master of mediocre sound quality that definitely works everywhere
* "tint" reduces the contrast of the playback bar
### playlists
create and play [m3u8](https://en.wikipedia.org/wiki/M3U) playlists -- see example [text](https://a.ocv.me/pub/demo/music/?doc=example-playlist.m3u) and [player](https://a.ocv.me/pub/demo/music/#m3u=example-playlist.m3u)
click a file with the extension `m3u` or `m3u8` (for example `mixtape.m3u` or `touhou.m3u8` ) and you get two choices: Play / Edit
playlists can include songs across folders anywhere on the server, but filekeys/dirkeys are NOT supported, so the listener must have read-access or get-access to the files
### creating a playlist
with a standalone mediaplayer or copyparty
you can use foobar2000, deadbeef, just about any standalone player should work -- but you might need to edit the filepaths in the playlist so they fit with the server-URLs
alternatively, you can create the playlist using copyparty itself:
* open the `[🎺]` media-player-settings tab and enable the `[📻]` create-playlist feature -- this adds two new buttons in the bottom-right tray, `[📻add]` and `[📻copy]` which appear when you listen to music, or when you select a few audiofiles
* click the `📻add` button while a song is playing (or when you've selected some songs) and they'll be added to "the list" (you can't see it yet)
* at any time, click `📻copy` to send the playlist to your clipboard
* you can then continue adding more songs if you'd like
* if you want to wipe the playlist and start from scratch, just refresh the page
* create a new textfile, name it `something.m3u` and paste the playlist there
### audio equalizer
and [dynamic range compressor](https://en.wikipedia.org/wiki/Dynamic_range_compression)
@@ -2383,6 +2420,8 @@ copyparty returns a truncated sha512sum of your PUT/POST as base64; you can gene
you can provide passwords using header `PW: hunter2`, cookie `cppwd=hunter2`, url-param `?pw=hunter2`, or with basic-authentication (either as the username or password)
> for basic-authentication, all of the following are accepted: `password` / `whatever:password` / `password:whatever` (the username is ignored)
NOTE: curl will not send the original filename if you use `-T` combined with url-params! Also, make sure to always leave a trailing slash in URLs unless you want to override the filename

View File

@@ -1,6 +1,6 @@
# Maintainer: icxes <dev.null@need.moe>
pkgname=copyparty
pkgver="1.16.19"
pkgver="1.16.21"
pkgrel=1
pkgdesc="File server with accelerated resumable uploads, dedup, WebDAV, FTP, TFTP, zeroconf, media indexer, thumbnails++"
arch=("any")
@@ -22,7 +22,7 @@ optdepends=("ffmpeg: thumbnails for videos, images (slower) and audio, music tag
)
source=("https://github.com/9001/${pkgname}/releases/download/v${pkgver}/${pkgname}-${pkgver}.tar.gz")
backup=("etc/${pkgname}.d/init" )
sha256sums=("e18a4a6943d47e87c94ac0bf76006de7674ad78155608b23192e527472e59291")
sha256sums=("2e416e18dc854c65643b8aaedca56e0a5c5a03b0c3d45b7ff3f68daa38d8e9c6")
build() {
cd "${srcdir}/${pkgname}-${pkgver}"

View File

@@ -1,5 +1,5 @@
{
"url": "https://github.com/9001/copyparty/releases/download/v1.16.19/copyparty-sfx.py",
"version": "1.16.19",
"hash": "sha256-IdQdoY7uNAQ4LoBrANud9vekL/Mske57D+m6RXfwgW8="
"url": "https://github.com/9001/copyparty/releases/download/v1.16.21/copyparty-sfx.py",
"version": "1.16.21",
"hash": "sha256-+/f4g8J2Mv0l6ChXzbNJ84G8LeB+mP1UfkWzQxizd/g="
}

View File

@@ -1025,7 +1025,7 @@ def add_upload(ap):
ap2.add_argument("--df", metavar="GiB", type=u, default="0", help="ensure \033[33mGiB\033[0m free disk space by rejecting upload requests; assumes gigabytes unless a unit suffix is given: [\033[32m256m\033[0m], [\033[32m4\033[0m], [\033[32m2T\033[0m] (volflag=df)")
ap2.add_argument("--sparse", metavar="MiB", type=int, default=4, help="windows-only: minimum size of incoming uploads through up2k before they are made into sparse files")
ap2.add_argument("--turbo", metavar="LVL", type=int, default=0, help="configure turbo-mode in up2k client; [\033[32m-1\033[0m] = forbidden/always-off, [\033[32m0\033[0m] = default-off and warn if enabled, [\033[32m1\033[0m] = default-off, [\033[32m2\033[0m] = on, [\033[32m3\033[0m] = on and disable datecheck")
ap2.add_argument("--u2j", metavar="JOBS", type=int, default=2, help="web-client: number of file chunks to upload in parallel; 1 or 2 is good for low-latency (same-country) connections, 4-8 for android clients, 16 for cross-atlantic (max=64)")
ap2.add_argument("--u2j", metavar="JOBS", type=int, default=2, help="web-client: number of file chunks to upload in parallel; 1 or 2 is good when latency is low (same-country), 2~4 for android-clients, 2~6 for cross-atlantic. Max is 6 in most browsers. Big values increase network-speed but may reduce HDD-speed")
ap2.add_argument("--u2sz", metavar="N,N,N", type=u, default="1,64,96", help="web-client: default upload chunksize (MiB); sets \033[33mmin,default,max\033[0m in the settings gui. Each HTTP POST will aim for \033[33mdefault\033[0m, and never exceed \033[33mmax\033[0m. Cloudflare max is 96. Big values are good for cross-atlantic but may increase HDD fragmentation on some FS. Disable this optimization with [\033[32m1,1,1\033[0m]")
ap2.add_argument("--u2ow", metavar="NUM", type=int, default=0, help="web-client: default setting for when to replace/overwrite existing files; [\033[32m0\033[0m]=never, [\033[32m1\033[0m]=if-client-newer, [\033[32m2\033[0m]=always (volflag=u2ow)")
ap2.add_argument("--u2sort", metavar="TXT", type=u, default="s", help="upload order; [\033[32ms\033[0m]=smallest-first, [\033[32mn\033[0m]=alphabetical, [\033[32mfs\033[0m]=force-s, [\033[32mfn\033[0m]=force-n -- alphabetical is a bit slower on fiber/LAN but makes it easier to eyeball if everything went fine")
@@ -1308,6 +1308,9 @@ def add_salt(ap, fk_salt, dk_salt, ah_salt):
ap2.add_argument("--fk-salt", metavar="SALT", type=u, default=fk_salt, help="per-file accesskey salt; used to generate unpredictable URLs for hidden files")
ap2.add_argument("--dk-salt", metavar="SALT", type=u, default=dk_salt, help="per-directory accesskey salt; used to generate unpredictable URLs to share folders with users who only have the 'get' permission")
ap2.add_argument("--warksalt", metavar="SALT", type=u, default="hunter2", help="up2k file-hash salt; serves no purpose, no reason to change this (but delete all databases if you do)")
ap2.add_argument("--show-ah-salt", action="store_true", help="on startup, print the effective value of \033[33m--ah-salt\033[0m (the autogenerated value in $XDG_CONFIG_HOME unless otherwise specified)")
ap2.add_argument("--show-fk-salt", action="store_true", help="on startup, print the effective value of \033[33m--fk-salt\033[0m (the autogenerated value in $XDG_CONFIG_HOME unless otherwise specified)")
ap2.add_argument("--show-dk-salt", action="store_true", help="on startup, print the effective value of \033[33m--dk-salt\033[0m (the autogenerated value in $XDG_CONFIG_HOME unless otherwise specified)")
def add_shutdown(ap):
@@ -1349,7 +1352,7 @@ def add_admin(ap):
def add_thumbnail(ap):
th_ram = (RAM_AVAIL or RAM_TOTAL or 9) * 0.6
th_ram = int(max(min(th_ram, 6), 1) * 10) / 10
th_ram = int(max(min(th_ram, 6), 0.3) * 10) / 10
ap2 = ap.add_argument_group('thumbnail options')
ap2.add_argument("--no-thumb", action="store_true", help="disable all thumbnails (volflag=dthumb)")
ap2.add_argument("--no-vthumb", action="store_true", help="disable video thumbnails (volflag=dvthumb)")

View File

@@ -1,8 +1,8 @@
# coding: utf-8
VERSION = (1, 16, 20)
CODENAME = "COPYparty"
BUILD_DT = (2025, 4, 13)
VERSION = (1, 17, 0)
CODENAME = "mixtape.m3u"
BUILD_DT = (2025, 4, 26)
S_VERSION = ".".join(map(str, VERSION))
S_BUILD_DT = "{0:04d}-{1:02d}-{2:02d}".format(*BUILD_DT)

View File

@@ -253,6 +253,14 @@ class SvcHub(object):
setattr(args, "ipu_iu", iu)
setattr(args, "ipu_nm", nm)
for zs in "ah_salt fk_salt dk_salt".split():
if getattr(args, "show_%s" % (zs,)):
self.log("root", "effective %s is %s" % (zs, getattr(args, zs)))
if args.ah_cli or args.ah_gen:
args.no_ses = True
args.shr = ""
if not self.args.no_ses:
self.setup_session_db()

View File

@@ -54,6 +54,7 @@ def gen_fdesc(sz: int, crc32: int, z64: bool) -> bytes:
def gen_hdr(
h_pos: Optional[int],
z64: bool,
fn: str,
sz: int,
lastmod: int,
@@ -70,7 +71,6 @@ def gen_hdr(
# appnote 4.5 / zip 3.0 (2008) / unzip 6.0 (2009) says to add z64
# extinfo for values which exceed H, but that becomes an off-by-one
# (can't tell if it was clamped or exactly maxval), make it obvious
z64 = sz >= 0xFFFFFFFF
z64v = [sz, sz] if z64 else []
if h_pos and h_pos >= 0xFFFFFFFF:
# central, also consider ptr to original header
@@ -244,6 +244,7 @@ class StreamZip(StreamArc):
sz = st.st_size
ts = st.st_mtime
h_pos = self.pos
crc = 0
if self.pre_crc:
@@ -252,8 +253,12 @@ class StreamZip(StreamArc):
crc &= 0xFFFFFFFF
h_pos = self.pos
buf = gen_hdr(None, name, sz, ts, self.utf8, crc, self.pre_crc)
# some unzip-programs expect a 64bit data-descriptor
# even if the only 32bit-exceeding value is the offset,
# so force that by placeholdering the filesize too
z64 = h_pos >= 0xFFFFFFFF or sz >= 0xFFFFFFFF
buf = gen_hdr(None, z64, name, sz, ts, self.utf8, crc, self.pre_crc)
yield self._ct(buf)
for buf in yieldfile(src, self.args.iobuf):
@@ -266,8 +271,6 @@ class StreamZip(StreamArc):
self.items.append((name, sz, ts, crc, h_pos))
z64 = sz >= 4 * 1024 * 1024 * 1024
if z64 or not self.pre_crc:
buf = gen_fdesc(sz, crc, z64)
yield self._ct(buf)
@@ -306,7 +309,8 @@ class StreamZip(StreamArc):
cdir_pos = self.pos
for name, sz, ts, crc, h_pos in self.items:
buf = gen_hdr(h_pos, name, sz, ts, self.utf8, crc, self.pre_crc)
z64 = h_pos >= 0xFFFFFFFF or sz >= 0xFFFFFFFF
buf = gen_hdr(h_pos, z64, name, sz, ts, self.utf8, crc, self.pre_crc)
mbuf += self._ct(buf)
if len(mbuf) >= 16384:
yield mbuf

View File

@@ -472,6 +472,8 @@ FN_EMB = set([".prologue.html", ".epilogue.html", "readme.md", "preadme.md"])
def read_ram() -> tuple[float, float]:
# NOTE: apparently no need to consider /sys/fs/cgroup/memory.max
# (cgroups2) since the limit is synced to /proc/meminfo
a = b = 0
try:
with open("/proc/meminfo", "rb", 0x10000) as f:

View File

@@ -1151,10 +1151,10 @@ html.y #widget.open {
background: #fff;
background: var(--bg-u3);
}
#wfs, #wfm, #wzip, #wnp {
#wfs, #wfm, #wzip, #wnp, #wm3u {
display: none;
}
#wfs, #wzip, #wnp {
#wfs, #wzip, #wnp, #wm3u {
margin-right: .2em;
padding-right: .2em;
border: 1px solid var(--bg-u5);
@@ -1175,6 +1175,7 @@ html.y #widget.open {
line-height: 1em;
}
#wtoggle.sel #wzip,
#wtoggle.m3u #wm3u,
#wtoggle.np #wnp {
display: inline-block;
}
@@ -1183,6 +1184,7 @@ html.y #widget.open {
}
#wfm a,
#wnp a,
#wm3u a,
#wzip a {
font-size: .5em;
padding: 0 .3em;
@@ -1190,6 +1192,10 @@ html.y #widget.open {
position: relative;
display: inline-block;
}
#wm3u a {
margin: -.2em .1em;
font-size: .45em;
}
#wfs {
font-size: .36em;
text-align: right;
@@ -1198,6 +1204,7 @@ html.y #widget.open {
border-width: 0 .25em 0 0;
}
#wfm span,
#wm3u span,
#wnp span {
font-size: .6em;
display: block;
@@ -1205,6 +1212,10 @@ html.y #widget.open {
#wnp span {
font-size: .7em;
}
#wm3u span {
font-size: .77em;
padding-top: .2em;
}
#wfm a:not(.en) {
opacity: .3;
color: var(--fm-off);

View File

@@ -144,6 +144,8 @@ var Ls = {
"wt_seldl": "download selection as separate files$NHotkey: Y",
"wt_npirc": "copy irc-formatted track info",
"wt_nptxt": "copy plaintext track info",
"wt_m3ua": "add to m3u playlist (click <code>📻copy</code> later)",
"wt_m3uc": "copy m3u playlist to clipboard",
"wt_grid": "toggle grid / list view$NHotkey: G",
"wt_prev": "previous track$NHotkey: J",
"wt_play": "play / pause$NHotkey: P",
@@ -271,6 +273,7 @@ var Ls = {
"ml_eq": "audio equalizer",
"ml_drc": "dynamic range compressor",
"mt_loop": "loop/repeat one song\">🔁",
"mt_shuf": "shuffle the songs in each folder\">🔀",
"mt_aplay": "autoplay if there is a song-ID in the link you clicked to access the server$N$Ndisabling this will also stop the page URL from being updated with song-IDs when playing music, to prevent autoplay if these settings are lost but the URL remains\">a▶",
"mt_preload": "start loading the next song near the end for gapless playback\">preload",
@@ -279,6 +282,7 @@ var Ls = {
"mt_fau": "on phones, prevent music from stopping if the next song doesn't preload fast enough (can make tags display glitchy)\">☕️",
"mt_waves": "waveform seekbar:$Nshow audio amplitude in the scrubber\">~s",
"mt_npclip": "show buttons for clipboarding the currently playing song\">/np",
"mt_m3u_c": "show buttons for clipboarding the$Nselected songs as m3u8 playlist entries\">📻",
"mt_octl": "os integration (media hotkeys / osd)\">os-ctl",
"mt_oseek": "allow seeking through os integration$N$Nnote: on some devices (iPhones),$Nthis replaces the next-song button\">seek",
"mt_oscv": "show album cover in osd\">art",
@@ -304,6 +308,7 @@ var Ls = {
"mb_play": "play",
"mm_hashplay": "play this audio file?",
"mm_m3u": "press <code>Enter/OK</code> to Play\npress <code>ESC/Cancel</code> to Edit",
"mp_breq": "need firefox 82+ or chrome 73+ or iOS 15+",
"mm_bload": "now loading...",
"mm_bconv": "converting to {0}, please wait...",
@@ -331,6 +336,7 @@ var Ls = {
"f_bigtxt": "this file is {0} MiB large -- really view as text?",
"fbd_more": '<div id="blazy">showing <code>{0}</code> of <code>{1}</code> files; <a href="#" id="bd_more">show {2}</a> or <a href="#" id="bd_all">show all</a></div>',
"fbd_all": '<div id="blazy">showing <code>{0}</code> of <code>{1}</code> files; <a href="#" id="bd_all">show all</a></div>',
"f_anota": "only {0} of the {1} items were selected;\nto select the full folder, first scroll to the bottom",
"f_dls": 'the file links in the current folder have\nbeen changed into download links',
@@ -433,6 +439,10 @@ var Ls = {
"tvt_sel": "select file &nbsp; ( for cut / copy / delete / ... )$NHotkey: S\">sel",
"tvt_edit": "open file in text editor$NHotkey: E\">✏️ edit",
"m3u_add1": "song added to m3u playlist",
"m3u_addn": "{0} songs added to m3u playlist",
"m3u_clip": "m3u playlist now copied to clipboard\n\nyou should create a new textfile named something.m3u and paste the playlist in that document; this will make it playable",
"gt_vau": "don't show videos, just play the audio\">🎧",
"gt_msel": "enable file selection; ctrl-click a file to override$N$N&lt;em&gt;when active: doubleclick a file / folder to open it&lt;/em&gt;$N$NHotkey: S\">multiselect",
"gt_crop": "center-crop thumbnails\">crop",
@@ -748,6 +758,8 @@ var Ls = {
"wt_seldl": "last ned de valgte filene$NSnarvei: Y",
"wt_npirc": "kopiér sang-info (irc-formatert)",
"wt_nptxt": "kopiér sang-info",
"wt_m3ua": "legg til sang i m3u-spilleliste$N(husk å klikke på <code>📻copy</code> senere)",
"wt_m3uc": "kopiér m3u-spillelisten til utklippstavlen",
"wt_grid": "bytt mellom ikoner og listevisning$NSnarvei: G",
"wt_prev": "forrige sang$NSnarvei: J",
"wt_play": "play / pause$NSnarvei: P",
@@ -875,6 +887,7 @@ var Ls = {
"ml_eq": "audio equalizer (tonejustering)",
"ml_drc": "compressor (volum-utjevning)",
"mt_loop": "spill den samme sangen om og om igjen\">🔁",
"mt_shuf": "sangene i hver mappe$Nspilles i tilfeldig rekkefølge\">🔀",
"mt_aplay": "forsøk å starte avspilling hvis linken du klikket på for å åpne nettsiden inneholder en sang-ID$N$Nhvis denne deaktiveres så vil heller ikke nettside-URLen bli oppdatert med sang-ID'er når musikk spilles, i tilfelle innstillingene skulle gå tapt og nettsiden lastes på ny\">a▶",
"mt_preload": "hent ned litt av neste sang i forkant,$Nslik at pausen i overgangen blir mindre\">forles",
@@ -883,6 +896,7 @@ var Ls = {
"mt_fau": "for telefoner: forhindre at avspilling stopper hvis nettet er for tregt til å laste neste sang i tide. Hvis påskrudd, kan forårsake at sang-info ikke vises korrekt i OS'et\">☕️",
"mt_waves": "waveform seekbar:$Nvis volumkurve i avspillingsfeltet\">~s",
"mt_npclip": "vis knapper for å kopiere info om sangen du hører på\">/np",
"mt_m3u_c": "vis knapper for å kopiere de valgte$Nsangene som innslag i en m3u8 spilleliste\">📻",
"mt_octl": "integrering med operativsystemet (fjernkontroll, info-skjerm)\">os-ctl",
"mt_oseek": "tillat spoling med fjernkontroll$N$Nmerk: på noen enheter (iPhones) så vil$Ndette erstatte knappen for neste sang\">spoling",
"mt_oscv": "vis album-cover på infoskjermen\">bilde",
@@ -908,6 +922,7 @@ var Ls = {
"mb_play": "lytt",
"mm_hashplay": "spill denne sangen?",
"mm_m3u": "trykk <code>Enter/OK</code> for å spille\ntrykk <code>ESC/Avbryt</code> for å redigere",
"mp_breq": "krever firefox 82+, chrome 73+, eller iOS 15+",
"mm_bload": "laster inn...",
"mm_bconv": "konverterer til {0}, vent litt...",
@@ -935,6 +950,7 @@ var Ls = {
"f_bigtxt": "denne filen er hele {0} MiB -- vis som tekst?",
"fbd_more": '<div id="blazy">viser <code>{0}</code> av <code>{1}</code> filer; <a href="#" id="bd_more">vis {2}</a> eller <a href="#" id="bd_all">vis alle</a></div>',
"fbd_all": '<div id="blazy">viser <code>{0}</code> av <code>{1}</code> filer; <a href="#" id="bd_all">vis alle</a></div>',
"f_anota": "kun {0} av totalt {1} elementer ble markert;\nfor å velge alt må du bla til bunnen av mappen først",
"f_dls": 'linkene i denne mappen er nå\nomgjort til nedlastningsknapper',
@@ -1037,6 +1053,10 @@ var Ls = {
"tvt_sel": "markér filen &nbsp; ( for utklipp / sletting / ... )$NSnarvei: S\">merk",
"tvt_edit": "redigér filen$NSnarvei: E\">✏️ endre",
"m3u_add1": "sangen ble lagt til i m3u-spillelisten",
"m3u_addn": "{0} sanger ble lagt til i m3u-spillelisten",
"m3u_clip": "m3u-spillelisten ble kopiert til utklippstavlen\n\nneste steg er å opprette et tekstdokument med filnavn som slutter på <code>.m3u</code> og lime inn spillelisten der",
"gt_vau": "ikke vis videofiler, bare spill lyden\">🎧",
"gt_msel": "markér filer istedenfor å åpne dem; ctrl-klikk filer for å overstyre$N$N&lt;em&gt;når aktiv: dobbelklikk en fil / mappe for å åpne&lt;/em&gt;$N$NSnarvei: S\">markering",
"gt_crop": "beskjær ikonene så de passer bedre\">✂",
@@ -1479,6 +1499,7 @@ var Ls = {
"ml_eq": "音频均衡器",
"ml_drc": "动态范围压缩器",
"mt_loop": "循环播放当前的歌曲\">🔁", //m
"mt_shuf": "在每个文件夹中随机播放歌曲\">🔀",
"mt_aplay": "如果链接中有歌曲 ID则自动播放,禁用此选项将停止在播放音乐时更新页面 URL 中的歌曲 ID以防止在设置丢失但 URL 保留时自动播放\">自动播放▶",
"mt_preload": "在歌曲快结束时开始加载下一首歌,以实现无缝播放\">预加载",
@@ -1886,6 +1907,9 @@ ebi('widget').innerHTML = (
'</span><span id="wnp"><a' +
' href="#" id="npirc" tt="' + L.wt_npirc + '">📋<span>irc</span></a><a' +
' href="#" id="nptxt" tt="' + L.wt_nptxt + '">📋<span>txt</span></a>' +
'</span><span id="wm3u"><a' +
' href="#" id="m3ua" tt="' + L.wt_m3ua + '">📻<span>add</span></a><a' +
' href="#" id="m3uc" tt="' + L.wt_m3uc + '">📻<span>copy</span></a>' +
'</span><a' +
' href="#" id="wtgrid" tt="' + L.wt_grid + '">田</a><a' +
' href="#" id="wtico">♫</a>' +
@@ -2292,6 +2316,7 @@ var mpl = (function () {
ebi('op_player').innerHTML = (
'<div><h3>' + L.cl_opts + '</h3><div>' +
'<a href="#" class="tgl btn" id="au_loop" tt="' + L.mt_loop + '</a>' +
'<a href="#" class="tgl btn" id="au_shuf" tt="' + L.mt_shuf + '</a>' +
'<a href="#" class="tgl btn" id="au_aplay" tt="' + L.mt_aplay + '</a>' +
'<a href="#" class="tgl btn" id="au_preload" tt="' + L.mt_preload + '</a>' +
@@ -2300,6 +2325,7 @@ var mpl = (function () {
'<a href="#" class="tgl btn" id="au_fau" tt="' + L.mt_fau + '</a>' +
'<a href="#" class="tgl btn" id="au_waves" tt="' + L.mt_waves + '</a>' +
'<a href="#" class="tgl btn" id="au_npclip" tt="' + L.mt_npclip + '</a>' +
'<a href="#" class="tgl btn" id="au_m3u_c" tt="' + L.mt_m3u_c + '</a>' +
'<a href="#" class="tgl btn" id="au_os_ctl" tt="' + L.mt_octl + '</a>' +
'<a href="#" class="tgl btn" id="au_os_seek" tt="' + L.mt_oseek + '</a>' +
'<a href="#" class="tgl btn" id="au_osd_cv" tt="' + L.mt_oscv + '</a>' +
@@ -2342,7 +2368,12 @@ var mpl = (function () {
"pb_mode": (sread('pb_mode', ['loop', 'next']) || 'next').split('-')[0],
"os_ctl": bcfg_get('au_os_ctl', have_mctl) && have_mctl,
'traversals': 0,
'm3ut': '#EXTM3U\n',
};
bcfg_bind(r, 'loop', 'au_loop', false, function (v) {
if (mp.au)
mp.au.loop = v;
});
bcfg_bind(r, 'shuf', 'au_shuf', false, function () {
mp.read_order(); // don't bind
});
@@ -2367,6 +2398,9 @@ var mpl = (function () {
bcfg_bind(r, 'clip', 'au_npclip', false, function (v) {
clmod(ebi('wtoggle'), 'np', v && mp.au);
});
bcfg_bind(r, 'm3uen', 'au_m3u_c', false, function (v) {
clmod(ebi('wtoggle'), 'm3u', v && (mp.au || msel.getsel().length));
});
bcfg_bind(r, 'follow', 'au_follow', false, setaufollow);
bcfg_bind(r, 'ac_flac', 'ac_flac', true);
bcfg_bind(r, 'ac_aac', 'ac_aac', false);
@@ -2620,6 +2654,7 @@ if (can_owa && APPLE && / OS ([1-9]|1[0-7])_/.test(UA))
mpl.init_ac2();
var re_m3u = /\.(m3u8?)$/i;
var re_au_native = (can_ogg || have_acode) ? /\.(aac|flac|m4a|mp3|ogg|opus|wav)$/i : /\.(aac|flac|m4a|mp3|wav)$/i,
re_au_all = /\.(aac|ac3|aif|aiff|alac|alaw|amr|ape|au|dfpwm|dts|flac|gsm|it|itgz|itxz|itz|m4a|mdgz|mdxz|mdz|mo3|mod|mp2|mp3|mpc|mptm|mt2|mulaw|ogg|okt|opus|ra|s3m|s3gz|s3xz|s3z|tak|tta|ulaw|wav|wma|wv|xm|xmgz|xmxz|xmz|xpk|3gp|asf|avi|flv|m4v|mkv|mov|mp4|mpeg|mpeg2|mpegts|mpg|mpg2|nut|ogm|ogv|rm|ts|vob|webm|wmv)$/i;
@@ -2646,9 +2681,9 @@ function MPlayer() {
link = link[link.length - 1];
var url = link.getAttribute('href'),
m = re_audio.exec(url.split('?')[0]);
fn = url.split('?')[0];
if (m) {
if (re_audio.exec(fn)) {
var tid = link.getAttribute('id');
r.order.push(tid);
r.tracks[tid] = url;
@@ -2656,6 +2691,11 @@ function MPlayer() {
ebi('a' + tid).onclick = ev_play;
clmod(trs[a], 'au', 1);
}
else if (re_m3u.exec(fn)) {
var tid = link.getAttribute('id');
tds[0].innerHTML = '<a id="a' + tid + '" href="#a' + tid + '" class="play">' + L.mb_play + '</a></td>';
ebi('a' + tid).onclick = ev_load_m3u;
}
}
r.vol = clamp(fcfg_get('vol', IPHONE ? 1 : dvol / 100), 0, 1);
@@ -2821,6 +2861,14 @@ function MPlayer() {
r.fau.loop = true;
r.fau.play();
};
r.set_ev = function () {
mp.au.onended = evau_end;
mp.au.onerror = evau_error;
mp.au.onprogress = pbar.drawpos;
mp.au.onplaying = mpui.progress_updater;
mp.au.onloadeddata = mp.au.onloadedmetadata = mp.nopause;
};
}
@@ -2862,6 +2910,8 @@ var widget = (function () {
wtico = ebi('wtico'),
nptxt = ebi('nptxt'),
npirc = ebi('npirc'),
m3ua = ebi('m3ua'),
m3uc = ebi('m3uc'),
touchmode = false,
was_paused = true;
@@ -2920,6 +2970,49 @@ var widget = (function () {
toast.ok(1, L.clipped, null, 'top');
});
};
m3ua.onclick = function (e) {
ev(e);
var el,
files = [],
sel = msel.getsel();
for (var a = 0; a < sel.length; a++) {
el = ebi(sel[a].id).closest('tr');
if (clgot(el, 'au'))
files.push(el);
}
el = QS('#files tr.play');
if (!sel.length && el)
files.push(el);
for (var a = 0; a < files.length; a++) {
var md = ft2dict(files[a])[0],
dur = md['.dur'] || '1',
tag = '';
if (md.artist && md.title)
tag = md.artist + ' - ' + md.title;
else if (md.artist)
tag = md.artist + ' - ' + md.file;
else if (md.title)
tag = md.title;
if (dur.indexOf(':') > 0) {
dur = dur.split(':');
dur = 60 * parseInt(dur[0]) + parseInt(dur[1]);
}
else dur = parseInt(dur);
mpl.m3ut += '#EXTINF:' + dur + ',' + tag + '\n' + uricom_dec(get_evpath()) + md.file + '\n';
}
toast.ok(2, files.length == 1 ? L.m3u_add1 : L.m3u_addn.format(files.length), null, 'top');
};
m3uc.onclick = function (e) {
ev(e);
cliptxt(mpl.m3ut, function () {
toast.ok(15, L.m3u_clip, null, 'top');
});
};
r.set(sread('au_open') == 1);
setTimeout(function () {
clmod(widget, 'anim', 1);
@@ -4058,10 +4151,7 @@ function play(tid, is_ev, seek) {
else {
mp.au = new Audio();
mp.au2 = new Audio();
mp.au.onerror = evau_error;
mp.au.onprogress = pbar.drawpos;
mp.au.onplaying = mpui.progress_updater;
mp.au.onended = next_song;
mp.set_ev();
widget.open();
}
mp.init_fau();
@@ -4074,13 +4164,9 @@ function play(tid, is_ev, seek) {
var t = mp.au;
mp.au = mp.au2;
mp.au2 = t;
t.onerror = t.onprogress = t.onended = null;
t.onerror = t.onprogress = t.onended = t.loop = null;
t.ld = 0; //owa
mp.au.onerror = evau_error;
mp.au.onprogress = pbar.drawpos;
mp.au.onplaying = mpui.progress_updater;
mp.au.onloadeddata = mp.au.onloadedmetadata = mp.nopause;
mp.au.onended = next_song;
mp.set_ev();
t = mp.au.currentTime;
if (isNum(t) && t > 0.1)
mp.au.currentTime = 0;
@@ -4110,6 +4196,7 @@ function play(tid, is_ev, seek) {
clmod(ebi(oid), 'act', 1);
clmod(ebi(oid).closest('tr'), 'play', 1);
clmod(ebi('wtoggle'), 'np', mpl.clip);
clmod(ebi('wtoggle'), 'm3u', mpl.m3uen);
if (thegrid)
thegrid.loadsel();
@@ -4118,6 +4205,7 @@ function play(tid, is_ev, seek) {
try {
mp.nopause();
mp.au.loop = mpl.loop;
if (mpl.aplay || is_ev !== -1)
mp.au.play();
@@ -4162,6 +4250,15 @@ function scroll2playing() {
}
function evau_end(e) {
if (!mpl.loop)
return next_song(e);
ev(e);
mp.au.currentTime = 0;
mp.au.play();
}
// event from the audio object if something breaks
function evau_error(e) {
var err = '',
@@ -4374,6 +4471,11 @@ function eval_hash() {
goto(v.slice(3));
return;
}
if (v.startsWith("#m3u=")) {
load_m3u(v.slice(5));
return;
}
}
@@ -4715,6 +4817,7 @@ var fileman = (function () {
clmod(bshr, 'hide', hshr);
clmod(ebi('wfm'), 'act', QS('#wfm a.en:not(.hide)'));
clmod(ebi('wtoggle'), 'm3u', mpl.m3uen && (nsel || (mp && mp.au)));
var wfs = ebi('wfs'), h = '';
try {
@@ -6740,11 +6843,16 @@ var ahotkeys = function (e) {
}
if (in_ftab || !aet || (ae && ae.closest('#ggrid'))) {
if ((k == 'KeyA' || k == 'a') && ctrl(e)) {
var sel = msel.getsel(),
var ntot = treectl.lsc.files.length + treectl.lsc.dirs.length,
sel = msel.getsel(),
all = msel.getall();
msel.evsel(e, sel.length < all.length);
msel.origin_id(null);
if (ntot > all.length)
toast.warn(10, L.f_anota.format(all.length, ntot), L.f_anota);
else if (toast.tag == L.f_anota)
toast.hide();
return ev(e);
}
}
@@ -6874,7 +6982,7 @@ var ahotkeys = function (e) {
// search
(function () {
var search_ui = (function () {
var sconf = [
[
L.s_sz,
@@ -6909,7 +7017,8 @@ var ahotkeys = function (e) {
]
];
var trs = [],
var r = {},
trs = [],
orig_url = null,
orig_html = null,
cap = 125;
@@ -7116,13 +7225,19 @@ var ahotkeys = function (e) {
search_in_progress = 0;
srch_msg(false, '');
var res = JSON.parse(this.responseText),
tagord = res.tag_order;
var res = JSON.parse(this.responseText);
r.render(res, this, true);
}
sortfiles(res.hits);
r.render = function (res, xhr, sort) {
var tagord = res.tag_order;
srch_msg(false, '');
if (sort)
sortfiles(res.hits);
var ofiles = ebi('files');
if (ofiles.getAttribute('ts') > this.ts)
if (xhr && ofiles.getAttribute('ts') > xhr.ts)
return;
treectl.hide();
@@ -7174,19 +7289,21 @@ var ahotkeys = function (e) {
}
ofiles = set_files_html(html.join('\n'));
ofiles.setAttribute("ts", this.ts);
ofiles.setAttribute("q_raw", this.q_raw);
ofiles.setAttribute("ts", xhr ? xhr.ts : 1);
ofiles.setAttribute("q_raw", xhr ? xhr.q_raw : 'playlist');
set_vq();
mukey.render();
reload_browser();
filecols.set_style(['File Name']);
sethash('q=' + uricom_enc(this.q_raw));
if (xhr)
sethash('q=' + uricom_enc(xhr.q_raw));
ebi('unsearch').onclick = unsearch;
var m = ebi('moar');
if (m)
m.onclick = moar;
}
};
function unsearch(e) {
ev(e);
@@ -7203,9 +7320,98 @@ var ahotkeys = function (e) {
cap *= 2;
do_search();
}
return r;
})();
function ev_load_m3u(e) {
ev(e);
var id = this.getAttribute('id').slice(1),
url = ebi(id).getAttribute('href').split('?')[0];
modal.confirm(L.mm_m3u,
function () { load_m3u(url); },
function () {
if (has(perms, 'write') && has(perms, 'delete'))
window.location = url + '?edit';
else
showfile.show(url);
}
);
return false;
}
function load_m3u(url) {
var xhr = new XHR();
xhr.open('GET', url, true);
xhr.onload = render_m3u;
xhr.url = url;
xhr.send();
return false;
}
function render_m3u() {
if (!xhrchk(this, L.tv_xe1, L.tv_xe2))
return;
var evp = get_evpath(),
m3u = this.responseText,
xtd = m3u.slice(0, 12).indexOf('#EXTM3U') + 1,
lines = m3u.replace(/\r/g, '\n').split('\n'),
dur = 1,
artist = '',
title = '',
ret = {'hits': [], 'tag_order': ['artist', 'title', '.dur'], 'trunc': false};
for (var a = 0; a < lines.length; a++) {
var ln = lines[a].trim();
if (xtd && ln.startsWith('#')) {
var m = /^#EXTINF:([0-9]+)[, ](.*)/.exec(ln);
if (m) {
dur = m[1];
title = m[2];
var ofs = title.indexOf(' - ');
if (ofs > 0) {
artist = title.slice(0, ofs);
title = title.slice(ofs + 3);
}
}
continue;
}
if (ln.indexOf('.') < 0)
continue;
var n = ret.hits.length + 1,
url = ln;
if (url.indexOf(':\\')) // C:\
url = url.split(/\\/g).pop();
url = url.replace(/\\/g, '/');
url = uricom_enc(url).replace(/%2f/gi, '/')
if (!url.startsWith('/'))
url = vjoin(evp, url);
ret.hits.push({
"ts": 946684800 + n,
"sz": 100000 + n,
"rp": url,
"tags": {".dur": dur, "artist": artist, "title": title}
});
dur = 1;
artist = title = '';
}
search_ui.render(ret, null, false);
sethash('m3u=' + this.url.split('?')[0].split('/').pop());
goto();
var el = QS('#files>tbody>tr.au>td>a.play');
if (el)
el.click();
}
function aligngriditems() {
if (!treectl)
return;
@@ -8107,7 +8313,7 @@ var treectl = (function () {
document.documentElement.scrollLeft = 0;
setTimeout(function () {
r.gentab(get_evpath(), r.lsc);
ebi('wrap').style.opacity = 'unset';
ebi('wrap').style.opacity = CLOSEST ? 'unset' : 1;
}, 1);
};
@@ -8260,7 +8466,7 @@ var wfp_debounce = (function () {
if (--r.n <= 0) {
r.n = 0;
clearTimeout(r.t);
ebi('wfp').style.opacity = 'unset';
ebi('wfp').style.opacity = CLOSEST ? 'unset' : 1;
}
};
r.reset = function () {
@@ -9431,6 +9637,11 @@ function sandbox(tgt, rules, allow, cls, html) {
clmod(tgt, 'sb');
return false;
}
if (!CLOSEST) {
tgt.textContent = html;
clmod(tgt, 'sb');
return false;
}
clmod(tgt, 'sb', 1);
var tid = tgt.getAttribute('id'),
@@ -9498,7 +9709,7 @@ window.addEventListener("message", function (e) {
el.parentNode.removeChild(el.previousSibling);
el.style.height = (parseInt(t[2]) + SBH) + 'px';
el.style.visibility = 'unset';
el.style.visibility = CLOSEST ? 'unset' : 'block';
wfp_debounce.show();
}
else if (t[0] == 'iscroll') {

View File

@@ -364,7 +364,8 @@ if (!Element.prototype.matches)
Element.prototype.mozMatchesSelector ||
Element.prototype.webkitMatchesSelector;
if (!Element.prototype.closest)
var CLOSEST = !!Element.prototype.closest;
if (!CLOSEST)
Element.prototype.closest = function (s) {
var el = this;
do {

View File

@@ -1,3 +1,50 @@
▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
# 2025-0420-1836 `v1.16.21` unzip-compat
a couple guys have been asking if I accept donations -- thanks a lot!! added a few options on [my github page](https://github.com/9001/) :>
## 🧪 new features
* #156 add button to loop/repeat music 71c55659
## 🩹 bugfixes
* #155 download-as-zip: increase compatibility with the unix `unzip` command db33d68d
* this unfortunately reduces support for huge zipfiles on old software (WinXP and such)
* and makes it less safe to stream zips into unzippers, so use tar.gz instead
* and is perhaps not even a copyparty bug; see commit-message for the full story
## 🔧 other changes
* show warning on Ctrl-A in lazy-loaded folders 5b3a5fe7
* docker: hide keepalive pings from logs d5a9bd80
▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
# 2025-0413-2151 `v1.16.20` all sorted
## 🧪 new features
* when enabled, natural-sort will now also apply to tags, not just filenames 7b2bd6da
## 🩹 bugfixes
* some sorting-related stuff 7b2bd6da
* folders with non-ascii names would sort incorrectly in the navpane/sidebar
* natural-sort didn't apply correctly after changing the sort order
* workaround [ffmpeg-bug 10797](https://trac.ffmpeg.org/ticket/10797) 98dcaee2
* reduces ram usage from 1534 to 230 MiB when generating spectrograms of s3xmodit songs (amiga chiptunes)
* disable mdns if only listening on uds (unix-sockets) ffc16109 361aebf8
## 🔧 other changes
* hotkey CTRL-A will now select all files in gridview 233075ae
* and it toggles (just like in list-view) so try pressing it again
* copyparty.exe: upgrade to pillow v11.2.1 c7aa1a35
▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
# 2025-0408-2132 `v1.16.19` GHOST

View File

@@ -17,7 +17,8 @@ services:
stop_grace_period: 15s # thumbnailer is allowed to continue finishing up for 10s after the shutdown signal
healthcheck:
test: ["CMD-SHELL", "wget --spider -q 127.0.0.1:3923/?reset"]
# hide it from logs with "/._" so it matches the default --lf-url filter
test: ["CMD-SHELL", "wget --spider -q 127.0.0.1:3923/?reset=/._"]
interval: 1m
timeout: 2s
retries: 5

View File

@@ -22,12 +22,6 @@ services:
- 'traefik.http.routers.fs.rule=Host(`fs.example.com`)'
- 'traefik.http.routers.fs.entrypoints=http'
#- 'traefik.http.routers.fs.middlewares=authelia@docker' # TODO: ???
healthcheck:
test: ["CMD-SHELL", "wget --spider -q 127.0.0.1:3923/?reset"]
interval: 1m
timeout: 2s
retries: 5
start_period: 15s
stop_grace_period: 15s # thumbnailer is allowed to continue finishing up for 10s after the shutdown signal
environment:
LD_PRELOAD: /usr/lib/libmimalloc-secure.so.NOPE

View File

@@ -357,6 +357,7 @@ var tl_browser = {
"ml_eq": "audio equalizer",
"ml_drc": "dynamic range compressor",
"mt_loop": "loop/repeat one song\">🔁",
"mt_shuf": "shuffle the songs in each folder\">🔀",
"mt_aplay": "autoplay if there is a song-ID in the link you clicked to access the server$N$Ndisabling this will also stop the page URL from being updated with song-IDs when playing music, to prevent autoplay if these settings are lost but the URL remains\">a▶",
"mt_preload": "start loading the next song near the end for gapless playback\">preload",
@@ -402,6 +403,7 @@ var tl_browser = {
"mm_eunk": "Unknown Errol",
"mm_e404": "Could not play audio; error 404: File not found.",
"mm_e403": "Could not play audio; error 403: Access denied.\n\nTry pressing F5 to reload, maybe you got logged out",
"mm_e500": "Could not play audio; error 500: Check server logs.",
"mm_e5xx": "Could not play audio; server error ",
"mm_nof": "not finding any more audio files nearby",
"mm_prescan": "Looking for music to play next...",
@@ -416,6 +418,7 @@ var tl_browser = {
"f_bigtxt": "this file is {0} MiB large -- really view as text?",
"fbd_more": '<div id="blazy">showing <code>{0}</code> of <code>{1}</code> files; <a href="#" id="bd_more">show {2}</a> or <a href="#" id="bd_all">show all</a></div>',
"fbd_all": '<div id="blazy">showing <code>{0}</code> of <code>{1}</code> files; <a href="#" id="bd_all">show all</a></div>',
"f_anota": "only {0} of the {1} items were selected;\nto select the full folder, first scroll to the bottom",
"f_dls": 'the file links in the current folder have\nbeen changed into download links',