Preferences
FSharp.ATProto provides convenience functions for reading and modifying Bluesky user preferences. Each function performs a read-modify-write under the hood via upsertPreferences, so concurrent modifications are safe.
All examples use taskResult {}. See the Error Handling guide for details.
open FSharp.ATProto.Core
open FSharp.ATProto.Bluesky
open FSharp.ATProto.Syntax
Functions
Function |
Description |
|---|---|
|
Read current preferences as raw JSON elements |
|
Read-modify-write preferences atomically |
|
Add a feed to saved feeds |
|
Remove a feed from saved feeds by ID |
|
Add a muted word |
|
Remove a muted word by value |
|
Set visibility for a content label |
|
Enable or disable adult content |
|
Set thread sorting preference |
|
Hide a post from your feeds |
|
Unhide a post |
Muted Words
Muted words hide posts containing the word from your feeds and notifications. The addMutedWord function takes an AppBskyActor.Defs.MutedWord record:
taskResult {
let! agent = Bluesky.login "https://bsky.social" "handle.bsky.social" "app-password"
// Mute a word in post content and tags
do! Bluesky.addMutedWord agent
{ Value = "spoilers"
Targets = [ AppBskyActor.Defs.MutedWordTarget.Content
AppBskyActor.Defs.MutedWordTarget.Tag ]
ActorTarget = Some AppBskyActor.Defs.MutedWordActorTarget.All
ExpiresAt = None
Id = None }
// Remove it later
do! Bluesky.removeMutedWord agent "spoilers"
}
Saved Feeds
Add or remove feeds from the user's saved feeds list:
taskResult {
let feed : AppBskyActor.Defs.SavedFeed =
{ Id = System.Guid.NewGuid().ToString()
Type = AppBskyActor.Defs.SavedFeedType.Feed
Value = AtUri.value feedGeneratorUri
Pinned = true }
do! Bluesky.addSavedFeed agent feed
// Remove by the feed ID
do! Bluesky.removeSavedFeed agent feed.Id
}
Content Filtering
Control how content labels affect your experience. The ContentLabelPrefVisibility DU has these cases:
Case |
Effect |
|---|---|
|
Always show labeled content |
|
Show a warning overlay (default for most labels) |
|
Hide labeled content entirely |
|
Ignore the label |
taskResult {
// Warn on NSFW content instead of hiding
do! Bluesky.setContentLabelPref agent
"nsfw"
AppBskyActor.Defs.ContentLabelPrefVisibility.Warn
None // None = Bluesky's built-in labeler
// Set preference for a custom labeler
do! Bluesky.setContentLabelPref agent
"spoiler"
AppBskyActor.Defs.ContentLabelPrefVisibility.Hide
(Some labelerDid)
}
Adult Content
Toggle the adult content master switch:
do! Bluesky.setAdultContentEnabled agent true
Thread Sorting
Set how replies are sorted when viewing a thread. The ThreadViewPrefSort DU options:
Case |
Description |
|---|---|
|
Chronological order (oldest first) |
|
Reverse chronological (newest first) |
|
Sort by like count |
|
Random order |
|
Sort by engagement |
do! Bluesky.setThreadViewPref agent AppBskyActor.Defs.ThreadViewPrefSort.Oldest
Hidden Posts
Hide or unhide individual posts from your feeds:
taskResult {
do! Bluesky.addHiddenPost agent postUri
// later...
do! Bluesky.removeHiddenPost agent postUri
}
Custom Preference Updates
For modifications not covered by the convenience functions, use upsertPreferences directly. It reads the current preferences, applies your update function, and writes the result back:
taskResult {
do! Bluesky.upsertPreferences agent (fun prefs ->
// prefs is a JsonElement list -- filter, modify, or append
prefs |> List.filter (fun el ->
// your custom logic here
true))
}
namespace FSharp
--------------------
namespace Microsoft.FSharp
module AtpAgent from FSharp.ATProto.Core
<summary> Functions for creating and authenticating <see cref="AtpAgent" /> instances. </summary>
--------------------
type AtpAgent = { HttpClient: HttpClient mutable BaseUrl: Uri mutable Session: AtpSession option ExtraHeaders: (string * string) list AuthenticateRequest: (HttpRequestMessage -> unit) option RefreshAuthentication: (unit -> Task<Result<unit,XrpcError>>) option OnSessionChanged: (unit -> unit) option }
<summary> Client agent for communicating with an AT Protocol Personal Data Server (PDS). Holds the HTTP client, base URL, optional authenticated session, and extra headers. </summary>
<remarks> Create an agent with <see cref="AtpAgent.create" /> or <see cref="AtpAgent.createWithClient" />, then authenticate with <see cref="AtpAgent.login" />. The agent's <see cref="Session" /> field is mutable: it is updated automatically on login and token refresh. </remarks>
<example><code> let agent = AtpAgent.create "https://bsky.social" let! session = AtpAgent.login "my-handle.bsky.social" "app-password-here" agent </code></example>
module AtUri from FSharp.ATProto.Syntax
<summary> Functions for creating, validating, and extracting data from <see cref="AtUri" /> values. </summary>
--------------------
type AtUri = private | AtUri of string override ToString: unit -> string
<summary> An AT-URI that identifies a resource in the AT Protocol network. AT-URIs use the scheme <c>at://</c> followed by an authority (DID or handle), an optional collection (NSID), and an optional record key. Format: <c>at://<authority>[/<collection>[/<rkey>]]</c>. Maximum length is 8192 characters. </summary>
<remarks> See the AT Protocol specification: https://atproto.com/specs/at-uri-scheme </remarks>
module Did from FSharp.ATProto.Syntax
<summary> Functions for creating, validating, and extracting data from <see cref="Did" /> values. </summary>
--------------------
type Did = private | Did of string override ToString: unit -> string
<summary> A decentralized identifier (DID) as defined by the AT Protocol. DIDs are the primary stable identifier for accounts. Two methods are currently supported: <c>did:plc:</c> (hosted, managed by PLC directory) and <c>did:web:</c> (self-hosted, DNS-based). </summary>
<remarks> See the AT Protocol specification: https://atproto.com/specs/did and the W3C DID specification: https://www.w3.org/TR/did-core/ </remarks>
<summary> High-level convenience methods for common Bluesky operations: posting, replying, liking, reposting, following, blocking, uploading blobs, and deleting records. All methods require an authenticated <see cref="AtpAgent" />. </summary>
<summary> Add a muted word to the user's preferences. </summary>
<param name="agent">An authenticated <see cref="AtpAgent" />.</param>
<param name="word">The <see cref="AppBskyActor.Defs.MutedWord" /> to add.</param>
<returns><c>Ok ()</c> on success, or an <see cref="XrpcError" />.</returns>
<summary> Remove a muted word from the user's preferences by value. </summary>
<param name="agent">An authenticated <see cref="AtpAgent" />.</param>
<param name="wordValue">The muted word string to remove.</param>
<returns><c>Ok ()</c> on success, or an <see cref="XrpcError" />.</returns>
[<Struct>] type Guid = new: b: byte array -> unit + 6 overloads member CompareTo: value: Guid -> int + 1 overload member Equals: g: Guid -> bool + 1 overload member GetHashCode: unit -> int member ToByteArray: unit -> byte array + 1 overload member ToString: unit -> string + 2 overloads member TryFormat: utf8Destination: Span<byte> * bytesWritten: byref<int> * ?format: ReadOnlySpan<char> -> bool + 1 overload member TryWriteBytes: destination: Span<byte> -> bool + 1 overload static member (<) : left: Guid * right: Guid -> bool static member (<=) : left: Guid * right: Guid -> bool ...
<summary>Represents a globally unique identifier (GUID).</summary>
--------------------
System.Guid ()
System.Guid(b: byte array) : System.Guid
System.Guid(b: System.ReadOnlySpan<byte>) : System.Guid
System.Guid(g: string) : System.Guid
System.Guid(b: System.ReadOnlySpan<byte>, bigEndian: bool) : System.Guid
System.Guid(a: int, b: int16, c: int16, d: byte array) : System.Guid
System.Guid(a: int, b: int16, c: int16, d: byte, e: byte, f: byte, g: byte, h: byte, i: byte, j: byte, k: byte) : System.Guid
System.Guid(a: uint32, b: uint16, c: uint16, d: byte, e: byte, f: byte, g: byte, h: byte, i: byte, j: byte, k: byte) : System.Guid
<summary> Extract the string representation of an AT-URI. </summary>
<param name="atUri">The AT-URI to extract the value from.</param>
<returns>The full AT-URI string (e.g. <c>"at://did:plc:z72i7hdynmk6r22z27h6tvur/app.bsky.feed.post/3k2la3b"</c>).</returns>
<summary> Add a saved feed to the user's preferences. </summary>
<param name="agent">An authenticated <see cref="AtpAgent" />.</param>
<param name="feed">The <see cref="AppBskyActor.Defs.SavedFeed" /> to add.</param>
<returns><c>Ok ()</c> on success, or an <see cref="XrpcError" />.</returns>
<summary> Remove a saved feed from the user's preferences by its ID. </summary>
<param name="agent">An authenticated <see cref="AtpAgent" />.</param>
<param name="feedId">The ID of the saved feed to remove.</param>
<returns><c>Ok ()</c> on success, or an <see cref="XrpcError" />.</returns>
<summary> Set the visibility for a content label. </summary>
<param name="agent">An authenticated <see cref="AtpAgent" />.</param>
<param name="label">The label identifier (e.g. "nsfw", "gore").</param>
<param name="visibility">The desired visibility setting.</param>
<param name="labelerDid">Optional labeler DID (for custom labelers).</param>
<returns><c>Ok ()</c> on success, or an <see cref="XrpcError" />.</returns>
<summary> Enable or disable adult content in the user's preferences. </summary>
<param name="agent">An authenticated <see cref="AtpAgent" />.</param>
<param name="enabled">Whether adult content should be enabled.</param>
<returns><c>Ok ()</c> on success, or an <see cref="XrpcError" />.</returns>
<summary> Set thread view preferences (sort order). </summary>
<param name="agent">An authenticated <see cref="AtpAgent" />.</param>
<param name="sort">The desired thread sort order.</param>
<returns><c>Ok ()</c> on success, or an <see cref="XrpcError" />.</returns>
<summary> Add a post URI to the hidden posts list. </summary>
<param name="agent">An authenticated <see cref="AtpAgent" />.</param>
<param name="postUri">The AT-URI of the post to hide.</param>
<returns><c>Ok ()</c> on success, or an <see cref="XrpcError" />.</returns>
<summary> Remove a post URI from the hidden posts list. </summary>
<param name="agent">An authenticated <see cref="AtpAgent" />.</param>
<param name="postUri">The AT-URI of the post to unhide.</param>
<returns><c>Ok ()</c> on success, or an <see cref="XrpcError" />.</returns>
<summary> Read-modify-write the authenticated user's preferences. Reads current preferences, applies your transform function, and writes the result back. Preferences use last-write-wins semantics (no CAS). </summary>
<param name="agent">An authenticated <see cref="AtpAgent" />.</param>
<param name="updateFn">A function that receives the current preferences list and returns the updated list.</param>
<returns><c>Ok ()</c> on success, or an <see cref="XrpcError" />.</returns>
module List from Microsoft.FSharp.Collections
--------------------
type List<'T> = | op_Nil | op_ColonColon of Head: 'T * Tail: 'T list interface IReadOnlyList<'T> interface IReadOnlyCollection<'T> interface IEnumerable interface IEnumerable<'T> member GetReverseIndex: rank: int * offset: int -> int member GetSlice: startIndex: int option * endIndex: int option -> 'T list static member Cons: head: 'T * tail: 'T list -> 'T list member Head: 'T with get member IsEmpty: bool with get member Item: index: int -> 'T with get ...