Skip to content

Commit

Permalink
Add setPostInteractionSettings and related prefs (#3494)
Browse files Browse the repository at this point in the history
* Add setPostInteractionSettings and related prefs

* Fix test

* Align types and implementation

* Tighten up, clarifying descriptions

* Fix test

* Format
  • Loading branch information
estrattonbailey authored Feb 5, 2025
1 parent 61dc0d6 commit 87ed907
Show file tree
Hide file tree
Showing 24 changed files with 588 additions and 1 deletion.
5 changes: 5 additions & 0 deletions .changeset/tame-cobras-lick.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@atproto/api": patch
---

Add `setPostInteractionSettings` for configuring default interaction settings for creation of posts
32 changes: 31 additions & 1 deletion lexicons/app/bsky/actor/defs.json
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,8 @@
"#mutedWordsPref",
"#hiddenPostsPref",
"#bskyAppStatePref",
"#labelersPref"
"#labelersPref",
"#postInteractionSettingsPref"
]
}
},
Expand Down Expand Up @@ -468,6 +469,35 @@
"description": "The date and time at which the NUX will expire and should be considered completed."
}
}
},
"postInteractionSettingsPref": {
"type": "object",
"description": "Default post interaction settings for the account. These values should be applied as default values when creating new posts. These refs should mirror the threadgate and postgate records exactly.",
"required": [],
"properties": {
"threadgateAllowRules": {
"description": "Matches threadgate record. List of rules defining who can reply to this users posts. If value is an empty array, no one can reply. If value is undefined, anyone can reply.",
"type": "array",
"maxLength": 5,
"items": {
"type": "union",
"refs": [
"app.bsky.feed.threadgate#mentionRule",
"app.bsky.feed.threadgate#followingRule",
"app.bsky.feed.threadgate#listRule"
]
}
},
"postgateEmbeddingRules": {
"description": "Matches postgate record. List of rules defining who can embed this users posts. If value is an empty array or is undefined, no particular rules apply and anyone can embed.",
"type": "array",
"maxLength": 5,
"items": {
"type": "union",
"refs": ["app.bsky.feed.postgate#disableRule"]
}
}
}
}
}
}
1 change: 1 addition & 0 deletions lexicons/app/bsky/feed/postgate.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
"description": "List of AT-URIs embedding this post that the author has detached from."
},
"embeddingRules": {
"description": "List of rules defining who can embed this post. If value is an empty array or is undefined, no particular rules apply and anyone can embed.",
"type": "array",
"maxLength": 5,
"items": {
Expand Down
1 change: 1 addition & 0 deletions lexicons/app/bsky/feed/threadgate.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"description": "Reference (AT-URI) to the post record."
},
"allow": {
"description": "List of rules defining who can reply to this post. If value is an empty array, no one can reply. If value is undefined, anyone can reply.",
"type": "array",
"maxLength": 5,
"items": {
Expand Down
55 changes: 55 additions & 0 deletions packages/api/src/agent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -583,6 +583,10 @@ export class Agent extends XrpcClient {
activeProgressGuide: undefined,
nuxs: [],
},
postInteractionSettings: {
threadgateAllowRules: undefined,
postgateEmbeddingRules: undefined,
},
}
const res = await this.app.bsky.actor.getPreferences({})
const labelPrefs: AppBskyActorDefs.ContentLabelPref[] = []
Expand Down Expand Up @@ -687,6 +691,14 @@ export class Agent extends XrpcClient {
prefs.bskyAppState.queuedNudges = v.queuedNudges || []
prefs.bskyAppState.activeProgressGuide = v.activeProgressGuide
prefs.bskyAppState.nuxs = v.nuxs || []
} else if (
AppBskyActorDefs.isPostInteractionSettingsPref(pref) &&
AppBskyActorDefs.validatePostInteractionSettingsPref(pref).success
) {
prefs.postInteractionSettings.threadgateAllowRules =
pref.threadgateAllowRules
prefs.postInteractionSettings.postgateEmbeddingRules =
pref.postgateEmbeddingRules
}
}

Expand Down Expand Up @@ -1463,6 +1475,49 @@ export class Agent extends XrpcClient {
})
}

async setPostInteractionSettings(
settings: AppBskyActorDefs.PostInteractionSettingsPref,
) {
if (
!AppBskyActorDefs.validatePostInteractionSettingsPref(settings).success
) {
throw new Error('Invalid post interaction settings')
}

await this.updatePreferences((prefs: AppBskyActorDefs.Preferences) => {
let prev = prefs.findLast(
(pref) =>
AppBskyActorDefs.isPostInteractionSettingsPref(pref) &&
AppBskyActorDefs.validatePostInteractionSettingsPref(pref).success,
) as AppBskyActorDefs.PostInteractionSettingsPref

if (!prev) {
prev = {
/**
* Matches handling of `threadgate.allow` where `undefined` means "everyone"
*/
threadgateAllowRules: undefined,
postgateEmbeddingRules: undefined,
}
}

/**
* Matches handling of `threadgate.allow` where `undefined` means "everyone"
*/
prev.threadgateAllowRules = settings.threadgateAllowRules
prev.postgateEmbeddingRules = settings.postgateEmbeddingRules

return prefs
.filter((p) => !AppBskyActorDefs.isPostInteractionSettingsPref(p))
.concat([
{
...prev,
$type: 'app.bsky.actor.defs#postInteractionSettingsPref',
},
])
})
}

//- Private methods

#prefsLock = new AwaitLock()
Expand Down
37 changes: 37 additions & 0 deletions packages/api/src/client/lexicons.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4381,6 +4381,7 @@ export const schemaDict = {
'lex:app.bsky.actor.defs#hiddenPostsPref',
'lex:app.bsky.actor.defs#bskyAppStatePref',
'lex:app.bsky.actor.defs#labelersPref',
'lex:app.bsky.actor.defs#postInteractionSettingsPref',
],
},
},
Expand Down Expand Up @@ -4714,6 +4715,38 @@ export const schemaDict = {
},
},
},
postInteractionSettingsPref: {
type: 'object',
description:
'Default post interaction settings for the account. These values should be applied as default values when creating new posts. These refs should mirror the threadgate and postgate records exactly.',
required: [],
properties: {
threadgateAllowRules: {
description:
'Matches threadgate record. List of rules defining who can reply to this users posts. If value is an empty array, no one can reply. If value is undefined, anyone can reply.',
type: 'array',
maxLength: 5,
items: {
type: 'union',
refs: [
'lex:app.bsky.feed.threadgate#mentionRule',
'lex:app.bsky.feed.threadgate#followingRule',
'lex:app.bsky.feed.threadgate#listRule',
],
},
},
postgateEmbeddingRules: {
description:
'Matches postgate record. List of rules defining who can embed this users posts. If value is an empty array or is undefined, no particular rules apply and anyone can embed.',
type: 'array',
maxLength: 5,
items: {
type: 'union',
refs: ['lex:app.bsky.feed.postgate#disableRule'],
},
},
},
},
},
},
AppBskyActorGetPreferences: {
Expand Down Expand Up @@ -7120,6 +7153,8 @@ export const schemaDict = {
'List of AT-URIs embedding this post that the author has detached from.',
},
embeddingRules: {
description:
'List of rules defining who can embed this post. If value is an empty array or is undefined, no particular rules apply and anyone can embed.',
type: 'array',
maxLength: 5,
items: {
Expand Down Expand Up @@ -7333,6 +7368,8 @@ export const schemaDict = {
description: 'Reference (AT-URI) to the post record.',
},
allow: {
description:
'List of rules defining who can reply to this post. If value is an empty array, no one can reply. If value is undefined, anyone can reply.',
type: 'array',
maxLength: 5,
items: {
Expand Down
36 changes: 36 additions & 0 deletions packages/api/src/client/types/app/bsky/actor/defs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import { CID } from 'multiformats/cid'
import * as ComAtprotoLabelDefs from '../../../com/atproto/label/defs'
import * as AppBskyGraphDefs from '../graph/defs'
import * as ComAtprotoRepoStrongRef from '../../../com/atproto/repo/strongRef'
import * as AppBskyFeedThreadgate from '../feed/threadgate'
import * as AppBskyFeedPostgate from '../feed/postgate'

export interface ProfileViewBasic {
did: string
Expand Down Expand Up @@ -188,6 +190,7 @@ export type Preferences = (
| HiddenPostsPref
| BskyAppStatePref
| LabelersPref
| PostInteractionSettingsPref
| { $type: string; [k: string]: unknown }
)[]

Expand Down Expand Up @@ -532,3 +535,36 @@ export function isNux(v: unknown): v is Nux {
export function validateNux(v: unknown): ValidationResult {
return lexicons.validate('app.bsky.actor.defs#nux', v)
}

/** Default post interaction settings for the account. These values should be applied as default values when creating new posts. These refs should mirror the threadgate and postgate records exactly. */
export interface PostInteractionSettingsPref {
/** Matches threadgate record. List of rules defining who can reply to this users posts. If value is an empty array, no one can reply. If value is undefined, anyone can reply. */
threadgateAllowRules?: (
| AppBskyFeedThreadgate.MentionRule
| AppBskyFeedThreadgate.FollowingRule
| AppBskyFeedThreadgate.ListRule
| { $type: string; [k: string]: unknown }
)[]
/** Matches postgate record. List of rules defining who can embed this users posts. If value is an empty array or is undefined, no particular rules apply and anyone can embed. */
postgateEmbeddingRules?: (
| AppBskyFeedPostgate.DisableRule
| { $type: string; [k: string]: unknown }
)[]
[k: string]: unknown
}

export function isPostInteractionSettingsPref(
v: unknown,
): v is PostInteractionSettingsPref {
return (
isObj(v) &&
hasProp(v, '$type') &&
v.$type === 'app.bsky.actor.defs#postInteractionSettingsPref'
)
}

export function validatePostInteractionSettingsPref(
v: unknown,
): ValidationResult {
return lexicons.validate('app.bsky.actor.defs#postInteractionSettingsPref', v)
}
1 change: 1 addition & 0 deletions packages/api/src/client/types/app/bsky/feed/postgate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export interface Record {
post: string
/** List of AT-URIs embedding this post that the author has detached from. */
detachedEmbeddingUris?: string[]
/** List of rules defining who can embed this post. If value is an empty array or is undefined, no particular rules apply and anyone can embed. */
embeddingRules?: (DisableRule | { $type: string; [k: string]: unknown })[]
[k: string]: unknown
}
Expand Down
1 change: 1 addition & 0 deletions packages/api/src/client/types/app/bsky/feed/threadgate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { CID } from 'multiformats/cid'
export interface Record {
/** Reference (AT-URI) to the post record. */
post: string
/** List of rules defining who can reply to this post. If value is an empty array, no one can reply. If value is undefined, anyone can reply. */
allow?: (
| MentionRule
| FollowingRule
Expand Down
1 change: 1 addition & 0 deletions packages/api/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,4 +109,5 @@ export interface BskyPreferences {
activeProgressGuide: AppBskyActorDefs.BskyAppProgressGuide | undefined
nuxs: AppBskyActorDefs.Nux[]
}
postInteractionSettings: AppBskyActorDefs.PostInteractionSettingsPref
}
Loading

0 comments on commit 87ed907

Please sign in to comment.