UNPKG

@agentdao/core

Version:

Core functionality, skills, and ready-made UI components for AgentDAO - Web3 subscriptions, content generation, social media, help support, live chat, RSS fetching, web search, and agent pricing integration

392 lines (391 loc) 15.9 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.PhotoSkill = void 0; class PhotoSkill { constructor(config) { if (config.providers?.unsplash?.enabled && !config.providers.unsplash.accessKey) { throw new Error('No Unsplash API key provided. Please add your key in Settings > API Keys.'); } this.config = config; } /** * Search for stock photos */ async searchPhotos(request) { const { query, provider = this.config.search.defaultProvider, size = this.config.search.defaultSize, orientation, color, category, maxResults = this.config.search.maxResults, page = 1 } = request; try { // Validate request if (!query || query.trim().length === 0) { throw new Error('Search query is required'); } let photos = []; // Search based on provider if (provider === 'all' || provider === 'unsplash') { if (this.config.providers.unsplash?.enabled) { const unsplashPhotos = await this.searchUnsplash(query, { size, orientation, color, maxResults, page }); photos.push(...unsplashPhotos); } } if (provider === 'all' || provider === 'pexels') { if (this.config.providers.pexels?.enabled) { const pexelsPhotos = await this.searchPexels(query, { size, orientation, color, maxResults, page }); photos.push(...pexelsPhotos); } } if (provider === 'all' || provider === 'pixabay') { if (this.config.providers.pixabay?.enabled) { const pixabayPhotos = await this.searchPixabay(query, { size, orientation, color, maxResults, page }); photos.push(...pixabayPhotos); } } // Limit results photos = photos.slice(0, maxResults); // Track analytics if enabled if (this.config.analytics?.enabled) { await this.trackSearch(query, photos.length, provider || 'all'); } return photos; } catch (error) { throw new Error(`Photo search failed: ${error instanceof Error ? error.message : 'Unknown error'}`); } } /** * Get trending photos */ async getTrendingPhotos(options) { const { provider = 'unsplash', category, maxResults = 10 } = options || {}; try { const trendingQueries = ['nature', 'business', 'technology', 'travel', 'food']; const randomQuery = trendingQueries[Math.floor(Math.random() * trendingQueries.length)]; return await this.searchPhotos({ query: category || randomQuery, provider, maxResults }); } catch (error) { throw new Error(`Failed to get trending photos: ${error instanceof Error ? error.message : 'Unknown error'}`); } } /** * Get photo collections */ async getCollections(options) { const { provider = 'unsplash', maxResults = 10 } = options || {}; try { // For now, return empty array as collections require specific API implementations // TODO: Implement real collection APIs for each provider const collections = []; return collections.slice(0, maxResults); } catch (error) { throw new Error(`Failed to get collections: ${error instanceof Error ? error.message : 'Unknown error'}`); } } /** * Get photo by ID */ async getPhotoById(photoId, provider = 'unsplash') { try { // TODO: Implement real photo-by-ID APIs for each provider throw new Error(`Photo by ID not yet implemented for ${provider}. Use searchPhotos() instead.`); } catch (error) { throw new Error(`Failed to get photo: ${error instanceof Error ? error.message : 'Unknown error'}`); } } /** * Download photo */ async downloadPhoto(photoId, provider = 'unsplash') { try { const photo = await this.getPhotoById(photoId, provider); return { url: photo.downloadUrl, filename: `${photoId}.${photo.format}`, size: photo.size }; } catch (error) { throw new Error(`Failed to download photo: ${error instanceof Error ? error.message : 'Unknown error'}`); } } /** * Get photo categories */ async getCategories() { return [ { id: 'nature', name: 'Nature', description: 'Landscapes, wildlife, and natural scenes', photoCount: 50000 }, { id: 'business', name: 'Business', description: 'Professional business and office scenes', photoCount: 25000 }, { id: 'technology', name: 'Technology', description: 'Computers, gadgets, and tech scenes', photoCount: 15000 }, { id: 'travel', name: 'Travel', description: 'Destinations, landmarks, and travel scenes', photoCount: 30000 }, { id: 'food', name: 'Food & Drink', description: 'Delicious food and beverage photography', photoCount: 20000 }, { id: 'people', name: 'People', description: 'Portraits and people in various settings', photoCount: 40000 }, { id: 'architecture', name: 'Architecture', description: 'Buildings, structures, and urban scenes', photoCount: 18000 }, { id: 'abstract', name: 'Abstract', description: 'Abstract and artistic photography', photoCount: 12000 } ]; } /** * Search Unsplash photos */ async searchUnsplash(query, options) { const accessKey = this.config.providers.unsplash?.accessKey; if (!accessKey) { throw new Error('Unsplash access key is required'); } try { const params = new URLSearchParams({ query: query, per_page: Math.min(options.maxResults || 10, 30).toString(), page: (options.page || 1).toString() }); if (options.orientation) { params.append('orientation', options.orientation); } const response = await fetch(`https://api.unsplash.com/search/photos?${params}`, { headers: { 'Authorization': `Client-ID ${accessKey}` } }); if (!response.ok) { throw new Error(`Unsplash API error: ${response.statusText}`); } const data = await response.json(); const photos = []; for (const photo of data.results) { const stockPhoto = { id: photo.id, url: photo.urls.regular, thumbnailUrl: photo.urls.thumb, previewUrl: photo.urls.small, downloadUrl: photo.links.download, title: photo.alt_description || `Photo by ${photo.user.name}`, description: photo.description, photographer: { name: photo.user.name, username: photo.user.username, profileUrl: photo.user.links.html }, dimensions: { width: photo.width, height: photo.height }, size: 0, // Unsplash doesn't provide file size format: 'jpeg', tags: photo.tags?.map((tag) => tag.title) || [], category: 'unsplash', license: 'free', provider: 'unsplash', createdAt: new Date(photo.created_at), metadata: { likes: photo.likes, downloads: photo.downloads, views: photo.views, color: photo.color } }; photos.push(stockPhoto); } return photos; } catch (error) { console.error('Unsplash API error:', error); throw new Error(`Failed to search Unsplash: ${error instanceof Error ? error.message : 'Unknown error'}`); } } /** * Search Pexels photos */ async searchPexels(query, options) { const apiKey = this.config.providers.pexels?.apiKey; if (!apiKey) { throw new Error('Pexels API key is required'); } try { const params = new URLSearchParams({ query: query, per_page: Math.min(options.maxResults || 10, 80).toString(), page: (options.page || 1).toString() }); if (options.orientation) { params.append('orientation', options.orientation); } const response = await fetch(`https://api.pexels.com/v1/search?${params}`, { headers: { 'Authorization': apiKey } }); if (!response.ok) { throw new Error(`Pexels API error: ${response.statusText}`); } const data = await response.json(); const photos = []; for (const photo of data.photos) { const stockPhoto = { id: photo.id.toString(), url: photo.src.large, thumbnailUrl: photo.src.small, previewUrl: photo.src.medium, downloadUrl: photo.src.original, title: photo.alt || `Photo by ${photo.photographer}`, description: photo.alt, photographer: { name: photo.photographer, username: photo.photographer_id.toString(), profileUrl: photo.photographer_url }, dimensions: { width: photo.width, height: photo.height }, size: 0, // Pexels doesn't provide file size format: 'jpeg', tags: [], category: 'pexels', license: 'free', provider: 'pexels', createdAt: new Date(), metadata: { likes: 0, downloads: 0, views: 0, color: photo.avg_color } }; photos.push(stockPhoto); } return photos; } catch (error) { console.error('Pexels API error:', error); throw new Error(`Failed to search Pexels: ${error instanceof Error ? error.message : 'Unknown error'}`); } } /** * Search Pixabay photos */ async searchPixabay(query, options) { const apiKey = this.config.providers.pixabay?.apiKey; if (!apiKey) { throw new Error('Pixabay API key is required'); } try { const params = new URLSearchParams({ key: apiKey, q: query, per_page: Math.min(options.maxResults || 10, 200).toString(), page: (options.page || 1).toString(), image_type: 'photo' }); if (options.orientation) { params.append('orientation', options.orientation); } const response = await fetch(`https://pixabay.com/api/?${params}`); if (!response.ok) { throw new Error(`Pixabay API error: ${response.statusText}`); } const data = await response.json(); const photos = []; for (const photo of data.hits) { const stockPhoto = { id: photo.id.toString(), url: photo.largeImageURL, thumbnailUrl: photo.previewURL, previewUrl: photo.webformatURL, downloadUrl: photo.largeImageURL, title: photo.tags || `Photo by ${photo.user}`, description: photo.tags, photographer: { name: photo.user, username: photo.user_id.toString(), profileUrl: `https://pixabay.com/users/${photo.user}-${photo.user_id}/` }, dimensions: { width: photo.imageWidth, height: photo.imageHeight }, size: 0, // Pixabay doesn't provide file size format: 'jpeg', tags: photo.tags.split(', '), category: 'pixabay', license: 'free', provider: 'pixabay', createdAt: new Date(), metadata: { likes: photo.likes, downloads: photo.downloads, views: photo.views, color: photo.dominantColor } }; photos.push(stockPhoto); } return photos; } catch (error) { console.error('Pixabay API error:', error); throw new Error(`Failed to search Pixabay: ${error instanceof Error ? error.message : 'Unknown error'}`); } } /** * Get a sample photo for testing */ async getSamplePhoto(provider = 'unsplash') { // This method is deprecated - use searchPhotos() for real photos throw new Error('getSamplePhoto is deprecated. Use searchPhotos() for real photos.'); } /** * Track search analytics */ async trackSearch(query, resultCount, provider) { if (!this.config.analytics?.enabled) return; if (!this.config.database || !this.config.database.endpoint) { throw new Error('No database endpoint configured for tracking analytics. Please configure a database endpoint to use this feature.'); } try { const analyticsData = { agentId: this.config.agentId, agentName: this.config.agentName, query, resultCount, provider, timestamp: new Date().toISOString() }; await fetch(this.config.database.endpoint, { method: 'POST', headers: { 'Content-Type': 'application/json', ...(this.config.database.apiKey ? { 'Authorization': `Bearer ${this.config.database.apiKey}` } : {}) }, body: JSON.stringify({ type: 'photo_search_analytics', data: analyticsData }) }); } catch (error) { throw new Error(`Failed to track photo search analytics: ${error instanceof Error ? error.message : 'Unknown error'}`); } } } exports.PhotoSkill = PhotoSkill;