Atproto AMA app
0
fork

Configure Feed

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

at main 171 lines 5.0 kB view raw
1/** 2 * AT Protocol client wrapper for publishing Askimut records 3 */ 4 5import { Client } from '@atproto/lex' 6import type { OAuthSession } from '@atproto/oauth-client-node' 7import { getOAuthClient } from './oauth' 8import { getCachedConfig, isPublishingEnabled } from './config' 9import * as lexicons from '../lexicons/index.js' 10import type { LexQuestion, LexAnswer, LexProfile } from './schema-bridge' 11 12/** 13 * AT Protocol client for Askimut operations 14 */ 15export class AskimutAtClient { 16 private client: Client | null = null 17 private session: OAuthSession | null = null 18 19 constructor(session?: OAuthSession) { 20 if (session) { 21 this.session = session 22 this.client = new Client(session, { 23 validateRequest: getCachedConfig().atProtocol.strictValidation, 24 validateResponse: true, 25 strictResponseProcessing: getCachedConfig().atProtocol.strictValidation 26 }) 27 } 28 } 29 30 /** 31 * Initialize client with OAuth session for a given DID 32 */ 33 static async fromDid(did: string): Promise<AskimutAtClient> { 34 try { 35 const oauthClient = await getOAuthClient() 36 const session = await oauthClient.restore(did) 37 return new AskimutAtClient(session) 38 } catch (error) { 39 console.error('Failed to restore AT Protocol session:', error) 40 return new AskimutAtClient() 41 } 42 } 43 44 /** 45 * Check if the client is authenticated 46 */ 47 isAuthenticated(): boolean { 48 return this.client !== null && this.session !== null 49 } 50 51 /** 52 * Get the authenticated user's DID 53 */ 54 getDid(): string | null { 55 return this.session?.did || null 56 } 57 58 /** 59 * Publish a question to AT Protocol 60 */ 61 async publishQuestion(question: LexQuestion): Promise<{ uri: string; cid: string } | null> { 62 if (!this.client || !isPublishingEnabled('question')) { 63 return null 64 } 65 66 try { 67 // Validate the question before publishing 68 lexicons.question.$validate(question) 69 70 // For now, we'll use a simplified approach until the Client API is more stable 71 console.log('Would publish question to AT Protocol:', question) 72 73 // Return a mock result for now 74 return { 75 uri: `at://${this.getDid()}/com.askimut.question/${Date.now()}`, 76 cid: 'bafyrei' + Math.random().toString(36).substring(2) 77 } 78 } catch (error) { 79 console.error('Failed to publish question to AT Protocol:', error) 80 throw error 81 } 82 } 83 84 /** 85 * Publish an answer to AT Protocol 86 */ 87 async publishAnswer(answer: LexAnswer): Promise<{ uri: string; cid: string } | null> { 88 if (!this.client || !isPublishingEnabled('answer')) { 89 return null 90 } 91 92 try { 93 // Validate the answer before publishing 94 lexicons.answer.$validate(answer) 95 96 // For now, we'll use a simplified approach until the Client API is more stable 97 console.log('Would publish answer to AT Protocol:', answer) 98 99 // Return a mock result for now 100 return { 101 uri: `at://${this.getDid()}/com.askimut.answer/${Date.now()}`, 102 cid: 'bafyrei' + Math.random().toString(36).substring(2) 103 } 104 } catch (error) { 105 console.error('Failed to publish answer to AT Protocol:', error) 106 throw error 107 } 108 } 109 110 /** 111 * Publish/update a profile to AT Protocol 112 */ 113 async publishProfile(profile: LexProfile): Promise<{ uri: string; cid: string } | null> { 114 if (!this.client || !isPublishingEnabled('profile')) { 115 return null 116 } 117 118 try { 119 // Validate the profile before publishing 120 lexicons.profile.$validate(profile) 121 122 // For now, we'll use a simplified approach until the Client API is more stable 123 console.log('Would publish profile to AT Protocol:', profile) 124 125 // Return a mock result for now 126 return { 127 uri: `at://${this.getDid()}/com.askimut.profile/self`, 128 cid: 'bafyrei' + Math.random().toString(36).substring(2) 129 } 130 } catch (error) { 131 console.error('Failed to publish profile to AT Protocol:', error) 132 throw error 133 } 134 } 135 136 // Note: Get, list, and delete methods are temporarily disabled 137 // until the Client API type issues are resolved in a future update 138} 139 140/** 141 * Create an AT Protocol client for a given session 142 */ 143export async function createAtClient(session?: OAuthSession): Promise<AskimutAtClient> { 144 return new AskimutAtClient(session) 145} 146 147/** 148 * Create an AT Protocol client for a given DID 149 */ 150export async function createAtClientForDid(did: string): Promise<AskimutAtClient> { 151 return AskimutAtClient.fromDid(did) 152} 153 154/** 155 * Utility function to extract record key (rkey) from AT-URI 156 */ 157export function extractRkeyFromUri(atUri: string): string | null { 158 try { 159 const parts = atUri.split('/') 160 return parts[parts.length - 1] || null 161 } catch { 162 return null 163 } 164} 165 166/** 167 * Utility function to construct AT-URI from DID and rkey 168 */ 169export function constructAtUri(did: string, collection: string, rkey: string): string { 170 return `at://${did}/${collection}/${rkey}` 171}