btch-gemini
Version:
A package for communicating with the Gemini API for chat and image processing.
211 lines (194 loc) • 9.15 kB
JavaScript
/**
* @class GeminiService
* @description A class that handles communication with the Gemini API for all services including chat, image, audio, video, and history processing.
* @remarks
* - The class includes methods for all Gemini API endpoints
* - Utilizes the `axios` library for making HTTP requests
* - Implements comprehensive error handling
* - Supports both GET and POST methods where applicable
*/
const axios = require('axios');
const { version, config } = require('../package.json');
class GeminiService {
constructor() {
this.baseUrl = config.baseUrl;
this.headers = {
'accept': 'application/json',
'Content-Type': 'application/json',
'User-Agent': `btch/${version}`,
};
}
/**
* @method gemini_chat
* @description Sends a chat prompt to the Gemini API and returns the response.
* @param {string} prompt - The prompt text to be sent to the API.
* @param {string} method - The HTTP method to use ('GET' or 'POST').
* @returns {Promise} - A promise that resolves with the response data.
* @throws {Error} - Throws an error if the request fails.
*/
async gemini_chat(prompt, method = 'POST') {
try {
//console.log('Processing chat request...');
return await this._processRequest('/gemini/chat', method, { prompt }, { q: prompt });
} catch (error) {
//console.error('Chat processing error:', error);
throw error;
}
}
/**
* @method gemini_image
* @description Sends a prompt and image URL to the Gemini API for image processing.
* @param {string} prompt - The prompt text to be sent to the API.
* @param {string} imageUrl - The URL of the image to be processed.
* @param {string} method - The HTTP method to use ('GET' or 'POST').
* @returns {Promise} - A promise that resolves with the response data.
* @throws {Error} - Throws an error if the request fails.
*/
async gemini_image(prompt, imageUrl, method = 'POST') {
try {
//console.log('Processing image request...');
const data = method === 'POST' ? { prompt, imgUrl: imageUrl } : null;
const params = method === 'GET' ? { q: prompt, url: imageUrl } : null;
return await this._processRequest('/gemini/image', method, data, params);
} catch (error) {
//console.error('Image processing error:', error);
throw error;
}
}
/**
* @method gemini_imgedit
* @description Edits an image using a given prompt and returns raw buffer data.
* @param {string} prompt - The transformation prompt.
* @param {string} imageUrl - The URL of the image to be edited.
* @param {string} method - The HTTP method to use ('GET' or 'POST').
* @returns {Promise<Buffer>} - A promise that resolves with the edited image buffer.
* @throws {Error} - Throws an error if the request fails.
*/
async gemini_imgedit(prompt, imageUrl, method = 'POST') {
try {
//console.log('Processing image edit request...');
const data = method === 'POST' ? { prompt, imgUrl: imageUrl } : null;
const params = method === 'GET' ? { q: prompt, url: imageUrl } : null;
// Override headers specifically for this request to get binary data
const customHeaders = {
...this.headers,
'accept': 'image/*' // Accept image content of any type
};
return await this._processRequest('/gemini/imgedit', method, data, params, true, customHeaders);
} catch (error) {
//console.error('Image edit processing error:', error);
throw error;
}
}
/**
* @method gemini_audio
* @description Processes audio content from a provided URL.
* @param {string} audioUrl - The URL of the audio to be processed.
* @param {string} prompt - Optional prompt for audio processing.
* @param {string} method - The HTTP method to use ('GET' or 'POST').
* @returns {Promise} - A promise that resolves with the response data.
* @throws {Error} - Throws an error if the request fails.
*/
async gemini_audio(audioUrl, prompt = null, method = 'POST') {
try {
//console.log('Processing audio request...');
const data = method === 'POST' ? { url: audioUrl, prompt } : null;
const params = method === 'GET' ? { url: audioUrl, q: prompt } : null;
return await this._processRequest('/gemini/audio', method, data, params);
} catch (error) {
//console.error('Audio processing error:', error);
throw error;
}
}
/**
* @method gemini_video
* @description Processes video content from a provided URL.
* @param {string} videoUrl - The URL of the video to be processed.
* @param {string} prompt - Optional prompt for video processing.
* @param {string} method - The HTTP method to use ('GET' or 'POST').
* @returns {Promise} - A promise that resolves with the response data.
* @throws {Error} - Throws an error if the request fails.
*/
async gemini_video(videoUrl, prompt = null, method = 'POST') {
try {
//console.log('Processing video request...');
const data = method === 'POST' ? { url: videoUrl, prompt } : null;
const params = method === 'GET' ? { url: videoUrl, q: prompt } : null;
return await this._processRequest('/gemini/video', method, data, params);
} catch (error) {
//console.error('Video processing error:', error);
throw error;
}
}
/**
* @method gemini_history
* @description Processes chat history and generates a response.
* @param {Array} messages - Array of message objects with role and content.
* @returns {Promise} - A promise that resolves with the response data.
* @throws {Error} - Throws an error if the request fails.
*/
async gemini_history(messages) {
try {
//console.log('Processing history request...');
return await this._processRequest('/gemini/history', 'POST', { messages });
} catch (error) {
//console.error('History processing error:', error);
throw error;
}
}
/**
* @method gemini_prompt
* @description Generates content using a custom system instruction and query.
* @param {string} systemPrompt - The system instruction to use.
* @param {string} query - The query to process.
* @param {string} method - The HTTP method to use ('GET' or 'POST').
* @returns {Promise} - A promise that resolves with the response data.
* @throws {Error} - Throws an error if the request fails.
*/
async gemini_prompt(systemPrompt, query, method = 'POST') {
try {
//console.log('Processing prompt request...');
const data = method === 'POST' ? { prompt: systemPrompt, q: query } : null;
const params = method === 'GET' ? { prompt: systemPrompt, q: query } : null;
return await this._processRequest('/prompt/gemini', method, data, params);
} catch (error) {
//console.error('Prompt processing error:', error);
throw error;
}
}
/**
* @method _processRequest
* @description Private method that handles all HTTP requests to the Gemini API.
* @param {string} endpoint - The API endpoint to call.
* @param {string} method - The HTTP method to use ('GET' or 'POST').
* @param {Object} data - The request body for POST requests.
* @param {Object} params - The query parameters for GET requests.
* @param {boolean} [asBuffer=false] - Whether to return the response as a buffer.
* @param {Object} [customHeaders=null] - Custom headers to use for this request.
* @returns {Promise} - A promise that resolves with the response data.
* @throws {Error} - Throws an error if the request fails.
* @private
*/
async _processRequest(endpoint, method, data = null, params = null, asBuffer = false, customHeaders = null) {
const url = `${this.baseUrl}${endpoint}`;
const config = {
headers: customHeaders || this.headers,
params: method === 'GET' ? params : undefined,
responseType: asBuffer ? 'arraybuffer' : 'json'
};
try {
const response = method === 'POST'
? await axios.post(url, data, config)
: await axios.get(url, config);
// For buffer responses, ensure we're returning a proper Buffer object
if (asBuffer && response.data) {
return Buffer.from(response.data);
}
return response.data;
} catch (error) {
//console.error(`Request to ${endpoint} failed:`, error);
throw error;
}
}
}
module.exports = new GeminiService();