1
Follow Management
Gabriel Kaszewski edited this page 2026-05-29 02:13:14 +00:00

Follow Management


Outbound follows (local → remote)

// Resolve and follow a remote handle.
// Sends a signed Follow activity via signed WebFinger — works with strict instances (e.g. Threads).
service.follow(local_user_id, "@user@remote.example").await?;

// Unfollow. Sends Undo(Follow), then removes the following record.
service.unfollow(local_user_id, remote_actor_url_str).await?;

Both methods support local follows (same instance) via the same API — k-ap detects the domain and routes accordingly.


Inbound follows (remote → local)

When a remote actor follows a local user, k-ap saves the follow with Pending status and calls no handler. You decide whether to accept or reject.

List pending followers:

let pending: Vec<RemoteActor> = service.get_pending_followers(local_user_id).await?;

Full flow (DB update + AP delivery + backfill)

// Accept: updates status → Accepted, sends Accept activity, triggers backfill.
service.accept_follower(local_user_id, remote_actor_url_str).await?;

// Reject: sends Reject activity, removes the follower record.
service.reject_follower(local_user_id, remote_actor_url_str).await?;

Backfill sends the local user's recent content to the new follower's inbox. If an EventPublisher is configured, backfill is published as BackfillRequested instead of running in-process.

DB only (no AP delivery)

Use these when you process Accept/Reject from a separate worker that handles its own delivery:

// Updates status → Accepted in DB only. No AP activity sent.
service.mark_follower_accepted(local_user_id, remote_actor_url_str).await?;

// Removes the follower record in DB only. No AP activity sent.
service.mark_follower_rejected(local_user_id, remote_actor_url_str).await?;

Querying followers

// DB-side count of accepted followers only. Efficient for large accounts.
let count: usize = service.count_accepted_followers(local_user_id).await?;

// DB-side paginated listing. offset is 0-based.
let page: Vec<RemoteActor> = service.get_accepted_followers_page(local_user_id, offset, limit).await?;

// All followers (any status). For large accounts, use the page variant.
let all: Vec<RemoteActor> = service.get_accepted_followers(local_user_id).await?;

Querying following

let following: Vec<RemoteActor> = service.get_following(local_user_id).await?;
let count: usize = service.count_following(local_user_id).await?;

Remove a follower (without AP delivery)

// Removes a follower record in DB only. No Reject activity sent.
service.remove_follower(local_user_id, actor_url_str).await?;