Skip to content

feat(messages): add mark-read to mark threads as read - #110

Merged
nickknissen merged 4 commits into
nickknissen:mainfrom
kasperhartwich:feat/mark-thread-read
Sep 26, 2026
Merged

nickknissen merged 4 commits into
nickknissen:mainfrom
kasperhartwich:feat/mark-thread-read

Conversation

@kasperhartwich

Copy link
Copy Markdown
Contributor

The client could read messages but not mark them as read, so a thread stayed
unread in Aula however it was handled elsewhere.

Aula keeps one read marker per thread: the ID of the last message read. Its
web client sets it with messaging.setLastReadMessage when a thread is
opened. This adds the same call.

Changes:

  • AulaApiClient.mark_thread_read(thread_id) finds the newest message of the
    thread (a Message, MessageEdited, MessageDeleted or AutoReply, the
    same types the web client accepts) and moves the marker there. A thread can
    start with events such as a recipient change, so it keeps paging until a
    message turns up, and returns False, without writing, when the thread has
    none.
  • Aula reports its own errors inside an HTTP 200, so every answer is checked
    for the {"status": {"code": 0}} envelope, not just the HTTP status. After
    the write it reads the thread again and requires lastReadMessageId to be
    the message that was sent, so a call Aula ignored is not reported as done.
  • Only threads in the guardian's own mailbox are handled: the inbox IDs are
    always sent as null, so the thread must show mailBoxOwner.mailBoxOwnerType
    institutionProfile. A common or OTP inbox, or an answer with no owner, a
    null or a malformed one, raises ValueError before anything is written.
  • Every GET URL is built from the API version in use at that moment, so a
    version negotiated by an earlier request is followed by the paging and the
    confirmation.
  • The page cap is 50 pages of 20. If they hold no message and Aula reports
    more pages, it raises ThreadScanLimitError rather than answering "nothing
    to mark". A thread that holds only events, with no more pages, is returned
    unmarked and makes the CLI exit 1. The marker targets the newest message
    found while reading; messages arriving afterward may remain unread
    (documented in the docstring and README).
  • aula mark-read THREAD_ID... marks each thread given and prints one line
    per thread (--output json gives [{"thread_id": ..., "marked": ...}]).
    A thread that fails is reported on stderr and does not stop the rest; the
    exit code is 1 when any thread was not marked.

Tests:

  • tests/test_api_client.py, with real HttpResponse objects so the status
    checks run: marker on the newest message and the request sent; events
    skipped; a message found on the second page and on the last permitted one;
    page cap exhausted with and without more pages; a deleted and an auto-reply
    message; a version bump between the first request and the later ones; a
    thread with no message writes nothing; API error inside a 200, malformed
    bodies, HTTP 500 and a network error all raise; an unconfirmed marker
    raises; nine kinds of missing or wrong mailbox owner are refused.
  • tests/test_cli.py: several threads, a failing or refused thread followed
    by a marked one, a thread with nothing to mark (exit code 1), valid JSON on
    stdout with the errors on stderr when all, some or none fail, a missing
    argument.
  • Full suite: 851 passed, 4 skipped. ruff format --check and ruff check
    clean.
  • Checked against a live account: three unread threads were marked and left
    the aula messages --unread list. One of them ends in a recipient-change
    event, and the marker went on the message before it.

Known limits:

  • A login prompt (a QR code, a code request) is written by the shared login
    code and can still reach stdout under --output json, as for every other
    command.
  • If the client cannot be set up at all, the command fails before any thread
    is tried and prints no results array.

@nickknissen
nickknissen merged commit 5a7ab97 into nickknissen:main Sep 26, 2026
3 checks passed
@kasperhartwich
kasperhartwich deleted the feat/mark-thread-read branch September 26, 2026 07:29
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