@atproto/api 0.6.14 → 0.6.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/README.md +10 -2
- package/dist/bsky-agent.d.ts +3 -1
- package/dist/client/lexicons.d.ts +46 -0
- package/dist/client/types/app/bsky/actor/defs.d.ts +19 -1
- package/dist/client/types/app/bsky/feed/threadgate.d.ts +2 -0
- package/dist/index.js +112 -7
- package/dist/index.js.map +2 -2
- package/dist/moderation/subjects/feed-generator.d.ts +1 -1
- package/dist/moderation/subjects/user-list.d.ts +1 -1
- package/dist/types.d.ts +15 -0
- package/package.json +11 -4
- package/src/agent.ts +0 -1
- package/src/bsky-agent.ts +73 -1
- package/src/client/lexicons.ts +53 -1
- package/src/client/types/app/bsky/actor/defs.ts +50 -0
- package/src/client/types/app/bsky/feed/threadgate.ts +6 -2
- package/src/moderation/subjects/feed-generator.ts +2 -2
- package/src/moderation/subjects/user-list.ts +2 -2
- package/src/moderation/util.ts +1 -5
- package/src/rich-text/sanitization.ts +2 -0
- package/src/types.ts +25 -1
- package/tests/bsky-agent.test.ts +494 -20
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { ModerationSubjectFeedGenerator, ModerationDecision, ModerationOpts } from '../types';
|
|
2
|
-
export declare function decideFeedGenerator(
|
|
2
|
+
export declare function decideFeedGenerator(_subject: ModerationSubjectFeedGenerator, _opts: ModerationOpts): ModerationDecision;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { ModerationSubjectUserList, ModerationOpts, ModerationDecision } from '../types';
|
|
2
|
-
export declare function decideUserList(
|
|
2
|
+
export declare function decideUserList(_subject: ModerationSubjectUserList, _opts: ModerationOpts): ModerationDecision;
|
package/dist/types.d.ts
CHANGED
|
@@ -33,11 +33,26 @@ export interface AtpAgentGlobalOpts {
|
|
|
33
33
|
fetch: AtpAgentFetchHandler;
|
|
34
34
|
}
|
|
35
35
|
export declare type BskyLabelPreference = LabelPreference | 'show';
|
|
36
|
+
export interface BskyFeedViewPreference {
|
|
37
|
+
hideReplies: boolean;
|
|
38
|
+
hideRepliesByUnfollowed: boolean;
|
|
39
|
+
hideRepliesByLikeCount: number;
|
|
40
|
+
hideReposts: boolean;
|
|
41
|
+
hideQuotePosts: boolean;
|
|
42
|
+
[key: string]: any;
|
|
43
|
+
}
|
|
44
|
+
export interface BskyThreadViewPreference {
|
|
45
|
+
sort: string;
|
|
46
|
+
prioritizeFollowedUsers: boolean;
|
|
47
|
+
[key: string]: any;
|
|
48
|
+
}
|
|
36
49
|
export interface BskyPreferences {
|
|
37
50
|
feeds: {
|
|
38
51
|
saved?: string[];
|
|
39
52
|
pinned?: string[];
|
|
40
53
|
};
|
|
54
|
+
feedViewPrefs: Record<string, BskyFeedViewPreference>;
|
|
55
|
+
threadViewPrefs: BskyThreadViewPreference;
|
|
41
56
|
adultContentEnabled: boolean;
|
|
42
57
|
contentLabels: Record<string, BskyLabelPreference>;
|
|
43
58
|
birthDate: Date | undefined;
|
package/package.json
CHANGED
|
@@ -1,13 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atproto/api",
|
|
3
|
-
"version": "0.6.
|
|
4
|
-
"main": "dist/index.js",
|
|
3
|
+
"version": "0.6.16",
|
|
5
4
|
"license": "MIT",
|
|
5
|
+
"description": "Client library for atproto and Bluesky",
|
|
6
|
+
"keywords": [
|
|
7
|
+
"atproto",
|
|
8
|
+
"bluesky",
|
|
9
|
+
"api"
|
|
10
|
+
],
|
|
11
|
+
"homepage": "https://atproto.com",
|
|
6
12
|
"repository": {
|
|
7
13
|
"type": "git",
|
|
8
|
-
"url": "https://github.com/bluesky-social/atproto
|
|
14
|
+
"url": "https://github.com/bluesky-social/atproto",
|
|
9
15
|
"directory": "packages/api"
|
|
10
16
|
},
|
|
17
|
+
"main": "dist/index.js",
|
|
11
18
|
"dependencies": {
|
|
12
19
|
"multiformats": "^9.9.0",
|
|
13
20
|
"tlds": "^1.234.0",
|
|
@@ -20,7 +27,7 @@
|
|
|
20
27
|
"devDependencies": {
|
|
21
28
|
"common-tags": "^1.8.2",
|
|
22
29
|
"@atproto/lex-cli": "^0.2.1",
|
|
23
|
-
"@atproto/pds": "^0.1.
|
|
30
|
+
"@atproto/pds": "^0.1.16"
|
|
24
31
|
},
|
|
25
32
|
"scripts": {
|
|
26
33
|
"codegen": "pnpm docgen && node ./scripts/generate-code.mjs && lex gen-api ./src/client ../../lexicons/com/atproto/*/* ../../lexicons/app/bsky/*/*",
|
package/src/agent.ts
CHANGED
package/src/bsky-agent.ts
CHANGED
|
@@ -6,7 +6,24 @@ import {
|
|
|
6
6
|
AppBskyActorDefs,
|
|
7
7
|
ComAtprotoRepoPutRecord,
|
|
8
8
|
} from './client'
|
|
9
|
-
import {
|
|
9
|
+
import {
|
|
10
|
+
BskyPreferences,
|
|
11
|
+
BskyLabelPreference,
|
|
12
|
+
BskyFeedViewPreference,
|
|
13
|
+
BskyThreadViewPreference,
|
|
14
|
+
} from './types'
|
|
15
|
+
|
|
16
|
+
const FEED_VIEW_PREF_DEFAULTS = {
|
|
17
|
+
hideReplies: false,
|
|
18
|
+
hideRepliesByUnfollowed: false,
|
|
19
|
+
hideRepliesByLikeCount: 0,
|
|
20
|
+
hideReposts: false,
|
|
21
|
+
hideQuotePosts: false,
|
|
22
|
+
}
|
|
23
|
+
const THREAD_VIEW_PREF_DEFAULTS = {
|
|
24
|
+
sort: 'oldest',
|
|
25
|
+
prioritizeFollowedUsers: true,
|
|
26
|
+
}
|
|
10
27
|
|
|
11
28
|
declare global {
|
|
12
29
|
interface Array<T> {
|
|
@@ -254,6 +271,12 @@ export class BskyAgent extends AtpAgent {
|
|
|
254
271
|
saved: undefined,
|
|
255
272
|
pinned: undefined,
|
|
256
273
|
},
|
|
274
|
+
feedViewPrefs: {
|
|
275
|
+
home: {
|
|
276
|
+
...FEED_VIEW_PREF_DEFAULTS,
|
|
277
|
+
},
|
|
278
|
+
},
|
|
279
|
+
threadViewPrefs: { ...THREAD_VIEW_PREF_DEFAULTS },
|
|
257
280
|
adultContentEnabled: false,
|
|
258
281
|
contentLabels: {},
|
|
259
282
|
birthDate: undefined,
|
|
@@ -289,6 +312,20 @@ export class BskyAgent extends AtpAgent {
|
|
|
289
312
|
if (pref.birthDate) {
|
|
290
313
|
prefs.birthDate = new Date(pref.birthDate)
|
|
291
314
|
}
|
|
315
|
+
} else if (
|
|
316
|
+
AppBskyActorDefs.isFeedViewPref(pref) &&
|
|
317
|
+
AppBskyActorDefs.validateFeedViewPref(pref).success
|
|
318
|
+
) {
|
|
319
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
320
|
+
const { $type, feed, ...v } = pref
|
|
321
|
+
prefs.feedViewPrefs[pref.feed] = { ...FEED_VIEW_PREF_DEFAULTS, ...v }
|
|
322
|
+
} else if (
|
|
323
|
+
AppBskyActorDefs.isThreadViewPref(pref) &&
|
|
324
|
+
AppBskyActorDefs.validateThreadViewPref(pref).success
|
|
325
|
+
) {
|
|
326
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
327
|
+
const { $type, ...v } = pref
|
|
328
|
+
prefs.threadViewPrefs = { ...prefs.threadViewPrefs, ...v }
|
|
292
329
|
}
|
|
293
330
|
}
|
|
294
331
|
return prefs
|
|
@@ -406,6 +443,41 @@ export class BskyAgent extends AtpAgent {
|
|
|
406
443
|
.concat([personalDetailsPref])
|
|
407
444
|
})
|
|
408
445
|
}
|
|
446
|
+
|
|
447
|
+
async setFeedViewPrefs(feed: string, pref: Partial<BskyFeedViewPreference>) {
|
|
448
|
+
await updatePreferences(this, (prefs: AppBskyActorDefs.Preferences) => {
|
|
449
|
+
const existing = prefs.findLast(
|
|
450
|
+
(pref) =>
|
|
451
|
+
AppBskyActorDefs.isFeedViewPref(pref) &&
|
|
452
|
+
AppBskyActorDefs.validateFeedViewPref(pref).success &&
|
|
453
|
+
pref.feed === feed,
|
|
454
|
+
)
|
|
455
|
+
if (existing) {
|
|
456
|
+
pref = { ...existing, ...pref }
|
|
457
|
+
}
|
|
458
|
+
return prefs
|
|
459
|
+
.filter(
|
|
460
|
+
(p) => !AppBskyActorDefs.isFeedViewPref(pref) || p.feed !== feed,
|
|
461
|
+
)
|
|
462
|
+
.concat([{ ...pref, $type: 'app.bsky.actor.defs#feedViewPref', feed }])
|
|
463
|
+
})
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
async setThreadViewPrefs(pref: Partial<BskyThreadViewPreference>) {
|
|
467
|
+
await updatePreferences(this, (prefs: AppBskyActorDefs.Preferences) => {
|
|
468
|
+
const existing = prefs.findLast(
|
|
469
|
+
(pref) =>
|
|
470
|
+
AppBskyActorDefs.isThreadViewPref(pref) &&
|
|
471
|
+
AppBskyActorDefs.validateThreadViewPref(pref).success,
|
|
472
|
+
)
|
|
473
|
+
if (existing) {
|
|
474
|
+
pref = { ...existing, ...pref }
|
|
475
|
+
}
|
|
476
|
+
return prefs
|
|
477
|
+
.filter((p) => !AppBskyActorDefs.isThreadViewPref(p))
|
|
478
|
+
.concat([{ ...pref, $type: 'app.bsky.actor.defs#threadViewPref' }])
|
|
479
|
+
})
|
|
480
|
+
}
|
|
409
481
|
}
|
|
410
482
|
|
|
411
483
|
/**
|
package/src/client/lexicons.ts
CHANGED
|
@@ -3687,6 +3687,8 @@ export const schemaDict = {
|
|
|
3687
3687
|
'lex:app.bsky.actor.defs#contentLabelPref',
|
|
3688
3688
|
'lex:app.bsky.actor.defs#savedFeedsPref',
|
|
3689
3689
|
'lex:app.bsky.actor.defs#personalDetailsPref',
|
|
3690
|
+
'lex:app.bsky.actor.defs#feedViewPref',
|
|
3691
|
+
'lex:app.bsky.actor.defs#threadViewPref',
|
|
3690
3692
|
],
|
|
3691
3693
|
},
|
|
3692
3694
|
},
|
|
@@ -3743,6 +3745,53 @@ export const schemaDict = {
|
|
|
3743
3745
|
},
|
|
3744
3746
|
},
|
|
3745
3747
|
},
|
|
3748
|
+
feedViewPref: {
|
|
3749
|
+
type: 'object',
|
|
3750
|
+
required: ['feed'],
|
|
3751
|
+
properties: {
|
|
3752
|
+
feed: {
|
|
3753
|
+
type: 'string',
|
|
3754
|
+
description:
|
|
3755
|
+
'The URI of the feed, or an identifier which describes the feed.',
|
|
3756
|
+
},
|
|
3757
|
+
hideReplies: {
|
|
3758
|
+
type: 'boolean',
|
|
3759
|
+
description: 'Hide replies in the feed.',
|
|
3760
|
+
},
|
|
3761
|
+
hideRepliesByUnfollowed: {
|
|
3762
|
+
type: 'boolean',
|
|
3763
|
+
description:
|
|
3764
|
+
'Hide replies in the feed if they are not by followed users.',
|
|
3765
|
+
},
|
|
3766
|
+
hideRepliesByLikeCount: {
|
|
3767
|
+
type: 'integer',
|
|
3768
|
+
description:
|
|
3769
|
+
'Hide replies in the feed if they do not have this number of likes.',
|
|
3770
|
+
},
|
|
3771
|
+
hideReposts: {
|
|
3772
|
+
type: 'boolean',
|
|
3773
|
+
description: 'Hide reposts in the feed.',
|
|
3774
|
+
},
|
|
3775
|
+
hideQuotePosts: {
|
|
3776
|
+
type: 'boolean',
|
|
3777
|
+
description: 'Hide quote posts in the feed.',
|
|
3778
|
+
},
|
|
3779
|
+
},
|
|
3780
|
+
},
|
|
3781
|
+
threadViewPref: {
|
|
3782
|
+
type: 'object',
|
|
3783
|
+
properties: {
|
|
3784
|
+
sort: {
|
|
3785
|
+
type: 'string',
|
|
3786
|
+
description: 'Sorting mode.',
|
|
3787
|
+
knownValues: ['oldest', 'newest', 'most-likes', 'random'],
|
|
3788
|
+
},
|
|
3789
|
+
prioritizeFollowedUsers: {
|
|
3790
|
+
type: 'boolean',
|
|
3791
|
+
description: 'Show followed users at the top of all replies.',
|
|
3792
|
+
},
|
|
3793
|
+
},
|
|
3794
|
+
},
|
|
3746
3795
|
},
|
|
3747
3796
|
},
|
|
3748
3797
|
AppBskyActorGetPreferences: {
|
|
@@ -5693,10 +5742,12 @@ export const schemaDict = {
|
|
|
5693
5742
|
mentionRule: {
|
|
5694
5743
|
type: 'object',
|
|
5695
5744
|
description: 'Allow replies from actors mentioned in your post.',
|
|
5745
|
+
properties: {},
|
|
5696
5746
|
},
|
|
5697
5747
|
followingRule: {
|
|
5698
5748
|
type: 'object',
|
|
5699
5749
|
description: 'Allow replies from actors you follow.',
|
|
5750
|
+
properties: {},
|
|
5700
5751
|
},
|
|
5701
5752
|
listRule: {
|
|
5702
5753
|
type: 'object',
|
|
@@ -6787,7 +6838,8 @@ export const schemaDict = {
|
|
|
6787
6838
|
defs: {
|
|
6788
6839
|
main: {
|
|
6789
6840
|
type: 'query',
|
|
6790
|
-
description:
|
|
6841
|
+
description:
|
|
6842
|
+
'DEPRECATED: will be removed soon, please find a feed generator alternative',
|
|
6791
6843
|
parameters: {
|
|
6792
6844
|
type: 'params',
|
|
6793
6845
|
properties: {
|
|
@@ -109,6 +109,8 @@ export type Preferences = (
|
|
|
109
109
|
| ContentLabelPref
|
|
110
110
|
| SavedFeedsPref
|
|
111
111
|
| PersonalDetailsPref
|
|
112
|
+
| FeedViewPref
|
|
113
|
+
| ThreadViewPref
|
|
112
114
|
| { $type: string; [k: string]: unknown }
|
|
113
115
|
)[]
|
|
114
116
|
|
|
@@ -182,3 +184,51 @@ export function isPersonalDetailsPref(v: unknown): v is PersonalDetailsPref {
|
|
|
182
184
|
export function validatePersonalDetailsPref(v: unknown): ValidationResult {
|
|
183
185
|
return lexicons.validate('app.bsky.actor.defs#personalDetailsPref', v)
|
|
184
186
|
}
|
|
187
|
+
|
|
188
|
+
export interface FeedViewPref {
|
|
189
|
+
/** The URI of the feed, or an identifier which describes the feed. */
|
|
190
|
+
feed: string
|
|
191
|
+
/** Hide replies in the feed. */
|
|
192
|
+
hideReplies?: boolean
|
|
193
|
+
/** Hide replies in the feed if they are not by followed users. */
|
|
194
|
+
hideRepliesByUnfollowed?: boolean
|
|
195
|
+
/** Hide replies in the feed if they do not have this number of likes. */
|
|
196
|
+
hideRepliesByLikeCount?: number
|
|
197
|
+
/** Hide reposts in the feed. */
|
|
198
|
+
hideReposts?: boolean
|
|
199
|
+
/** Hide quote posts in the feed. */
|
|
200
|
+
hideQuotePosts?: boolean
|
|
201
|
+
[k: string]: unknown
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
export function isFeedViewPref(v: unknown): v is FeedViewPref {
|
|
205
|
+
return (
|
|
206
|
+
isObj(v) &&
|
|
207
|
+
hasProp(v, '$type') &&
|
|
208
|
+
v.$type === 'app.bsky.actor.defs#feedViewPref'
|
|
209
|
+
)
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
export function validateFeedViewPref(v: unknown): ValidationResult {
|
|
213
|
+
return lexicons.validate('app.bsky.actor.defs#feedViewPref', v)
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
export interface ThreadViewPref {
|
|
217
|
+
/** Sorting mode. */
|
|
218
|
+
sort?: 'oldest' | 'newest' | 'most-likes' | 'random' | (string & {})
|
|
219
|
+
/** Show followed users at the top of all replies. */
|
|
220
|
+
prioritizeFollowedUsers?: boolean
|
|
221
|
+
[k: string]: unknown
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
export function isThreadViewPref(v: unknown): v is ThreadViewPref {
|
|
225
|
+
return (
|
|
226
|
+
isObj(v) &&
|
|
227
|
+
hasProp(v, '$type') &&
|
|
228
|
+
v.$type === 'app.bsky.actor.defs#threadViewPref'
|
|
229
|
+
)
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
export function validateThreadViewPref(v: unknown): ValidationResult {
|
|
233
|
+
return lexicons.validate('app.bsky.actor.defs#threadViewPref', v)
|
|
234
|
+
}
|
|
@@ -32,7 +32,9 @@ export function validateRecord(v: unknown): ValidationResult {
|
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
/** Allow replies from actors mentioned in your post. */
|
|
35
|
-
export interface MentionRule {
|
|
35
|
+
export interface MentionRule {
|
|
36
|
+
[k: string]: unknown
|
|
37
|
+
}
|
|
36
38
|
|
|
37
39
|
export function isMentionRule(v: unknown): v is MentionRule {
|
|
38
40
|
return (
|
|
@@ -47,7 +49,9 @@ export function validateMentionRule(v: unknown): ValidationResult {
|
|
|
47
49
|
}
|
|
48
50
|
|
|
49
51
|
/** Allow replies from actors you follow. */
|
|
50
|
-
export interface FollowingRule {
|
|
52
|
+
export interface FollowingRule {
|
|
53
|
+
[k: string]: unknown
|
|
54
|
+
}
|
|
51
55
|
|
|
52
56
|
export function isFollowingRule(v: unknown): v is FollowingRule {
|
|
53
57
|
return (
|
|
@@ -5,8 +5,8 @@ import {
|
|
|
5
5
|
} from '../types'
|
|
6
6
|
|
|
7
7
|
export function decideFeedGenerator(
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
_subject: ModerationSubjectFeedGenerator,
|
|
9
|
+
_opts: ModerationOpts,
|
|
10
10
|
): ModerationDecision {
|
|
11
11
|
// TODO handle labels applied on the feed generator itself
|
|
12
12
|
return ModerationDecision.noop()
|
|
@@ -5,8 +5,8 @@ import {
|
|
|
5
5
|
} from '../types'
|
|
6
6
|
|
|
7
7
|
export function decideUserList(
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
_subject: ModerationSubjectUserList,
|
|
9
|
+
_opts: ModerationOpts,
|
|
10
10
|
): ModerationDecision {
|
|
11
11
|
// TODO handle labels applied on the list itself
|
|
12
12
|
return ModerationDecision.noop()
|
package/src/moderation/util.ts
CHANGED
|
@@ -1,8 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
AppBskyEmbedRecord,
|
|
3
|
-
AppBskyEmbedRecordWithMedia,
|
|
4
|
-
AppBskyFeedPost,
|
|
5
|
-
} from '../client'
|
|
1
|
+
import { AppBskyEmbedRecord, AppBskyEmbedRecordWithMedia } from '../client'
|
|
6
2
|
import { ModerationDecision, ModerationUI } from './types'
|
|
7
3
|
|
|
8
4
|
export function takeHighestPriorityDecision(
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { RichText } from './rich-text'
|
|
2
2
|
import { UnicodeString } from './unicode'
|
|
3
3
|
|
|
4
|
+
// this regex is intentionally matching on the zero-with-separator codepoint
|
|
5
|
+
// eslint-disable-next-line no-misleading-character-class
|
|
4
6
|
const EXCESS_SPACE_RE = /[\r\n]([\u00AD\u2060\u200D\u200C\u200B\s]*[\r\n]){2,}/
|
|
5
7
|
const REPLACEMENT_STR = '\n\n'
|
|
6
8
|
|
package/src/types.ts
CHANGED
|
@@ -80,13 +80,37 @@ export type BskyLabelPreference = LabelPreference | 'show'
|
|
|
80
80
|
// TEMP we need to permanently convert 'show' to 'ignore', for now we manually convert -prf
|
|
81
81
|
|
|
82
82
|
/**
|
|
83
|
-
* Bluesky preferences
|
|
83
|
+
* Bluesky feed view preferences
|
|
84
|
+
*/
|
|
85
|
+
|
|
86
|
+
export interface BskyFeedViewPreference {
|
|
87
|
+
hideReplies: boolean
|
|
88
|
+
hideRepliesByUnfollowed: boolean
|
|
89
|
+
hideRepliesByLikeCount: number
|
|
90
|
+
hideReposts: boolean
|
|
91
|
+
hideQuotePosts: boolean
|
|
92
|
+
[key: string]: any
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Bluesky thread view preferences
|
|
97
|
+
*/
|
|
98
|
+
export interface BskyThreadViewPreference {
|
|
99
|
+
sort: string
|
|
100
|
+
prioritizeFollowedUsers: boolean
|
|
101
|
+
[key: string]: any
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Bluesky preferences
|
|
84
106
|
*/
|
|
85
107
|
export interface BskyPreferences {
|
|
86
108
|
feeds: {
|
|
87
109
|
saved?: string[]
|
|
88
110
|
pinned?: string[]
|
|
89
111
|
}
|
|
112
|
+
feedViewPrefs: Record<string, BskyFeedViewPreference>
|
|
113
|
+
threadViewPrefs: BskyThreadViewPreference
|
|
90
114
|
adultContentEnabled: boolean
|
|
91
115
|
contentLabels: Record<string, BskyLabelPreference>
|
|
92
116
|
birthDate: Date | undefined
|