Skip to content

feat(kad): retrieve & display Kad notes (ratings/comments) with eMule parity (#434) - #462

Merged
got3nks merged 1 commit into
amule-org:masterfrom
got3nks:feat/kad-notes-434
Jul 13, 2026
Merged

feat(kad): retrieve & display Kad notes (ratings/comments) with eMule parity (#434)#462
got3nks merged 1 commit into
amule-org:masterfrom
got3nks:feat/kad-notes-434

Conversation

@got3nks

@got3nks got3nks commented Jul 13, 2026

Copy link
Copy Markdown

Implements #434 — retrieving and displaying Kad notes (per-file community ratings/comments) across the native GUI, the remote GUI, and the REST/SSE API, matching eMule 0.70b on the wire. Scope is the download side; shared-file parity is a planned follow-up.

aMule already publishes notes to Kad (STORENOTES) and answers other clients' note lookups, but nothing ever triggered a retrieval and the results were never surfaced. This wires the read side end to end and fixes two rating-encoding divergences from eMule.

Core

  • On-demand lookupCKnownFile::RequestKadNoteSearch() fires PrepareLookup(NOTES), guarded to files in the shared list / download queue. A per-file running flag is set on start and cleared in ~CSearch; both edges and each note arrival call MarkECChanged(), so amulegui/amuleapi learn the lookup started, stream results in live, and see it finish (a plain GET_UPDATE skips an unchanged partfile). When it can't start, the specific reason is logged at notice level (visible in release).
  • Kad rating decode — Kad keyword hits decode raw 0–5 instead of the ed2k server-packed (x&0xF)/3 (which mangled them). ed2k unchanged.
  • ed2k client-write — rating is sent packed (×51) to a peer client, raw to a server, matching eMule (remote clients previously read aMule's as 0).

GUI (monolithic + amulegui)

  • A "Get from Kad" button in the download-comments dialog; notes merge into the existing list, with a timer that auto-refreshes while the lookup runs and stops when the daemon reports done. "Show all comments" is enabled whenever Kad is connected, so it's reachable for a file with no comments yet.
  • amulegui triggers over EC (EC_OP_SHARED_FILE_SEARCH_KAD_NOTES); notes ride the existing partfile-comments channel; a new EC_TAG_PARTFILE_KAD_COMMENT_SEARCHING makes the remote dialog stateful.

REST (amuleapi)

  • POST /downloads/{hash}/comments triggers the lookup (202); notes then appear on GET.
  • kad_search_running on the download object (list/detail/comments) and on the download_updated SSE event.
  • New comments_updated SSE event carries a download's full comment list (Kad notes + ed2k source comments) whenever it changes — live comments without polling.
  • curl tests + REFERENCE.md / EVENTS.md updated. (Also fixes a pre-existing test gap: the download-status allowlist now accepts the documented stopped value.)

Testing

Automated: full amuleapi curl suite, clang-format v18, clang-tidy Tier-1 + Tier-2, app catalogs in sync, all six binaries. Live-validated on macOS against the live Kad network: real notes retrieved (rating 5) on two annotated files; the running-flag lifecycle false → true → false reaching amuleapi; SSE download_updated (flag edges) and comments_updated (note payload) firing correctly; ed2k ratings render.

… parity (amule-project#434)

aMule already publishes notes to Kad (STORENOTES) and answers other clients'
note lookups, but nothing triggered a retrieval and the results were never
surfaced. This wires the read side end to end and fixes two rating-encoding
divergences from eMule 0.70b. Scope is the download side; shared-file parity
is a planned follow-up.

Core:
- CKnownFile::RequestKadNoteSearch() fires an on-demand NOTES lookup, guarded
  to files in the shared list / download queue. A per-file running flag is set
  on start and cleared in ~CSearch; both edges, and each note arrival, call
  MarkECChanged() so the partfile is re-emitted in the next incremental EC
  update - this is how amulegui / amuleapi learn the lookup started, stream in
  results live, and see it finish (GET_UPDATE otherwise skips an unchanged
  partfile). When the lookup can't start, the specific reason (Kad down,
  a search already using this hash, file not shared/queued, ...) is logged at
  notice level so it is visible in release builds.
- Kad search-result rating: decode raw 0-5 for Kad keyword hits instead of the
  ed2k server-packed (x&0xF)/3 formula. (Kad keyword results carry no rating
  tag in practice - ratings live in NOTES - but the decode is now correct if
  one is present. ed2k results are unchanged.)
- ed2k client-write: send the rating packed (x51) to a peer client, raw to a
  server, matching eMule (remote clients previously decoded aMule's as 0).

GUI (monolithic + amulegui):
- "Get from Kad" button in the download comments dialog; retrieved notes merge
  into the existing comments list. A timer auto-refreshes while the lookup runs
  and stops when the daemon reports it finished (60s safety cap). "Show all
  comments" is enabled when Kad is connected (not only when source comments
  already exist), so the button is reachable for a file with no comments yet.
- amulegui triggers over EC (EC_OP_SHARED_FILE_SEARCH_KAD_NOTES); notes ride
  the existing partfile-comments channel; the running flag is surfaced via a
  new EC_TAG_PARTFILE_KAD_COMMENT_SEARCHING so the remote dialog is stateful.

REST (amuleapi):
- POST /downloads/{hash}/comments triggers the lookup (202 Accepted).
- kad_search_running exposed on the download object (list, detail, GET
  .../comments) and on the download_added/_updated SSE event, so clients can
  watch the start -> finish edge.
- New comments_updated SSE event carries a download's full comment list
  (retrieved Kad notes + ed2k source comments) whenever it changes, so web
  clients get live comments without polling.
- curl tests (04, 22) + REFERENCE.md / EVENTS.md updated.
@got3nks
got3nks force-pushed the feat/kad-notes-434 branch from 8454396 to 0845b3a Compare July 13, 2026 09:49
@got3nks
got3nks marked this pull request as ready for review July 13, 2026 09:49
@got3nks
got3nks merged commit 8bcd05c into amule-org:master Jul 13, 2026
12 checks passed
@got3nks
got3nks deleted the feat/kad-notes-434 branch July 13, 2026 10:13
@danim7

danim7 commented Jul 16, 2026

Copy link
Copy Markdown

Correct me if I'm wrong, but the first point of the request from #434 is not implemented:

eMule can show comments and ratings for a file the user has not downloaded —
you can right-click a search result, hit "Search Kad", and see comments/ratings
that other users published for that file. aMule cannot: its search results carry
only a weak self-rating, and comments are available only for files that are
already downloading (from connected sources).

We can now get Kad notes from the comments dialog once the file is being downloaded. But we cannot get those comments from Kad in the Search window, before the download is initiated. Am I missing something? I tested amulegui, and i don't find the option (I guess same applies to monolithic)

@got3nks

got3nks commented Jul 16, 2026

Copy link
Copy Markdown
Author

@danim7 the shared-file / search-result parity you flagged is now wired up in #500.

It turned out less trivial than "just call the same lookup", for a few reasons. The comments dialog and the Kad-note machinery were all bound to CPartFile (downloads), whereas a search result (CSearchFile) and a plain shared file (CKnownFile) are different types — so the note storage, the trigger, and the dialog had to be lifted onto their common base, CAbstractFile. The remote GUI added two more wrinkles: amulegui's incremental EC updates dedup unchanged tags through a per-connection value-map, which silently dropped a search result's comments after the first send (search results, unlike downloads, carry no EC change-generation to reset it), so those had to be sent raw; and a file can exist locally as two objects at once — a download and a search hit sharing one hash — so the "lookup running" flag and the arriving notes had to be routed to every match, otherwise triggering from a search result for a file you're already downloading left it stuck and the notes landed on the wrong object.

Net result in #500: "Show all comments" now works from search results and shared files across the monolithic GUI, amulegui, and the REST API, reusing the same dialog and a single comment cache.

@danim7

danim7 commented Jul 16, 2026

Copy link
Copy Markdown

Thanks for your continuous work to improve aMule, got3nks! And very interesting technical explanation on why it was now wired in the first pass.

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.

2 participants