All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
- Bearer API key auth on the qBittorrent-compat API — Sonarr's recent (May 2026) qBittorrent download client added an "API Key" mode that sends
Authorization: Bearer <apiKey>on every request and skips the cookie login round-trip entirely. The protected/api/v2/*middleware now accepts this header alongside the existing modes, looking up the key via the user's personal API key. Admin role required. See INTEGRATIONS.md for the per-mode setup table (#52). - Session cookie support on
/api/v2/auth/login— successful login now issuesSet-Cookie: SID=<token>; HttpOnly; Path=/api/v2; SameSite=Laxwith a 1h sliding-window TTL. This makes Sonarr's classic username/password mode actually work when authentication is enabled (previously broken — see Fixed). qBit-native browser clients also work against the compat layer now. Logout invalidates the session server-side and clears the cookie.
- Deluge statistics zeroed out by every Deluge restart. Deluge exposes
total_upload/total_downloadviacore.get_session_status, which are libtorrent session counters that reset to 0 on every Deluge restart. We were writing the raw value straight intoinstance_metrics.total_uploaded, so each restart became a 0-row and the bucket aggregation'sMIN(total_uploaded) = 0 → 0guard wiped the entire containing bucket — 1h on the 24h chart (mostly unaffected), 1d on the 7d/30d charts (one restart killed an entire day). Reporter saw7d total < 24h total. Deluge's WebUI JSON-RPC doesn't expose a stable PID we could key off (the way we do for rTorrent), so the new path detects restarts via value-decrease — session counters are monotonic during a single run by definition, socurrent < previousis itself a reliable signal. NewtracksCounterResetcapability gates a parallel branch in_writeInstanceMetricsthat mirrors the rTorrent carryforward, just with a different trigger. Forward-looking: existing zero-rows inmetrics.dbstay zero (we can't reconstruct what the counter would have been); the 7d/30d charts fill back in correctly over the following 30 days as post-fix samples accumulate (#47). - Sonarr/Radarr's classic username/password mode was silently broken with server-side auth enabled. Login returned
"Ok."but never set a Set-Cookie, so every subsequent request hit our Basic-Auth-only middleware demanding credentials Sonarr never sends (it expects the session cookie it just got). The only way *arr integrations worked previously was withauth.enabled = false. Fixed in the same pass as the Bearer support — the middleware now accepts the SID cookie issued by login, returns 403 (not 401) on invalid/expired sessions so Sonarr'sQBittorrentProxyV2.csre-auth path fires correctly (#52).
- False-positive aMule "Download Complete" notifications when corrupted pieces transiently lifted byte counters past file size. The v3.8.2
isCompleteflag for aMule downloads used bytes-equality onfileSizeDownloaded(=EC_TAG_PARTFILE_SIZE_DONE), which counts every byte received from peers including pieces that subsequently failed hash check before being discarded — so the counter could briefly meet or exceedfileSizewhile real file content was still missing, firing adownloadFinishedevent before the file was actually on disk. The check now derives completion from the lib's decoded gap status: an empty range list means every byte is hashed and written (the same computation aMule shows as "Verified & Written" in its UI). Read on the raw lib field beforeflattenRangePairs(), since that helper collapses both the empty and undefined cases tonull.
- aMule reconnect loop after deleting the last shared file. The 1→0 shared-list desync heuristic couldn't tell a legitimate "deleted my only file" transition from a phantom drop, and the throw at the desync site short-circuited the snapshot update two lines below — so the previous-frame count stayed stuck and every successful reconnect re-fired the same desync, looping indefinitely. Detection now matches against hashes we deleted ourselves (recorded by
deleteItem's shared branch) and only fires when there's an unexplained disappearance, with the snapshot update always running so worst case is one reconnect (#49). - Repeated
downloadFinishednotifications for a single aMule download. The history-update path was still keyed off the toFixed-rounded display progress, which flips at 99.995% bytes. Combined with the activeKeys SQL resettingcompleted → downloading, lib-reported progress oscillating around "100.00"/"99.99" re-fired the notification on every flip. Now uses the same per-clientisCompleteflag the rest of the system unified on in v3.8.2.
- Downloads marked complete at 99.995% of bytes received. Every normalizer was running progress through
parseFloat((x).toFixed(2))for display, and the unified item builder then used that rounded value (progress >= 100) as the completion oracle. JavaScript's.toFixed(2)rounds half-away-from-zero, so e.g. a 100GB aMule file with 5MB still missing (99.9952%) got flipped tocomplete=true— prematurepausedUPstate in the qBit-compat layer, premature shared-vs-active routing in delete/pause handlers. Completion is now sourced per-client from authoritative signals: aMule from bytes-equality onEC_TAG_PARTFILE_SIZE_DONE(verified parts only), rTorrent fromd.complete=, qBittorrent from rawprogress >= 1.0, Deluge from rawprogress >= 100, Transmission frompercentDone >= 1.0. Displayprogressstays at 2-decimal precision; only the completion flag changed. - Transmission
downloadedcounter could exceed total size on poisoned torrents — the field was being shipped fromdownloadedEver, which Transmission's docs explicitly warn "can grow very large" since it includes redundant re-fetches of corrupt data. NowhaveValid + haveUnchecked(bytes actually on disk). - Sonarr/Radarr never called
torrents/deleteafter import even after the v3.8.1pausedUPstate fix. Tracing Radarr'sQBittorrent.cs:240:CanBeRemovedrequires three conjuncts —RemoveCompletedDownloads,state ∈ {pausedUP, stoppedUP}, ANDHasReachedSeedLimit. We were emittingratio_limit: -2(= "use global config"), which only resolves to true if the user hasMaxRatioEnabledin qBit's preferences. The compat layer now emitsratio_limit: 0, realratio/uploaded/upspeedvalues fromEC_TAG_KNOWNFILE_XFERRED_ALL, so all three conjuncts are satisfied at completion and*arrcleanup fires (#42). /api/v2/torrents/inforeturned[]intermittently when no WebSocket clients were connected —autoRefreshManagerskipsgetBatchData()entirely when no WS clients are connected (the WS-or-history-due gate), so the cache aged out past the qBit-compat handler's 10s freshness window and the handler shipped empty arrays. The handler now uses a newDataFetchService.getOrFetchBatchData()that fetches on cache miss;getBatchData()itself is coalesced — concurrent callers (autoRefresh loop + Sonarr/Radarr/Prowlarr polls) share one in-flight fetch instead of triggering parallel client queries (#42).
- Dedicated WARN/ERROR ring buffer — the main 2000-record log ring is FIFO across all levels, so a chatty DEBUG source could scroll warnings out of the LogsView within minutes. A secondary 500-record ring now keeps WARN/ERROR records exclusively, queried when LogsView's level filter is set to "Warnings & errors" or "Errors only". The main ring still serves info/debug as before; the source filter dropdown unions sources from both rings so older warnings stay discoverable.
- LogsView level filter routes through the dedicated ring server-side — passing
minLeveltogetAppLoglets the server walk the dedicated ERROR/WARN ring when warn/error is selected, surfacing entries far older than the 2000-record main window. Replaces the previous client-side post-filter which depended on whatever happened to be in the main ring at fetch time. - Backward-walking log seed on startup — instead of replaying the last 2000 file lines (which would evict every WARN/ERROR if those were rare in the tail), the seeder now walks the file backwards filling two buckets independently: up to 2000 records for the main ring, up to 500 ERROR/WARN records for the important ring. Stops as soon as both fill, so scan cost stays bounded even on huge logs.
- LogsView timestamp format — drops millisecond precision from the visible row (kept in hover tooltip) and prepends a date when the record isn't from today:
HH:MM:SSfor today,MM-DD HH:MM:SSfor older same-year history,YYYY-MM-DD HH:MM:SSacross year boundaries.
- qBittorrent 5.2.0 connection failure ("Login failed: Invalid credentials"). qBittorrent 5.2 renamed the session cookie from
SIDtoQBT_SID_<webUIPort>and dropped theOk.body in favor ofHTTP 204with empty content. The HTTP client now stores whatever cookie name the server returns (also handles 5.1.x's user-configurableWebAPISessionCookieNamepreference) and treats any 2xx response as success. Backward compatible with qBittorrent 5.1.4 and earlier (#48). - qBittorrent compat layer (Sonarr/Radarr/Prowlarr) —
pauseTorrentnow actually pauses the matching aMule download (was a no-op before),deleteTorrenthonors thedeleteFilesflag, and completed downloads now reportpausedUPstate so *arr cleanup correctly identifies them as ready for import (#42).
- Structured logging across the server — every log call now produces a record with a level (
error/warn/info/debug), a source tag (instance ID, module name, or<ip>(user, nick)for WS sessions), and an ISO timestamp. The file format is[ts] [LEVEL] [source] message; an in-memory ring buffer keeps the last 2000 records, seeded from the file tail at startup so the LogsView keeps history across restarts. - Filterable LogsView with three controls: minimum-level (
Errors only/Warnings & errors/Info & above/All (debug)), multi-select source filter (OR semantics, sources grouped semantically as(server)→ instances → user sessions → modules), and free-text search. Records render with per-level row coloring (red / amber / default / muted), absolute-positioned local-timezone timestamp, and a truncated source chip. - Mobile LogsView UX —
ExpandableSearch+MobileFilterButtonin the header (active-filter count badge), filters housed in aMobileFilterSheet(level radio + source checkboxes), and reflowed row layout that doesn't push content off-screen on narrow viewports. MultiSelectPopover(shared) — generic checkbox-list popover extracted fromTrackerMultiSelect. Same OR-semantics multi-select UX is now reused by the LogsView source filter;TrackerMultiSelectis a thin wrapper that injects favicon decorations.
- aMule state desync detection — when
getUpdate()returns successfully but_updateStatecollapses (sharedFiles count drops from non-zero to zero), the manager now treats it the same as a thrown failure: closes the stale socket so aMule'sCValueMapresets, schedules a 1 s reconnect, and lets the next full-state fetch resync both sides. Previously this case was silently accepted and the UI kept showing a stale "no items" frame indefinitely. - Log levels properly tuned across the codebase — every
this.log('❌ …')is nowthis.error(…), everythis.log('⚠️ …')isthis.warn(…), and unprefixed catch-block logs (Error / Failed / Cannot / Unable patterns) were upgraded too. High-cadence trace lines (HTTP request middleware, WS message receipts, routine fetch-success traces) demoted todebugso theinfostream is meaningful by default. Auth/SSO events at correct severity throughout.
- Add Download modal grew beyond the viewport when many
.torrentfiles were selected, hiding the download path field and action buttons (#40). The modal box now caps at85vh(mobile-md) /90vh(desktop), letting the body scroll while the header and footer stay visible.
- Doubled
refreshSharedFiles()every auto-reload cycle — the v3.7.0 fix that maderescanAndWrite()reload aMule on connect also unintentionally caused the hourly auto-reload scheduler to callrefreshSharedFiles()twice per cycle (once insiderescanAndWrite(), once standalone right after). Over many hours with large shared libraries this could wedge aMule's EC handler. The scheduler now delegates the reload torescanAndWrite()when shared-dir roots are configured, or does a standalone refresh when not — never both. - Silent
getUpdate()failure masking state drift — the aMule fetch loop was swallowinggetUpdate()errors and returning empty arrays, making the UI show "no items" while on-demand calls (search, logs, categories) still worked. Worse, aMule's server-sideCValueMapflips to "delivered" even when our request times out, permanently desyncing the incremental diff state for any fields that changed in that cycle. Now: a failedgetUpdate()explicitly closes the stale socket (resetting aMule's valuemap), clears the client, and schedules a 1 s reconnect — so the next full-state fetch resynchronizes both sides cleanly. - Transient fetch failures no longer flash the UI to empty —
DataFetchServicenow caches the last successful frame per client manager and reuses it for one cycle on a transient fetch exception (aMule reconnecting, a BitTorrent client's HTTP timeout, etc.). The next cycle reflects whatever real state then returns. Applies to all managers, not just aMule.
- Set Rating & Comment on shared files (aMule) — new action in the Shared files context menu opens a star-picker + textarea modal. Exposed via WebSocket (
setFileRatingComment) and HTTP (POST /api/v1/downloads/rating-comment). Guarded by a newset_commentcapability set_commentcapability — new sibling torename_files, added toALL_CAPABILITIES,SSO_DEFAULT_CAPABILITIES, the "Full" preset, CAPABILITY_GROUPS (Downloads), and the history-import migration defaults. Shown in the User Management UI- Star rating column on aMule search results (desktop, sortable) — rendered when aMule emits a rating (requires aMule PR #452). Mobile cards show the rating in the detail row alongside size and sources
- Canonical
comment/ratingfields on unified shared items replace the rawEC_TAG_KNOWNFILE_*plumbing in the File Info modal. Rating + Comment rows are always shown under "File Identification" with "Not rated" / "No comment" placeholders when unset - Peer completion percentage for aMule in the File Info modal — the "Done" column now renders for aMule peers too, matching the native aMule GUI's segment-bar semantics. Download sources use
EC_TAG_CLIENT_AVAILABLE_PARTSdirectly; upload peers use the peer-reportedEC_TAG_CLIENT_UPLOAD_PART_STATUSbitmap (bits counted on our side) because aMule'savailablePartsreads the download-side bitmap and is always 0 for pure uploaders. - Download Path column in Downloads and Shared Files views (desktop, hidden by default, togglable via "Configure columns"). For aMule partfiles without a filesystem path, falls back to the category's configured path or the client's default download directory
- Tracker favicons across the app — fetched on first use, cached to disk under
data/favicons/with a 24h TTL and stale-on-failure fallback, served viaGET /api/favicon/tracker/:host. Rendered in tracker labels, desktop filter trigger/dropdown, mobile filter sheet, and mobile filter pills; falls back to aservericon when a favicon isn't reachable. 1MB per-blob cap, single-flight per host to dedupe concurrent fetches - Multi-select tracker filter (desktop) — custom popover dropdown with per-row favicons, summary count in the trigger, click-outside/Escape dismissal, and "Clear" action. Multiple trackers use OR logic; selections reflect into the mobile pills/sheet
shareddir.datreload fires on connect —rescanAndWrite()now threads the manager intoexpandAndWrite(), so aMule re-reads the refreshed file after the server-side sync on connect (previously wrote the file but never triggered the reload)- Segments bar renders for aMule files with 0 sources — both in the File Info modal and on the Downloads-view progress bar hover. aMule skips emitting
EC_TAG_PARTFILE_PART_STATUSwhen no sources are contributing part-frequency data, but still emitsEC_TAG_PARTFILE_GAP_STATUS. We now fall back to gap-only rendering: completed regions stay green, missing regions show solid red (the "missing, no sources" color in aMule's own palette) - File Info modal is wider on desktop — bumped from
max-w-4xltomax-w-5xlso long tracker URLs, paths, and peer comment lists breathe a bit more. Mobile is unchanged (stillw-full) - Multiple peer ratings now rendered in the Download Info modal — aMule emits
EC_TAG_PARTFILE_COMMENTSas a flat sequence of 4 child tags per peer (username, filename, rating, comment), all under the same tag ID. The formatter now chunks the array back into tuples and renders one card per peer (previously silently truncated to the first peer only) - Column config respects
defaultHiddenfor newly-added columns — previously, once a user saved a column configuration, any column added in a later release was forced visible. Now columns declared hidden-by-default stay hidden for existing users too - SSO / history-import capability defaults unified —
userManager.jsis the single source of truth forSSO_DEFAULT_CAPABILITIES;trustedProxy.jsand the legacy history-user import both consume the same list, so adding a default-on capability only requires one edit - Dockerfile copies
server/package-lock.jsonand usesnpm ci— ensures deterministic installs and that lockfile bumps (e.g. git-dep SHA updates) actually invalidate the Docker layer instead of serving cachednode_modules
- amule-ec-node — four updates since 3.6.1:
- Mojibake filename correction — non-ASCII filenames (CJK, accented European, etc.) that aMule reports in the wrong encoding are now decoded correctly. The raw value is preserved as
rawFileNameso move/category commands still address the file by the name aMule expects - Canonical
comment/ratingparsing plus a newsetFileRatingCommentmethod for shared files (8da8eaa) - Aggregated user rating on search results (95879bb, requires aMule PR #452 to be merged upstream or applied to your aMule build for the tag to actually be emitted)
EC_TAG_CLIENT_UPLOAD_PART_STATUSparsing (df97f5e) — exposes the peer-reported part bitmap for upload peers so we can compute their real completion %, matching what aMule's native GUI shows
- Mojibake filename correction — non-ASCII filenames (CJK, accented European, etc.) that aMule reports in the wrong encoding are now decoded correctly. The raw value is preserved as
- Queued uploads in Uploads view — shows queued, connecting, and pending aMule upload peers (not just active uploaders). Upload state labels (e.g. "Queued", "Connecting") shown with clock icon when peer has no active transfer
- Shared Dirs button in Settings — aMule client cards show a "Shared Dirs" button when connected, opening the Shared Dirs modal pre-selected to that instance
- Chart crosshair interaction (mobile) — home speed widget replaces the obstructive tooltip with a vertical crosshair line; hovering/touching shows historical speed + timestamp in the status bar, reverting to live speeds on release
- Chart tooltip timestamps (Statistics) — 7-day and 30-day chart tooltips now show
DD/MM HH:MMinstead of justDD/MM
- eMule client software labels —
CLIENT_SOFTWARE_LABELSmapping corrected to match aMule sourceEClientSoftwareenum (18 client types); SO_EMULE=0 was incorrectly mapped to "aMule" instead of "eMule"
- amule-ec-node — updated with authentication salt fix (leading zeros)
- Custom save path for downloads — "Edit Save Path" button in the Add Download modal lets you override the category's default download directory. Available for all BitTorrent clients (rTorrent, qBittorrent, Deluge, Transmission). Quick destination buttons reuse category paths, or enter a custom path manually. Summary line shows the effective path in bold
- aMule shared directory management (experimental) — manage aMule's
shareddir.datfrom the Shared Files view via "Manage Shared Dirs". Add/remove root directories with automatic subdirectory expansion. Roots are persisted to config and survive aMule reboots — auto-synced on connect and periodic reload. Includes directory browser, instance selector for multi-aMule setups, and Docker-aware info box
- rTorrent magnet handling — properties (label, directory, priority) now passed as inline load commands instead of post-load RPC calls, fixing metadata resolution resetting properties
- rTorrent torrent file handling — also uses inline load commands, removing the paused-load workaround
- Docker host detection for default hostname — wizard and settings default client host to
host.docker.internalwhen running in Docker - Client connection defaults centralized in
clientMeta.js(connectionDefaults) — single source of truth for default ports, paths, and usernames.config.jsandClientInstanceModalboth derive from it - Move to... modal — filename now uses
break-allfor long names
- Setup wizard test button stuck disabled — Deluge/Transmission fields had no default port values in the API defaults response, causing the "Test BitTorrent Connections" button to stay disabled. Fixed by populating
connectionDefaultsfor all client types
- IPv6 fallback for server listen — server now tries
::(dual-stack) first and automatically falls back to0.0.0.0if IPv6 is not available (EAFNOSUPPORT/EADDRNOTAVAIL), fixing startup failures on IPv4-only hosts (#38) - Setup wizard blocked by auth on first run — when
WEB_AUTH_ENABLED=truewas set without aWEB_AUTH_PASSWORD(the default in the Unraid template), the login page blocked access to the setup wizard. Auth is now automatically disabled for the setup wizard when no password is configured, and re-enabled once the user sets one during setup (#39) - Config status endpoint auth —
/api/config/status(returns onlyfirstRunandisDocker) no longer requires admin authentication, allowing the frontend to detect first-run state before login
- REST API v1 — full HTTP REST API at
/api/v1/exposing all download management features: add/pause/resume/stop/delete downloads, categories CRUD, ED2K search (blocking and non-blocking), move files, permission checks, logs, and data snapshots. Zero code duplication — bridges directly to existing WebSocket handlers - API key authentication for REST API —
X-API-Keyheader support in the auth middleware, allowing stateless REST API access without session cookies. Populates session from the user's API key for seamless capability/ownership checks - API keys for all users — API keys are now generated for all users (not just admins), enabling scoped REST API access with limited capabilities (e.g., a user with only
add_downloadspermission). Torznab and qBittorrent-compatible APIs remain admin-only - Reverse proxy URL path for qBittorrent and Deluge — optional URL path field (e.g.,
/qbittorrent) for clients behind a reverse proxy. Available in Settings UI, Setup Wizard, and viaQBITTORRENT_PATH/DELUGE_PATHenvironment variables
- getStats disconnect detection — all client managers (rTorrent, qBittorrent, Deluge, Transmission) now trigger reconnect on stats fetch failure, not just data fetch failure. Fixes cases where client goes offline but health events don't fire
- API documentation — comprehensive docs for all REST API v1 endpoints with request/response examples, capability requirements, and authentication methods
- aMule category creation — aMule EC protocol returns no category ID on creation (
EC_OP_NOOP); now re-fetches category list after successful creation to discover the new ID by name - Batch delete event clientType resolution — delete event emission now uses the manager's
clientType(always reliable) instead of relying on request body or cache lookup, fixing "Unknown client type: undefined" errors - aMule segment bar corruption — direct EC calls from qBittorrent-compatible API were interfering with aMule's server-side incremental diff state for
getUpdate(), causing XOR buffer corruption in segment visualization data.getTorrentsInfonow reads from cached DataFetchService data instead of callinggetDownloadQueue()/getSharedFiles()directly on the EC connection, preventing aMule incremental diff state corruption - Metrics recording — skips recording when
getStats()returns empty data (client unresponsive), preventing zero-value rows that drag down chart averages - SCGI socket config validation — config validation correctly requires
socketPathinstead ofhost/portfor SCGI socket mode. Fixes "host is required" error blocking config saves and version-seen tracking - Deluge and Transmission in wizard review step — setup wizard now shows all 5 client configurations in the final review step
- "Move to..." feature — standalone file move action in context menus (Downloads & Shared views) with category quick links, manual path input, permission pre-check, and batch support. Works with all clients via
MoveOperationManager - Per-instance download tracking — search results track which client instances have each download, allowing re-download to different clients.
- Magnet name resolution — rTorrent magnet downloads show the real name from history DB instead of
HASH.meta, with(resolving)indicator that clears automatically when metadata resolves - SCGI connection info — Settings client cards show
SCGI TCP: host:portorSCGI Socket: /pathinstead of "Not configured"
- rTorrent post-load property setting — label, directory, and priority are now set via separate
system.multicallafterload.raw_startinstead of inline arguments, avoiding rTorrent's 4KB execute arg buffer overflow (exec_file.cc buffer_size = 4096) - Tooltip component — Improved dark mode contrast with lighter background and border
- aMule EC timeout — increased from 30s to 60s for large shared file lists
- Reconnection resilience — requests are skipped during EC reconnection to prevent "Invalid request" spam on the aMule side
- aMule segment bar corruption — qBittorrent compatibility API was calling
getDownloadQueue()/getSharedFiles()directly on the EC connection, interfering with aMule's server-side incremental diff state forgetUpdate(). Now reads from cached data instead - aMule EC XOR reconstruction — fixed buffer resize logic to match aMule's
Realloc+ XOR algorithm. Clears client-side XOR state on reconnection to prevent stale diff corruption - rTorrent completed status — stopped torrents at 100% now correctly show "Stopped" instead of "Seeding" in Shared Files view (
completedstatus no longer mapped toseeding) - Client disconnect detection — all client managers now trigger reconnect on any fetch error, not just specific error codes (fixes SCGI socket
ENOENTnot being detected) - Search result delete tracking — deletion from one client only removes that instance from the per-instance download map, preserving other instances' status. Alias lookup handles Prowlarr GUID → real hash mapping
- Client health events — new
clientUnavailableandclientAvailableevents fire on connection state transitions, with debouncing (3 consecutive failures before declaring offline, immediate recovery on first success) - Health notifications — push notifications via Apprise when a client goes offline or comes back online, with configurable event toggles in the Notifications settings
- Notification flood prevention — per-client per-event-type rate limiter: after 3 notifications of the same type within 10 minutes, further notifications are suppressed for 1 hour. The last notification before suppression includes a warning. Online and offline notifications are tracked independently
- Health event scripting — new
EVENT_STATUS,EVENT_PREVIOUS_STATUS,EVENT_ERROR,EVENT_DOWNTIME_DURATIONenvironment variables for custom event scripts. Scripts receive all health events without flood suppression
- aMule EC connection recovery — consecutive request timeouts now trigger automatic socket destruction and reconnection, fixing stale connections that would hang indefinitely
- aMule null stats crash — fixed
Cannot read properties of null (reading 'EC_TAG_STATS_UL_SPEED')error during EC reconnection whengetStats()returned null from the request queue
- rTorrent SCGI connection modes — connect directly to rTorrent via SCGI TCP or Unix socket, bypassing the need for an HTTP proxy (nginx/ruTorrent). Three modes available: HTTP (default, existing behavior), SCGI (direct TCP), and SCGI Socket (Unix domain socket)
- Connection mode selector — new dropdown in both Settings and Setup Wizard for rTorrent instances, with conditional field visibility based on the selected mode (host/port for TCP modes, socket path for Unix socket, XML-RPC path/auth/SSL for HTTP only)
- SCGI environment variables —
RTORRENT_MODEandRTORRENT_SOCKET_PATHfor Docker/env-based configuration - Data fetch diagnostics — warnings logged when a connected client suddenly returns empty data, when an individual client fetch takes >10s, or when the full batch cycle exceeds 15s
- aMule fetch diagnostics — warning logged when
getUpdate()returns no data, indicating potential connection issues - Config test error logging — failed connection tests now log the error message (previously only showed pass/fail emoji)
- Global .torrent drag-and-drop — drop
.torrentfiles anywhere in the app to open the Add Download modal with files pre-loaded, not just from the Downloads view. Visual overlay guides the drop - FileInfoModal loading spinner — shows a spinner while fetching item detail data (raw fields, trackers) instead of blank sections
- EmptyState loading spinner — all table views (Downloads, Uploads, History, Shared) now show a spinner alongside loading messages instead of plain text
- Setup wizard auth blocking — fixed a bug where enabling authentication during first-run setup would fail with "Cannot enable authentication without an admin account", because the admin-account guard ran before the admin user was created by the migration step
- Move operation timeouts — timeout now scales with file size (assumes ~25 MB/s for 5200 RPM HDD under concurrent I/O, with 50% margin + 30s overhead, rounded to 30s intervals) instead of a fixed 2-minute limit
- Move operation logging — deduplicated failure logs from 3 redundant messages down to 1 with full context (file name, error cause, timeout duration)
- Unified native move naming — renamed
executeQBittorrentNativeMovetoexecuteNativeMoveand made all log messages use the actual client type (qBittorrent, Deluge, or Transmission) dynamically - Unified LoadingSpinner — replaced all 17 instances of the CSS
.loaderclass with theLoadingSpinnerReact component and removed the custom CSS rule/keyframes
- WebSocket delta updates — new DeltaEngine sends only changed fields per item instead of full snapshots, with seq-based synchronization and automatic snapshot recovery on gaps. Includes peer-level diffing (by peer ID, only changed fields transmitted — ~26KB → ~2KB per cycle) and flat array format for segment data (~56% smaller)
- Subscription-based segment data —
gapStatus/reqStatusonly sent to clients subscribed to thesegmentDatachannel (DownloadsView, FileInfoModal), with reference-counted subscribe/unsubscribe and automatic re-subscribe on reconnect. Saves ~27KB per update for all other views - Username in notifications — Apprise notifications now show the file owner and, when different, who triggered the action (e.g.
👤 john (by admin) · 🏷️ Linux) - Username in event scripts — new
EVENT_OWNERandEVENT_TRIGGERED_BYenvironment variables and JSON fields for custom event scripts - EC_TAG_PARTFILE_SHARED support — aMule downloads that are also being shared now appear in SharedView, matching BitTorrent behavior where all items have
shared = true - FileInfoModal auto-refresh — detail API call refreshes every 5 seconds while the modal is open
- SegmentsBar colors — fixed gap/requested segment colors in the progress bar visualization
- FileInfoModal tree auto-expand — file tree nodes now auto-expand correctly on open
- Category path mapping not shown in edit modal — when only one instance of a client type is connected, stored instanceId-based path mappings were not loaded into the edit form (showed placeholder instead of actual path)
- aMule incremental updates — new
getUpdate()method in amule-ec-node usesEC_OP_GET_UPDATEwithEC_DETAIL_INC_UPDATEfor stateful incremental polling. Only changed fields are transferred after the initial full response, significantly reducing bandwidth and CPU usage for aMule connections. Replaces the previous full-queue polling approach (getDownloadQueue+getSharedFiles+getClients) - Download Sources table in FileInfoModal — aMule download sources (peers we download from) now have a dedicated table section with columns for User, State, Source origin, Queue rank, Downloaded, and DL speed. Previously only upload peers were shown
- aMule peer state labels — download states (Downloading, On Queue, Connecting, etc.), upload states, and source origin labels (Server, Kad, Exchange, etc.) are displayed in human-readable form in the peers tables
- File rename — rename downloads and shared files from the context menu (aMule only). Gated by
renameFileclient capability andrename_filesuser permission. NewFileRenameModalwith smart filename selection (selects name without extension) - Rename files user capability — new
rename_filescapability in the Downloads group, configurable per-user in the User Management UI. Included by default in Full preset and SSO auto-provisioned users
- Unified peers model — replaced three separate peer arrays (
peersDetailed,activeUploads,downloadSources) with a singleitem.peersarray across all 5 client types. Each peer carries arolefield:'peer'(BitTorrent),'upload'(aMule upload),'download'(aMule source). Eliminates ~200 lines of duplicated peer extraction/normalization code - Peers embedded in source objects — managers now embed peers directly into download/shared file objects instead of returning separate arrays. Simplifies the data pipeline from 5 parameters to 3 in
assembleUnifiedItems() - Removed source names caching from QueuedAmuleClient — the
getDownloadQueueWithCachewrapper andmergeSourceNameslogic are replaced by amule-ec-node's native incremental update with deep merge, which handles the aMule EC protocol's ID-based source name diffing correctly - Removed dead
ipToString— IP decoding now lives solely in amule-ec-node (EC protocol-specific little-endian uint32 conversion). Removed unused function and imports fromnetworkUtils.js,downloadNormalizer.js,geoIPManager.js,hostnameResolver.js
- Stale item removal — aMule
getUpdate()uses set-based reconciliation to remove disconnected peers, completed downloads, and unshared files from the incremental cache - Deep merge for incremental EC updates — raw tag tree merging uses deep merge with ID-based array reconciliation, matching aMule GUI's
CPartFile_Encoderbehaviour. Fixes Source Reported Filenames disappearing after incremental updates replaced nested objects with partial data - Empty download source rows — peers in "Connecting" state with no IP are now filtered out in
amuleManager.fetchData() - UploadsView duplicate rows — peer IDs generated from
address:portand row keys includeparentHashto prevent duplicates when the same peer appears across multiple torrents
- Unraid Community Applications template — Docker template XML (
unraid/amutorrent.xml) for one-click install from the Unraid CA store. Includes all client configurations, SSL toggles, screenshots, and Prowlarr integration
- Empty env vars treated as unset — environment variables set to empty strings (e.g.
PASSWORD=''from Unraid/Portainer templates) are now correctly ignored, allowing the setup wizard to collect values interactively instead of treating them as blank overrides
- Remove unused Deluge file tree fetch — the bulk torrent refresh was requesting the full file list for every torrent every ~3 seconds, parsing tens of MB per cycle that was never used. This drastically reduces memory and CPU usage for large Deluge libraries (#29)
- Cap tracker/peer refresh concurrency — per-torrent tracker and peer requests are now batched (10 concurrent) instead of firing all at once. Applied to Deluge, qBittorrent, and Transmission to prevent request storms with large torrent counts (#29)
- Skip data fetching when idle — when no browser tabs are connected and download history updates aren't due, the app skips the expensive data fetch cycle entirely, reducing CPU and network usage to near zero in the background
- Auto-disconnect WebSocket on hidden tabs — when the browser tab is hidden (sleep, tab switch, minimize), the WebSocket disconnects cleanly and reconnects when the tab becomes visible again. Prevents stale connection buildup and Chrome renderer hangs after sleep/wake
- Debug API for memory diagnostics — opt-in endpoints (
/api/debug/memoryand/api/debug/heapsnapshot) for analyzing memory usage. Enable withNODE_INSPECT=trueenvironment variable. Admin-only access - Node.js inspector support — setting
NODE_INSPECT=truealso enables the V8 inspector on port 9229 for remote profiling via Chrome DevTools
- History view tracker label — tracker labels were not showing in the desktop table view due to a column key mismatch. Now displays correctly in both desktop and mobile views
- rTorrent HTTPS Support - Connect to rTorrent XML-RPC endpoints over HTTPS/SSL, matching qBittorrent, Deluge, and Transmission. Configurable via Settings UI,
RTORRENT_USE_SSLenv var, or config.json - Self-Hosted Country Flags - Country flag SVGs are now bundled locally instead of loading from an external CDN, eliminating Content Security Policy issues and external dependencies
- Self-Hosted Chart.js - Chart.js is now bundled locally instead of loading from jsdelivr CDN, removing the last external script dependency
- Event Script CRLF Detection - Scripts with Windows line endings (CRLF) are detected before execution with a clear warning and fix command in logs
- Event Script Error Logging - stderr output is now always logged regardless of exit code, and stdout is included on failures for easier debugging
- Settings Auto-Scroll on Mobile - Fixed section auto-scroll not working on mobile when expanding sections that stretch the page content
- Tighter CSP - Removed
cdn.jsdelivr.netfromscript-srcContent Security Policy directive — all assets are now self-hosted
This release adds Deluge and Transmission as fully supported clients, introduces multi-instance support allowing multiple instances of the same client type, and a complete user management system with capability-based authorization. The entire client architecture has been rebuilt around an abstract, capability-driven model.
- Full Deluge Support - Connect to Deluge via its WebUI JSON-RPC API
- Category Sync - Bidirectional label synchronization between aMuTorrent and Deluge
- Torrent Management - Add magnets and torrent files, pause/resume/delete
- Transfer Statistics - Upload/download speeds and totals tracked in metrics
- File Browser - View torrent file trees via
GET /api/deluge/files/:hash - Configuration - Setup via Settings page or environment variables (
DELUGE_ENABLED,DELUGE_HOST,DELUGE_PORT,DELUGE_PASSWORD)
- Full Transmission Support - Connect to Transmission via its RPC API
- Category Sync - Bidirectional category synchronization between aMuTorrent and Transmission
- Torrent Management - Add magnets and torrent files, pause/resume/stop/delete
- Transfer Statistics - Upload/download speeds and totals tracked in metrics
- File Browser - View torrent file trees via
GET /api/transmission/files/:hash - Configuration - Setup via Settings page or environment variables (
TRANSMISSION_ENABLED,TRANSMISSION_HOST,TRANSMISSION_PORT,TRANSMISSION_USERNAME,TRANSMISSION_PASSWORD)
- Multiple Instances Per Client Type - Run multiple aMule, rTorrent, qBittorrent, Deluge, or Transmission instances simultaneously
- Dynamic Instance Management - Add, configure, and remove client instances from Settings without restart
- Deterministic Instance IDs - Stable
{type}-{host}-{port}identifiers for each instance - Compound Item Keys - Downloads identified by
instanceId:hashfor cross-instance uniqueness - Per-Instance Category Sync - Each instance syncs categories independently on connect
- Environment Variable Configuration - First instance of each client type configurable via env vars; additional instances managed through Settings UI
- Multi-User Authentication - Create and manage multiple user accounts with username/password login
- Trusted Proxy SSO - Single sign-on via trusted proxy headers (e.g., Authelia, Authentik) with auto-provisioning of SSO users
- Capability-Based Authorization - Fine-grained permissions:
add_downloads,edit_downloads,edit_all_downloads,delete_downloads,clear_history,manage_categories - Admin Users - Full system access with user management abilities
- Download Ownership - Downloads are owned by the user who added them; mutation restricted to owner (or users with
edit_all_downloads) - Per-User WebSocket Filtering - Each user only sees downloads they own (admins see all)
- Per-User API Keys - External API integrations (Torznab, qBittorrent compat) use individual API keys instead of shared password
- User Management UI - Admin panel to create, edit, disable, and delete users with capability presets
- Profile Management - Self-service password change
- Session Invalidation - Disabling a user or changing capabilities force-disconnects their active sessions and WebSocket connections
- BaseClientManager - Shared base class for all client managers with common category/download CRUD interface
- ClientRegistry - Runtime client dispatch by instance ID, replacing hardcoded client-type lookups
- clientMeta.js - Static capability registry (
categories,nativeMove,sharedFiles,stopReplacesPause,logs,trackers,search, etc.) - Capability-Driven Logic - Frontend and backend use capabilities instead of
clientType === 'x'checks - Field Registry - Modular field definitions replacing monolithic field formatters
- IPv6 Peer Address Parsing - Fixed parsing of IPv6 addresses in qBittorrent peer data
- Healthcheck Dual-Stack Binding - Healthcheck no longer fails when server binds to
::(IPv6 dual-stack) - Table Column Alignment - Fixed column alignment and width consistency across views
- Mobile Download Speed - Error state items now show download speed in mobile card view
- Login Delay Timer - Countdown timer correctly shown on page load after refresh
- Node 22 - Upgraded Docker base image from Node 18 to Node 22
- Improved Layer Caching - npm install runs before source copy for faster rebuilds
- Simplified docker-compose - Uses
env_filedirective pointing to.envinstead of inline commented environment variables - Removed qBittorrent Volume - No download directory mount needed (uses native API for moves/deletes)
- CategoryManager Refactored - Per-instance category sync, propagation to other clients on connect,
importCategory()/linkAmuleId()/getCategoriesSnapshot()primitives - Per-Instance aMule IDs - Category-to-aMule-ID mapping is now per-instance instead of global
- Download Normalizer - Extended with Deluge and Transmission normalizers
- Unified Item Builder -
isTorrentClient()helper, torrent utilities extracted totorrentUtils.js - WebSocket Handlers - Capability-gated actions, per-item ownership checks, filtered broadcasts
- Client Instance Management - Add/edit/remove client instances from Settings UI
- Capability-Gated Navigation - Nav items, action buttons, and views filtered by user capabilities
- Header User Dropdown - Profile and logout accessible from header
- aMule Instance Selector - Dropdown to select target aMule instance for ED2K downloads
- New Client Logos - Dedicated SVG icons for Deluge and Transmission
helmet- HTTP security headersipaddr.js- IP address parsing and validationexpress-rate-limit- Request rate limiting
xmlbuilder23.x → 4.x
js-yaml- No longer needed
- Deluge Integration Guide - New
docs/DELUGE.mdcovering setup, Docker, and label sync - Transmission Integration Guide - New
docs/TRANSMISSION.mdcovering setup, Docker, and group mapping - User Management Guide - New
docs/USERS.mdcovering multi-user setup, capabilities, SSO, and API keys - Updated Configuration Docs - Multi-instance env vars, new client configs, user management settings
- Updated Client Docs - aMule, rTorrent, qBittorrent docs refreshed for multi-instance
- Configurable Bind Address - New
BIND_ADDRESSenv var andserver.hostconfig field to control which network interface the server listens on (default:0.0.0.0). Select dropdown in Settings and Setup Wizard shows detected interfaces. Restart warning shown when changed. - Network Interfaces API - New
GET /api/config/interfacesendpoint returns available IPv4 network interfaces for bind address selection - Global Rate Limit - Second layer of brute force protection: 50 failed login attempts across all IPs within 15 minutes triggers lockout, defending against IPv6 rotation attacks
- Login Delay Countdown - Live countdown timer on login button during server-side delay; countdown also shown in error message when rate-limited (429)
- Exponential Login Delay - Replace fixed delay tiers with exponential formula (
count * 1.5^(count-1) * 500ms) starting from first failed attempt - curl in Docker Image - Added
curlto the Docker image for custom scripting use
- Login Delay Rounding - Round login delay to whole seconds for clean UI countdown alignment
- Error Logging - Improved error logging with cause detail for all download clients
- Website Carousel - Fixed slide counts after screenshot cleanup
- Password Validator - Broadened special character validation to accept any non-alphanumeric character
- Request Validation - Removed
validateRequestmiddleware, inlined validation intoauthAPIandmetricsAPI
- Notification Emojis & Redesign - Apprise notifications now use emoji titles (⬇️ ✅ 🏷️ 📦 🗑️), show client type in title with dot separator, and category with 🏷️ tag
- MobileStatusTabs Icons - Status filter pills now show icons from STATUS_DISPLAY_MAP
- CategoryModal qBittorrent Info - Path mapping section shows message that qBittorrent doesn't need mapping (uses native API)
- Demo Mode Environment Variable -
DEMO_MODE=trueenv var was overridden by config.json; now reads directly fromprocess.env - Website Stale Screenshots - Removed 12 stale screenshots, updated carousels from 12→6 desktop slides and 4→2 mobile slide groups
- Docs Sync Script - Screenshot sync now cleans destination before copying to prevent stale files
- File Browser for Script Path - Settings page script path field now has a browse button that opens a file picker modal
- Category in Download Events -
downloadAdded,downloadFinished,fileDeleted, andfileMovedevents now include thecategoryfield - Delete Event - Now includes
categoryfield in the event payload
- fileMoved Event Category - Category was always
nullin fileMoved events due to missing field in DB row mapping and missing parameter in move queue calls - fileMoved Notification Destination - Apprise notification showed "To: Unknown" due to field name mismatch (
destinationvsdestPath) - aMule Category Name Resolution - aMule category IDs are resolved to human-readable names for event scripting
- aMule Relative Path in History -
downloadFinishedevents showed relative.partpaths (e.g.,003.part/file.mkv) instead of absolute paths; now only uses absolute paths from aMule shared files - Path Validation Race Condition - Multiple client connections triggering concurrent
validateAllPaths()calls caused inconsistent results; now debounced with 500ms delay - Path Validation Error Detail - Permission check failures now show detailed diagnostics (uid, gid, directory ownership, file mode) instead of generic "Missing write permission"
- qBittorrent Downloaded Bytes - Fixed incorrect field name (
sizeDownloaded→downloaded) in history metadata for qBittorrent - qBittorrent Peer Data - Normalize peer data at source to match rTorrent format
- qBittorrent Peer Counter - Fix peer counter for qBittorrent downloads in Active Downloads widget
- Download History Ratio - Ratio values now rounded to 2 decimal places
- UI Path Display - AlertBox supports
breakAllprop for better word-breaking of long paths and hashes - Client Selector - BitTorrentClientSelector supports
showFullNameprop to always display full client name - Download Normalizer - rTorrent hash lowercased for consistency, added
categoryalias andfinishedTimefield - File Selection Mode in Directory Browser -
DirectoryBrowserModalsupportsmode="file"to browse and select files (directories still navigable)
- Event Scripting README - Updated
downloadAddedevent documentation with newcategoryfield and JSON examples - Installation Docs - Updated for three-client support
- Landing Page - Updated for three-client support
This release adds full qBittorrent integration, making aMuTorrent a unified download manager for aMule, rTorrent, and qBittorrent simultaneously.
- Full qBittorrent Support - Connect to qBittorrent via its WebUI API
- Auto-Reconnect - Automatic connection recovery on disconnect
- Torrent Management - Add magnets and torrent files, pause/resume/stop/delete
- Category Sync - Bidirectional category synchronization between aMuTorrent and qBittorrent
- Native File Moves - Uses qBittorrent's
setLocation()API for efficient moves (no filesystem access needed) - Native File Deletion - Deletes via API (no volume mount required for delete operations)
- Transfer Statistics - Upload/download speeds and totals tracked in metrics
- Connection Status - Real-time status with port information in footer
- Application Logs - View qBittorrent logs in the Logs page
- Configuration - Full setup via Settings page or environment variables (
QBITTORRENT_ENABLED,QBITTORRENT_HOST,QBITTORRENT_PORT,QBITTORRENT_USERNAME,QBITTORRENT_PASSWORD,QBITTORRENT_USE_SSL)
- File Path in Events -
downloadFinished,fileDeleted, andcategoryChangedevents now includepath(full file/directory path) andmultiFilefields - Debug Script - New
scripts/log-to-file.shlogs all event data toserver/logs/events.logfor debugging - JSON Payload Examples - Complete examples for all 5 event types in
scripts/README.md
- Unified BitTorrent Section - Settings page combines rTorrent and qBittorrent under "BitTorrent Integration" with sub-sections
- Client Filter Toggle - Header ED2K/BT toggle filters all BitTorrent clients (rTorrent + qBittorrent) as one group
- Multi-Client Footer - Speed totals from all connected clients with per-client tooltip breakdown
- Statistics Charts - Renamed from "rTorrent" to "BitTorrent" to reflect all BT clients
- Client Display Names - New
CLIENT_NAMESconstant as single source of truth for client names across the UI - Client Icons - Distinct icons for rTorrent (dedicated SVG) and qBittorrent (dedicated SVG); generic BitTorrent icon for the BT filter toggle
- Download Normalizer - Extended with
normalizeQBittorrentDownload()for unified item format - Unified Item Builder - Renamed
RTORRENT_DEFAULTStoTORRENT_DEFAULTS, addedisTorrentClient()helper - Data Fetch Service - qBittorrent added as data source alongside aMule and rTorrent
- Metrics Collection - qBittorrent speeds and totals tracked (uses all-time totals, no restart detection needed)
- Auto Refresh Manager - Extended refresh loop with qBittorrent stats, history tracking, and external download detection
- Config Tester - Added qBittorrent connection testing with detailed diagnostics
- Field Formatters - Support for 50+ qBittorrent-specific field labels and state formatting
- qBittorrent Category Sync - Categories created/updated/deleted in aMuTorrent are synced to qBittorrent
- Path Validation - Enhanced logging showing specific paths and reasons for each warning
- Default Paths - Tracked per client (aMule, rTorrent, qBittorrent) for accurate Default category display
- qBittorrent Native Moves - Uses API-based
setLocation()instead of manual file operations - Improved Size Verification - Uses actual measured size for incomplete downloads
- Cross-Filesystem Fallback - Falls back from rename to copy with logging
- aMule Delete Event -
deletedFromDisknow correctly reportstruewhen cancelling aMule downloads (aMule always deletes temp files) - Move Size Verification - Fixed incorrect size comparison for incomplete downloads
- Path Translation - Fixed path mapping to handle both prefix matching and fallback patterns
- qBittorrent Integration Guide - New
docs/QBITTORRENT.mdcovering setup, Docker, categories, and first-time password configuration - Updated All Docs - CONFIGURATION.md, RTORRENT.md, PROWLARR.md, and README.md updated to reflect three-client support
- Event Scripting README - Added full JSON payload examples for all event types, documented
pathandmultiFilefields - Debug Script - New
scripts/log-to-file.shwith usage documentation - Documentation Website - Added GitHub Pages deployment with Starlight, qBittorrent added to sidebar
- Demo Mode - Generate random data for screenshots and showcasing the app without real clients. Enable with
DEMO_MODE=trueenvironment variable.
- Apprise CLI Detection - Fix detection of Apprise installed via pipx. Now searches common paths including
~/.local/bin,/usr/local/bin, and other standard locations.
- Path Resolution - Fix path resolution for categories with
pathMappings: null. Categories with apathbut nopathMappingsnow correctly usepathas the local path instead of falling back to Default category. - Version Check - Handle HTTP redirects in version check to support repo renames. Old images checking the previous repo name will now correctly follow the redirect to find new releases.
This release transforms the app from an aMule-only controller into a unified download manager supporting multiple clients. The app has been rebranded to aMuTorrent to reflect its expanded capabilities.
- Full rTorrent Support - Connect to rTorrent via XML-RPC over HTTP
- Unified Download Views - Manage aMule and rTorrent downloads in a single interface
- Torrent File Upload - Add torrents via file upload or magnet links
- Label/Category Support - Automatic directory assignment based on categories
- Tracker Information - Display tracker domain for torrent downloads
- Torrent Search - Search for torrents via Prowlarr indexer manager
- Direct Downloads - Add search results directly to rTorrent
- Indexer Filtering - Filter search results by indexer source
- Category Mapping - Assign categories when adding from search results
- Apprise Integration - Push notifications via 80+ services (Discord, Telegram, Slack, Pushover, ntfy, Gotify, Email, Webhooks, and more)
- Form-Based Configuration - Easy service setup through web UI (no YAML editing)
- Event Selection - Choose which events trigger notifications (download added, completed, moved, deleted, category changed)
- Test Notifications - Verify service configuration before enabling
- Apprise Detection - Graceful handling when Apprise CLI is not installed
- Script Execution - Run custom scripts when download events occur
- Multiple Input Methods - Event data via argument, environment variables, and JSON stdin
- Example Script - Included
scripts/custom.shwith documentation and examples - Timeout Protection - Configurable script timeout to prevent hung processes
- Multi-Selection - Select multiple search results for batch download
- Category Selection - Assign category when downloading search results
- Improved Results Display - Better formatting and source information
- Column Visibility - Show/hide columns per view
- Column Reordering - Drag to reorder columns
- Secondary Sorting - Configure secondary sort column for tie-breaking
- Persistent Settings - Column preferences saved to localStorage
- Per-View Configuration - Different column setups for each view
- Move to Category Path - Move downloads (active or completed) to their category's configured directory
- Directory Browser - Visual directory picker for category path configuration
- Background Move Operations - File moves tracked with progress indication
- Frozen Sorting - Sort order locked while in selection mode to prevent confusion
- Select All/Page - Quick shortcuts to select all items or current page
- Visual Indicators - Clear feedback for selected items count
- Upload Speed Indicator - Real-time upload speed per shared file
- Peer Count in Info Modal - See connected peers for each shared file
- Automatic Folder Reload - Configurable interval to rescan shared folders
- Application Logs View - View aMuTorrent server logs in the Logs tab
- Log Rotation - Automatic log file management
- Real-time Updates - Live log streaming via WebSocket
- Client Icons - Visual indicators showing which client (aMule/rTorrent) each item belongs to
- Combined Statistics - Unified speed and transfer charts for both clients
- Sticky View Headers - Headers stay visible while scrolling on mobile
- Improved Tooltips - Tooltips now use portals to avoid clipping issues
- Background Status Tracking - Download status now maintained by background task instead of computed on each request
- Improved aMule Tracking - Downloads correctly marked as completed after full download
- Username Tracking Fix - Fixed username capture for Prowlarr-initiated downloads
- Performance Improvements - Reduced database queries for history operations
- Unified Item Views - Downloads, uploads, and shared files use consistent item components
- Combined Columns - Merged related columns with partial sorting for compact views
- Responsive Breakpoints - Better adaptation between mobile, tablet, and desktop
- Modular Client Handlers - Separate handler classes for rTorrent and Prowlarr
- Unified Item Builder - Common data structure for items from different clients
- Download Normalizer - Consistent download representation across clients
- Category Manager - Centralized category handling with path mapping
- History Completion Status - aMule downloads now correctly marked as completed
- Tooltip Positioning - Fixed tooltips being clipped by container overflow
- Selection Mode Sorting - Prevented confusing reorder while items are selected
- Username in History - Fixed username not being recorded for some download methods
- Chart Memory Leaks - Proper cleanup of Chart.js instances on unmount
- WebSocket Reconnection - Improved handling of connection drops
- aMule Integration Guide - EC protocol setup in
docs/AMULE.md - rTorrent Integration Guide - XML-RPC setup in
docs/RTORRENT.md - Prowlarr Integration Guide - Torrent search setup in
docs/PROWLARR.md - Notifications Guide - Apprise configuration in
docs/NOTIFICATIONS.md - Custom Scripting Guide - Event script development in
scripts/README.md - Configuration Guide Updated - New environment variables and multi-client setup
- App Renamed - Project renamed from "aMule Web Controller" to "aMuTorrent"
- Repository Renamed - GitHub repository URL changed
- Docker Image - New Docker Hub repository (old image deprecated)
- Web UI Password Protection - Optional password authentication with brute force protection (exponential backoff and IP lockout after 10 failed attempts)
- API Authentication - Torznab and qBittorrent APIs now require authentication when web UI auth is enabled (API key = UI password)
- History Tracking - Optional persistent download history with filtering and search
- New Home Dashboard - Mobile-optimized widgets for quick overview
- Bottom Navigation Bar - Easy thumb-accessible navigation
- Optimized Card Views - Improved mobile layouts for all views
- Mobile Table Features - Sort and filter controls adapted for touch
- Download Selection Mode - Mass pause/resume, category assignment, and delete
- Shared Files Selection - Bulk ED2K link export
- Detailed Info Modals - Rich information dialogs for downloads and shared files
- Context Menus - Right-click quick actions on downloads and shared files
- Filter by Filename - Text filter for downloads, uploads, shared files, and search results
- Items-per-page Selector - Configurable page sizes for all views
- ED2K Link Export - Export links from shared files
- Disk Space Indicator - Real-time disk usage in footer
- CPU Usage Indicator - System CPU load in footer
- Hostname Resolution - Peer hostnames displayed in uploads view
- Version Badge - Automatic update check and app version info
- Font Size Toggle - Adjustable UI font size
- Reload Shared Folders Button - New button in Shared Files view to rescan shared folders from disk
- JavaScript Bundling - All frontend JS bundled into single file using esbuild
- Updated bcrypt - Version 6.0.0 removes deprecated dependencies
- Config Management - Refactored config.js/configAPI.js with improved secrets handling
- Sensitive Env Vars - Environment variables for passwords/API keys now always override config.json and lock UI fields
- Torznab/qBittorrent APIs - Refactored indexer and download client implementations
- Frontend Architecture - Massive app.js refactoring with contexts, consolidated state management, simplified views
- Batched WebSocket Updates - Reduced UI re-renders via autoRefreshManager
- Deduplicated Code - Consolidated Sonarr/Radarr logic in configTester.js and arrManager.js
- Server Disconnect Button - Only shown on currently connected server
- Header Tooltips - Added tooltips on navigation buttons
- Tablet Layout Fixes - Improved sidebar and view layouts for tablets
- Form Element Styles - Unified form styling across views
- Settings Page - Reduced horizontal padding on mobile for more content width
- Arr Integration - Fixed automatic search not initializing when enabled from settings after startup
- Sonarr TBA Episodes - Unreleased episodes (TBA) no longer trigger searches
- Loading States - Fixed "no files" message shown instead of "loading" on slow connections
- Chart Rendering - Fixed laggy home view by deferring chart rendering
- Mobile Scroll - Fixed viewport auto-scroll to top on page changes
- Theme Persistence - Theme selection now properly remembered
- Light Mode - Fixed progress bar text visibility in downloads
- iOS Safari - Fixed CSS viewport issues on iOS Safari
- Loading Spinner - Fixed spinner CSS styling
- Restructured Docs - Separated into focused guides (Configuration, Integrations, GeoIP, API, Development)
- Docker Hub Link - Added link to Docker Hub repository
- Auth Documentation - Added authentication setup for Torznab and qBittorrent APIs
- Comprehensive monitoring dashboard on Home view (desktop)
- Real-time active downloads and uploads widgets
- 24h statistics with charts and metric cards
- Quick search integration on dashboard
- Auto-refresh every 15 seconds
- Improve Torznab category support for Prowlarr
This is a major release featuring a complete codebase refactoring and numerous new features that significantly enhance functionality and user experience.
- Interactive Setup Wizard - First-run guided configuration with real-time validation and testing
- Settings Page - Manage all configuration through the web interface with live testing
- Persistent Configuration - Settings saved to
config.jsonwith environment variable fallback - Configuration Precedence - Clear hierarchy: config file > env vars > defaults
- Test Before Save - Validate individual sections or all settings before applying changes
- Torznab Indexer API - Full Torznab compatibility for ED2K network searches
- qBittorrent Download Client Compatibility - Works as download client for *arr apps
- Automatic Library Scanning - Configurable interval-based searches for missing content
- Quality Profile Support - Respects quality upgrade preferences from Sonarr/Radarr
- Interactive Search Support - Manual searches from Sonarr/Radarr interface
- ED2K Rate Limiting - Prevents server flood protection bans
- Search Result Caching - Efficient pagination handling for *arr apps
- MaxMind GeoLite2 Support - Display geographic location of upload peers
- Country Flags - Visual country indicators in uploads view
- City Information - Detailed location data when available
- Docker Integration - GeoIP updater container for automatic database updates
- Optional Feature - Works without databases, gracefully degrades
- Category Management - Create, edit, and delete download categories
- Color-Coded Categories - Customizable colors for visual organization
- Category Assignment - Assign downloads to categories via UI
- Category Filtering - Filter downloads by category
- Pause/Resume Downloads - Control individual download states
- Multiple ED2K Link Support - Add multiple ED2K links at once (one per line)
- Segments Bar Visualization - Visual representation of file parts availability
- Detailed Source Counts - Shows total, current, transferring, and A4AF sources
- Last Seen Complete - Color-coded indicators for source freshness
- Persistent Sorting Preferences - Sort preferences saved to localStorage
- Secondary Sorting - Files with equal values sorted alphabetically by name
- Improved Mobile UI - Better touch interactions and responsive design
- Enhanced Dark Mode - Improved contrast and visual hierarchy
- Interactive Charts - Chart.js integration for speed and transfer visualization
- Multiple Time Ranges - 24h, 7d, and 30d views with appropriate aggregation
- Accurate Calculations - Fixed statistics calculation bugs (totals, averages, peaks)
- Peak Speed Tracking - True peak speeds from raw data, not averaged buckets
- Database Optimization - Efficient queries for large datasets
- Modular Server Architecture - Separated concerns into focused modules
amuleHandler.js- aMule EC protocol handlingmetricsAPI.js- Historical statistics endpointstorznabAPI.js- Torznab indexer implementationqbittorrentAPI.js- qBittorrent API compatibilitygeoIPManager.js- GeoIP database managementconfig.js- Centralized configurationcategoriesManager.js- Category operationssonarrClient.js/radarrClient.js- *arr integration
- Component-Based Frontend - Organized React components
components/common/- Reusable UI componentscomponents/layout/- Layout components (Header, Sidebar, Footer)components/views/- Page view componentscomponents/modals/- Modal dialogshooks/- Custom React hooksutils/- Utility functions (formatters, validators, sorters)
- Improved Code Reusability - Extracted common patterns and utilities
- Better Error Handling - Comprehensive try-catch blocks and user feedback
- Performance Optimizations - Memoization, efficient queries, reduced re-renders
- Code Readability - Consistent naming, better comments, clear structure
- Maintainability - Easier to extend, test, and debug
- RESTful Endpoints - Proper HTTP methods and status codes
- Consistent Response Format - Standardized JSON responses
- Better Error Messages - Actionable error information
- WebSocket Protocol - Cleaner message structure
- Rate Limiting - Configurable delays for ED2K operations
- Efficient Queries - Added helper methods for common operations
getFirstMetric()- Get earliest record in rangegetLastMetric()- Get latest record in rangegetPeakSpeeds()- Get true peak speeds from raw data
- Better Indexing - Optimized timestamp lookups
- Cleanup Routines - Automatic old data retention management
- Statistics Calculation Bugs:
- Fixed 30d total upload/download showing less than 7d (100k record limit issue)
- Fixed peak speeds calculated from averaged buckets instead of raw data
- Fixed average speeds incorrectly averaging already-averaged bucket data
- Now uses proper calculations: total/time for averages, MAX() for peaks
- Secondary Sorting - Files with equal sort values now alphabetically sorted
- Dark Mode Consistency - Improved color schemes across all views
- Mobile Touch Interactions - Better tap targets and touch feedback
- Category Color Display - Proper hex color rendering
- WebSocket Reconnection - More stable connection handling
- Search Result Caching - Prevents duplicate ED2K searches
- Progress Bar Rendering - Smooth animations and accurate percentages
- Comprehensive README - Updated with all new features and configuration options
- Setup Instructions - Clear Docker and native installation guides
- Configuration Guide - Detailed explanation of configuration precedence
- Integration Guides - Step-by-step Sonarr/Radarr setup
- API Documentation - Torznab and qBittorrent API endpoints
- Troubleshooting Section - Common issues and solutions
- GeoIP Setup Guide - MaxMind license and database configuration
maxmind- GeoIP database reader- Chart.js (via CDN) - Interactive charts
- React 18 - Latest stable version
- Tailwind CSS - Latest utilities
- better-sqlite3 - Latest database driver
- Interactive charts for historical statistics
- Support for multiple ED2K links
- Improved statistics visualization
- Various bug fixes and performance improvements
- Real-time search functionality
- Download management
- Upload monitoring
- Shared files view
- Historical statistics (24h/7d/30d)
- Dark mode support
- Responsive design
- WebSocket real-time updates
- Docker support
- Native installation support