From ee58534ceb65195893837fffa42027bb44f191f0 Mon Sep 17 00:00:00 2001 From: Aditya Mathur Date: Mon, 20 Jan 2025 11:21:16 +0530 Subject: [PATCH 01/23] chore: rename bsky module to feed and update imports --- packages/client/src/{bsky => feed}/feed.ts | 0 packages/client/src/{bsky => feed}/index.test.ts | 0 packages/client/src/{bsky => feed}/index.ts | 2 +- packages/client/src/index.ts | 2 +- packages/client/src/tsky/tsky.ts | 2 +- 5 files changed, 3 insertions(+), 3 deletions(-) rename packages/client/src/{bsky => feed}/feed.ts (100%) rename packages/client/src/{bsky => feed}/index.test.ts (100%) rename packages/client/src/{bsky => feed}/index.ts (94%) diff --git a/packages/client/src/bsky/feed.ts b/packages/client/src/feed/feed.ts similarity index 100% rename from packages/client/src/bsky/feed.ts rename to packages/client/src/feed/feed.ts diff --git a/packages/client/src/bsky/index.test.ts b/packages/client/src/feed/index.test.ts similarity index 100% rename from packages/client/src/bsky/index.test.ts rename to packages/client/src/feed/index.test.ts diff --git a/packages/client/src/bsky/index.ts b/packages/client/src/feed/index.ts similarity index 94% rename from packages/client/src/bsky/index.ts rename to packages/client/src/feed/index.ts index 61df734..203271f 100644 --- a/packages/client/src/bsky/index.ts +++ b/packages/client/src/feed/index.ts @@ -1,5 +1,5 @@ import type { AppBskyActorDefs } from '@tsky/lexicons'; -import { Feed } from '~/bsky/feed'; +import { Feed } from '~/feed/feed'; import type { Client } from '~/tsky/client'; export class Bsky { diff --git a/packages/client/src/index.ts b/packages/client/src/index.ts index 9450186..c395d61 100644 --- a/packages/client/src/index.ts +++ b/packages/client/src/index.ts @@ -1,2 +1,2 @@ -export * from './bsky'; +export * from './feed'; export * from './tsky'; diff --git a/packages/client/src/tsky/tsky.ts b/packages/client/src/tsky/tsky.ts index c6a3fc5..5a64cfa 100644 --- a/packages/client/src/tsky/tsky.ts +++ b/packages/client/src/tsky/tsky.ts @@ -1,7 +1,7 @@ import type { CredentialManager } from '@atcute/client'; import { XRPC } from '@atcute/client'; import type { Queries } from '@tsky/lexicons'; -import { Bsky } from '~/bsky'; +import { Bsky } from '~/feed'; import { Client } from './client'; export class Tsky { From f4d80176200517edc83002a63c0c1cf6fe2a92f3 Mon Sep 17 00:00:00 2001 From: Aditya Mathur Date: Mon, 20 Jan 2025 11:21:22 +0530 Subject: [PATCH 02/23] chore(client): add path mapping for @tsky/lexicons in tsconfig --- packages/client/tsconfig.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/client/tsconfig.json b/packages/client/tsconfig.json index 9d459d6..1191e37 100644 --- a/packages/client/tsconfig.json +++ b/packages/client/tsconfig.json @@ -9,7 +9,8 @@ "module": "ESNext", "moduleResolution": "bundler", "paths": { - "~/*": ["src/*"] + "~/*": ["src/*"], + "@tsky/lexicons": ["../lexicons/index.ts"], }, "resolveJsonModule": true, "allowJs": true, From f6647626300a91c45ea5a8376cc8ef9e7e29a412 Mon Sep 17 00:00:00 2001 From: Aditya Mathur Date: Mon, 20 Jan 2025 11:48:46 +0530 Subject: [PATCH 03/23] chore(client): renamed the test file for feed --- packages/client/src/feed/{index.test.ts => feed.test.ts} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename packages/client/src/feed/{index.test.ts => feed.test.ts} (100%) diff --git a/packages/client/src/feed/index.test.ts b/packages/client/src/feed/feed.test.ts similarity index 100% rename from packages/client/src/feed/index.test.ts rename to packages/client/src/feed/feed.test.ts From dc2e1b187bb6087b8ce294d1dc1f5a77923b214a Mon Sep 17 00:00:00 2001 From: Aditya Mathur Date: Mon, 20 Jan 2025 16:36:09 +0530 Subject: [PATCH 04/23] chore(client): added the paginator under utils --- packages/client/src/feed/feed.ts | 2 +- packages/client/src/utils/index.ts | 1 + packages/client/src/{tsky => utils}/paginator.ts | 0 3 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 packages/client/src/utils/index.ts rename packages/client/src/{tsky => utils}/paginator.ts (100%) diff --git a/packages/client/src/feed/feed.ts b/packages/client/src/feed/feed.ts index ffc1a30..1c525eb 100644 --- a/packages/client/src/feed/feed.ts +++ b/packages/client/src/feed/feed.ts @@ -3,7 +3,7 @@ import type { AppBskyFeedGetTimeline, } from '@tsky/lexicons'; import type { Client } from '~/tsky/client'; -import { Paginator } from '~/tsky/paginator'; +import { Paginator } from '~/utils'; export class Feed { constructor(private client: Client) {} diff --git a/packages/client/src/utils/index.ts b/packages/client/src/utils/index.ts new file mode 100644 index 0000000..544dc7f --- /dev/null +++ b/packages/client/src/utils/index.ts @@ -0,0 +1 @@ +export * from './paginator'; diff --git a/packages/client/src/tsky/paginator.ts b/packages/client/src/utils/paginator.ts similarity index 100% rename from packages/client/src/tsky/paginator.ts rename to packages/client/src/utils/paginator.ts From cda241a832fdef1b71a66e12ffc3e53315674776 Mon Sep 17 00:00:00 2001 From: Aditya Mathur Date: Mon, 20 Jan 2025 16:38:20 +0530 Subject: [PATCH 05/23] chore(client): remove paginator export from tsky module --- packages/client/src/tsky/index.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/client/src/tsky/index.ts b/packages/client/src/tsky/index.ts index 3ef8518..615ea17 100644 --- a/packages/client/src/tsky/index.ts +++ b/packages/client/src/tsky/index.ts @@ -1,2 +1 @@ -export * from './paginator'; export * from './tsky'; From 75838f7a03726aa1fe917ee2a8636640bc4d9ad4 Mon Sep 17 00:00:00 2001 From: Aditya Mathur Date: Mon, 20 Jan 2025 17:47:20 +0530 Subject: [PATCH 06/23] chore(client): added manager --- packages/client/src/manager/index.ts | 1 + packages/client/src/manager/manager.ts | 39 ++++++++++++++++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 packages/client/src/manager/index.ts create mode 100644 packages/client/src/manager/manager.ts diff --git a/packages/client/src/manager/index.ts b/packages/client/src/manager/index.ts new file mode 100644 index 0000000..f8179ed --- /dev/null +++ b/packages/client/src/manager/index.ts @@ -0,0 +1 @@ +export * from './manager'; diff --git a/packages/client/src/manager/manager.ts b/packages/client/src/manager/manager.ts new file mode 100644 index 0000000..68a0972 --- /dev/null +++ b/packages/client/src/manager/manager.ts @@ -0,0 +1,39 @@ +import { type AtpSessionData, CredentialManager } from '@atcute/client'; + +export class Manager { + manager: CredentialManager; + sessions: Map = new Map(); + + constructor() { + this.manager = new CredentialManager({ service: 'https://bsky.social' }); + } + + async login(identifier: string, password: string) { + const session = await this.manager.login({ + identifier, + password, + }); + + this.sessions.set(session.did, session); + + return session; + } + + async switch(did: string) { + const session = this.sessions.get(did); + + if (!session) { + throw new Error('Session not found'); + } + + return await this.manager.resume(session); + } + + logout(did: string) { + this.sessions.delete(did); + } + + get currentSession() { + return this.manager.session; + } +} From cd71e1b542661c653e504e4800af1f1c1e23082a Mon Sep 17 00:00:00 2001 From: Aditya Mathur <57684218+MathurAditya724@users.noreply.github.com> Date: Mon, 20 Jan 2025 21:51:39 +0530 Subject: [PATCH 07/23] chore(client): update Manager to accept options and integrate with Tsky --- packages/client/src/manager/manager.ts | 12 +++++++++--- packages/client/src/tsky/tsky.ts | 8 +++++--- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/packages/client/src/manager/manager.ts b/packages/client/src/manager/manager.ts index 68a0972..bc1596d 100644 --- a/packages/client/src/manager/manager.ts +++ b/packages/client/src/manager/manager.ts @@ -1,11 +1,17 @@ -import { type AtpSessionData, CredentialManager } from '@atcute/client'; +import { + type AtpSessionData, + CredentialManager, + type CredentialManagerOptions, +} from '@atcute/client'; export class Manager { manager: CredentialManager; sessions: Map = new Map(); - constructor() { - this.manager = new CredentialManager({ service: 'https://bsky.social' }); + constructor(options?: CredentialManagerOptions) { + this.manager = new CredentialManager( + options ?? { service: 'https://bsky.social' }, + ); } async login(identifier: string, password: string) { diff --git a/packages/client/src/tsky/tsky.ts b/packages/client/src/tsky/tsky.ts index 5a64cfa..351c007 100644 --- a/packages/client/src/tsky/tsky.ts +++ b/packages/client/src/tsky/tsky.ts @@ -1,14 +1,16 @@ -import type { CredentialManager } from '@atcute/client'; import { XRPC } from '@atcute/client'; import type { Queries } from '@tsky/lexicons'; import { Bsky } from '~/feed'; +import { Manager } from '~/manager'; import { Client } from './client'; export class Tsky { + auth: Manager; client: Client; - constructor(manager: CredentialManager) { - const xrpc = new XRPC({ handler: manager }); + constructor() { + this.auth = new Manager(); + const xrpc = new XRPC({ handler: this.auth.manager }); this.client = new Client(xrpc); } From 42622f0094c9eb6fcd677839aa86a97f75ee9abe Mon Sep 17 00:00:00 2001 From: Aditya Mathur <57684218+MathurAditya724@users.noreply.github.com> Date: Mon, 20 Jan 2025 21:53:35 +0530 Subject: [PATCH 08/23] chore: renamed manager to auth --- packages/client/src/{manager/manager.ts => auth/auth.ts} | 2 +- packages/client/src/{manager => auth}/index.ts | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename packages/client/src/{manager/manager.ts => auth/auth.ts} (97%) rename packages/client/src/{manager => auth}/index.ts (100%) diff --git a/packages/client/src/manager/manager.ts b/packages/client/src/auth/auth.ts similarity index 97% rename from packages/client/src/manager/manager.ts rename to packages/client/src/auth/auth.ts index bc1596d..a1f969c 100644 --- a/packages/client/src/manager/manager.ts +++ b/packages/client/src/auth/auth.ts @@ -4,7 +4,7 @@ import { type CredentialManagerOptions, } from '@atcute/client'; -export class Manager { +export class Auth { manager: CredentialManager; sessions: Map = new Map(); diff --git a/packages/client/src/manager/index.ts b/packages/client/src/auth/index.ts similarity index 100% rename from packages/client/src/manager/index.ts rename to packages/client/src/auth/index.ts From c01024196b755f46544509150bc853dea69893c3 Mon Sep 17 00:00:00 2001 From: Aditya Mathur <57684218+MathurAditya724@users.noreply.github.com> Date: Mon, 20 Jan 2025 21:54:03 +0530 Subject: [PATCH 09/23] chore: updated imports for auth --- packages/client/src/auth/index.ts | 2 +- packages/client/src/tsky/tsky.ts | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/client/src/auth/index.ts b/packages/client/src/auth/index.ts index f8179ed..269586e 100644 --- a/packages/client/src/auth/index.ts +++ b/packages/client/src/auth/index.ts @@ -1 +1 @@ -export * from './manager'; +export * from './auth'; diff --git a/packages/client/src/tsky/tsky.ts b/packages/client/src/tsky/tsky.ts index 351c007..7ff7803 100644 --- a/packages/client/src/tsky/tsky.ts +++ b/packages/client/src/tsky/tsky.ts @@ -1,15 +1,15 @@ import { XRPC } from '@atcute/client'; import type { Queries } from '@tsky/lexicons'; +import { Auth } from '~/auth'; import { Bsky } from '~/feed'; -import { Manager } from '~/manager'; import { Client } from './client'; export class Tsky { - auth: Manager; + auth: Auth; client: Client; constructor() { - this.auth = new Manager(); + this.auth = new Auth(); const xrpc = new XRPC({ handler: this.auth.manager }); this.client = new Client(xrpc); } From dada011fe06a56d2a045f46fac6db00d3d8c21a2 Mon Sep 17 00:00:00 2001 From: Aditya Mathur <57684218+MathurAditya724@users.noreply.github.com> Date: Mon, 20 Jan 2025 22:02:23 +0530 Subject: [PATCH 10/23] chore: restructured the bsky class --- packages/client/src/{feed/index.ts => bsky/bsky.ts} | 2 +- packages/client/src/{ => bsky}/feed/feed.test.ts | 0 packages/client/src/{ => bsky}/feed/feed.ts | 0 packages/client/src/bsky/feed/index.ts | 1 + packages/client/src/bsky/index.ts | 2 ++ packages/client/src/index.ts | 2 +- packages/client/src/tsky/tsky.ts | 5 ++++- 7 files changed, 9 insertions(+), 3 deletions(-) rename packages/client/src/{feed/index.ts => bsky/bsky.ts} (93%) rename packages/client/src/{ => bsky}/feed/feed.test.ts (100%) rename packages/client/src/{ => bsky}/feed/feed.ts (100%) create mode 100644 packages/client/src/bsky/feed/index.ts create mode 100644 packages/client/src/bsky/index.ts diff --git a/packages/client/src/feed/index.ts b/packages/client/src/bsky/bsky.ts similarity index 93% rename from packages/client/src/feed/index.ts rename to packages/client/src/bsky/bsky.ts index 203271f..faa0036 100644 --- a/packages/client/src/feed/index.ts +++ b/packages/client/src/bsky/bsky.ts @@ -1,5 +1,5 @@ import type { AppBskyActorDefs } from '@tsky/lexicons'; -import { Feed } from '~/feed/feed'; +import { Feed } from '~/bsky/feed/feed'; import type { Client } from '~/tsky/client'; export class Bsky { diff --git a/packages/client/src/feed/feed.test.ts b/packages/client/src/bsky/feed/feed.test.ts similarity index 100% rename from packages/client/src/feed/feed.test.ts rename to packages/client/src/bsky/feed/feed.test.ts diff --git a/packages/client/src/feed/feed.ts b/packages/client/src/bsky/feed/feed.ts similarity index 100% rename from packages/client/src/feed/feed.ts rename to packages/client/src/bsky/feed/feed.ts diff --git a/packages/client/src/bsky/feed/index.ts b/packages/client/src/bsky/feed/index.ts new file mode 100644 index 0000000..0b2a3ad --- /dev/null +++ b/packages/client/src/bsky/feed/index.ts @@ -0,0 +1 @@ +export * from './feed'; diff --git a/packages/client/src/bsky/index.ts b/packages/client/src/bsky/index.ts new file mode 100644 index 0000000..a29617f --- /dev/null +++ b/packages/client/src/bsky/index.ts @@ -0,0 +1,2 @@ +export * from './bsky'; +export * from './feed'; diff --git a/packages/client/src/index.ts b/packages/client/src/index.ts index c395d61..9450186 100644 --- a/packages/client/src/index.ts +++ b/packages/client/src/index.ts @@ -1,2 +1,2 @@ -export * from './feed'; +export * from './bsky'; export * from './tsky'; diff --git a/packages/client/src/tsky/tsky.ts b/packages/client/src/tsky/tsky.ts index 7ff7803..19e5963 100644 --- a/packages/client/src/tsky/tsky.ts +++ b/packages/client/src/tsky/tsky.ts @@ -1,7 +1,7 @@ import { XRPC } from '@atcute/client'; import type { Queries } from '@tsky/lexicons'; import { Auth } from '~/auth'; -import { Bsky } from '~/feed'; +import { Bsky } from '~/bsky'; import { Client } from './client'; export class Tsky { @@ -9,7 +9,10 @@ export class Tsky { client: Client; constructor() { + // Initialize the auth manager this.auth = new Auth(); + + // Initialize the client const xrpc = new XRPC({ handler: this.auth.manager }); this.client = new Client(xrpc); } From b813deaf1a15391e8fcee576b23528319e50c19a Mon Sep 17 00:00:00 2001 From: Aditya Mathur <57684218+MathurAditya724@users.noreply.github.com> Date: Tue, 21 Jan 2025 09:30:05 +0530 Subject: [PATCH 11/23] chore: made client prop private --- packages/client/src/bsky/bsky.ts | 4 ++-- packages/client/src/tsky/tsky.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/client/src/bsky/bsky.ts b/packages/client/src/bsky/bsky.ts index faa0036..953664e 100644 --- a/packages/client/src/bsky/bsky.ts +++ b/packages/client/src/bsky/bsky.ts @@ -1,9 +1,9 @@ import type { AppBskyActorDefs } from '@tsky/lexicons'; -import { Feed } from '~/bsky/feed/feed'; +import { Feed } from '~/bsky/feed'; import type { Client } from '~/tsky/client'; export class Bsky { - client: Client; + private client: Client; constructor(client: Client) { this.client = client; diff --git a/packages/client/src/tsky/tsky.ts b/packages/client/src/tsky/tsky.ts index 19e5963..7c229e8 100644 --- a/packages/client/src/tsky/tsky.ts +++ b/packages/client/src/tsky/tsky.ts @@ -6,7 +6,7 @@ import { Client } from './client'; export class Tsky { auth: Auth; - client: Client; + private client: Client; constructor() { // Initialize the auth manager From c7917f9df7b039fc8084e4092010256f4b4dcec2 Mon Sep 17 00:00:00 2001 From: Aditya Mathur Date: Tue, 21 Jan 2025 17:09:45 +0530 Subject: [PATCH 12/23] feat(client): added preference class --- packages/client/src/tsky/tsky.ts | 5 ++ packages/client/src/user/index.ts | 10 ++++ packages/client/src/user/preferences/index.ts | 1 + .../src/user/preferences/preferences.test.ts | 58 +++++++++++++++++++ .../src/user/preferences/preferences.ts | 30 ++++++++++ 5 files changed, 104 insertions(+) create mode 100644 packages/client/src/user/index.ts create mode 100644 packages/client/src/user/preferences/index.ts create mode 100644 packages/client/src/user/preferences/preferences.test.ts create mode 100644 packages/client/src/user/preferences/preferences.ts diff --git a/packages/client/src/tsky/tsky.ts b/packages/client/src/tsky/tsky.ts index 7c229e8..5973771 100644 --- a/packages/client/src/tsky/tsky.ts +++ b/packages/client/src/tsky/tsky.ts @@ -2,6 +2,7 @@ import { XRPC } from '@atcute/client'; import type { Queries } from '@tsky/lexicons'; import { Auth } from '~/auth'; import { Bsky } from '~/bsky'; +import { User } from '~/user'; import { Client } from './client'; export class Tsky { @@ -17,6 +18,10 @@ export class Tsky { this.client = new Client(xrpc); } + get user() { + return new User(this.client); + } + get bsky() { return new Bsky(this.client); } diff --git a/packages/client/src/user/index.ts b/packages/client/src/user/index.ts new file mode 100644 index 0000000..3ba6c50 --- /dev/null +++ b/packages/client/src/user/index.ts @@ -0,0 +1,10 @@ +import type { Client } from '~/tsky/client'; +import { Preferences } from './preferences'; + +export class User { + constructor(private client: Client) {} + + get preferences() { + return new Preferences(this.client); + } +} diff --git a/packages/client/src/user/preferences/index.ts b/packages/client/src/user/preferences/index.ts new file mode 100644 index 0000000..a17a3da --- /dev/null +++ b/packages/client/src/user/preferences/index.ts @@ -0,0 +1 @@ +export * from './preferences'; diff --git a/packages/client/src/user/preferences/preferences.test.ts b/packages/client/src/user/preferences/preferences.test.ts new file mode 100644 index 0000000..d6a82df --- /dev/null +++ b/packages/client/src/user/preferences/preferences.test.ts @@ -0,0 +1,58 @@ +import { describe, expect, it } from 'vitest'; +import { Tsky } from '~/index'; + +const TEST_CREDENTIALS = { + alice: { + handle: 'alice.tsky.dev', + did: 'did:plc:jguhdmnjclquqf5lsvkyxqy3', + password: 'alice_and_bob', + }, + bob: { + handle: 'bob.tsky.dev', + did: 'did:plc:2ig7akkyfq256j42uxvc4g2h', + password: 'alice_and_bob', + }, +}; + +async function getAliceTsky() { + const tsky = new Tsky(); + + await tsky.auth.login( + TEST_CREDENTIALS.alice.handle, + TEST_CREDENTIALS.alice.password, + ); + + return tsky; +} + +describe('preferences', () => { + it('.get()', async () => { + const tsky = await getAliceTsky(); + const preferences = await tsky.user.preferences.get(); + + expect(preferences).toBeDefined(); + }); + + it('.set()', async () => { + const tsky = await getAliceTsky(); + + const payload = { + $type: 'app.bsky.actor.defs.adultContentPref', + enabled: false, + }; + + await tsky.user.preferences.set([payload]); + + const preferences = await tsky.user.preferences.get(); + + expect(preferences).toBeDefined(); + + const pref = preferences.find((p) => p.$type === payload.$type); + + expect(pref).toBeDefined(); + expect(pref).toHaveProperty('enabled'); + + // @ts-ignore + expect(pref.enabled).toBe(payload.enabled); + }); +}); diff --git a/packages/client/src/user/preferences/preferences.ts b/packages/client/src/user/preferences/preferences.ts new file mode 100644 index 0000000..56dd586 --- /dev/null +++ b/packages/client/src/user/preferences/preferences.ts @@ -0,0 +1,30 @@ +import type { AppBskyActorPutPreferences } from '@tsky/lexicons'; +import type { Client } from '~/tsky/client'; + +type RPCOptions = { signal?: AbortSignal; headers?: HeadersInit }; + +export class Preferences { + constructor(private client: Client) {} + + /** + * Get private preferences attached to the current account. Expected use is synchronization between multiple devices, and import/export during account migration. Requires auth. + */ + async get(options: RPCOptions = {}) { + const res = await this.client.get('app.bsky.actor.getPreferences', options); + + return res.data.preferences; + } + + /** + * Set the private preferences attached to the account. + */ + async set( + preferences: AppBskyActorPutPreferences.Input['preferences'], + options: RPCOptions = {}, + ) { + await this.client.call('app.bsky.actor.putPreferences', { + data: { preferences }, + ...options, + }); + } +} From c296086e249394e254620f847709d01e6fd77eca Mon Sep 17 00:00:00 2001 From: Aditya Mathur Date: Tue, 21 Jan 2025 17:10:06 +0530 Subject: [PATCH 13/23] refactor(client): simplify client initialization and update feed tests --- packages/client/src/bsky/bsky.ts | 6 +- packages/client/src/bsky/feed/feed.test.ts | 67 +++++++--------------- 2 files changed, 21 insertions(+), 52 deletions(-) diff --git a/packages/client/src/bsky/bsky.ts b/packages/client/src/bsky/bsky.ts index 953664e..6ba9691 100644 --- a/packages/client/src/bsky/bsky.ts +++ b/packages/client/src/bsky/bsky.ts @@ -3,11 +3,7 @@ import { Feed } from '~/bsky/feed'; import type { Client } from '~/tsky/client'; export class Bsky { - private client: Client; - - constructor(client: Client) { - this.client = client; - } + constructor(private client: Client) {} /** * Get detailed profile view of an actor. Does not require auth, but contains relevant metadata with auth. diff --git a/packages/client/src/bsky/feed/feed.test.ts b/packages/client/src/bsky/feed/feed.test.ts index 4e68c4c..3142bfe 100644 --- a/packages/client/src/bsky/feed/feed.test.ts +++ b/packages/client/src/bsky/feed/feed.test.ts @@ -1,4 +1,3 @@ -import { CredentialManager } from '@atcute/client'; import { describe, expect, it } from 'vitest'; import { Tsky } from '~/index'; @@ -16,56 +15,30 @@ const TEST_CREDENTIALS = { }; async function getAliceTsky() { - const manager = new CredentialManager({ service: 'https://bsky.social' }); - await manager.login({ - identifier: TEST_CREDENTIALS.alice.handle, - password: TEST_CREDENTIALS.alice.password, - }); + const tsky = new Tsky(); + + await tsky.auth.login( + TEST_CREDENTIALS.alice.handle, + TEST_CREDENTIALS.alice.password, + ); - return new Tsky(manager); + return tsky; } -describe('bsky', () => { - it('.profile()', async () => { +describe('feed', () => { + it('.getFeed()', async () => { const tsky = await getAliceTsky(); - const profile = await tsky.bsky.profile(TEST_CREDENTIALS.alice.did); - - expect(profile).toBeDefined(); - expect(profile).toHaveProperty('handle', TEST_CREDENTIALS.alice.handle); - }); - - describe('feed', () => { - it('.timeline()', async () => { - const tsky = await getAliceTsky(); - - const paginator = await tsky.bsky.feed.getTimeline({ - limit: 30, - }); - - expect(paginator).toBeDefined(); - expect(paginator.values).toBeDefined(); - expect(paginator.values).toBeInstanceOf(Array); - expect(paginator.values.length).toBe(1); // we should get the first page from the paginator - expect(paginator.values[0].feed.length).toBeGreaterThan(0); // alice has some posts ;) - expect(paginator.values[0].feed[0]).toHaveProperty('post'); - }); - - it('.feed()', async () => { - const tsky = await getAliceTsky(); - - const paginator = await tsky.bsky.feed.getFeed({ - // "Birds! 🦉" custom feed - // - https://bsky.app/profile/daryllmarie.bsky.social/feed/aaagllxbcbsje - feed: 'at://did:plc:ffkgesg3jsv2j7aagkzrtcvt/app.bsky.feed.generator/aaagllxbcbsje', - limit: 30, - }); - - expect(paginator).toBeDefined(); - expect(paginator.values).toBeDefined(); - expect(paginator.values).toBeInstanceOf(Array); - expect(paginator.values.length).toBe(1); // we should get the first page from the paginator - expect(paginator.values[0].feed.length).toBeGreaterThan(0); // we found some birds posts ;) - expect(paginator.values[0].feed[0]).toHaveProperty('post'); + const paginator = await tsky.bsky.feed.getFeed({ + // "Birds! 🦉" custom feed + // - https://bsky.app/profile/daryllmarie.bsky.social/feed/aaagllxbcbsje + feed: 'at://did:plc:ffkgesg3jsv2j7aagkzrtcvt/app.bsky.feed.generator/aaagllxbcbsje', + limit: 30, }); + expect(paginator).toBeDefined(); + expect(paginator.values).toBeDefined(); + expect(paginator.values).toBeInstanceOf(Array); + expect(paginator.values.length).toBe(1); // we should get the first page from the paginator + expect(paginator.values[0].feed.length).toBeGreaterThan(0); // we found some birds posts ;) + expect(paginator.values[0].feed[0]).toHaveProperty('post'); }); }); From 8d873780845743ee08a263b386f626130749530f Mon Sep 17 00:00:00 2001 From: Aditya Mathur Date: Tue, 21 Jan 2025 17:22:11 +0530 Subject: [PATCH 14/23] chore(client): shifted profile in user class and added tests --- packages/client/src/bsky/bsky.ts | 14 -------- packages/client/src/tsky/tsky.ts | 6 +++- packages/client/src/user/index.ts | 17 ++++++++- packages/client/src/user/profile.test.ts | 45 ++++++++++++++++++++++++ 4 files changed, 66 insertions(+), 16 deletions(-) create mode 100644 packages/client/src/user/profile.test.ts diff --git a/packages/client/src/bsky/bsky.ts b/packages/client/src/bsky/bsky.ts index 6ba9691..4a2e113 100644 --- a/packages/client/src/bsky/bsky.ts +++ b/packages/client/src/bsky/bsky.ts @@ -1,23 +1,9 @@ -import type { AppBskyActorDefs } from '@tsky/lexicons'; import { Feed } from '~/bsky/feed'; import type { Client } from '~/tsky/client'; export class Bsky { constructor(private client: Client) {} - /** - * Get detailed profile view of an actor. Does not require auth, but contains relevant metadata with auth. - */ - async profile( - identifier: string, - ): Promise { - const res = await this.client.get('app.bsky.actor.getProfile', { - params: { actor: identifier }, - }); - - return res.data; - } - get feed() { return new Feed(this.client); } diff --git a/packages/client/src/tsky/tsky.ts b/packages/client/src/tsky/tsky.ts index 5973771..515253d 100644 --- a/packages/client/src/tsky/tsky.ts +++ b/packages/client/src/tsky/tsky.ts @@ -19,7 +19,11 @@ export class Tsky { } get user() { - return new User(this.client); + if (!this.auth.currentSession) { + throw new Error('There is no active session'); + } + + return new User(this.client, this.auth.currentSession.handle); } get bsky() { diff --git a/packages/client/src/user/index.ts b/packages/client/src/user/index.ts index 3ba6c50..1104446 100644 --- a/packages/client/src/user/index.ts +++ b/packages/client/src/user/index.ts @@ -1,8 +1,23 @@ +import type { AppBskyActorDefs } from '@tsky/lexicons'; import type { Client } from '~/tsky/client'; import { Preferences } from './preferences'; export class User { - constructor(private client: Client) {} + constructor( + private client: Client, + private identifier: string, + ) {} + + /** + * Get detailed profile view of the current user. + */ + async profile(): Promise { + const res = await this.client.get('app.bsky.actor.getProfile', { + params: { actor: this.identifier }, + }); + + return res.data; + } get preferences() { return new Preferences(this.client); diff --git a/packages/client/src/user/profile.test.ts b/packages/client/src/user/profile.test.ts new file mode 100644 index 0000000..3d24b53 --- /dev/null +++ b/packages/client/src/user/profile.test.ts @@ -0,0 +1,45 @@ +import { describe, expect, it } from 'vitest'; +import { Tsky } from '~/index'; + +const TEST_CREDENTIALS = { + alice: { + handle: 'alice.tsky.dev', + did: 'did:plc:jguhdmnjclquqf5lsvkyxqy3', + password: 'alice_and_bob', + }, + bob: { + handle: 'bob.tsky.dev', + did: 'did:plc:2ig7akkyfq256j42uxvc4g2h', + password: 'alice_and_bob', + }, +}; + +describe('profile', async () => { + const tsky = new Tsky(); + + await tsky.auth.login( + TEST_CREDENTIALS.alice.handle, + TEST_CREDENTIALS.alice.password, + ); + + it("Getting alice's profile", async () => { + const profile = await tsky.user.profile(); + + expect(profile).toBeDefined(); + expect(profile.handle).toBe(TEST_CREDENTIALS.alice.handle); + }); + + it("Switching to bob's profile", async () => { + await tsky.auth.login( + TEST_CREDENTIALS.bob.handle, + TEST_CREDENTIALS.bob.password, + ); + }); + + it("Getting bob's profile", async () => { + const profile = await tsky.user.profile(); + + expect(profile).toBeDefined(); + expect(profile.handle).toBe(TEST_CREDENTIALS.bob.handle); + }); +}); From 211fcb6f011566e7d8dad770a52acba9137e6a79 Mon Sep 17 00:00:00 2001 From: Aditya Mathur Date: Tue, 21 Jan 2025 18:41:10 +0530 Subject: [PATCH 15/23] feat(client): added feat generator --- packages/client/src/bsky/feed/feed.test.ts | 2 +- packages/client/src/bsky/feed/feed.ts | 35 +++++----- packages/client/src/bsky/feed/generator.ts | 76 ++++++++++++++++++++++ packages/client/src/types.ts | 1 + 4 files changed, 96 insertions(+), 18 deletions(-) create mode 100644 packages/client/src/bsky/feed/generator.ts create mode 100644 packages/client/src/types.ts diff --git a/packages/client/src/bsky/feed/feed.test.ts b/packages/client/src/bsky/feed/feed.test.ts index 3142bfe..40f88bf 100644 --- a/packages/client/src/bsky/feed/feed.test.ts +++ b/packages/client/src/bsky/feed/feed.test.ts @@ -28,7 +28,7 @@ async function getAliceTsky() { describe('feed', () => { it('.getFeed()', async () => { const tsky = await getAliceTsky(); - const paginator = await tsky.bsky.feed.getFeed({ + const paginator = await tsky.bsky.feed.get({ // "Birds! 🦉" custom feed // - https://bsky.app/profile/daryllmarie.bsky.social/feed/aaagllxbcbsje feed: 'at://did:plc:ffkgesg3jsv2j7aagkzrtcvt/app.bsky.feed.generator/aaagllxbcbsje', diff --git a/packages/client/src/bsky/feed/feed.ts b/packages/client/src/bsky/feed/feed.ts index 1c525eb..7d0aacb 100644 --- a/packages/client/src/bsky/feed/feed.ts +++ b/packages/client/src/bsky/feed/feed.ts @@ -1,9 +1,11 @@ import type { AppBskyFeedGetFeed, - AppBskyFeedGetTimeline, + AppBskyFeedSendInteractions, } from '@tsky/lexicons'; import type { Client } from '~/tsky/client'; +import type { RPCOptions } from '~/types'; import { Paginator } from '~/utils'; +import { FeedGenerator } from './generator'; export class Feed { constructor(private client: Client) {} @@ -11,7 +13,7 @@ export class Feed { /** * Get a hydrated feed from an actor's selected feed generator. Implemented by App View. */ - async getFeed( + async get( params: AppBskyFeedGetFeed.Params, options?: AppBskyFeedGetFeed.Input, ): Promise> { @@ -29,22 +31,21 @@ export class Feed { } /** - * Get a view of the requesting account's home timeline. This is expected to be some form of reverse-chronological feed. + * Send information about interactions with feed items back to the feed generator that served them. */ - getTimeline( - params: AppBskyFeedGetTimeline.Params, - options?: AppBskyFeedGetTimeline.Input, - ): Promise> { - return Paginator.init(async (cursor) => { - const res = await this.client.get('app.bsky.feed.getTimeline', { - ...(options ?? {}), - params: { - cursor, - ...params, - }, - }); - - return res.data; + async sendInteractions( + interactions: AppBskyFeedSendInteractions.Input['interactions'], + options: RPCOptions = {}, + ) { + const res = await this.client.call('app.bsky.feed.sendInteractions', { + data: { interactions }, + ...options, }); + + return res.data; + } + + generator() { + return new FeedGenerator(this.client); } } diff --git a/packages/client/src/bsky/feed/generator.ts b/packages/client/src/bsky/feed/generator.ts new file mode 100644 index 0000000..f2d5064 --- /dev/null +++ b/packages/client/src/bsky/feed/generator.ts @@ -0,0 +1,76 @@ +import type { + AppBskyFeedGetFeedGenerator, + AppBskyFeedGetFeedGenerators, + AppBskyFeedGetFeedSkeleton, +} from '@tsky/lexicons'; +import type { Client } from '~/tsky/client'; +import type { RPCOptions } from '~/types'; +import { Paginator } from '~/utils'; + +export class FeedGenerator { + constructor(private client: Client) {} + + /** + * Get information about a feed generator, including policies and offered feed URIs. Does not require auth; implemented by Feed Generator services (not App View). + */ + async describe(options: RPCOptions = {}) { + const res = await this.client.get( + 'app.bsky.feed.describeFeedGenerator', + options, + ); + + return res.data; + } + + /** + * Get information about a feed generator. Implemented by AppView. + */ + feed( + feed: string, + options: RPCOptions, + ): Promise; + /** + * Get information about a list of feed generators. + */ + feed( + feeds: string[], + options: RPCOptions, + ): Promise; + + async feed(feed: string | string[], options: RPCOptions) { + if (Array.isArray(feed)) { + const res = await this.client.get('app.bsky.feed.getFeedGenerators', { + params: { + feeds: feed, + }, + ...options, + }); + + return res.data.feeds; + } + + const res = await this.client.get('app.bsky.feed.getFeedGenerator', { + params: { feed }, + ...options, + }); + + return res.data; + } + + /** + * Get a skeleton of a feed provided by a feed generator. Auth is optional, depending on provider requirements, and provides the DID of the requester. Implemented by Feed Generator Service. + */ + skeleton( + params: AppBskyFeedGetFeedSkeleton.Params, + options: RPCOptions = {}, + ) { + return Paginator.init(async (cursor) => { + const res = await this.client.get('app.bsky.feed.getFeedSkeleton', { + params: { cursor, ...params }, + ...options, + }); + + return res.data; + }); + } +} diff --git a/packages/client/src/types.ts b/packages/client/src/types.ts new file mode 100644 index 0000000..5819b72 --- /dev/null +++ b/packages/client/src/types.ts @@ -0,0 +1 @@ +export type RPCOptions = { signal?: AbortSignal; headers?: HeadersInit }; From 7ce0093f7a389ec42268c03edf6aeaedbb1f2962 Mon Sep 17 00:00:00 2001 From: Aditya Mathur Date: Tue, 21 Jan 2025 18:41:20 +0530 Subject: [PATCH 16/23] feat(client): added actor class --- packages/client/src/bsky/autor/autor.ts | 93 +++++++++++++++++++ packages/client/src/bsky/autor/index.ts | 1 + packages/client/src/bsky/bsky.ts | 5 + packages/client/src/user/index.ts | 76 ++++++++++++--- packages/client/src/user/mute_unmute/actor.ts | 29 ++++++ packages/client/src/user/mute_unmute/index.ts | 3 + packages/client/src/user/mute_unmute/list.ts | 31 +++++++ .../client/src/user/mute_unmute/thread.ts | 29 ++++++ .../src/user/preferences/preferences.ts | 3 +- 9 files changed, 254 insertions(+), 16 deletions(-) create mode 100644 packages/client/src/bsky/autor/autor.ts create mode 100644 packages/client/src/bsky/autor/index.ts create mode 100644 packages/client/src/user/mute_unmute/actor.ts create mode 100644 packages/client/src/user/mute_unmute/index.ts create mode 100644 packages/client/src/user/mute_unmute/list.ts create mode 100644 packages/client/src/user/mute_unmute/thread.ts diff --git a/packages/client/src/bsky/autor/autor.ts b/packages/client/src/bsky/autor/autor.ts new file mode 100644 index 0000000..f4eb87c --- /dev/null +++ b/packages/client/src/bsky/autor/autor.ts @@ -0,0 +1,93 @@ +import type { AppBskyActorDefs } from '@tsky/lexicons'; +import type { Client } from '~/tsky/client'; +import type { RPCOptions } from '~/types'; +import { Paginator } from '~/utils'; + +export class Actor { + client: Client; + identifier: string; + + constructor(client: Client, identifier: string) { + this.client = client; + this.identifier = identifier; + } + + /** + * Get detailed profile view of an actor. Does not require auth, but contains relevant metadata with auth. + */ + async profile(): Promise { + const res = await this.client.get('app.bsky.actor.getProfile', { + params: { actor: this.identifier }, + }); + + return res.data; + } + + /** + * Get a list of starter packs created by the actor. + */ + starterPacks(limit?: number, options: RPCOptions = {}) { + return Paginator.init(async (cursor) => { + const res = await this.client.get('app.bsky.graph.getActorStarterPacks', { + params: { cursor, actor: this.identifier, limit }, + ...options, + }); + + return res.data; + }); + } + + /** + * Enumerates accounts which follow a specified account (actor). + */ + followers(limit?: number, options: RPCOptions = {}) { + return Paginator.init(async (cursor) => { + const res = await this.client.get('app.bsky.graph.getFollowers', { + params: { + cursor, + actor: this.identifier, + limit, + }, + ...options, + }); + + return res.data; + }); + } + + /** + * Enumerates accounts which a specified account (actor) follows. + */ + follows(limit?: number, options: RPCOptions = {}) { + return Paginator.init(async (cursor) => { + const res = await this.client.get('app.bsky.graph.getFollows', { + params: { + cursor, + actor: this.identifier, + limit, + }, + ...options, + }); + + return res.data; + }); + } + + /** + * Enumerates the lists created by a specified account (actor). + */ + lists(limit?: number, options: RPCOptions = {}) { + return Paginator.init(async (cursor) => { + const res = await this.client.get('app.bsky.graph.getLists', { + params: { + cursor, + actor: this.identifier, + limit, + }, + ...options, + }); + + return res.data; + }); + } +} diff --git a/packages/client/src/bsky/autor/index.ts b/packages/client/src/bsky/autor/index.ts new file mode 100644 index 0000000..21bee6d --- /dev/null +++ b/packages/client/src/bsky/autor/index.ts @@ -0,0 +1 @@ +export * from './autor'; diff --git a/packages/client/src/bsky/bsky.ts b/packages/client/src/bsky/bsky.ts index 4a2e113..9a778f2 100644 --- a/packages/client/src/bsky/bsky.ts +++ b/packages/client/src/bsky/bsky.ts @@ -1,9 +1,14 @@ import { Feed } from '~/bsky/feed'; import type { Client } from '~/tsky/client'; +import { Actor } from './autor'; export class Bsky { constructor(private client: Client) {} + actor(identifier: string) { + return new Actor(this.client, identifier); + } + get feed() { return new Feed(this.client); } diff --git a/packages/client/src/user/index.ts b/packages/client/src/user/index.ts index 1104446..39bcbdf 100644 --- a/packages/client/src/user/index.ts +++ b/packages/client/src/user/index.ts @@ -1,25 +1,73 @@ -import type { AppBskyActorDefs } from '@tsky/lexicons'; -import type { Client } from '~/tsky/client'; +import type { AppBskyFeedGetTimeline } from '@tsky/lexicons'; +import { Actor } from '~/bsky/autor'; +import type { RPCOptions } from '~/types'; +import { Paginator } from '~/utils'; +import { + MuteUnmuteActor, + MuteUnmuteActorList, + MuteUnmuteThread, +} from './mute_unmute'; import { Preferences } from './preferences'; -export class User { - constructor( - private client: Client, - private identifier: string, - ) {} +export class User extends Actor { + get preferences() { + return new Preferences(this.client); + } /** - * Get detailed profile view of the current user. + * Get a view of the requesting account's home timeline. This is expected to be some form of reverse-chronological feed. */ - async profile(): Promise { - const res = await this.client.get('app.bsky.actor.getProfile', { - params: { actor: this.identifier }, + timeline( + params: AppBskyFeedGetTimeline.Params, + options?: AppBskyFeedGetTimeline.Input, + ): Promise> { + return Paginator.init(async (cursor) => { + const res = await this.client.get('app.bsky.feed.getTimeline', { + ...(options ?? {}), + params: { + cursor, + ...params, + }, + }); + + return res.data; }); + } - return res.data; + /** + * Get a list of posts liked by the current user + */ + likes(limit?: number, options: RPCOptions = {}) { + return Paginator.init(async (cursor) => { + const res = await this.client.get('app.bsky.feed.getActorLikes', { + params: { cursor, actor: this.identifier, limit }, + ...options, + }); + + return res.data; + }); } - get preferences() { - return new Preferences(this.client); + /** ----- */ + + /** + * Mute or unmute a thread + */ + thread(thread: string) { + return new MuteUnmuteThread(this.client, thread); + } + + /** + * Mute or unmute an actor + */ + actor(identifier: string) { + return new MuteUnmuteActor(this.client, identifier); + } + + /** + * Mute or unmute an actor list + */ + actorList(identifier: string) { + return new MuteUnmuteActorList(this.client, identifier); } } diff --git a/packages/client/src/user/mute_unmute/actor.ts b/packages/client/src/user/mute_unmute/actor.ts new file mode 100644 index 0000000..f207c65 --- /dev/null +++ b/packages/client/src/user/mute_unmute/actor.ts @@ -0,0 +1,29 @@ +import type { Client } from '~/tsky/client'; +import type { RPCOptions } from '~/types'; + +export class MuteUnmuteActor { + constructor( + private client: Client, + private identifier: string, + ) {} + + /** + * Creates a mute relationship for the specified account. Mutes are private in Bluesky. + */ + mute(options: RPCOptions = {}) { + return this.client.call('app.bsky.graph.muteActor', { + data: { actor: this.identifier }, + ...options, + }); + } + + /** + * Unmutes the specified account. + */ + unmute(options: RPCOptions = {}) { + return this.client.call('app.bsky.graph.unmuteActor', { + data: { actor: this.identifier }, + ...options, + }); + } +} diff --git a/packages/client/src/user/mute_unmute/index.ts b/packages/client/src/user/mute_unmute/index.ts new file mode 100644 index 0000000..e8739c5 --- /dev/null +++ b/packages/client/src/user/mute_unmute/index.ts @@ -0,0 +1,3 @@ +export * from './actor'; +export * from './list'; +export * from './thread'; diff --git a/packages/client/src/user/mute_unmute/list.ts b/packages/client/src/user/mute_unmute/list.ts new file mode 100644 index 0000000..3ad1145 --- /dev/null +++ b/packages/client/src/user/mute_unmute/list.ts @@ -0,0 +1,31 @@ +import type { Client } from '~/tsky/client'; +import type { RPCOptions } from '~/types'; + +export class MuteUnmuteActorList { + constructor( + private client: Client, + private identifier: string, + ) {} + + /** + * Mute an entire list (specified by AT-URI) of actors. This creates a mute relationship for all actors + * on the specified list. Mutes are private on Bluesky. + */ + mute(options: RPCOptions = {}) { + return this.client.call('app.bsky.graph.muteActorList', { + data: { list: this.identifier }, + ...options, + }); + } + + /** + * Unmute an entire list (specified by AT-URI) of actors. This removes the mute relationship for all actors + * on the specified list. + */ + unmute(options: RPCOptions = {}) { + return this.client.call('app.bsky.graph.unmuteActorList', { + data: { list: this.identifier }, + ...options, + }); + } +} diff --git a/packages/client/src/user/mute_unmute/thread.ts b/packages/client/src/user/mute_unmute/thread.ts new file mode 100644 index 0000000..56621f3 --- /dev/null +++ b/packages/client/src/user/mute_unmute/thread.ts @@ -0,0 +1,29 @@ +import type { Client } from '~/tsky/client'; +import type { RPCOptions } from '~/types'; + +export class MuteUnmuteThread { + constructor( + private client: Client, + private thread: string, + ) {} + + /** + * Mutes a thread preventing notifications from the thread and any of its children. Mutes are private in Bluesky. + */ + mute(options: RPCOptions = {}) { + return this.client.call('app.bsky.graph.muteThread', { + data: { root: this.thread }, + ...options, + }); + } + + /** + * Unmutes the specified thread. + */ + unmute(options: RPCOptions = {}) { + return this.client.call('app.bsky.graph.unmuteThread', { + data: { root: this.thread }, + ...options, + }); + } +} diff --git a/packages/client/src/user/preferences/preferences.ts b/packages/client/src/user/preferences/preferences.ts index 56dd586..652614b 100644 --- a/packages/client/src/user/preferences/preferences.ts +++ b/packages/client/src/user/preferences/preferences.ts @@ -1,7 +1,6 @@ import type { AppBskyActorPutPreferences } from '@tsky/lexicons'; import type { Client } from '~/tsky/client'; - -type RPCOptions = { signal?: AbortSignal; headers?: HeadersInit }; +import type { RPCOptions } from '~/types'; export class Preferences { constructor(private client: Client) {} From bc5b04317038560b9b9ce9ace2bb10cd14acb791 Mon Sep 17 00:00:00 2001 From: Aditya Mathur Date: Tue, 21 Jan 2025 18:48:32 +0530 Subject: [PATCH 17/23] fix(client): added more props in the actor class --- packages/client/src/bsky/autor/autor.ts | 51 ++++++++++++++++++++++++- 1 file changed, 50 insertions(+), 1 deletion(-) diff --git a/packages/client/src/bsky/autor/autor.ts b/packages/client/src/bsky/autor/autor.ts index f4eb87c..94cd3ae 100644 --- a/packages/client/src/bsky/autor/autor.ts +++ b/packages/client/src/bsky/autor/autor.ts @@ -1,4 +1,7 @@ -import type { AppBskyActorDefs } from '@tsky/lexicons'; +import type { + AppBskyActorDefs, + AppBskyFeedGetAuthorFeed, +} from '@tsky/lexicons'; import type { Client } from '~/tsky/client'; import type { RPCOptions } from '~/types'; import { Paginator } from '~/utils'; @@ -90,4 +93,50 @@ export class Actor { return res.data; }); } + + /** + * Enumerates public relationships between one account, and a list of other accounts. Does not require auth. + */ + async relationships(others?: string[], options?: RPCOptions) { + const res = await this.client.get('app.bsky.graph.getRelationships', { + params: { + actor: this.identifier, + others, + }, + ...options, + }); + + return res.data; + } + + /** + * Get a view of an actor's 'author feed' (post and reposts by the author). Does not require auth. + */ + feeds(limit?: number, options?: RPCOptions) { + return Paginator.init(async (cursor) => { + const res = await this.client.get('app.bsky.feed.getActorFeeds', { + params: { cursor, actor: this.identifier, limit }, + ...options, + }); + + return res.data; + }); + } + + /** + * Get a list of feeds (feed generator records) created by the actor (in the actor's repo). + */ + feed( + params?: Omit, + options?: RPCOptions, + ) { + return Paginator.init(async (cursor) => { + const res = await this.client.get('app.bsky.feed.getAuthorFeed', { + params: { cursor, ...params, actor: this.identifier }, + ...options, + }); + + return res.data; + }); + } } From 61ee2377bb15c9bead8f5f811de24182f274198f Mon Sep 17 00:00:00 2001 From: Aditya Mathur <57684218+MathurAditya724@users.noreply.github.com> Date: Tue, 21 Jan 2025 22:49:07 +0530 Subject: [PATCH 18/23] feat(client): added the remaining modules --- packages/client/package.json | 12 +- packages/client/src/bsky/bsky.ts | 5 + packages/client/src/bsky/list/index.ts | 1 + packages/client/src/bsky/list/list.ts | 46 ++++++++ packages/client/src/bsky/post/index.ts | 0 packages/client/src/bsky/post/post.ts | 108 ++++++++++++++++++ packages/client/src/starterpack/index.ts | 1 + .../client/src/starterpack/starterpack.ts | 64 +++++++++++ packages/client/src/tsky/tsky.ts | 14 +++ packages/client/src/user/index.ts | 10 ++ packages/client/src/user/muted/index.ts | 1 + packages/client/src/user/muted/muted.ts | 41 +++++++ packages/client/src/user/suggestion/index.ts | 1 + .../client/src/user/suggestion/suggestion.ts | 50 ++++++++ packages/client/src/video/index.ts | 1 + packages/client/src/video/video.ts | 87 ++++++++++++++ packages/lexicons/src/lib/lexicons.ts | 52 ++++++++- pnpm-lock.yaml | 91 ++++++++++++++- 18 files changed, 576 insertions(+), 9 deletions(-) create mode 100644 packages/client/src/bsky/list/index.ts create mode 100644 packages/client/src/bsky/list/list.ts create mode 100644 packages/client/src/bsky/post/index.ts create mode 100644 packages/client/src/bsky/post/post.ts create mode 100644 packages/client/src/starterpack/index.ts create mode 100644 packages/client/src/starterpack/starterpack.ts create mode 100644 packages/client/src/user/muted/index.ts create mode 100644 packages/client/src/user/muted/muted.ts create mode 100644 packages/client/src/user/suggestion/index.ts create mode 100644 packages/client/src/user/suggestion/suggestion.ts create mode 100644 packages/client/src/video/index.ts create mode 100644 packages/client/src/video/video.ts diff --git a/packages/client/package.json b/packages/client/package.json index dd4036d..ccf90df 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -21,22 +21,24 @@ "main": "dist/index.cjs", "module": "dist/index.js", "types": "dist/index.d.ts", - "files": ["dist"], + "files": [ + "dist" + ], "scripts": { "dev": "pkgroll --watch", - "build": "pkgroll", + "build": "pkgroll --minify", "test": "vitest", "test:typescript": "tsc --noEmit" }, "dependencies": { - "@atcute/client": "^2.0.6", - "@tsky/lexicons": "workspace:*" + "@atcute/client": "^2.0.6" }, "devDependencies": { + "@tsky/lexicons": "workspace:*", "globals": "^15.12.0", "pkgroll": "^2.5.1", "tsx": "^4.19.2", "typescript": "^5.7.2", "vitest": "^2.1.6" } -} +} \ No newline at end of file diff --git a/packages/client/src/bsky/bsky.ts b/packages/client/src/bsky/bsky.ts index 9a778f2..96cd9e1 100644 --- a/packages/client/src/bsky/bsky.ts +++ b/packages/client/src/bsky/bsky.ts @@ -1,6 +1,7 @@ import { Feed } from '~/bsky/feed'; import type { Client } from '~/tsky/client'; import { Actor } from './autor'; +import { List } from './list'; export class Bsky { constructor(private client: Client) {} @@ -9,6 +10,10 @@ export class Bsky { return new Actor(this.client, identifier); } + list(uri: string) { + return new List(this.client, uri); + } + get feed() { return new Feed(this.client); } diff --git a/packages/client/src/bsky/list/index.ts b/packages/client/src/bsky/list/index.ts new file mode 100644 index 0000000..7182513 --- /dev/null +++ b/packages/client/src/bsky/list/index.ts @@ -0,0 +1 @@ +export * from './list'; diff --git a/packages/client/src/bsky/list/list.ts b/packages/client/src/bsky/list/list.ts new file mode 100644 index 0000000..313b403 --- /dev/null +++ b/packages/client/src/bsky/list/list.ts @@ -0,0 +1,46 @@ +import type { Client } from '~/tsky/client'; +import type { RPCOptions } from '~/types'; +import { Paginator } from '~/utils'; + +export class List { + constructor( + private client: Client, + private uri: string, + ) {} + + /** + * Gets a 'view' (with additional context) of a specified list. + */ + about(limit?: number, options?: RPCOptions) { + return Paginator.init(async (cursor) => { + const res = await this.client.get('app.bsky.graph.getList', { + params: { + cursor, + list: this.uri, + limit, + }, + ...options, + }); + + return res.data; + }); + } + + /** + * Get a feed of recent posts from a list (posts and reposts from any actors on the list). Does not require auth. + */ + feed(limit?: number, options?: RPCOptions) { + return Paginator.init(async (cursor) => { + const res = await this.client.get('app.bsky.feed.getListFeed', { + params: { + cursor, + list: this.uri, + limit, + }, + ...options, + }); + + return res.data; + }); + } +} diff --git a/packages/client/src/bsky/post/index.ts b/packages/client/src/bsky/post/index.ts new file mode 100644 index 0000000..e69de29 diff --git a/packages/client/src/bsky/post/post.ts b/packages/client/src/bsky/post/post.ts new file mode 100644 index 0000000..41112a6 --- /dev/null +++ b/packages/client/src/bsky/post/post.ts @@ -0,0 +1,108 @@ +import type { + AppBskyFeedGetLikes, + AppBskyFeedGetPostThread, + AppBskyFeedGetQuotes, + AppBskyFeedGetRepostedBy, + AppBskyFeedSearchPosts, +} from '@tsky/lexicons'; +import type { Client } from '~/tsky/client'; +import type { RPCOptions } from '~/types'; +import { Paginator } from '~/utils'; + +export class Post { + constructor(private client: Client) {} + + /** + * Get posts in a thread. Does not require auth, but additional metadata and filtering will be applied for authed requests. + */ + async threads( + params: AppBskyFeedGetPostThread.Params, + options: RPCOptions = {}, + ) { + const res = await this.client.get('app.bsky.feed.getPostThread', { + params, + ...options, + }); + + return res.data; + } + + /** + * Get like records which reference a subject (by AT-URI and CID). + */ + likes(params: AppBskyFeedGetLikes.Params, options: RPCOptions = {}) { + return Paginator.init(async (cursor) => { + const res = await this.client.get('app.bsky.feed.getLikes', { + params: { cursor, ...params }, + ...options, + }); + + return res.data; + }); + } + + /** + * Get a list of quotes for a given post. + */ + quotes(params: AppBskyFeedGetQuotes.Params, options: RPCOptions = {}) { + return Paginator.init(async (cursor) => { + const res = await this.client.get('app.bsky.feed.getQuotes', { + params: { cursor, ...params }, + ...options, + }); + + return res.data; + }); + } + + /** + * Get a list of reposts for a given post. + */ + repostedBy( + params: AppBskyFeedGetRepostedBy.Params, + options: RPCOptions = {}, + ) { + return Paginator.init(async (cursor) => { + const res = await this.client.get('app.bsky.feed.getRepostedBy', { + params: { cursor, ...params }, + ...options, + }); + + return res.data; + }); + } + + /** + * Find posts matching search criteria, returning views of those posts. + */ + static search( + client: Client, + params: AppBskyFeedSearchPosts.Params, + options: RPCOptions = {}, + ) { + return Paginator.init(async (cursor) => { + const res = await client.get('app.bsky.feed.searchPosts', { + params: { cursor, ...params }, + ...options, + }); + + return res.data; + }); + } + + /** + * Gets post views for a specified list of posts (by AT-URI). This is sometimes referred to as 'hydrating' a 'feed skeleton'. + */ + static async getMany( + client: Client, + posts: string[], + options: RPCOptions = {}, + ) { + const res = await client.get('app.bsky.feed.getPosts', { + params: { uris: posts }, + ...options, + }); + + return res.data.posts; + } +} diff --git a/packages/client/src/starterpack/index.ts b/packages/client/src/starterpack/index.ts new file mode 100644 index 0000000..e55a57e --- /dev/null +++ b/packages/client/src/starterpack/index.ts @@ -0,0 +1 @@ +export * from './starterpack'; diff --git a/packages/client/src/starterpack/starterpack.ts b/packages/client/src/starterpack/starterpack.ts new file mode 100644 index 0000000..dc2e559 --- /dev/null +++ b/packages/client/src/starterpack/starterpack.ts @@ -0,0 +1,64 @@ +import type { + AppBskyGraphGetStarterPack, + AppBskyGraphGetStarterPacks, +} from '@tsky/lexicons'; +import type { Client } from '~/tsky/client'; +import type { RPCOptions } from '~/types'; +import { Paginator } from '~/utils'; + +export class StarterPack { + constructor(private client: Client) {} + + /** + * Gets a view of a starter pack. + */ + view( + uri: string, + options: RPCOptions, + ): Promise; + /** + * Get views for a list of starter packs. + */ + view( + uris: string[], + options: RPCOptions, + ): Promise; + + async view(uris: string | string[], options: RPCOptions) { + if (Array.isArray(uris)) { + const res = await this.client.get('app.bsky.graph.getStarterPacks', { + params: { + uris, + }, + ...options, + }); + + return res.data.starterPacks; + } + + const res = await this.client.get('app.bsky.graph.getStarterPack', { + params: { starterPack: uris }, + ...options, + }); + + return res.data; + } + + /** + * Search for starter packs. + */ + search(query: string, limit?: number, options?: RPCOptions) { + return Paginator.init(async (cursor) => { + const res = await this.client.get('app.bsky.graph.searchStarterPacks', { + params: { + cursor, + q: query, + limit, + }, + ...options, + }); + + return res.data; + }); + } +} diff --git a/packages/client/src/tsky/tsky.ts b/packages/client/src/tsky/tsky.ts index 515253d..a19fa76 100644 --- a/packages/client/src/tsky/tsky.ts +++ b/packages/client/src/tsky/tsky.ts @@ -2,7 +2,9 @@ import { XRPC } from '@atcute/client'; import type { Queries } from '@tsky/lexicons'; import { Auth } from '~/auth'; import { Bsky } from '~/bsky'; +import { StarterPack } from '~/starterpack'; import { User } from '~/user'; +import { Video } from '~/video'; import { Client } from './client'; export class Tsky { @@ -29,4 +31,16 @@ export class Tsky { get bsky() { return new Bsky(this.client); } + + get video() { + if (!this.auth.currentSession) { + throw new Error('There is no active session'); + } + + return new Video(this.client); + } + + get starterpack() { + return new StarterPack(this.client); + } } diff --git a/packages/client/src/user/index.ts b/packages/client/src/user/index.ts index 39bcbdf..52cd797 100644 --- a/packages/client/src/user/index.ts +++ b/packages/client/src/user/index.ts @@ -7,7 +7,9 @@ import { MuteUnmuteActorList, MuteUnmuteThread, } from './mute_unmute'; +import { Muted } from './muted'; import { Preferences } from './preferences'; +import { Suggestion } from './suggestion'; export class User extends Actor { get preferences() { @@ -48,6 +50,14 @@ export class User extends Actor { }); } + get muted() { + return new Muted(this.client); + } + + get suggestion() { + return new Suggestion(this.client); + } + /** ----- */ /** diff --git a/packages/client/src/user/muted/index.ts b/packages/client/src/user/muted/index.ts new file mode 100644 index 0000000..c0af9b3 --- /dev/null +++ b/packages/client/src/user/muted/index.ts @@ -0,0 +1 @@ +export * from './muted'; diff --git a/packages/client/src/user/muted/muted.ts b/packages/client/src/user/muted/muted.ts new file mode 100644 index 0000000..4c81219 --- /dev/null +++ b/packages/client/src/user/muted/muted.ts @@ -0,0 +1,41 @@ +import type { Client } from '~/tsky/client'; +import type { RPCOptions } from '~/types'; +import { Paginator } from '~/utils'; + +export class Muted { + constructor(private client: Client) {} + + /** + * Enumerates mod lists that the requesting account (actor) currently has muted. Requires auth. + */ + lists(limit?: number, options?: RPCOptions) { + return Paginator.init(async (cursor) => { + const res = await this.client.get('app.bsky.graph.getListMutes', { + params: { + cursor, + limit, + }, + ...options, + }); + + return res.data; + }); + } + + /** + * Enumerates accounts that the requesting account (actor) currently has muted. Requires auth. + */ + profiles(limit?: number, options?: RPCOptions) { + return Paginator.init(async (cursor) => { + const res = await this.client.get('app.bsky.graph.getMutes', { + params: { + cursor, + limit, + }, + ...options, + }); + + return res.data; + }); + } +} diff --git a/packages/client/src/user/suggestion/index.ts b/packages/client/src/user/suggestion/index.ts new file mode 100644 index 0000000..33fe965 --- /dev/null +++ b/packages/client/src/user/suggestion/index.ts @@ -0,0 +1 @@ +export * from './suggestion'; diff --git a/packages/client/src/user/suggestion/suggestion.ts b/packages/client/src/user/suggestion/suggestion.ts new file mode 100644 index 0000000..c6af88c --- /dev/null +++ b/packages/client/src/user/suggestion/suggestion.ts @@ -0,0 +1,50 @@ +import type { Client } from '~/tsky/client'; +import type { RPCOptions } from '~/types'; +import { Paginator } from '~/utils'; + +export class Suggestion { + constructor(private client: Client) {} + + /** + * Get a list of suggested actors. Expected use is discovery of accounts to follow during new account onboarding. + */ + follow(limit?: number, options?: RPCOptions) { + return Paginator.init(async (cursor) => { + const res = await this.client.get('app.bsky.actor.getSuggestions', { + params: { + cursor, + limit, + }, + ...options, + }); + + return res.data; + }); + } + + /** + * Enumerates follows similar to a given account (actor). Expected use is to recommend additional accounts immediately after following one account. + */ + afterFollowing(actor: string, options?: RPCOptions) { + return this.client.get('app.bsky.graph.getSuggestedFollowsByActor', { + params: { + actor, + }, + ...options, + }); + } + + /** + * Get a list of suggested feeds (feed generators) for the requesting account. + */ + feeds(limit?: number, options?: RPCOptions) { + return Paginator.init(async (cursor) => { + const res = await this.client.get('app.bsky.feed.getSuggestedFeeds', { + params: { cursor, limit }, + ...options, + }); + + return res.data; + }); + } +} diff --git a/packages/client/src/video/index.ts b/packages/client/src/video/index.ts new file mode 100644 index 0000000..777af2d --- /dev/null +++ b/packages/client/src/video/index.ts @@ -0,0 +1 @@ +export * from './video'; diff --git a/packages/client/src/video/video.ts b/packages/client/src/video/video.ts new file mode 100644 index 0000000..96af382 --- /dev/null +++ b/packages/client/src/video/video.ts @@ -0,0 +1,87 @@ +import type { AppBskyVideoDefs, AppBskyVideoUploadVideo } from '@tsky/lexicons'; +import type { Client } from '~/tsky/client'; +import type { RPCOptions } from '~/types'; + +export class Video { + constructor(private client: Client) {} + + /** + * Get video upload limits for the authenticated user. + */ + async limit(options: RPCOptions = {}) { + const res = await this.client.get( + 'app.bsky.video.getUploadLimits', + options, + ); + + return res.data; + } + + /** + * Get status details for a video processing job. + */ + async status(jobId: string, options?: RPCOptions) { + const res = await this.client.get('app.bsky.video.getJobStatus', { + params: { jobId }, + ...options, + }); + + return new JobStatus(this.client, res.data.jobStatus); + } + + /** + * Upload a video to be processed then stored on the PDS. + */ + async upload(data: AppBskyVideoUploadVideo.Input, options?: RPCOptions) { + const res = await this.client.call('app.bsky.video.uploadVideo', { + data, + ...options, + }); + + return new JobStatus(this.client, res.data.jobStatus); + } +} + +class JobStatus { + jobId: string; + did: string; + /** The state of the video processing job. All values not listed as a known value indicate that the job is in process. */ + state: 'JOB_STATE_COMPLETED' | 'JOB_STATE_FAILED' | (string & {}); + /** Progress within the current processing state. */ + progress?: number; + blob?: AppBskyVideoDefs.JobStatus['blob']; + error?: string; + message?: string; + + constructor( + private client: Client, + data: AppBskyVideoDefs.JobStatus, + ) { + this.jobId = data.jobId; + this.did = data.did; + + this.state = data.state; + + this.progress = data.progress; + this.blob = data.blob; + this.error = data.error; + this.message = data.message; + } + + /** + * Update status details for a video processing job. + */ + async refresh(options?: RPCOptions) { + const res = await this.client.get('app.bsky.video.getJobStatus', { + params: { jobId: this.jobId }, + ...options, + }); + + this.state = res.data.jobStatus.state; + + this.progress = res.data.jobStatus.progress; + this.blob = res.data.jobStatus.blob; + this.error = res.data.jobStatus.error; + this.message = res.data.jobStatus.message; + } +} diff --git a/packages/lexicons/src/lib/lexicons.ts b/packages/lexicons/src/lib/lexicons.ts index b4d9979..e1a8d5d 100644 --- a/packages/lexicons/src/lib/lexicons.ts +++ b/packages/lexicons/src/lib/lexicons.ts @@ -5,9 +5,9 @@ * @module * Contains type declarations for Bluesky lexicons * @generated - * Generated on: 2025-01-19T08:09:58.687Z + * Generated on: 2025-01-21T16:36:07.633Z * Version: main - * Source: https://github.com/bluesky-social/atproto/tree/cbf17066f314fbc7f2e943127ee4a9f589f8bec2/lexicons + * Source: https://github.com/bluesky-social/atproto/tree/ee9779d07405d991b6be1b1780dae7828ff9d619/lexicons */ /** Base type with optional type field */ @@ -4279,6 +4279,19 @@ export declare namespace ToolsOzoneModerationDefs { reactivatedAt?: string; updatedAt?: string; } + /** Statistics about a particular account subject */ + interface AccountStats extends TypedBase { + /** Total number of appeals against a moderation action on the account */ + appealCount?: number; + /** Number of times the account was escalated */ + escalateCount?: number; + /** Total number of reports on the account */ + reportCount?: number; + /** Number of times the account was suspended */ + suspendCount?: number; + /** Number of times the account was taken down */ + takedownCount?: number; + } interface BlobView extends TypedBase { cid: At.CID; createdAt: string; @@ -4474,6 +4487,25 @@ export declare namespace ToolsOzoneModerationDefs { deletedAt?: string; updatedAt?: string; } + /** Statistics about a set of record subject items */ + interface RecordsStats extends TypedBase { + /** Number of items that were appealed at least once */ + appealedCount?: number; + /** Number of items that were escalated at least once */ + escalatedCount?: number; + /** Number of item currently in "reviewOpen" or "reviewEscalated" state */ + pendingCount?: number; + /** Number of item currently in "reviewNone" or "reviewClosed" state */ + processedCount?: number; + /** Number of items that were reported at least once */ + reportedCount?: number; + /** Total number of item in the set */ + subjectCount?: number; + /** Number of item currently taken down */ + takendownCount?: number; + /** Cumulative sum of the number of reports on the items in the set */ + totalReports?: number; + } interface RecordView extends TypedBase { blobCids: At.CID[]; cid: At.CID; @@ -4548,6 +4580,8 @@ export declare namespace ToolsOzoneModerationDefs { >; /** Timestamp referencing when the last update was made to the moderation status of the subject */ updatedAt: string; + /** Statistics related to the account subject */ + accountStats?: AccountStats; /** True indicates that the a previously taken moderator action was appealed against, by the author of the content. False indicates last appeal was resolved by moderators. */ appealed?: boolean; /** Sticky comment on the subject. */ @@ -4560,6 +4594,8 @@ export declare namespace ToolsOzoneModerationDefs { lastReviewedBy?: At.DID; muteReportingUntil?: string; muteUntil?: string; + /** Statistics related to the record subjects authored by the subject's account */ + recordsStats?: RecordsStats; subjectBlobCids?: At.CID[]; subjectRepoHandle?: string; suspendUntil?: string; @@ -4767,6 +4803,12 @@ export declare namespace ToolsOzoneModerationQueryStatuses { * \@default 50 */ limit?: number; + /** If specified, only subjects that belong to an account that has at least this many suspensions will be returned. */ + minAccountSuspendCount?: number; + /** If specified, only subjects that belong to an account that has at least this many reported records will be returned. */ + minReportedRecordsCount?: number; + /** If specified, only subjects that belong to an account that has at least this many taken down records will be returned. */ + minTakendownRecordsCount?: number; /** When set to true, only muted subjects and reporters will be returned. */ onlyMuted?: boolean; /** Number of queues being used by moderators. Subjects will be split among all queues. */ @@ -4788,7 +4830,11 @@ export declare namespace ToolsOzoneModerationQueryStatuses { /** \@default "desc" */ sortDirection?: "asc" | "desc"; /** \@default "lastReportedAt" */ - sortField?: "lastReviewedAt" | "lastReportedAt"; + sortField?: + | "lastReviewedAt" + | "lastReportedAt" + | "reportedRecordsCount" + | "takendownRecordsCount"; /** The subject to get the status for. */ subject?: string; /** If specified, subjects of the given type (account or record) will be returned. When this is set to 'account' the 'collections' parameter will be ignored. When includeAllUserRecords or subject is set, this will be ignored. */ diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b7a6cf2..6e7db18 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -26,10 +26,13 @@ importers: '@atcute/client': specifier: ^2.0.6 version: 2.0.6 + devDependencies: + '@atproto/api': + specifier: ^0.13.29 + version: 0.13.29 '@tsky/lexicons': specifier: workspace:* version: link:../lexicons - devDependencies: globals: specifier: ^15.12.0 version: 15.12.0 @@ -166,6 +169,21 @@ packages: '@atcute/client@2.0.6': resolution: {integrity: sha512-mhdqEicGUx0s5HTFOLpz91rcLS9j/g63de0nmAqv7blhU3j+xBf4le54qr2YIXNfnReZI7EwLYLX/YIBez4LGA==} + '@atproto/api@0.13.29': + resolution: {integrity: sha512-j+2mZikK7dibAll4TrQBVFMUVlZ9UZKTlTuFMMJ/x/JrngdYSvPoCcujbPHSj3XuKuG+MCNps5e7wK4mXXQsSA==} + + '@atproto/common-web@0.3.2': + resolution: {integrity: sha512-Vx0JtL1/CssJbFAb0UOdvTrkbUautsDfHNOXNTcX2vyPIxH9xOameSqLLunM1hZnOQbJwyjmQCt6TV+bhnanDg==} + + '@atproto/lexicon@0.4.5': + resolution: {integrity: sha512-fljWqMGKn+XWtTprBcS3F1hGBREnQYh6qYHv2sjENucc7REms1gtmZXSerB9N6pVeHVNOnXiILdukeAcic5OEw==} + + '@atproto/syntax@0.3.1': + resolution: {integrity: sha512-fzW0Mg1QUOVCWUD3RgEsDt6d1OZ6DdFmbKcDdbzUfh0t4rhtRAC05KbZYmxuMPWDAiJ4BbbQ5dkAc/mNypMXkw==} + + '@atproto/xrpc@0.6.6': + resolution: {integrity: sha512-umXEYVMo9/pyIBoKmIAIi64RXDW9tSXY+wqztlQ6I2GZtjLfNZqmAWU+wADk3SxUe54mvjxxGyA4TtyGtDMfhA==} + '@babel/helper-string-parser@7.25.9': resolution: {integrity: sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==} engines: {node: '>=6.9.0'} @@ -926,6 +944,9 @@ packages: resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} engines: {node: '>=12'} + await-lock@2.2.2: + resolution: {integrity: sha512-aDczADvlvTGajTDjcjpJMqRkOF6Qdz3YbPZm/PyW6tKPkx2hlYBzxMhEywM/tU72HrVZjgl5VCdRuMlA7pZ8Gw==} + balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} @@ -1097,6 +1118,9 @@ packages: resolution: {integrity: sha512-1+gLErljJFhbOVyaetcwJiJ4+eLe45S2E7P5UiZ9xGfeq3ATQf5DOv9G7MH3gGbKQLkzmNh2DxfZwLdw+j6oTQ==} engines: {node: '>=18'} + graphemer@1.4.0: + resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} + hasown@2.0.2: resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} engines: {node: '>= 0.4'} @@ -1146,6 +1170,9 @@ packages: isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + iso-datestring-validator@2.2.2: + resolution: {integrity: sha512-yLEMkBbLZTlVQqOnQ4FiMujR6T4DEcCb1xizmvXS+OxuhwcbtynoosRzdMA69zZCShCNAbi+gJ71FxZBBXx1SA==} + jackspeak@3.4.3: resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} @@ -1213,6 +1240,9 @@ packages: ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + multiformats@9.9.0: + resolution: {integrity: sha512-HoMUjhH9T8DDBNT+6xzkrd9ga/XiBI4xLr58LJACwK6G3HTOPeMz4nB4KJs33L2BelrIJa7P0VuNaVF3hMYfjg==} + nano-staged@0.8.0: resolution: {integrity: sha512-QSEqPGTCJbkHU2yLvfY6huqYPjdBrOaTMKatO1F8nCSrkQGXeKwtCiCnsdxnuMhbg3DTVywKaeWLGCE5oJpq0g==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} @@ -1414,6 +1444,10 @@ packages: resolution: {integrity: sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==} engines: {node: '>=14.0.0'} + tlds@1.255.0: + resolution: {integrity: sha512-tcwMRIioTcF/FcxLev8MJWxCp+GUALRhFEqbDoZrnowmKSGqPrl5pqS+Sut2m8BgJ6S4FExCSSpGffZ0Tks6Aw==} + hasBin: true + to-regex-range@5.0.1: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} @@ -1434,6 +1468,9 @@ packages: engines: {node: '>=14.17'} hasBin: true + uint8arrays@3.0.0: + resolution: {integrity: sha512-HRCx0q6O9Bfbp+HHSfQQKD7wU70+lydKVt4EghkdOvlK/NlrF90z+eXV34mUd48rNvVJXwkrMSPpCATkct8fJA==} + undici-types@6.20.0: resolution: {integrity: sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==} @@ -1572,6 +1609,9 @@ packages: resolution: {integrity: sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==} engines: {node: '>=18'} + zod@3.24.1: + resolution: {integrity: sha512-muH7gBL9sI1nciMZV67X5fTKKBLtwpZ5VBp1vsOQzj1MhrBZ4wlVCm3gedKZWLp0Oyel8sIGfeiz54Su+OVT+A==} + zwitch@2.0.4: resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==} @@ -1684,6 +1724,39 @@ snapshots: '@atcute/client@2.0.6': {} + '@atproto/api@0.13.29': + dependencies: + '@atproto/common-web': 0.3.2 + '@atproto/lexicon': 0.4.5 + '@atproto/syntax': 0.3.1 + '@atproto/xrpc': 0.6.6 + await-lock: 2.2.2 + multiformats: 9.9.0 + tlds: 1.255.0 + zod: 3.24.1 + + '@atproto/common-web@0.3.2': + dependencies: + graphemer: 1.4.0 + multiformats: 9.9.0 + uint8arrays: 3.0.0 + zod: 3.24.1 + + '@atproto/lexicon@0.4.5': + dependencies: + '@atproto/common-web': 0.3.2 + '@atproto/syntax': 0.3.1 + iso-datestring-validator: 2.2.2 + multiformats: 9.9.0 + zod: 3.24.1 + + '@atproto/syntax@0.3.1': {} + + '@atproto/xrpc@0.6.6': + dependencies: + '@atproto/lexicon': 0.4.5 + zod: 3.24.1 + '@babel/helper-string-parser@7.25.9': {} '@babel/helper-validator-identifier@7.25.9': {} @@ -2278,6 +2351,8 @@ snapshots: assertion-error@2.0.1: {} + await-lock@2.2.2: {} + balanced-match@1.0.2: {} birpc@0.2.19: {} @@ -2472,6 +2547,8 @@ snapshots: globals@15.12.0: {} + graphemer@1.4.0: {} + hasown@2.0.2: dependencies: function-bind: 1.1.2 @@ -2522,6 +2599,8 @@ snapshots: isexe@2.0.0: {} + iso-datestring-validator@2.2.2: {} + jackspeak@3.4.3: dependencies: '@isaacs/cliui': 8.0.2 @@ -2593,6 +2672,8 @@ snapshots: ms@2.1.3: {} + multiformats@9.9.0: {} + nano-staged@0.8.0: dependencies: picocolors: 1.1.1 @@ -2794,6 +2875,8 @@ snapshots: tinyspy@3.0.2: {} + tlds@1.255.0: {} + to-regex-range@5.0.1: dependencies: is-number: 7.0.0 @@ -2811,6 +2894,10 @@ snapshots: typescript@5.7.2: {} + uint8arrays@3.0.0: + dependencies: + multiformats: 9.9.0 + undici-types@6.20.0: {} unist-util-is@6.0.0: @@ -2995,4 +3082,6 @@ snapshots: yallist@5.0.0: {} + zod@3.24.1: {} + zwitch@2.0.4: {} From 06573bb389940667a3f27f786e3a78c739c16f83 Mon Sep 17 00:00:00 2001 From: Aditya Mathur <57684218+MathurAditya724@users.noreply.github.com> Date: Tue, 21 Jan 2025 22:49:32 +0530 Subject: [PATCH 19/23] chore: minor changes --- packages/client/src/bsky/post/index.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/client/src/bsky/post/index.ts b/packages/client/src/bsky/post/index.ts index e69de29..336abe1 100644 --- a/packages/client/src/bsky/post/index.ts +++ b/packages/client/src/bsky/post/index.ts @@ -0,0 +1 @@ +export * from './post'; From b9a7237d962c3b8c237d513e006b8cb03a747e11 Mon Sep 17 00:00:00 2001 From: Aditya Mathur <57684218+MathurAditya724@users.noreply.github.com> Date: Tue, 21 Jan 2025 22:52:38 +0530 Subject: [PATCH 20/23] chore: updated lockfile --- pnpm-lock.yaml | 89 -------------------------------------------------- 1 file changed, 89 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6e7db18..416b6f0 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -27,9 +27,6 @@ importers: specifier: ^2.0.6 version: 2.0.6 devDependencies: - '@atproto/api': - specifier: ^0.13.29 - version: 0.13.29 '@tsky/lexicons': specifier: workspace:* version: link:../lexicons @@ -169,21 +166,6 @@ packages: '@atcute/client@2.0.6': resolution: {integrity: sha512-mhdqEicGUx0s5HTFOLpz91rcLS9j/g63de0nmAqv7blhU3j+xBf4le54qr2YIXNfnReZI7EwLYLX/YIBez4LGA==} - '@atproto/api@0.13.29': - resolution: {integrity: sha512-j+2mZikK7dibAll4TrQBVFMUVlZ9UZKTlTuFMMJ/x/JrngdYSvPoCcujbPHSj3XuKuG+MCNps5e7wK4mXXQsSA==} - - '@atproto/common-web@0.3.2': - resolution: {integrity: sha512-Vx0JtL1/CssJbFAb0UOdvTrkbUautsDfHNOXNTcX2vyPIxH9xOameSqLLunM1hZnOQbJwyjmQCt6TV+bhnanDg==} - - '@atproto/lexicon@0.4.5': - resolution: {integrity: sha512-fljWqMGKn+XWtTprBcS3F1hGBREnQYh6qYHv2sjENucc7REms1gtmZXSerB9N6pVeHVNOnXiILdukeAcic5OEw==} - - '@atproto/syntax@0.3.1': - resolution: {integrity: sha512-fzW0Mg1QUOVCWUD3RgEsDt6d1OZ6DdFmbKcDdbzUfh0t4rhtRAC05KbZYmxuMPWDAiJ4BbbQ5dkAc/mNypMXkw==} - - '@atproto/xrpc@0.6.6': - resolution: {integrity: sha512-umXEYVMo9/pyIBoKmIAIi64RXDW9tSXY+wqztlQ6I2GZtjLfNZqmAWU+wADk3SxUe54mvjxxGyA4TtyGtDMfhA==} - '@babel/helper-string-parser@7.25.9': resolution: {integrity: sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==} engines: {node: '>=6.9.0'} @@ -944,9 +926,6 @@ packages: resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} engines: {node: '>=12'} - await-lock@2.2.2: - resolution: {integrity: sha512-aDczADvlvTGajTDjcjpJMqRkOF6Qdz3YbPZm/PyW6tKPkx2hlYBzxMhEywM/tU72HrVZjgl5VCdRuMlA7pZ8Gw==} - balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} @@ -1118,9 +1097,6 @@ packages: resolution: {integrity: sha512-1+gLErljJFhbOVyaetcwJiJ4+eLe45S2E7P5UiZ9xGfeq3ATQf5DOv9G7MH3gGbKQLkzmNh2DxfZwLdw+j6oTQ==} engines: {node: '>=18'} - graphemer@1.4.0: - resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} - hasown@2.0.2: resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} engines: {node: '>= 0.4'} @@ -1170,9 +1146,6 @@ packages: isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} - iso-datestring-validator@2.2.2: - resolution: {integrity: sha512-yLEMkBbLZTlVQqOnQ4FiMujR6T4DEcCb1xizmvXS+OxuhwcbtynoosRzdMA69zZCShCNAbi+gJ71FxZBBXx1SA==} - jackspeak@3.4.3: resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} @@ -1240,9 +1213,6 @@ packages: ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - multiformats@9.9.0: - resolution: {integrity: sha512-HoMUjhH9T8DDBNT+6xzkrd9ga/XiBI4xLr58LJACwK6G3HTOPeMz4nB4KJs33L2BelrIJa7P0VuNaVF3hMYfjg==} - nano-staged@0.8.0: resolution: {integrity: sha512-QSEqPGTCJbkHU2yLvfY6huqYPjdBrOaTMKatO1F8nCSrkQGXeKwtCiCnsdxnuMhbg3DTVywKaeWLGCE5oJpq0g==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} @@ -1444,10 +1414,6 @@ packages: resolution: {integrity: sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==} engines: {node: '>=14.0.0'} - tlds@1.255.0: - resolution: {integrity: sha512-tcwMRIioTcF/FcxLev8MJWxCp+GUALRhFEqbDoZrnowmKSGqPrl5pqS+Sut2m8BgJ6S4FExCSSpGffZ0Tks6Aw==} - hasBin: true - to-regex-range@5.0.1: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} @@ -1468,9 +1434,6 @@ packages: engines: {node: '>=14.17'} hasBin: true - uint8arrays@3.0.0: - resolution: {integrity: sha512-HRCx0q6O9Bfbp+HHSfQQKD7wU70+lydKVt4EghkdOvlK/NlrF90z+eXV34mUd48rNvVJXwkrMSPpCATkct8fJA==} - undici-types@6.20.0: resolution: {integrity: sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==} @@ -1609,9 +1572,6 @@ packages: resolution: {integrity: sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==} engines: {node: '>=18'} - zod@3.24.1: - resolution: {integrity: sha512-muH7gBL9sI1nciMZV67X5fTKKBLtwpZ5VBp1vsOQzj1MhrBZ4wlVCm3gedKZWLp0Oyel8sIGfeiz54Su+OVT+A==} - zwitch@2.0.4: resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==} @@ -1724,39 +1684,6 @@ snapshots: '@atcute/client@2.0.6': {} - '@atproto/api@0.13.29': - dependencies: - '@atproto/common-web': 0.3.2 - '@atproto/lexicon': 0.4.5 - '@atproto/syntax': 0.3.1 - '@atproto/xrpc': 0.6.6 - await-lock: 2.2.2 - multiformats: 9.9.0 - tlds: 1.255.0 - zod: 3.24.1 - - '@atproto/common-web@0.3.2': - dependencies: - graphemer: 1.4.0 - multiformats: 9.9.0 - uint8arrays: 3.0.0 - zod: 3.24.1 - - '@atproto/lexicon@0.4.5': - dependencies: - '@atproto/common-web': 0.3.2 - '@atproto/syntax': 0.3.1 - iso-datestring-validator: 2.2.2 - multiformats: 9.9.0 - zod: 3.24.1 - - '@atproto/syntax@0.3.1': {} - - '@atproto/xrpc@0.6.6': - dependencies: - '@atproto/lexicon': 0.4.5 - zod: 3.24.1 - '@babel/helper-string-parser@7.25.9': {} '@babel/helper-validator-identifier@7.25.9': {} @@ -2351,8 +2278,6 @@ snapshots: assertion-error@2.0.1: {} - await-lock@2.2.2: {} - balanced-match@1.0.2: {} birpc@0.2.19: {} @@ -2547,8 +2472,6 @@ snapshots: globals@15.12.0: {} - graphemer@1.4.0: {} - hasown@2.0.2: dependencies: function-bind: 1.1.2 @@ -2599,8 +2522,6 @@ snapshots: isexe@2.0.0: {} - iso-datestring-validator@2.2.2: {} - jackspeak@3.4.3: dependencies: '@isaacs/cliui': 8.0.2 @@ -2672,8 +2593,6 @@ snapshots: ms@2.1.3: {} - multiformats@9.9.0: {} - nano-staged@0.8.0: dependencies: picocolors: 1.1.1 @@ -2875,8 +2794,6 @@ snapshots: tinyspy@3.0.2: {} - tlds@1.255.0: {} - to-regex-range@5.0.1: dependencies: is-number: 7.0.0 @@ -2894,10 +2811,6 @@ snapshots: typescript@5.7.2: {} - uint8arrays@3.0.0: - dependencies: - multiformats: 9.9.0 - undici-types@6.20.0: {} unist-util-is@6.0.0: @@ -3082,6 +2995,4 @@ snapshots: yallist@5.0.0: {} - zod@3.24.1: {} - zwitch@2.0.4: {} From 88b0c22277f2be70fcf35a0a43afafc0ae315f35 Mon Sep 17 00:00:00 2001 From: Aditya Mathur Date: Wed, 22 Jan 2025 11:32:49 +0530 Subject: [PATCH 21/23] fix: corrected the typo --- packages/client/src/bsky/{autor/autor.ts => actor/actor.ts} | 0 packages/client/src/bsky/{autor => actor}/index.ts | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename packages/client/src/bsky/{autor/autor.ts => actor/actor.ts} (100%) rename packages/client/src/bsky/{autor => actor}/index.ts (100%) diff --git a/packages/client/src/bsky/autor/autor.ts b/packages/client/src/bsky/actor/actor.ts similarity index 100% rename from packages/client/src/bsky/autor/autor.ts rename to packages/client/src/bsky/actor/actor.ts diff --git a/packages/client/src/bsky/autor/index.ts b/packages/client/src/bsky/actor/index.ts similarity index 100% rename from packages/client/src/bsky/autor/index.ts rename to packages/client/src/bsky/actor/index.ts From 2fc985a2ca797f5761bc3286067e353917fd6fb2 Mon Sep 17 00:00:00 2001 From: Aditya Mathur Date: Wed, 22 Jan 2025 11:33:08 +0530 Subject: [PATCH 22/23] chore: corrected the imports --- packages/client/src/bsky/actor/index.ts | 2 +- packages/client/src/bsky/bsky.ts | 2 +- packages/client/src/user/index.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/client/src/bsky/actor/index.ts b/packages/client/src/bsky/actor/index.ts index 21bee6d..bce1ce5 100644 --- a/packages/client/src/bsky/actor/index.ts +++ b/packages/client/src/bsky/actor/index.ts @@ -1 +1 @@ -export * from './autor'; +export * from './actor'; diff --git a/packages/client/src/bsky/bsky.ts b/packages/client/src/bsky/bsky.ts index 96cd9e1..813677b 100644 --- a/packages/client/src/bsky/bsky.ts +++ b/packages/client/src/bsky/bsky.ts @@ -1,6 +1,6 @@ import { Feed } from '~/bsky/feed'; import type { Client } from '~/tsky/client'; -import { Actor } from './autor'; +import { Actor } from './actor'; import { List } from './list'; export class Bsky { diff --git a/packages/client/src/user/index.ts b/packages/client/src/user/index.ts index 52cd797..4c0325b 100644 --- a/packages/client/src/user/index.ts +++ b/packages/client/src/user/index.ts @@ -1,5 +1,5 @@ import type { AppBskyFeedGetTimeline } from '@tsky/lexicons'; -import { Actor } from '~/bsky/autor'; +import { Actor } from '~/bsky/actor'; import type { RPCOptions } from '~/types'; import { Paginator } from '~/utils'; import { From a682320e38a7f306ed9eb6f7845618c9acc62b80 Mon Sep 17 00:00:00 2001 From: Aditya Mathur <57684218+MathurAditya724@users.noreply.github.com> Date: Wed, 22 Jan 2025 12:17:09 +0530 Subject: [PATCH 23/23] fix: updated the mute and unmute api (#48) --- packages/client/src/user/index.ts | 30 +++------------ packages/client/src/user/mute/index.ts | 1 + packages/client/src/user/mute/mute.ts | 37 +++++++++++++++++++ packages/client/src/user/mute_unmute/actor.ts | 29 --------------- packages/client/src/user/mute_unmute/index.ts | 3 -- packages/client/src/user/mute_unmute/list.ts | 31 ---------------- .../client/src/user/mute_unmute/thread.ts | 29 --------------- packages/client/src/user/unmute/index.ts | 1 + packages/client/src/user/unmute/unmute.ts | 37 +++++++++++++++++++ 9 files changed, 82 insertions(+), 116 deletions(-) create mode 100644 packages/client/src/user/mute/index.ts create mode 100644 packages/client/src/user/mute/mute.ts delete mode 100644 packages/client/src/user/mute_unmute/actor.ts delete mode 100644 packages/client/src/user/mute_unmute/index.ts delete mode 100644 packages/client/src/user/mute_unmute/list.ts delete mode 100644 packages/client/src/user/mute_unmute/thread.ts create mode 100644 packages/client/src/user/unmute/index.ts create mode 100644 packages/client/src/user/unmute/unmute.ts diff --git a/packages/client/src/user/index.ts b/packages/client/src/user/index.ts index 4c0325b..99e2809 100644 --- a/packages/client/src/user/index.ts +++ b/packages/client/src/user/index.ts @@ -2,14 +2,11 @@ import type { AppBskyFeedGetTimeline } from '@tsky/lexicons'; import { Actor } from '~/bsky/actor'; import type { RPCOptions } from '~/types'; import { Paginator } from '~/utils'; -import { - MuteUnmuteActor, - MuteUnmuteActorList, - MuteUnmuteThread, -} from './mute_unmute'; +import { Mute } from './mute'; import { Muted } from './muted'; import { Preferences } from './preferences'; import { Suggestion } from './suggestion'; +import { Unmute } from './unmute'; export class User extends Actor { get preferences() { @@ -58,26 +55,11 @@ export class User extends Actor { return new Suggestion(this.client); } - /** ----- */ - - /** - * Mute or unmute a thread - */ - thread(thread: string) { - return new MuteUnmuteThread(this.client, thread); + get mute() { + return new Mute(this.client); } - /** - * Mute or unmute an actor - */ - actor(identifier: string) { - return new MuteUnmuteActor(this.client, identifier); - } - - /** - * Mute or unmute an actor list - */ - actorList(identifier: string) { - return new MuteUnmuteActorList(this.client, identifier); + get unmute() { + return new Unmute(this.client); } } diff --git a/packages/client/src/user/mute/index.ts b/packages/client/src/user/mute/index.ts new file mode 100644 index 0000000..c456722 --- /dev/null +++ b/packages/client/src/user/mute/index.ts @@ -0,0 +1 @@ +export * from './mute'; diff --git a/packages/client/src/user/mute/mute.ts b/packages/client/src/user/mute/mute.ts new file mode 100644 index 0000000..a6c65d8 --- /dev/null +++ b/packages/client/src/user/mute/mute.ts @@ -0,0 +1,37 @@ +import type { Client } from '~/tsky/client'; +import type { RPCOptions } from '~/types'; + +export class Mute { + constructor(private client: Client) {} + + /** + * Creates a mute relationship for the specified account. Mutes are private in Bluesky. + */ + actor(identifier: string, options: RPCOptions = {}) { + return this.client.call('app.bsky.graph.muteActor', { + data: { actor: identifier }, + ...options, + }); + } + + /** + * Mutes a thread preventing notifications from the thread and any of its children. Mutes are private in Bluesky. + */ + thread(identifier: string, options: RPCOptions = {}) { + return this.client.call('app.bsky.graph.muteThread', { + data: { root: identifier }, + ...options, + }); + } + + /** + * Mute an entire list (specified by AT-URI) of actors. This creates a mute relationship for all actors + * on the specified list. Mutes are private on Bluesky. + */ + actorList(identifier: string, options: RPCOptions = {}) { + return this.client.call('app.bsky.graph.muteActorList', { + data: { list: identifier }, + ...options, + }); + } +} diff --git a/packages/client/src/user/mute_unmute/actor.ts b/packages/client/src/user/mute_unmute/actor.ts deleted file mode 100644 index f207c65..0000000 --- a/packages/client/src/user/mute_unmute/actor.ts +++ /dev/null @@ -1,29 +0,0 @@ -import type { Client } from '~/tsky/client'; -import type { RPCOptions } from '~/types'; - -export class MuteUnmuteActor { - constructor( - private client: Client, - private identifier: string, - ) {} - - /** - * Creates a mute relationship for the specified account. Mutes are private in Bluesky. - */ - mute(options: RPCOptions = {}) { - return this.client.call('app.bsky.graph.muteActor', { - data: { actor: this.identifier }, - ...options, - }); - } - - /** - * Unmutes the specified account. - */ - unmute(options: RPCOptions = {}) { - return this.client.call('app.bsky.graph.unmuteActor', { - data: { actor: this.identifier }, - ...options, - }); - } -} diff --git a/packages/client/src/user/mute_unmute/index.ts b/packages/client/src/user/mute_unmute/index.ts deleted file mode 100644 index e8739c5..0000000 --- a/packages/client/src/user/mute_unmute/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from './actor'; -export * from './list'; -export * from './thread'; diff --git a/packages/client/src/user/mute_unmute/list.ts b/packages/client/src/user/mute_unmute/list.ts deleted file mode 100644 index 3ad1145..0000000 --- a/packages/client/src/user/mute_unmute/list.ts +++ /dev/null @@ -1,31 +0,0 @@ -import type { Client } from '~/tsky/client'; -import type { RPCOptions } from '~/types'; - -export class MuteUnmuteActorList { - constructor( - private client: Client, - private identifier: string, - ) {} - - /** - * Mute an entire list (specified by AT-URI) of actors. This creates a mute relationship for all actors - * on the specified list. Mutes are private on Bluesky. - */ - mute(options: RPCOptions = {}) { - return this.client.call('app.bsky.graph.muteActorList', { - data: { list: this.identifier }, - ...options, - }); - } - - /** - * Unmute an entire list (specified by AT-URI) of actors. This removes the mute relationship for all actors - * on the specified list. - */ - unmute(options: RPCOptions = {}) { - return this.client.call('app.bsky.graph.unmuteActorList', { - data: { list: this.identifier }, - ...options, - }); - } -} diff --git a/packages/client/src/user/mute_unmute/thread.ts b/packages/client/src/user/mute_unmute/thread.ts deleted file mode 100644 index 56621f3..0000000 --- a/packages/client/src/user/mute_unmute/thread.ts +++ /dev/null @@ -1,29 +0,0 @@ -import type { Client } from '~/tsky/client'; -import type { RPCOptions } from '~/types'; - -export class MuteUnmuteThread { - constructor( - private client: Client, - private thread: string, - ) {} - - /** - * Mutes a thread preventing notifications from the thread and any of its children. Mutes are private in Bluesky. - */ - mute(options: RPCOptions = {}) { - return this.client.call('app.bsky.graph.muteThread', { - data: { root: this.thread }, - ...options, - }); - } - - /** - * Unmutes the specified thread. - */ - unmute(options: RPCOptions = {}) { - return this.client.call('app.bsky.graph.unmuteThread', { - data: { root: this.thread }, - ...options, - }); - } -} diff --git a/packages/client/src/user/unmute/index.ts b/packages/client/src/user/unmute/index.ts new file mode 100644 index 0000000..42ac0a4 --- /dev/null +++ b/packages/client/src/user/unmute/index.ts @@ -0,0 +1 @@ +export * from './unmute'; diff --git a/packages/client/src/user/unmute/unmute.ts b/packages/client/src/user/unmute/unmute.ts new file mode 100644 index 0000000..c100a66 --- /dev/null +++ b/packages/client/src/user/unmute/unmute.ts @@ -0,0 +1,37 @@ +import type { Client } from '~/tsky/client'; +import type { RPCOptions } from '~/types'; + +export class Unmute { + constructor(private client: Client) {} + + /** + * Unmutes the specified account. + */ + actor(identifier: string, options: RPCOptions = {}) { + return this.client.call('app.bsky.graph.unmuteActor', { + data: { actor: identifier }, + ...options, + }); + } + + /** + * Unmutes the specified thread. + */ + thread(identifier: string, options: RPCOptions = {}) { + return this.client.call('app.bsky.graph.unmuteThread', { + data: { root: identifier }, + ...options, + }); + } + + /** + * Unmute an entire list (specified by AT-URI) of actors. This removes the mute relationship for all actors + * on the specified list. + */ + actorList(identifier: string, options: RPCOptions = {}) { + return this.client.call('app.bsky.graph.unmuteActorList', { + data: { list: identifier }, + ...options, + }); + } +}