Last active
June 9, 2025 01:56
-
-
Save weskerty/1ca1027f34e28cb90f7a76841ae971dd to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// MR. De la Comunidad para la Comunidad. Prohibida su Venta. | |
// El Software se proporciona bajo los términos de la Licencia MIT, excepto que usted no puede: | |
// 1. Vender, revender o arrendar el Software. | |
// 2. Cobrar a otros por el acceso, la distribución o cualquier otro uso comercial del Software. | |
// 3. Usar el Software como parte de un producto comercial o una oferta de servicio. | |
const FormData = require('form-data'); | |
const { bot, logger } = require('../lib'); | |
class RequestError extends Error { | |
constructor(message, type = 'GenericError') { | |
super(message); | |
this.name = type; | |
} | |
} | |
const utils = { | |
cleanCommand: (text) => text.replace(/^gr\s*/i, '').trim(), | |
sanitizeInput: (input) => input.substring(0, 2000), | |
}; | |
async function apiRequest(endpoint, method, headers, body, config, retries = 3) { | |
const fetch = (await import('node-fetch')).default; | |
const completeHeaders = { | |
...headers, | |
'Authorization': `Bearer ${config.GROQ_API_KEY}`, | |
}; | |
for (let attempt = 1; attempt <= retries; attempt++) { | |
try { | |
const response = await fetch(endpoint, { | |
method, | |
headers: completeHeaders, | |
body, | |
}); | |
if (!response.ok) { | |
const errorText = await response.text(); | |
throw new RequestError(`API Error: ${response.status} - ${errorText}`, 'APIError'); | |
} | |
return await response.json(); | |
} catch (error) { | |
logger.error(`Request attempt ${attempt} failed:`, error); | |
if (attempt === retries) throw error; | |
await new Promise(resolve => setTimeout(resolve, 1000 * Math.pow(2, attempt))); | |
} | |
} | |
} | |
const mediaHandler = { | |
async transcribeAudio(mediaBuffer, config) { | |
const formData = new FormData(); | |
formData.append('model', config.GROQ_AUDIO_MODEL); | |
formData.append('file', mediaBuffer, { | |
filename: 'audio.ogg', | |
contentType: 'audio/ogg', | |
}); | |
try { | |
const result = await apiRequest( | |
'https://api.groq.com/openai/v1/audio/transcriptions', | |
'POST', | |
formData.getHeaders(), | |
formData, | |
config | |
); | |
return result.text?.trim() || 'No transcription available'; | |
} catch (error) { | |
logger.error('Audio transcription failed', error); | |
throw error; | |
} | |
}, | |
async analyzeImage(mediaBuffer, userMessage, config) { | |
const imageDataUrl = `data:image/jpeg;base64,${mediaBuffer.toString('base64')}`; | |
const apiBody = { | |
messages: [ | |
{ | |
role: 'user', | |
content: [ | |
{ type: 'text', text: userMessage || 'explain this' }, | |
{ type: 'image_url', image_url: { url: imageDataUrl } }, | |
], | |
}, | |
], | |
model: config.GROQ_IMAGE_MODEL, | |
temperature: 1, | |
max_tokens: 1024, | |
top_p: 1, | |
stream: false, | |
stop: null, | |
}; | |
try { | |
const result = await apiRequest( | |
'https://api.groq.com/openai/v1/chat/completions', | |
'POST', | |
{ 'Content-Type': 'application/json' }, | |
JSON.stringify(apiBody), | |
config | |
); | |
return result.choices[0].message.content.trim(); | |
} catch (error) { | |
logger.error('Image analysis failed', error); | |
throw error; | |
} | |
}, | |
}; | |
async function processRequest(message, userMessage, context) { | |
try { | |
const config = { | |
GROQ_API_KEY: process.env.GROQ_API_KEY || context.GROQ_API_KEY, | |
GROQ_MODEL: process.env.GROQ_MODEL || context.GROQ_MODEL || 'llama-3.3-70b-versatile', | |
GROQ_SYSTEM_MSG: process.env.GROQ_SYSTEM_MSG || context.GROQ_SYSTEM_MSG || 'Eres LEvanterBot.', | |
GROQ_IMAGE_MODEL: process.env.GROQ_IMAGE_MODEL || context.GROQ_IMAGE_MODEL || 'meta-llama/llama-4-maverick-17b-128e-instruct', | |
GROQ_AUDIO_MODEL: process.env.GROQ_AUDIO_MODEL || context.GROQ_AUDIO_MODEL || 'whisper-large-v3', | |
}; | |
if (!config.GROQ_API_KEY) { | |
throw new RequestError('> ❌ You can set `setvar GROQ_API_KEY = APIKEY` \n Key in: https://console.groq.com/keys', 'AuthenticationError'); | |
} | |
if (message.reply_message?.mimetype?.startsWith('audio')) { | |
const mediaBuffer = await message.reply_message.downloadMediaMessage(); | |
const transcription = await mediaHandler.transcribeAudio(mediaBuffer, config); | |
if (userMessage) { | |
return handleTextRequest( | |
message, | |
transcription, | |
{ ...config, GROQ_SYSTEM_MSG: userMessage } | |
); | |
} else { | |
return message.send(transcription, { quoted: message.quoted }); | |
} | |
} | |
if (message.reply_message?.mimetype?.startsWith('image')) { | |
const mediaBuffer = await message.reply_message.downloadMediaMessage(); | |
const analysisResult = await mediaHandler.analyzeImage( | |
mediaBuffer, | |
userMessage, | |
config | |
); | |
return message.send(analysisResult, { quoted: message.quoted }); | |
} | |
return handleTextRequest(message, userMessage, config); | |
} catch (error) { | |
logger.error('Request processing error', error); | |
message.send(`❌ ${error.message || 'Unexpected error occurred'}`, { quoted: message.quoted }); | |
} | |
} | |
async function handleTextRequest(message, userMessage, config) { | |
const apiBody = { | |
messages: [ | |
{ role: 'system', content: config.GROQ_SYSTEM_MSG }, | |
{ role: 'user', content: utils.sanitizeInput(userMessage) }, | |
], | |
model: config.GROQ_MODEL, | |
temperature: 1, | |
max_tokens: 2024, | |
top_p: 1, | |
stream: false, | |
stop: null, | |
}; | |
const result = await apiRequest( | |
'https://api.groq.com/openai/v1/chat/completions', | |
'POST', | |
{ 'Content-Type': 'application/json' }, | |
JSON.stringify(apiBody), | |
config | |
); | |
return message.send(result.choices[0].message.content.trim(), { quoted: message.quoted }); | |
} | |
bot( | |
{ | |
pattern: 'gr ?(.*)', | |
desc: 'Transcribe audio, Images, TXT.', | |
type: 'AI', | |
}, | |
async (message, match, context) => { | |
const cleanedMatch = utils.cleanCommand(match); | |
return processRequest(message, cleanedMatch, context); | |
} | |
); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment