Lanyards is a dedicated profile for researchers, built on the AT Protocol.
1/**
2 * Server-side authenticated agent utilities
3 *
4 * Provides authenticated AtpAgent instances for server-side operations
5 * using the configured app password credentials.
6 */
7
8import { AtpAgent } from '@atproto/api';
9import { getConfiguredCredentials } from './app-password';
10
11let cachedAgent: AtpAgent | null = null;
12let cacheTime: number = 0;
13const CACHE_DURATION = 5 * 60 * 1000; // 5 minutes
14
15/**
16 * Gets an authenticated AtpAgent for server-side use
17 * Uses app password authentication configured in environment variables
18 *
19 * @returns Authenticated AtpAgent
20 * @throws Error if credentials are not configured or login fails
21 */
22export async function getServerAgent(): Promise<AtpAgent> {
23 // Return cached agent if still valid
24 if (cachedAgent && Date.now() - cacheTime < CACHE_DURATION) {
25 return cachedAgent;
26 }
27
28 const credentials = await getConfiguredCredentials();
29 if (!credentials) {
30 throw new Error(
31 'Server authentication not configured. Set BLUESKY_HANDLE and BLUESKY_APP_PASSWORD in .env'
32 );
33 }
34
35 const agent = new AtpAgent({
36 service: process.env.PDS_URL || 'https://bsky.social',
37 });
38
39 await agent.login({
40 identifier: credentials.handle,
41 password: credentials.password,
42 });
43
44 cachedAgent = agent;
45 cacheTime = Date.now();
46
47 return agent;
48}
49
50/**
51 * Creates a public (unauthenticated) AtpAgent
52 * Use this for operations that don't require authentication
53 *
54 * @returns Unauthenticated AtpAgent
55 */
56export function getPublicAgent(): AtpAgent {
57 return new AtpAgent({
58 service: process.env.PDS_URL || 'https://bsky.social',
59 });
60}