Skip to content

Seedingtime: Add optional row highlight for finished torrents - #3319

Merged
xirvik merged 1 commit into
Novik:masterfrom
mariotacke:feat-highlight-finished-by-threshold
Oct 6, 2026
Merged

xirvik merged 1 commit into
Novik:masterfrom
mariotacke:feat-highlight-finished-by-threshold

Conversation

@mariotacke

@mariotacke mariotacke commented Sep 20, 2026 •

Copy link
Copy Markdown
Contributor

Add optional row highlight for finished torrents exceeding some configurable time

This can help distinguish torrents which have reached their minimum seeding time to avoid removing them too early. For example, many trackers require a minimum seeding time of 2 weeks, regardless of ratio, to avoid a hit-and-run. This feature is entirely opt-in and can be configured in the "General" settings section.

Translations provided via Google Sheets' =GOOGLETRANSLATE()

Testing

  • Been running this patch for a while on my personal instance of rtorrent 0.9.8 with latest rutorrent.
  • This feature is visual only; no extra calls to rtorrent.
  • Opt-in: not enabled by default

Example (from Standard theme)

hltest$t

@ranirahn

Copy link
Copy Markdown
Contributor

So you want to creat already existing plugin?
https://github.com/bestboxbe/rutorrent-ratiocolor

@mariotacke

Copy link
Copy Markdown
Contributor Author

No, this feature handles coloring based on seeding time, NOT ratio. It is an opt-in addition to the existing default plug-in seedingtime.

@ranirahn

Copy link
Copy Markdown
Contributor

Okay, but it still looks like something I would not want for myself. Finished torrents already have different icon and can filter out in State panel. I really dont understand the purpose of this. But if I can turn this off then its fine probably.

@mariotacke

Copy link
Copy Markdown
Contributor Author

@ranirahn , this feature is opt-in and off by default. Further, the "done" icon and state is different from what I am describing: this concerns only the time you are seeding a torrent AFTER it has completed already. The purpose of this is to visually indicate when the hit-and-run window has exceeded for particular trackers to free up space if you are inclined to do so. Again, totally optional, does not affect your use of the software at all unless you turn it on.

@ranirahn

Copy link
Copy Markdown
Contributor

Had to think about a little more and I think it would be useful when you dont limit upload by time and want to see how long torrents have seeded. When using RatioGroups, then exceeding upload or time limit stopping the torrent automatically already, but if dont want to stop the torrent automatically, but just want to see visually how long torrents have seeded then it can be useful. Not sure how long the rtorrent 0.9.8 will be supported, but if its off by default I dont see any problems with that. seedingtime plugin needs rewrite anyway to use rtorrent finished timestimp instead of adding seedingtime timestamp to the torrent to calculate the seeding time. New rtorrent already have this variable so at some point its better to use rtorrent own variable not add another one from rutorrent. Then probably the old rtorrent 0.9.8 dont have working seedingtime plugin at all on new rutorrent.

@xirvik
xirvik self-requested a review September 24, 2026 00:44

@xirvik xirvik left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some issues

  • theDialogManager.setHandler replaces the handler already registered for that
    dialog and event. The theme plugin registers 'stg'/'beforeShow' at runlevel 5
    to re-sync the theme select; this plugin is runlevel 11.4, so it loads later
    and overwrites it. A theme change that the user cancels then stays in the
    select and is applied on the next OK, which switches the theme and reloads the
    UI. Drop the handler: showSettings -> addAndShowSettings -> addSettings ->
    loadSettings already restores every input whose id is a key in
    theWebUI.settings, and this plugin seeds its key there. Use addHandler instead
    if the rtorrent-down path (addAndShowSettings called with no data) matters.
  • hu.js contains the Italian string, not Hungarian.
  • ko, lv, el and fr are wrong in meaning, not just clumsy. ko says the torrent
    took at least that long to complete; lv uses "izlase" (a selection or sample);
    el leaves "highlight" in English and reads as a statement rather than an
    instruction; fr reads as a noun phrase about already-highlighted torrents.
    They cannot simply be deleted: loadLangPrim falls back to English only when the
    whole locale file is missing, so a locale that omits the key renders an empty
    label.
  • Add tests for the settings-key seeding, the prototype restore in onRemove, and
    applyHighlight. Removing each of those three leaves the suite green.
  • The settings field is added only if the options page already exists, and there
    is no retry. It holds today because the options window is built before the
    plugin and its language file arrive, but if that order ever changes the field
    disappears with no error.
  • Every other cell in that settings row holds a control and its label together in
    one col-md-6. This adds the label in one cell and the input in the next.
  • cs.js aligns the new line with spaces; the rest of the file and the other
    locales use tabs.
  • Say in the code why dxSTable.prototype.setRowById is wrapped: rows are handed
    to the table while addTorrents is still running as a background task, so an
    attribute applied after addTorrents returns would miss rows until the next
    poll. It is the only prototype patch in the tree and the next reader will
    otherwise assume a torrent-list hook would have done.

@mariotacke

Copy link
Copy Markdown
Contributor Author

Thanks for the feedback. I'll make those updates in two weeks. I'll also find a better translation tool (I used Google Sheets...)

This feature is entirely opt-in and can be configured in the General
settings. It can help distinguish torrents which have reached their minimum
seeding time as required by certain trackers to avoid removing them too
early.
@mariotacke
mariotacke force-pushed the feat-highlight-finished-by-threshold branch from 72b5777 to 07de0bf Compare October 6, 2026 21:02

@mariotacke mariotacke left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please have another look at the PR. I've addressed the comments as best I could. I switched the translations to generate via Opus 5.5 instead of =GOOGLETRANSLATE() and they seem better. We can also drop the translations altogether until folks with proficiency in those language contribute the localization.

A couple of notes:

  • I switched from setHandler to addHandler, so the theme plugin's stg/beforeShow handler keeps running. I kept a handler rather than dropping it, because when rtorrent is down addAndShowSettings gets no data and doesn't reload the settings, so a cancelled edit would otherwise stay in the field.
  • Added further tests to prove behavior works as intended
  • I've generated comments as requested to justify why something is done the way it is.

Please let me know about any other feedback you have before we can merge this.

@mariotacke
mariotacke requested a review from xirvik October 6, 2026 21:14
@xirvik
xirvik merged commit b0a7a65 into Novik:master Oct 6, 2026
8 checks passed
xirvik added a commit to xirvik/ruTorrent that referenced this pull request Oct 6, 2026
xirvik added a commit to xirvik/ruTorrent that referenced this pull request Oct 7, 2026
The seedingtime custom field is written when a download finishes and,
since Novik#3329, when one is found complete on a hash check. Neither reaches
a download that was already complete before the plugin first ran: no
event fires for it again, so its Finished column stays empty for good,
and so do the row highlight that reads it (Novik#3319) and the pubDate the
feeds plugin takes from it.

Ask the daemon to close that gap when the plugin starts, with the same
expression the hash_done handler stores: for a complete download whose
seedingtime is empty, set it from addtime. An existing value is left
alone and an incomplete download is skipped, so the pass is idempotent
and settles after one run.

Measured over 1000 complete downloads on rTorrent 0.16.24: 5.4 ms while
filling and 4.1 ms once filled, answering 74 KB -- below the 121 KB of
the d.hash= column the interface already asks for on every load.

The pass travels in a request of its own, so a daemon that refuses it
still gets the event handlers, and it is skipped when those fail rather
than waiting on the same daemon twice.
xirvik added a commit to xirvik/ruTorrent that referenced this pull request Oct 7, 2026
The seedingtime custom field is written when a download finishes and,
since Novik#3329, when one is found complete on a hash check. Neither reaches
a download that was already complete before the plugin first ran: no
event fires for it again, so its Finished column stays empty for good,
and so do the row highlight that reads it (Novik#3319) and the pubDate the
feeds plugin takes from it.

Ask the daemon to close that gap when the plugin starts, with the same
expression the hash_done handler stores: for a complete download whose
seedingtime is empty, set it from addtime. An existing value is left
alone and an incomplete download is skipped, so the pass is idempotent
and settles after one run.

Measured over 1000 complete downloads on rTorrent 0.16.24: 5.4 ms while
filling and 4.1 ms once filled, answering 74 KB -- below the 121 KB of
the d.hash= column the interface already asks for on every load.

The pass travels in a request of its own, so a daemon that refuses it
still gets the event handlers, and it is skipped when those fail rather
than waiting on the same daemon twice.
xirvik added a commit that referenced this pull request Oct 7, 2026
* Let the test daemon answer with a fault

A reply carrying no values is not a failure to php/xmlrpc.php: run()
reads count($response) from preg_match_all's group array, which is
non-empty even when nothing matched, so an empty <data></data> parses
as a successful request.

A test that needs a request to fail therefore has to be answered with a
real fault body, which FakeRtorrentDaemon had no way to send.

* Fill a missing seedingtime on existing downloads

The seedingtime custom field is written when a download finishes and,
since #3329, when one is found complete on a hash check. Neither reaches
a download that was already complete before the plugin first ran: no
event fires for it again, so its Finished column stays empty for good,
and so do the row highlight that reads it (#3319) and the pubDate the
feeds plugin takes from it.

Ask the daemon to close that gap when the plugin starts, with the same
expression the hash_done handler stores: for a complete download whose
seedingtime is empty, set it from addtime. An existing value is left
alone and an incomplete download is skipped, so the pass is idempotent
and settles after one run.

Measured over 1000 complete downloads on rTorrent 0.16.24: 5.4 ms while
filling and 4.1 ms once filled, answering 74 KB -- below the 121 KB of
the d.hash= column the interface already asks for on every load.

The pass travels in a request of its own, so a daemon that refuses it
still gets the event handlers, and it is skipped when those fail rather
than waiting on the same daemon twice.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants