From 95193fb66d1a934356cd5c7062601cc86457dcae Mon Sep 17 00:00:00 2001 From: SoXX Date: Tue, 2 Jun 2026 22:52:50 +0200 Subject: [PATCH] fix(notes): take last numeric segment of href, not the first The notes listing renders each thread link as /msg/pms/{folder}/{noteID}/#message. extractIntFromHref returned the first numeric segment it found, which was always the folder index (1 for the inbox), so every NotePreview.ID came out as 1 and any follow-up GetNote(np.ID) call failed with "this message has either been deleted or is not yours". Surfaced by an end-to-end smoke run against the live site. Limited to the notes parser; the other extractIntFromHref callers (/view/{id}/, /journal/{id}/) only ever have a single numeric segment so they are unaffected. --- notes_parser.go | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/notes_parser.go b/notes_parser.go index 25ea430..40fc718 100644 --- a/notes_parser.go +++ b/notes_parser.go @@ -52,11 +52,17 @@ func parseNoteListItem(item *goquery.Selection) *NotePreview { } // Note ID lives in the href: /msg/pms/{folder}/{id}/#message. Strip the - // fragment first so extractIntFromHref picks the trailing numeric path. + // fragment first, then take the *last* numeric segment — the folder + // number (e.g. 1) appears before the note ID and would otherwise win + // the "first numeric segment" race in extractIntFromHref. if i := strings.Index(href, "#"); i != -1 { href = href[:i] } - np.ID = NoteID(extractIntFromHref(href)) + for _, seg := range strings.Split(href, "/") { + if n, err := parseID[NoteID](seg); err == nil && n != 0 { + np.ID = n + } + } // Read/unread: classes on the subject link. if class, _ := subjectLink.Attr("class"); strings.Contains(class, "note-unread") || strings.Contains(class, "unread") && !strings.Contains(class, "note-read") {