/** * Plants.net API Integration Service * Provides connectivity to the plants.net API for plant identification, * data enrichment, and community features */ export interface PlantsNetSearchResult { id: string; commonName: string; scientificName: string; genus?: string; family?: string; imageUrl?: string; description?: string; careInstructions?: string; } export interface PlantsNetCommunity { nearbyGrowers: { userId: string; username: string; location: { city?: string; country?: string; distance?: number; }; plantsOwned: string[]; }[]; } export class PlantsNetService { private apiKey: string; private baseUrl: string; constructor(apiKey?: string) { this.apiKey = apiKey || process.env.PLANTS_NET_API_KEY || ''; this.baseUrl = 'https://api.plants.net/v1'; } /** * Search for plant by common or scientific name */ async searchPlant(query: string): Promise { try { const response = await fetch( `${this.baseUrl}/search?q=${encodeURIComponent(query)}`, { headers: { 'Authorization': `Bearer ${this.apiKey}`, 'Content-Type': 'application/json', }, } ); if (!response.ok) { console.error('Plants.net API error:', response.statusText); return []; } const data = await response.json(); return data.results || []; } catch (error) { console.error('Error searching plants.net:', error); return []; } } /** * Get detailed plant information by ID */ async getPlantDetails(plantId: string): Promise { try { const response = await fetch(`${this.baseUrl}/plants/${plantId}`, { headers: { 'Authorization': `Bearer ${this.apiKey}`, 'Content-Type': 'application/json', }, }); if (!response.ok) { console.error('Plants.net API error:', response.statusText); return null; } return await response.json(); } catch (error) { console.error('Error fetching plant details:', error); return null; } } /** * Find nearby growers who have similar plants */ async findNearbyGrowers( plantSpecies: string, latitude: number, longitude: number, radiusKm: number = 50 ): Promise { try { const response = await fetch( `${this.baseUrl}/community/nearby?species=${encodeURIComponent(plantSpecies)}&lat=${latitude}&lon=${longitude}&radius=${radiusKm}`, { headers: { 'Authorization': `Bearer ${this.apiKey}`, 'Content-Type': 'application/json', }, } ); if (!response.ok) { console.error('Plants.net API error:', response.statusText); return { nearbyGrowers: [] }; } return await response.json(); } catch (error) { console.error('Error finding nearby growers:', error); return { nearbyGrowers: [] }; } } /** * Identify plant from image (if API supports it) */ async identifyPlantFromImage(imageUrl: string): Promise { try { const response = await fetch(`${this.baseUrl}/identify`, { method: 'POST', headers: { 'Authorization': `Bearer ${this.apiKey}`, 'Content-Type': 'application/json', }, body: JSON.stringify({ imageUrl }), }); if (!response.ok) { console.error('Plants.net API error:', response.statusText); return []; } const data = await response.json(); return data.suggestions || []; } catch (error) { console.error('Error identifying plant:', error); return []; } } /** * Get care instructions for a plant */ async getCareInstructions(scientificName: string): Promise { try { const response = await fetch( `${this.baseUrl}/care/${encodeURIComponent(scientificName)}`, { headers: { 'Authorization': `Bearer ${this.apiKey}`, 'Content-Type': 'application/json', }, } ); if (!response.ok) { console.error('Plants.net API error:', response.statusText); return null; } const data = await response.json(); return data.careInstructions || null; } catch (error) { console.error('Error fetching care instructions:', error); return null; } } /** * Report a plant to the plants.net network * This allows integration with their global plant tracking */ async reportPlantToNetwork(plantData: { commonName: string; scientificName?: string; location: { latitude: number; longitude: number }; ownerId: string; propagationType?: string; }): Promise<{ success: boolean; plantsNetId?: string }> { try { const response = await fetch(`${this.baseUrl}/reports`, { method: 'POST', headers: { 'Authorization': `Bearer ${this.apiKey}`, 'Content-Type': 'application/json', }, body: JSON.stringify(plantData), }); if (!response.ok) { console.error('Plants.net API error:', response.statusText); return { success: false }; } const data = await response.json(); return { success: true, plantsNetId: data.id, }; } catch (error) { console.error('Error reporting plant to network:', error); return { success: false }; } } } // Singleton instance let plantsNetService: PlantsNetService | null = null; export function getPlantsNetService(): PlantsNetService { if (!plantsNetService) { plantsNetService = new PlantsNetService(); } return plantsNetService; }