@atproto/api 0.6.7 → 0.6.8

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.
Files changed (111) hide show
  1. package/build.js +8 -0
  2. package/dist/agent.d.ts +25 -44
  3. package/dist/bsky-agent.d.ts +24 -0
  4. package/dist/client/types/app/bsky/actor/createScene.d.ts +32 -0
  5. package/dist/client/types/app/bsky/actor/defs.d.ts +65 -74
  6. package/dist/client/types/app/bsky/actor/ref.d.ts +28 -0
  7. package/dist/client/types/app/bsky/actor/search.d.ts +22 -0
  8. package/dist/client/types/app/bsky/actor/searchTypeahead.d.ts +20 -0
  9. package/dist/client/types/app/bsky/actor/updateProfile.d.ts +40 -0
  10. package/dist/client/types/app/bsky/embed/external.d.ts +23 -23
  11. package/dist/client/types/app/bsky/embed/images.d.ts +20 -20
  12. package/dist/client/types/app/bsky/embed/recordWithMedia.d.ts +20 -26
  13. package/dist/client/types/app/bsky/feed/feedViewPost.d.ts +28 -0
  14. package/dist/client/types/app/bsky/feed/getSavedFeeds.d.ts +21 -0
  15. package/dist/client/types/app/bsky/feed/getVotes.d.ts +36 -0
  16. package/dist/client/types/app/bsky/feed/like.d.ts +7 -7
  17. package/dist/client/types/app/bsky/feed/repost.d.ts +7 -7
  18. package/dist/client/types/app/bsky/feed/saveFeed.d.ts +17 -0
  19. package/dist/client/types/app/bsky/feed/setVote.d.ts +25 -0
  20. package/dist/client/types/app/bsky/feed/trend.d.ts +9 -0
  21. package/dist/client/types/app/bsky/feed/unsaveFeed.d.ts +17 -0
  22. package/dist/client/types/app/bsky/feed/vote.d.ts +10 -0
  23. package/dist/client/types/app/bsky/graph/assertCreator.d.ts +1 -0
  24. package/dist/client/types/app/bsky/graph/assertMember.d.ts +1 -0
  25. package/dist/client/types/app/bsky/graph/assertion.d.ts +10 -0
  26. package/dist/client/types/app/bsky/graph/block.d.ts +6 -6
  27. package/dist/client/types/app/bsky/graph/confirmation.d.ts +11 -0
  28. package/dist/client/types/app/bsky/graph/defs.d.ts +36 -36
  29. package/dist/client/types/app/bsky/graph/follow.d.ts +6 -6
  30. package/dist/client/types/app/bsky/graph/getAssertions.d.ts +48 -0
  31. package/dist/client/types/app/bsky/graph/getListBlocks.d.ts +21 -0
  32. package/dist/client/types/app/bsky/graph/getMembers.d.ts +36 -0
  33. package/dist/client/types/app/bsky/graph/getMemberships.d.ts +36 -0
  34. package/dist/client/types/app/bsky/graph/listblock.d.ts +8 -0
  35. package/dist/client/types/app/bsky/graph/listitem.d.ts +7 -7
  36. package/dist/client/types/app/bsky/graph/mute.d.ts +17 -0
  37. package/dist/client/types/app/bsky/graph/subscribeMuteList.d.ts +17 -0
  38. package/dist/client/types/app/bsky/graph/unmute.d.ts +17 -0
  39. package/dist/client/types/app/bsky/graph/unsubscribeMuteList.d.ts +17 -0
  40. package/dist/client/types/app/bsky/notification/getCount.d.ts +17 -0
  41. package/dist/client/types/app/bsky/notification/list.d.ts +35 -0
  42. package/dist/client/types/app/bsky/richtext/facet.d.ts +22 -26
  43. package/dist/client/types/app/bsky/system/actorScene.d.ts +1 -0
  44. package/dist/client/types/app/bsky/system/actorUser.d.ts +1 -0
  45. package/dist/client/types/app/bsky/system/declRef.d.ts +8 -0
  46. package/dist/client/types/app/bsky/system/declaration.d.ts +7 -0
  47. package/dist/client/types/com/atproto/account/create.d.ts +41 -0
  48. package/dist/client/types/com/atproto/account/createInviteCode.d.ts +22 -0
  49. package/dist/client/types/com/atproto/account/delete.d.ts +25 -0
  50. package/dist/client/types/com/atproto/account/get.d.ts +12 -0
  51. package/dist/client/types/com/atproto/account/requestDelete.d.ts +13 -0
  52. package/dist/client/types/com/atproto/account/requestPasswordReset.d.ts +17 -0
  53. package/dist/client/types/com/atproto/account/resetPassword.d.ts +24 -0
  54. package/dist/client/types/com/atproto/admin/blob.d.ts +37 -0
  55. package/dist/client/types/com/atproto/admin/moderationAction.d.ts +60 -0
  56. package/dist/client/types/com/atproto/admin/moderationReport.d.ts +37 -0
  57. package/dist/client/types/com/atproto/admin/record.d.ts +43 -0
  58. package/dist/client/types/com/atproto/admin/repo.d.ts +45 -0
  59. package/dist/client/types/com/atproto/blob/upload.d.ts +19 -0
  60. package/dist/client/types/com/atproto/handle/resolve.d.ts +18 -0
  61. package/dist/client/types/com/atproto/handle/update.d.ts +17 -0
  62. package/dist/client/types/com/atproto/label/subscribeLabels.d.ts +12 -12
  63. package/dist/client/types/com/atproto/moderation/defs.d.ts +7 -16
  64. package/dist/client/types/com/atproto/repo/batchWrite.d.ts +46 -0
  65. package/dist/client/types/com/atproto/repo/describe.d.ts +22 -0
  66. package/dist/client/types/com/atproto/repo/recordRef.d.ts +8 -0
  67. package/dist/client/types/com/atproto/repo/repoRef.d.ts +7 -0
  68. package/dist/client/types/com/atproto/repo/strongRef.d.ts +6 -6
  69. package/dist/client/types/com/atproto/report/create.d.ts +39 -0
  70. package/dist/client/types/com/atproto/report/reasonType.d.ts +3 -0
  71. package/dist/client/types/com/atproto/report/subject.d.ts +23 -0
  72. package/dist/client/types/com/atproto/server/defs.d.ts +16 -16
  73. package/dist/client/types/com/atproto/server/getAccountsConfig.d.ts +27 -0
  74. package/dist/client/types/com/atproto/session/create.d.ts +29 -0
  75. package/dist/client/types/com/atproto/session/delete.d.ts +13 -0
  76. package/dist/client/types/com/atproto/session/get.d.ts +18 -0
  77. package/dist/client/types/com/atproto/session/refresh.d.ts +24 -0
  78. package/dist/client/types/com/atproto/sync/getRoot.d.ts +18 -0
  79. package/dist/client/types/com/atproto/sync/subscribeAllRepos.d.ts +9 -0
  80. package/dist/client/types/com/atproto/sync/subscribeRepos.d.ts +46 -46
  81. package/dist/client/types/com/atproto/sync/updateRepo.d.ts +15 -0
  82. package/dist/client/util.d.ts +2 -5
  83. package/dist/helpers/bsky.d.ts +20 -0
  84. package/dist/index.d.ts +1 -1
  85. package/dist/index.js +1260 -865
  86. package/dist/index.js.map +4 -4
  87. package/dist/mixins/bsky.d.ts +23 -0
  88. package/dist/rich-text/detection.d.ts +4 -4
  89. package/dist/rich-text/rich-text.d.ts +31 -31
  90. package/dist/rich-text/sanitization.d.ts +4 -7
  91. package/dist/rich-text/sanitize.d.ts +4 -0
  92. package/dist/rich-text/unicode.d.ts +9 -9
  93. package/dist/session.d.ts +42 -0
  94. package/dist/types.d.ts +32 -34
  95. package/package.json +23 -22
  96. package/src/bsky-agent.ts +181 -1
  97. package/src/client/index.ts +36 -39
  98. package/src/client/lexicons.ts +76 -129
  99. package/src/client/types/com/atproto/sync/getCheckout.ts +0 -2
  100. package/src/client/types/com/atproto/sync/{getCommitPath.ts → getLatestCommit.ts} +9 -5
  101. package/src/client/types/com/atproto/sync/getRepo.ts +2 -4
  102. package/src/client/types/com/atproto/sync/listBlobs.ts +5 -4
  103. package/src/client/types/com/atproto/sync/subscribeRepos.ts +5 -1
  104. package/src/client/types/com/atproto/{admin/rebaseRepo.ts → temp/upgradeRepoVersion.ts} +1 -18
  105. package/src/index.ts +1 -1
  106. package/src/types.ts +20 -0
  107. package/tests/bsky-agent.test.ts +149 -0
  108. package/tsconfig.build.tsbuildinfo +1 -1
  109. package/update-pkg.js +14 -0
  110. package/LICENSE +0 -21
  111. package/src/client/types/com/atproto/repo/rebaseRepo.ts +0 -49
@@ -0,0 +1,23 @@
1
+ import { AtpAgentType } from '../types';
2
+ export declare function addBsky<TBase extends AtpAgentType>(Base: TBase): {
3
+ new (...args: any[]): {
4
+ like(uri: string, cid: string): Promise<{
5
+ uri: string;
6
+ cid: string;
7
+ }>;
8
+ unlike(likeUri: string): Promise<void>;
9
+ repost(uri: string, cid: string): Promise<{
10
+ uri: string;
11
+ cid: string;
12
+ }>;
13
+ unrepost(repostUri: string): Promise<void>;
14
+ follow(subjectDid: string): Promise<{
15
+ uri: string;
16
+ cid: string;
17
+ }>;
18
+ unfollow(followUri: string): Promise<void>;
19
+ service: URL;
20
+ api: import("..").AtpServiceClient;
21
+ session?: import("../types").AtpSessionData | undefined;
22
+ };
23
+ } & TBase;
@@ -1,4 +1,4 @@
1
- import { AppBskyRichtextFacet } from '../client'
2
- import { UnicodeString } from './unicode'
3
- export declare type Facet = AppBskyRichtextFacet.Main
4
- export declare function detectFacets(text: UnicodeString): Facet[] | undefined
1
+ import { AppBskyRichtextFacet } from '../client';
2
+ import { UnicodeString } from './unicode';
3
+ export declare type Facet = AppBskyRichtextFacet.Main;
4
+ export declare function detectFacets(text: UnicodeString): Facet[] | undefined;
@@ -1,39 +1,39 @@
1
- import { AtpAgent } from '../agent'
2
- import { AppBskyFeedPost, AppBskyRichtextFacet } from '../client'
3
- import { UnicodeString } from './unicode'
4
- export declare type Facet = AppBskyRichtextFacet.Main
5
- export declare type FacetLink = AppBskyRichtextFacet.Link
6
- export declare type FacetMention = AppBskyRichtextFacet.Mention
7
- export declare type Entity = AppBskyFeedPost.Entity
1
+ import { AtpAgent } from '../agent';
2
+ import { AppBskyFeedPost, AppBskyRichtextFacet } from '../client';
3
+ import { UnicodeString } from './unicode';
4
+ export declare type Facet = AppBskyRichtextFacet.Main;
5
+ export declare type FacetLink = AppBskyRichtextFacet.Link;
6
+ export declare type FacetMention = AppBskyRichtextFacet.Mention;
7
+ export declare type Entity = AppBskyFeedPost.Entity;
8
8
  export interface RichTextProps {
9
- text: string
10
- facets?: Facet[]
11
- entities?: Entity[]
9
+ text: string;
10
+ facets?: Facet[];
11
+ entities?: Entity[];
12
12
  }
13
13
  export interface RichTextOpts {
14
- cleanNewlines?: boolean
14
+ cleanNewlines?: boolean;
15
15
  }
16
16
  export declare class RichTextSegment {
17
- text: string
18
- facet?: AppBskyRichtextFacet.Main | undefined
19
- constructor(text: string, facet?: AppBskyRichtextFacet.Main | undefined)
20
- get link(): FacetLink | undefined
21
- isLink(): boolean
22
- get mention(): FacetMention | undefined
23
- isMention(): boolean
17
+ text: string;
18
+ facet?: AppBskyRichtextFacet.Main | undefined;
19
+ constructor(text: string, facet?: AppBskyRichtextFacet.Main | undefined);
20
+ get link(): FacetLink | undefined;
21
+ isLink(): boolean;
22
+ get mention(): FacetMention | undefined;
23
+ isMention(): boolean;
24
24
  }
25
25
  export declare class RichText {
26
- unicodeText: UnicodeString
27
- facets?: Facet[]
28
- constructor(props: RichTextProps, opts?: RichTextOpts)
29
- get text(): string
30
- get length(): number
31
- get graphemeLength(): number
32
- clone(): RichText
33
- copyInto(target: RichText): void
34
- segments(): Generator<RichTextSegment, void, void>
35
- insert(insertIndex: number, insertText: string): this
36
- delete(removeStartIndex: number, removeEndIndex: number): this
37
- detectFacets(agent: AtpAgent): Promise<void>
38
- detectFacetsWithoutResolution(): void
26
+ unicodeText: UnicodeString;
27
+ facets?: Facet[];
28
+ constructor(props: RichTextProps, opts?: RichTextOpts);
29
+ get text(): string;
30
+ get length(): number;
31
+ get graphemeLength(): number;
32
+ clone(): RichText;
33
+ copyInto(target: RichText): void;
34
+ segments(): Generator<RichTextSegment, void, void>;
35
+ insert(insertIndex: number, insertText: string): this;
36
+ delete(removeStartIndex: number, removeEndIndex: number): this;
37
+ detectFacets(agent: AtpAgent): Promise<void>;
38
+ detectFacetsWithoutResolution(): void;
39
39
  }
@@ -1,7 +1,4 @@
1
- import { RichText } from './rich-text'
2
- export declare function sanitizeRichText(
3
- richText: RichText,
4
- opts: {
5
- cleanNewlines?: boolean
6
- },
7
- ): RichText
1
+ import { RichText } from './rich-text';
2
+ export declare function sanitizeRichText(richText: RichText, opts: {
3
+ cleanNewlines?: boolean;
4
+ }): RichText;
@@ -0,0 +1,4 @@
1
+ import { RichText } from './rich-text';
2
+ export declare function sanitizeRichText(richText: RichText, opts: {
3
+ cleanNewlines?: boolean;
4
+ }): RichText;
@@ -1,11 +1,11 @@
1
1
  export declare class UnicodeString {
2
- utf16: string
3
- utf8: Uint8Array
4
- private _graphemeLen?
5
- constructor(utf16: string)
6
- get length(): number
7
- get graphemeLength(): number
8
- slice(start?: number, end?: number): string
9
- utf16IndexToUtf8Index(i: number): number
10
- toString(): string
2
+ utf16: string;
3
+ utf8: Uint8Array;
4
+ private _graphemeLen?;
5
+ constructor(utf16: string);
6
+ get length(): number;
7
+ get graphemeLength(): number;
8
+ slice(start?: number, end?: number): string;
9
+ utf16IndexToUtf8Index(i: number): number;
10
+ toString(): string;
11
11
  }
@@ -0,0 +1,42 @@
1
+ import { CallOptions, Client as XrpcClient, ServiceClient as XrpcServiceClient, QueryParams, XRPCResponse } from '@atproto/xrpc';
2
+ import TypedEmitter from 'typed-emitter';
3
+ import { Client, ServiceClient } from './client';
4
+ export declare class SessionClient extends Client {
5
+ service(serviceUri: string | URL): SessionServiceClient;
6
+ }
7
+ declare const defaultInst: SessionClient;
8
+ export default defaultInst;
9
+ export declare class SessionServiceClient extends ServiceClient {
10
+ xrpc: SessionXrpcServiceClient;
11
+ sessionManager: SessionManager;
12
+ constructor(baseClient: Client, xrpcService: SessionXrpcServiceClient);
13
+ }
14
+ export declare class SessionXrpcServiceClient extends XrpcServiceClient {
15
+ sessionManager: SessionManager;
16
+ refreshing?: Promise<XRPCResponse>;
17
+ constructor(baseClient: XrpcClient, serviceUri: string | URL);
18
+ call(methodNsid: string, params?: QueryParams, data?: unknown, opts?: CallOptions): Promise<XRPCResponse>;
19
+ refresh(opts?: CallOptions): Promise<XRPCResponse>;
20
+ private _refresh;
21
+ }
22
+ declare const SessionManager_base: new () => TypedEmitter<SessionEvents>;
23
+ export declare class SessionManager extends SessionManager_base {
24
+ session?: Session;
25
+ get(): Session | undefined;
26
+ set(session: Session): void;
27
+ unset(): void;
28
+ active(): boolean;
29
+ accessHeaders(): {
30
+ authorization: string;
31
+ } | undefined;
32
+ refreshHeaders(): {
33
+ authorization: string;
34
+ } | undefined;
35
+ }
36
+ export declare type Session = {
37
+ refreshJwt: string;
38
+ accessJwt: string;
39
+ };
40
+ declare type SessionEvents = {
41
+ session: (session?: Session) => void;
42
+ };
package/dist/types.d.ts CHANGED
@@ -1,46 +1,44 @@
1
- export declare type AtpSessionEvent =
2
- | 'create'
3
- | 'create-failed'
4
- | 'update'
5
- | 'expired'
1
+ import { LabelPreference } from './moderation/types';
2
+ export declare type AtpSessionEvent = 'create' | 'create-failed' | 'update' | 'expired';
6
3
  export interface AtpSessionData {
7
- refreshJwt: string
8
- accessJwt: string
9
- handle: string
10
- did: string
11
- email?: string
4
+ refreshJwt: string;
5
+ accessJwt: string;
6
+ handle: string;
7
+ did: string;
8
+ email?: string;
12
9
  }
13
- export declare type AtpPersistSessionHandler = (
14
- evt: AtpSessionEvent,
15
- session: AtpSessionData | undefined,
16
- ) => void | Promise<void>
10
+ export declare type AtpPersistSessionHandler = (evt: AtpSessionEvent, session: AtpSessionData | undefined) => void | Promise<void>;
17
11
  export interface AtpAgentOpts {
18
- service: string | URL
19
- persistSession?: AtpPersistSessionHandler
12
+ service: string | URL;
13
+ persistSession?: AtpPersistSessionHandler;
20
14
  }
21
15
  export interface AtpAgentCreateAccountOpts {
22
- email: string
23
- password: string
24
- handle: string
25
- inviteCode?: string
16
+ email: string;
17
+ password: string;
18
+ handle: string;
19
+ inviteCode?: string;
26
20
  }
27
21
  export interface AtpAgentLoginOpts {
28
- identifier: string
29
- password: string
22
+ identifier: string;
23
+ password: string;
30
24
  }
31
- declare type AtpAgentFetchHeaders = Record<string, string>
25
+ declare type AtpAgentFetchHeaders = Record<string, string>;
32
26
  export interface AtpAgentFetchHandlerResponse {
33
- status: number
34
- headers: Record<string, string>
35
- body: any
27
+ status: number;
28
+ headers: Record<string, string>;
29
+ body: any;
36
30
  }
37
- export declare type AtpAgentFetchHandler = (
38
- httpUri: string,
39
- httpMethod: string,
40
- httpHeaders: AtpAgentFetchHeaders,
41
- httpReqBody: any,
42
- ) => Promise<AtpAgentFetchHandlerResponse>
31
+ export declare type AtpAgentFetchHandler = (httpUri: string, httpMethod: string, httpHeaders: AtpAgentFetchHeaders, httpReqBody: any) => Promise<AtpAgentFetchHandlerResponse>;
43
32
  export interface AtpAgentGlobalOpts {
44
- fetch: AtpAgentFetchHandler
33
+ fetch: AtpAgentFetchHandler;
45
34
  }
46
- export {}
35
+ export declare type BskyLabelPreference = LabelPreference | 'show';
36
+ export interface BskyPreferences {
37
+ feeds: {
38
+ saved?: string[];
39
+ pinned?: string[];
40
+ };
41
+ adultContentEnabled: boolean;
42
+ contentLabels: Record<string, BskyLabelPreference>;
43
+ }
44
+ export {};
package/package.json CHANGED
@@ -1,7 +1,20 @@
1
1
  {
2
2
  "name": "@atproto/api",
3
- "version": "0.6.7",
3
+ "version": "0.6.8",
4
4
  "main": "dist/index.js",
5
+ "scripts": {
6
+ "codegen": "yarn docgen && node ./scripts/generate-code.mjs && lex gen-api ./src/client ../../lexicons/com/atproto/*/* ../../lexicons/app/bsky/*/*",
7
+ "docgen": "node ./scripts/generate-docs.mjs",
8
+ "build": "node ./build.js",
9
+ "postbuild": "tsc --build tsconfig.build.json",
10
+ "update-main-to-dist": "node ./update-pkg.js --update-main-to-dist",
11
+ "update-main-to-src": "node ./update-pkg.js --update-main-to-src",
12
+ "prepublish": "npm run update-main-to-dist",
13
+ "postpublish": "npm run update-main-to-src",
14
+ "test": "jest",
15
+ "bench": "jest --config jest.bench.config.js",
16
+ "bench:profile": "node --inspect-brk ../../node_modules/.bin/jest --config jest.bench.config.js"
17
+ },
5
18
  "license": "MIT",
6
19
  "repository": {
7
20
  "type": "git",
@@ -9,27 +22,15 @@
9
22
  "directory": "packages/api"
10
23
  },
11
24
  "dependencies": {
12
- "multiformats": "^9.9.0",
25
+ "@atproto/common-web": "*",
26
+ "@atproto/syntax": "*",
27
+ "@atproto/xrpc": "*",
13
28
  "tlds": "^1.234.0",
14
- "typed-emitter": "^2.1.0",
15
- "@atproto/common-web": "^0.2.0",
16
- "@atproto/lexicon": "^0.2.0",
17
- "@atproto/uri": "^0.1.0",
18
- "@atproto/xrpc": "^0.2.0"
29
+ "typed-emitter": "^2.1.0"
19
30
  },
20
31
  "devDependencies": {
21
- "common-tags": "^1.8.2",
22
- "@atproto/lex-cli": "^0.2.0",
23
- "@atproto/pds": "^0.1.12"
24
- },
25
- "scripts": {
26
- "codegen": "pnpm docgen && node ./scripts/generate-code.mjs && lex gen-api ./src/client ../../lexicons/com/atproto/*/* ../../lexicons/app/bsky/*/*",
27
- "docgen": "node ./scripts/generate-docs.mjs",
28
- "build": "node ./build.js",
29
- "postbuild": "tsc --build tsconfig.build.json",
30
- "test": "jest",
31
- "bench": "jest --config jest.bench.config.js",
32
- "bench:profile": "node --inspect-brk ../../node_modules/.bin/jest --config jest.bench.config.js"
33
- },
34
- "types": "dist/index.d.ts"
35
- }
32
+ "@atproto/lex-cli": "*",
33
+ "@atproto/pds": "*",
34
+ "common-tags": "^1.8.2"
35
+ }
36
+ }
package/src/bsky-agent.ts CHANGED
@@ -1,10 +1,12 @@
1
- import { AtUri } from '@atproto/uri'
1
+ import { AtUri } from '@atproto/syntax'
2
2
  import { AtpAgent } from './agent'
3
3
  import {
4
4
  AppBskyFeedPost,
5
5
  AppBskyActorProfile,
6
+ AppBskyActorDefs,
6
7
  ComAtprotoRepoPutRecord,
7
8
  } from './client'
9
+ import { BskyPreferences, BskyLabelPreference } from './types'
8
10
 
9
11
  export class BskyAgent extends AtpAgent {
10
12
  get app() {
@@ -236,4 +238,182 @@ export class BskyAgent extends AtpAgent {
236
238
  seenAt,
237
239
  })
238
240
  }
241
+
242
+ async getPreferences(): Promise<BskyPreferences> {
243
+ const prefs: BskyPreferences = {
244
+ feeds: {
245
+ saved: undefined,
246
+ pinned: undefined,
247
+ },
248
+ adultContentEnabled: false,
249
+ contentLabels: {},
250
+ }
251
+ const res = await this.app.bsky.actor.getPreferences({})
252
+ for (const pref of res.data.preferences) {
253
+ if (
254
+ AppBskyActorDefs.isAdultContentPref(pref) &&
255
+ AppBskyActorDefs.validateAdultContentPref(pref).success
256
+ ) {
257
+ prefs.adultContentEnabled = pref.enabled
258
+ } else if (
259
+ AppBskyActorDefs.isContentLabelPref(pref) &&
260
+ AppBskyActorDefs.validateAdultContentPref(pref).success
261
+ ) {
262
+ let value = pref.visibility
263
+ if (value === 'show') {
264
+ value = 'ignore'
265
+ }
266
+ if (value === 'ignore' || value === 'warn' || value === 'hide') {
267
+ prefs.contentLabels[pref.label] = value as BskyLabelPreference
268
+ }
269
+ } else if (
270
+ AppBskyActorDefs.isSavedFeedsPref(pref) &&
271
+ AppBskyActorDefs.validateSavedFeedsPref(pref).success
272
+ ) {
273
+ prefs.feeds.saved = pref.saved
274
+ prefs.feeds.pinned = pref.pinned
275
+ }
276
+ }
277
+ return prefs
278
+ }
279
+
280
+ async setSavedFeeds(saved: string[], pinned: string[]) {
281
+ return updateFeedPreferences(this, () => ({
282
+ saved,
283
+ pinned,
284
+ }))
285
+ }
286
+
287
+ async addSavedFeed(v: string) {
288
+ return updateFeedPreferences(this, (saved: string[], pinned: string[]) => ({
289
+ saved: [...saved.filter((uri) => uri !== v), v],
290
+ pinned,
291
+ }))
292
+ }
293
+
294
+ async removeSavedFeed(v: string) {
295
+ return updateFeedPreferences(this, (saved: string[], pinned: string[]) => ({
296
+ saved: saved.filter((uri) => uri !== v),
297
+ pinned: pinned.filter((uri) => uri !== v),
298
+ }))
299
+ }
300
+
301
+ async addPinnedFeed(v: string) {
302
+ return updateFeedPreferences(this, (saved: string[], pinned: string[]) => ({
303
+ saved: [...saved.filter((uri) => uri !== v), v],
304
+ pinned: [...pinned.filter((uri) => uri !== v), v],
305
+ }))
306
+ }
307
+
308
+ async removePinnedFeed(v: string) {
309
+ return updateFeedPreferences(this, (saved: string[], pinned: string[]) => ({
310
+ saved,
311
+ pinned: pinned.filter((uri) => uri !== v),
312
+ }))
313
+ }
314
+
315
+ async setAdultContentEnabled(v: boolean) {
316
+ await updatePreferences(this, (prefs: AppBskyActorDefs.Preferences) => {
317
+ const existing = prefs.find(
318
+ (pref) =>
319
+ AppBskyActorDefs.isAdultContentPref(pref) &&
320
+ AppBskyActorDefs.validateAdultContentPref(pref).success,
321
+ )
322
+ if (existing) {
323
+ existing.enabled = v
324
+ } else {
325
+ prefs.push({
326
+ $type: 'app.bsky.actor.defs#adultContentPref',
327
+ enabled: v,
328
+ })
329
+ }
330
+ return prefs
331
+ })
332
+ }
333
+
334
+ async setContentLabelPref(key: string, value: BskyLabelPreference) {
335
+ // TEMP update old value
336
+ if (value === 'show') {
337
+ value = 'ignore'
338
+ }
339
+
340
+ await updatePreferences(this, (prefs: AppBskyActorDefs.Preferences) => {
341
+ const existing = prefs.find(
342
+ (pref) =>
343
+ AppBskyActorDefs.isContentLabelPref(pref) &&
344
+ AppBskyActorDefs.validateAdultContentPref(pref).success &&
345
+ pref.label === key,
346
+ )
347
+ if (existing) {
348
+ existing.visibility = value
349
+ } else {
350
+ prefs.push({
351
+ $type: 'app.bsky.actor.defs#contentLabelPref',
352
+ label: key,
353
+ visibility: value,
354
+ })
355
+ }
356
+ return prefs
357
+ })
358
+ }
359
+ }
360
+
361
+ /**
362
+ * This function updates the preferences of a user and allows for a callback function to be executed
363
+ * before the update.
364
+ * @param cb - cb is a callback function that takes in a single parameter of type
365
+ * AppBskyActorDefs.Preferences and returns either a boolean or void. This callback function is used to
366
+ * update the preferences of the user. The function is called with the current preferences as an
367
+ * argument and if the callback returns false, the preferences are not updated.
368
+ */
369
+ async function updatePreferences(
370
+ agent: BskyAgent,
371
+ cb: (
372
+ prefs: AppBskyActorDefs.Preferences,
373
+ ) => AppBskyActorDefs.Preferences | false,
374
+ ) {
375
+ const res = await agent.app.bsky.actor.getPreferences({})
376
+ const newPrefs = cb(res.data.preferences)
377
+ if (newPrefs === false) {
378
+ return
379
+ }
380
+ await agent.app.bsky.actor.putPreferences({
381
+ preferences: newPrefs,
382
+ })
383
+ }
384
+
385
+ /**
386
+ * A helper specifically for updating feed preferences
387
+ */
388
+ async function updateFeedPreferences(
389
+ agent: BskyAgent,
390
+ cb: (
391
+ saved: string[],
392
+ pinned: string[],
393
+ ) => { saved: string[]; pinned: string[] },
394
+ ): Promise<{ saved: string[]; pinned: string[] }> {
395
+ let res
396
+ await updatePreferences(agent, (prefs: AppBskyActorDefs.Preferences) => {
397
+ let feedsPref = prefs.find(
398
+ (pref) =>
399
+ AppBskyActorDefs.isSavedFeedsPref(pref) &&
400
+ AppBskyActorDefs.validateSavedFeedsPref(pref).success,
401
+ ) as AppBskyActorDefs.SavedFeedsPref | undefined
402
+ if (feedsPref) {
403
+ res = cb(feedsPref.saved, feedsPref.pinned)
404
+ feedsPref.saved = res.saved
405
+ feedsPref.pinned = res.pinned
406
+ } else {
407
+ res = cb([], [])
408
+ feedsPref = {
409
+ $type: 'app.bsky.actor.defs#savedFeedsPref',
410
+ saved: res.saved,
411
+ pinned: res.pinned,
412
+ }
413
+ }
414
+ return prefs
415
+ .filter((pref) => !AppBskyActorDefs.isSavedFeedsPref(pref))
416
+ .concat([feedsPref])
417
+ })
418
+ return res
239
419
  }