github tonikelope/megabasterd v8.54
MegaBasterd 8.54

latest release: v8.55
2 hours ago

TL;DR

  • Implements #774 -- two new independent "execute this command when the queue finishes" hooks, one for downloads and one for uploads. Configured under Settings → Advanced, right below the existing 509-bandwidth-limit command. Both new commands are fully independent of the legacy 509 command and of each other; if all three converge on the same tick they run concurrently. Each one has its own cooldown so neither can starve the others.
  • Trigger is the natural "queue went from non-empty to empty" transition, gated by "at least one transference finished without error or cancellation" -- a queue that ended only in failures does not fire the user's post-processing script. Fires regardless of main-window visibility (the tray notification stays gated to hidden-window only, the script does not).

New in 8.54

#774 -- Independent post-finish hooks for downloads and uploads

  • What changed. MainPanel grows two new pairs of fields modelled on the existing 509 command: _run_command_dl_finish + _run_command_dl_finish_path (with LAST_DL_FINISH_COMMAND_TIMESTAMP) and the upload-side equivalents. Two new public methods, MainPanel.run_dl_finish_command() and MainPanel.run_ul_finish_command(), each short-circuit when their feature flag is off and otherwise spawn a non-blocking ProcessBuilder.inheritIO().start() exactly the same way the legacy 509 path has been doing for years. The actual argv-resolution body (single-arg if the configured value is a real file, whitespace-token split otherwise) lives in a single shared _spawnExternalProcess(...) helper used by all three call sites so the three commands stay byte-for-byte identical in execution semantics.

  • Where the trigger lives. TransferenceManager gains a virtual hook onAllTransferencesFinished() (default no-op) and a new latch _finish_command_fired separate from the existing _all_finished / _tray_icon_finish latches. _genStatus() fires the hook exactly once per "non-empty → empty with at least one OK finish" transition, regardless of main-window visibility (the existing tray-notification block still requires !isVisible() and is left untouched). The latch resets together with _all_finished whenever a new transference enters the pipeline, so each fresh batch retriggers the command on completion. DownloadManager and UploadManager override the hook to call their respective MainPanel.run_*_finish_command().

  • Why a separate latch and timestamp. Sharing LAST_EXTERNAL_COMMAND_TIMESTAMP (or even a single new finish timestamp) with both queues would mean a download finish landing inside the cooldown window of an upload finish silently skips its command, which is the opposite of what #774 asks for. Each command gets its own cooldown so all three (509, downloads-finish, uploads-finish) can fire on the same tick if the timing works out. The separate _finish_command_fired latch (one per TransferenceManager subclass, since each side has its own instance) keeps the natural "queue must transition from non-empty to empty" gate intact without coupling to the visibility-aware tray notification.

  • Why gate on _isOKFinishedInQueue(). A queue that emptied because the user cancelled everything, or because every transfer failed with an error, almost certainly does not have files for the post-processing script to act on. Silently no-firing on all-error / all-cancelled is the safer default than running the script against an empty result set. If you want the script to fire regardless, leaving at least one successful transfer in the finished queue before clearing it satisfies the gate.

Settings dialog (Advanced tab)

  • Two new checkbox-and-textbox rows appear directly below the existing "Execute this command when MEGA download limit is reached:" row:
    • Execute this command when ALL downloads finish:
    • Execute this command when ALL uploads finish:
  • Each row has its own Test button that spawns the configured command immediately, identical to the 509 row's Test. The textbox starts disabled and is enabled by toggling the checkbox above.
  • Persistence: four new SQLite settings rows (run_command_dl_finish, run_command_dl_finish_path, run_command_ul_finish, run_command_ul_finish_path) loaded in the dialog's constructor and saved by the Save handler alongside the existing run_command / run_command_path keys. No migration is needed; missing rows default to "feature disabled".

i18n

  • New keys execute_this_command_when_all_downloads_finish and execute_this_command_when_all_uploads_finish added to all 8 bundles. EN carries the canonical English literal, ES has the Spanish translation, and IT/DE/HU/TR/VI/ZH carry the English placeholder pending translator pickup via the #397 contributor thread. LabelTranslatorSingleton's inverse-index lookup resolves the literal in SettingsDialog to the active locale's key at component-walk time, so the new checkboxes render localised wherever the bundle has a real translation and fall through to English otherwise.

Other

  • Version bumped to 8.54 in pom.xml and MainPanel.VERSION.
  • No changes to the legacy 509 command path: same DB rows, same field names, same run_external_command() entry point. Only the inner argv-builder body was factored into the shared helper that the new methods also use.
  • No changes to transfer-path logic, the global thread pool cap from 8.53, or the mono chunk buffer optimisation from 8.53. Memory mitigations from #773 stay intact.

Don't miss a new megabasterd release

NewReleases is sending notifications on new releases.