This repository has no description
0

Configure Feed

Select the types of activity you want to include in your feed.

semble / src / modules / atproto / infrastructure / services / FakeAgentService.ts
5.1 kB 154 lines
1import { Result, ok, err } from 'src/shared/core/Result'; 2import { IAgentService } from '../../application/IAgentService'; 3import { DID } from '../../domain/DID'; 4import { Agent, AtpAgent } from '@atproto/api'; 5import { ATPROTO_SERVICE_ENDPOINTS } from './ServiceEndpoints'; 6 7export class FakeAgentService implements IAgentService { 8 getUnauthenticatedAgent(): Result<Agent, Error> { 9 try { 10 // Create a mock agent - in a real implementation this would be a proper Agent instance 11 const mockAgent = { 12 getProfile: async ({ actor }: { actor: string }) => { 13 const mockData = this.getMockDataForUserId(actor); 14 return { 15 success: true, 16 data: { 17 did: actor, 18 handle: mockData.handle, 19 displayName: mockData.name, 20 description: mockData.bio, 21 avatar: mockData.avatarUrl, 22 }, 23 }; 24 }, 25 resolveHandle: async ({ handle }: { handle: string }) => { 26 const mockData = this.getMockDataForHandle(handle); 27 return { 28 success: true, 29 data: { 30 did: mockData.did, 31 }, 32 }; 33 }, 34 } as Agent; 35 36 return ok(mockAgent); 37 } catch (error: any) { 38 return err(error); 39 } 40 } 41 42 async getUnauthenticatedAgentForDid(did: DID): Promise<Result<Agent, Error>> { 43 try { 44 // For the fake service, just return the same mock agent as getUnauthenticatedAgent 45 return this.getUnauthenticatedAgent(); 46 } catch (error: any) { 47 return err(error); 48 } 49 } 50 51 async getAuthenticatedAgent(did: DID): Promise<Result<Agent, Error>> { 52 try { 53 // Return the same mock agent for authenticated requests 54 // uncomment the line below to test error handling 55 // throw new Error('Not implemented in FakeAgentService'); 56 return this.getUnauthenticatedAgent(); 57 } catch (error: any) { 58 return err(error); 59 } 60 } 61 62 async getAuthenticatedServiceAccountAgent(): Promise<Result<Agent, Error>> { 63 try { 64 const serviceAccountIdentifier = 65 process.env.BSKY_SERVICE_ACCOUNT_IDENTIFIER; 66 const serviceAccountAppPassword = 67 process.env.BSKY_SERVICE_ACCOUNT_APP_PASSWORD; 68 69 if (!serviceAccountIdentifier || !serviceAccountAppPassword) { 70 return err( 71 new Error( 72 'Service account credentials not configured. Please set BSKY_SERVICE_ACCOUNT_IDENTIFIER and BSKY_SERVICE_ACCOUNT_APP_PASSWORD environment variables.', 73 ), 74 ); 75 } 76 77 const agent = new AtpAgent({ 78 service: ATPROTO_SERVICE_ENDPOINTS.AUTHENTICATED_BSKY_SERVICE, 79 }); 80 81 await agent.login({ 82 identifier: serviceAccountIdentifier, 83 password: serviceAccountAppPassword, 84 }); 85 86 return ok(agent); 87 } catch (error: any) { 88 return err( 89 new Error( 90 `Failed to authenticate service account: ${ 91 error instanceof Error ? error.message : String(error) 92 }`, 93 ), 94 ); 95 } 96 } 97 98 private getMockDataForUserId(userId: string): { 99 name: string; 100 handle: string; 101 avatarUrl: string; 102 bio: string; 103 did: string; 104 bannerUrl: string; 105 } { 106 const did2 = process.env.BSKY_DID_2 || 'did:plc:mock456'; 107 108 if (userId === did2) { 109 return { 110 name: 'Mock User Bob', 111 handle: process.env.BSKY_HANDLE_2 || 'bob.bsky.social', 112 avatarUrl: 113 'https://cdn.bsky.app/img/avatar/plain/did:plc:rlknsba2qldjkicxsmni3vyn/bafkreid4nmxspygkftep5b3m2wlcm3xvnwefkswzej7dhipojjxylkzfby@jpeg', 114 bio: 'This is Bob - a second mock profile for testing purposes (https://semble.so/), made by @cosmik.network.', 115 did: did2, 116 bannerUrl: 117 'https://cdn.bsky.app/img/banner/plain/did:plc:rlknsba2qldjkicxsmni3vyn/bafkreicgrrurfx5uicisd4nuqhbgn5pihlth5ssjzyl2egg32rxvjvtory@jpeg', 118 }; 119 } 120 121 // Default to account 1 122 const did1 = process.env.BSKY_DID_1 || 'did:plc:mock123'; 123 return { 124 name: 'Mock User Alice', 125 handle: process.env.BSKY_HANDLE_1 || 'alice.bsky.social', 126 avatarUrl: 127 'https://cdn.bsky.app/img/avatar/plain/did:plc:rlknsba2qldjkicxsmni3vyn/bafkreid4nmxspygkftep5b3m2wlcm3xvnwefkswzej7dhipojjxylkzfby@jpeg', 128 bio: 'This is Alice - a mock profile for testing purposes (https://semble.so/), made by @cosmik.network.', 129 did: did1, 130 bannerUrl: 131 'https://cdn.bsky.app/img/banner/plain/did:plc:rlknsba2qldjkicxsmni3vyn/bafkreicgrrurfx5uicisd4nuqhbgn5pihlth5ssjzyl2egg32rxvjvtory@jpeg', 132 }; 133 } 134 135 private getMockDataForHandle(handle: string): { 136 did: string; 137 handle: string; 138 } { 139 // Check if handle matches account 2 140 const handle2 = process.env.BSKY_HANDLE_2 || 'bob.bsky.social'; 141 if (handle === handle2 || handle.includes('bob')) { 142 return { 143 did: process.env.BSKY_DID_2 || 'did:plc:mock456', 144 handle: handle2, 145 }; 146 } 147 148 // Default to account 1 149 return { 150 did: process.env.BSKY_DID_1 || 'did:plc:mock123', 151 handle: process.env.BSKY_HANDLE_1 || 'alice.bsky.social', 152 }; 153 } 154}