Skip to content

Commit

Permalink
Modlist updates: add "blockingByList" information and some utility fu…
Browse files Browse the repository at this point in the history
…nctions to the sdk (#1779)

* Add blockingByList to app.bsky.actor.defs#viewerState

* Add blocking-by-list behaviors to moderation sdk

* Add modlist helper functions to bsky-agent

* codegen

* hydrate blockingByList in profile viewer state

* ignore self-mutes and self-blocks in read path

* format

* changeset

---------

Co-authored-by: Devin Ivy <[email protected]>
  • Loading branch information
pfrazee and devinivy authored Oct 27, 2023
1 parent 35d108c commit 9c98a5b
Show file tree
Hide file tree
Showing 25 changed files with 303 additions and 23 deletions.
5 changes: 5 additions & 0 deletions .changeset/giant-humans-argue.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@atproto/api': patch
---

modlist helpers added to bsky-agent, add blockingByList to viewer state lexicon
4 changes: 4 additions & 0 deletions lexicons/app/bsky/actor/defs.json
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,10 @@
},
"blockedBy": { "type": "boolean" },
"blocking": { "type": "string", "format": "at-uri" },
"blockingByList": {
"type": "ref",
"ref": "app.bsky.graph.defs#listViewBasic"
},
"following": { "type": "string", "format": "at-uri" },
"followedBy": { "type": "string", "format": "at-uri" }
}
Expand Down
4 changes: 4 additions & 0 deletions packages/api/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,10 @@ await agent.searchActors(params, opts)
await agent.searchActorsTypeahead(params, opts)
await agent.mute(did)
await agent.unmute(did)
await agent.muteModList(listUri)
await agent.unmuteModList(listUri)
await agent.blockModList(listUri)
await agent.unblockModList(listUri)

// Notifications
await agent.listNotifications(params, opts)
Expand Down
1 change: 1 addition & 0 deletions packages/api/definitions/moderation-behaviors.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ export interface ModerationBehaviors {
string,
{
blocking: boolean
blockingByList: boolean
blockedBy: boolean
muted: boolean
mutedByList: boolean
Expand Down
25 changes: 25 additions & 0 deletions packages/api/definitions/profile-moderation-behaviors.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,45 +2,59 @@
"users": {
"self": {
"blocking": false,
"blockingByList": false,
"blockedBy": false,
"muted": false,
"mutedByList": false
},
"alice": {
"blocking": false,
"blockingByList": false,
"blockedBy": false,
"muted": false,
"mutedByList": false
},
"bob": {
"blocking": true,
"blockingByList": false,
"blockedBy": false,
"muted": false,
"mutedByList": false
},
"carla": {
"blocking": false,
"blockingByList": false,
"blockedBy": true,
"muted": false,
"mutedByList": false
},
"dan": {
"blocking": false,
"blockingByList": false,
"blockedBy": false,
"muted": true,
"mutedByList": false
},
"elise": {
"blocking": false,
"blockingByList": false,
"blockedBy": false,
"muted": false,
"mutedByList": true
},
"fern": {
"blocking": true,
"blockingByList": false,
"blockedBy": true,
"muted": false,
"mutedByList": false
},
"georgia": {
"blocking": false,
"blockingByList": true,
"blockedBy": false,
"muted": false,
"mutedByList": false
}
},
"configurations": {
Expand Down Expand Up @@ -377,6 +391,17 @@
}
},

"Mute/block: Blocking-by-list user": {
"cfg": "none",
"subject": "profile",
"author": "georgia",
"labels": {},
"behaviors": {
"account": { "cause": "blocking-by-list", "filter": true },
"avatar": { "blur": true, "noOverride": true }
}
},

"Mute/block: Blocked by user": {
"cfg": "none",
"subject": "profile",
Expand Down
17 changes: 17 additions & 0 deletions packages/api/docs/moderation-behaviors/profiles.md
Original file line number Diff line number Diff line change
Expand Up @@ -547,6 +547,23 @@ Key:
</td>
</tr>

<tr>
<td><strong>Mute/block: Blocking-by-list user</strong></td>
<td>
</td>
<td>

</td>
<td>

</td>
<td>
🚫

</td>
</tr>

<tr>
<td><strong>Mute/block: Blocked by user</strong></td>
<td>
Expand Down
43 changes: 43 additions & 0 deletions packages/api/src/bsky-agent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,49 @@ export class BskyAgent extends AtpAgent {
return this.api.app.bsky.graph.unmuteActor({ actor })
}

async muteModList(uri: string) {
return this.api.app.bsky.graph.muteActorList({
list: uri,
})
}

async unmuteModList(uri: string) {
return this.api.app.bsky.graph.unmuteActorList({
list: uri,
})
}

async blockModList(uri: string) {
if (!this.session) {
throw new Error('Not logged in')
}
return await this.api.app.bsky.graph.listblock.create(
{ repo: this.session.did },
{
subject: uri,
createdAt: new Date().toISOString(),
},
)
}

async unblockModList(uri: string) {
if (!this.session) {
throw new Error('Not logged in')
}
const listInfo = await this.api.app.bsky.graph.getList({
list: uri,
limit: 1,
})
if (!listInfo.data.list.viewer?.blocked) {
return
}
const { rkey } = new AtUri(listInfo.data.list.viewer.blocked)
return await this.api.app.bsky.graph.listblock.delete({
repo: this.session.did,
rkey,
})
}

async updateSeenNotifications(seenAt?: string) {
seenAt = seenAt || new Date().toISOString()
return this.api.app.bsky.notification.updateSeen({
Expand Down
4 changes: 4 additions & 0 deletions packages/api/src/client/lexicons.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3827,6 +3827,10 @@ export const schemaDict = {
type: 'string',
format: 'at-uri',
},
blockingByList: {
type: 'ref',
ref: 'lex:app.bsky.graph.defs#listViewBasic',
},
following: {
type: 'string',
format: 'at-uri',
Expand Down
1 change: 1 addition & 0 deletions packages/api/src/client/types/app/bsky/actor/defs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ export interface ViewerState {
mutedByList?: AppBskyGraphDefs.ListViewBasic
blockedBy?: boolean
blocking?: string
blockingByList?: AppBskyGraphDefs.ListViewBasic
following?: string
followedBy?: string
[k: string]: unknown
Expand Down
13 changes: 13 additions & 0 deletions packages/api/src/moderation/accumulator.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { AppBskyGraphDefs } from '../client/index'
import { AtUri } from '@atproto/syntax'

Check warning on line 2 in packages/api/src/moderation/accumulator.ts

View workflow job for this annotation

GitHub Actions / Build & Publish

'AtUri' is defined but never used. Allowed unused vars must match /^_/u
import {
Label,
LabelPreference,
Expand Down Expand Up @@ -28,6 +29,18 @@ export class ModerationCauseAccumulator {
}
}

addBlockingByList(
blockingByList: AppBskyGraphDefs.ListViewBasic | undefined,
) {
if (blockingByList) {
this.causes.push({
type: 'blocking',
source: { type: 'list', list: blockingByList },
priority: 3,
})
}
}

addBlockedBy(blockedBy: boolean | undefined) {
if (blockedBy) {
this.causes.push({
Expand Down
8 changes: 7 additions & 1 deletion packages/api/src/moderation/subjects/account.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,13 @@ export function decideAccount(
acc.addMuted(subject.viewer?.muted)
}
}
acc.addBlocking(subject.viewer?.blocking)
if (subject.viewer?.blocking) {
if (subject.viewer?.blockingByList) {
acc.addBlockingByList(subject.viewer?.blockingByList)
} else {
acc.addBlocking(subject.viewer?.blocking)
}
}
acc.addBlockedBy(subject.viewer?.blockedBy)

for (const label of filterAccountLabels(subject.labels)) {
Expand Down
3 changes: 3 additions & 0 deletions packages/api/tests/util/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,13 +135,15 @@ export const mock = {
mutedByList,
blockedBy,
blocking,
blockingByList,
following,
followedBy,
}: {
muted?: boolean
mutedByList?: AppBskyGraphDefs.ListViewBasic
blockedBy?: boolean
blocking?: string
blockingByList?: AppBskyGraphDefs.ListViewBasic
following?: string
followedBy?: string
}): AppBskyActorDefs.ViewerState {
Expand All @@ -150,6 +152,7 @@ export const mock = {
mutedByList,
blockedBy,
blocking,
blockingByList,
following,
followedBy,
}
Expand Down
12 changes: 10 additions & 2 deletions packages/api/tests/util/moderation-behavior.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ expect.extend({
if (actual.cause.source.type === 'list') {
cause = 'muted-by-list'
}
} else if (actual.cause?.type === 'blocking') {
if (actual.cause.source.type === 'list') {
cause = 'blocking-by-list'
}
}
if (!expected) {
if (!ignoreCause && actual.cause) {
Expand Down Expand Up @@ -153,8 +157,12 @@ export class ModerationBehaviorSuiteRunner {
? m.listViewBasic({ name: 'Fake List' })
: undefined,
blockedBy: def.blockedBy,
blocking: def.blocking
? 'at://did:web:self.test/app.bsky.graph.block/fake'
blocking:
def.blocking || def.blockingByList
? 'at://did:web:self.test/app.bsky.graph.block/fake'
: undefined,
blockingByList: def.blockingByList
? m.listViewBasic({ name: 'Fake List' })
: undefined,
}),
})
Expand Down
4 changes: 4 additions & 0 deletions packages/bsky/src/lexicon/lexicons.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3827,6 +3827,10 @@ export const schemaDict = {
type: 'string',
format: 'at-uri',
},
blockingByList: {
type: 'ref',
ref: 'lex:app.bsky.graph.defs#listViewBasic',
},
following: {
type: 'string',
format: 'at-uri',
Expand Down
1 change: 1 addition & 0 deletions packages/bsky/src/lexicon/types/app/bsky/actor/defs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ export interface ViewerState {
mutedByList?: AppBskyGraphDefs.ListViewBasic
blockedBy?: boolean
blocking?: string
blockingByList?: AppBskyGraphDefs.ListViewBasic
following?: string
followedBy?: string
[k: string]: unknown
Expand Down
1 change: 1 addition & 0 deletions packages/bsky/src/services/actor/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export type ActorInfo = {
mutedByList?: ListViewBasic
blockedBy?: boolean
blocking?: string
blockingByList?: ListViewBasic
following?: string
followedBy?: string
}
Expand Down
34 changes: 26 additions & 8 deletions packages/bsky/src/services/actor/views.ts
Original file line number Diff line number Diff line change
Expand Up @@ -137,10 +137,13 @@ export class ActorViews {
),
])
const listUris = mapDefined(profiles, ({ did }) => {
const list = viewer && bam.muteList([viewer, did])
if (!list) return
return list
})
const muteList = viewer && bam.muteList([viewer, did])
const blockList = viewer && bam.blockList([viewer, did])
const lists: string[] = []
if (muteList) lists.push(muteList)
if (blockList) lists.push(blockList)
return lists
}).flat()
const lists = await this.services.graph.getListViews(listUris, viewer)
return { profilesDetailed: toMapByDid(profiles), labels, bam, lists }
}
Expand Down Expand Up @@ -168,6 +171,11 @@ export class ActorViews {
mutedByListUri && lists[mutedByListUri]
? this.services.graph.formatListViewBasic(lists[mutedByListUri])
: undefined
const blockingByListUri = viewer && bam.blockList([viewer, did])
const blockingByList =
blockingByListUri && lists[blockingByListUri]
? this.services.graph.formatListViewBasic(lists[blockingByListUri])
: undefined
const actorLabels = labels[did] ?? []
const selfLabels = getSelfLabels({
uri: prof.profileUri,
Expand All @@ -194,6 +202,7 @@ export class ActorViews {
mutedByList,
blockedBy: !!bam.blockedBy([viewer, did]),
blocking: bam.blocking([viewer, did]) ?? undefined,
blockingByList,
following:
prof?.viewerFollowing && !bam.block([viewer, did])
? prof.viewerFollowing
Expand Down Expand Up @@ -265,10 +274,13 @@ export class ActorViews {
),
])
const listUris = mapDefined(profiles, ({ did }) => {
const list = viewer && bam.muteList([viewer, did])
if (!list) return
return list
})
const muteList = viewer && bam.muteList([viewer, did])
const blockList = viewer && bam.blockList([viewer, did])
const lists: string[] = []
if (muteList) lists.push(muteList)
if (blockList) lists.push(blockList)
return lists
}).flat()
const lists = await this.services.graph.getListViews(listUris, viewer)
return { profiles: toMapByDid(profiles), labels, bam, lists }
}
Expand Down Expand Up @@ -298,6 +310,11 @@ export class ActorViews {
mutedByListUri && lists[mutedByListUri]
? this.services.graph.formatListViewBasic(lists[mutedByListUri])
: undefined
const blockingByListUri = viewer && bam.blockList([viewer, did])
const blockingByList =
blockingByListUri && lists[blockingByListUri]
? this.services.graph.formatListViewBasic(lists[blockingByListUri])
: undefined
const actorLabels = labels[did] ?? []
const selfLabels = getSelfLabels({
uri: prof.profileUri,
Expand All @@ -320,6 +337,7 @@ export class ActorViews {
mutedByList,
blockedBy: !!bam.blockedBy([viewer, did]),
blocking: bam.blocking([viewer, did]) ?? undefined,
blockingByList,
following:
prof?.viewerFollowing && !bam.block([viewer, did])
? prof.viewerFollowing
Expand Down
Loading

0 comments on commit 9c98a5b

Please sign in to comment.