Add recipe and weather command handling for WhatsApp bot
This commit is contained in:
parent
bd26a59081
commit
4c9455f644
41
commands/recipes_command.js
Normal file
41
commands/recipes_command.js
Normal file
@ -0,0 +1,41 @@
|
||||
const recipesService = require('../services/recipes_service');
|
||||
const recipeUtils = require('../utils/recipe_utils');
|
||||
|
||||
/**
|
||||
* Maneja el comando de recetas.
|
||||
* @param {Object} client - Instancia del cliente de WhatsApp.
|
||||
* @param {Object} message - Mensaje recibido.
|
||||
*/
|
||||
const handleRecipeCommand = async (client, message) => {
|
||||
const parts = message.body.trim().split(' ');
|
||||
const subCommand = parts[0].toLowerCase();
|
||||
const query = parts.slice(1).join(' ');
|
||||
|
||||
try {
|
||||
let recipe;
|
||||
|
||||
if (subCommand === '!receta') {
|
||||
if (query) {
|
||||
// Buscar receta por nombre
|
||||
recipe = await recipesService.searchMealByName(query);
|
||||
} else {
|
||||
// Obtener receta aleatoria
|
||||
recipe = await recipesService.getRandomMeal();
|
||||
}
|
||||
|
||||
const recipeInfo = recipeUtils.formatRecipeInfo(recipe);
|
||||
await client.sendMessage(message.from, recipeInfo);
|
||||
console.log(`📤 Información de la receta enviada a ${message.from}`);
|
||||
} else {
|
||||
// Manejar otros subcomandos si es necesario
|
||||
await client.sendMessage(message.from, '❌ Comando no reconocido.');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('❌ Error al manejar el comando de recetas:', error);
|
||||
await client.sendMessage(message.from, `❌ Error al obtener la receta: ${error.message}`);
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
handleRecipeCommand
|
||||
};
|
48
commands/weather_command.js
Normal file
48
commands/weather_command.js
Normal file
@ -0,0 +1,48 @@
|
||||
const weatherService = require('../services/weather_service');
|
||||
const weatherUtils = require('../utils/weather_utils');
|
||||
|
||||
/**
|
||||
* Maneja el comando de clima.
|
||||
* @param {Client} client - Instancia del cliente de WhatsApp.
|
||||
* @param {Object} message - Mensaje recibido.
|
||||
*/
|
||||
const handleWeatherCommand = async (client, message) => {
|
||||
const parts = message.body.trim().split(' ');
|
||||
const command = parts[0].toLowerCase();
|
||||
const city = parts.length > 1 ? parts.slice(1).join(' ') : 'Guatemala';
|
||||
|
||||
try {
|
||||
const { latitude, longitude } = await weatherUtils.getCoordinates(city);
|
||||
const weather = await weatherService.getWeather(latitude, longitude);
|
||||
const weatherDescription = weatherUtils.translateWeatherCode(weather.weathercode);
|
||||
|
||||
const weatherInfo = formatWeatherInfo(city, weather, weatherDescription);
|
||||
await client.sendMessage(message.from, weatherInfo);
|
||||
console.log(`📤 Información del clima de ${city} enviada a ${message.from}`);
|
||||
} catch (error) {
|
||||
console.error('❌ Error al obtener el clima:', error);
|
||||
await client.sendMessage(message.from, `❌ Error al obtener el clima: ${error.message}`);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Formatea la información del clima para enviarla como mensaje.
|
||||
* @param {String} city - Nombre de la ciudad.
|
||||
* @param {Object} weather - Datos del clima obtenidos del servicio.
|
||||
* @param {String} weatherDescription - Descripción traducida del código de clima.
|
||||
* @returns {String} - Mensaje formateado con la información del clima.
|
||||
*/
|
||||
const formatWeatherInfo = (city, weather, weatherDescription) => {
|
||||
return `
|
||||
🌤️ *Clima Actual en ${city}*:
|
||||
- 🌡️ Temperatura: ${weather.temperature}°C
|
||||
- 💨 Viento: ${weather.windspeed} km/h
|
||||
- 🧭 Dirección del viento: ${weather.winddirection}°
|
||||
- ☁️ Condición: ${weatherDescription}
|
||||
- ⏰ Hora: ${new Date(weather.time).toLocaleTimeString('es-ES')}
|
||||
`.trim();
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
handleWeatherCommand
|
||||
};
|
41
index.js
41
index.js
@ -1,8 +1,12 @@
|
||||
// index.js
|
||||
|
||||
const { Client, LocalAuth } = require('whatsapp-web.js');
|
||||
const qrcode = require('qrcode-terminal');
|
||||
const dotenv = require('dotenv');
|
||||
const weatherUtils = require('./utils/weather_utils');
|
||||
const weatherService = require('./services/weather_service');
|
||||
const { handleRecipeCommand } = require('./commands/recipes_command'); // Importar el comando de recetas
|
||||
const { handleWeatherCommand } = require('./commands/weather_command'); // Importar el comando de clima
|
||||
|
||||
// Configuración inicial
|
||||
dotenv.config();
|
||||
@ -80,11 +84,13 @@ class WhatsAppBot {
|
||||
});
|
||||
|
||||
const command = message.body.trim().toLowerCase();
|
||||
|
||||
|
||||
if (command === '!ping') {
|
||||
await this.handlePingCommand(message);
|
||||
} else if (command.startsWith('!clima')) {
|
||||
await this.handleWeatherCommand(message);
|
||||
await handleWeatherCommand(this.client, message);
|
||||
} else if (command.startsWith('!receta')) {
|
||||
await handleRecipeCommand(this.client, message);
|
||||
}
|
||||
}
|
||||
|
||||
@ -97,35 +103,6 @@ class WhatsAppBot {
|
||||
}
|
||||
}
|
||||
|
||||
async handleWeatherCommand(message) {
|
||||
const parts = message.body.split(' ');
|
||||
const city = parts.length > 1 ? parts.slice(1).join(' ') : 'Guatemala';
|
||||
|
||||
try {
|
||||
const { latitude, longitude } = await weatherUtils.getCoordinates(city);
|
||||
const weather = await weatherService.getWeather(latitude, longitude);
|
||||
const weatherDescription = weatherUtils.translateWeatherCode(weather.weathercode);
|
||||
|
||||
const weatherInfo = this.formatWeatherInfo(city, weather, weatherDescription);
|
||||
await this.client.sendMessage(message.from, weatherInfo);
|
||||
console.log(`📤 Información del clima de ${city} enviada a ${message.from}`);
|
||||
} catch (error) {
|
||||
console.error('❌ Error al obtener el clima:', error);
|
||||
await this.client.sendMessage(message.from, `❌ Error al obtener el clima: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
formatWeatherInfo(city, weather, weatherDescription) {
|
||||
return `
|
||||
🌤️ *Clima Actual en ${city}*:
|
||||
- 🌡️ Temperatura: ${weather.temperature}°C
|
||||
- 💨 Viento: ${weather.windspeed} km/h
|
||||
- 🧭 Dirección del viento: ${weather.winddirection}°
|
||||
- ☁️ Condición: ${weatherDescription}
|
||||
- ⏰ Hora: ${new Date(weather.time).toLocaleTimeString('es-ES')}
|
||||
`.trim();
|
||||
}
|
||||
|
||||
logMessage(message) {
|
||||
console.log('📩 Mensaje recibido:', {
|
||||
from: message.from,
|
||||
@ -145,4 +122,4 @@ class WhatsAppBot {
|
||||
|
||||
// Iniciar el bot
|
||||
const bot = new WhatsAppBot();
|
||||
bot.start();
|
||||
bot.start();
|
||||
|
72
services/recipes_service.js
Normal file
72
services/recipes_service.js
Normal file
@ -0,0 +1,72 @@
|
||||
const axios = require('axios');
|
||||
|
||||
/**
|
||||
* Busca una receta por nombre utilizando la API de TheMealDB.
|
||||
* @param {String} name - Nombre de la receta a buscar.
|
||||
* @returns {Object} - Objeto de receta encontrado.
|
||||
* @throws {Error} - Si no se encuentra la receta o hay un error en la solicitud.
|
||||
*/
|
||||
const searchMealByName = async (name) => {
|
||||
try {
|
||||
const response = await axios.get('https://www.themealdb.com/api/json/v1/1/search.php', {
|
||||
params: {
|
||||
s: name
|
||||
}
|
||||
});
|
||||
|
||||
if (!response.data.meals) {
|
||||
throw new Error('No se encontraron recetas para tu búsqueda.');
|
||||
}
|
||||
|
||||
return response.data.meals[0]; // Retorna la primera receta encontrada
|
||||
} catch (error) {
|
||||
throw new Error(`Error al buscar la receta: ${error.message}`);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Obtiene una receta aleatoria utilizando la API de TheMealDB.
|
||||
* @returns {Object} - Objeto de receta aleatoria.
|
||||
* @throws {Error} - Si hay un error en la solicitud.
|
||||
*/
|
||||
const getRandomMeal = async () => {
|
||||
try {
|
||||
const response = await axios.get('https://www.themealdb.com/api/json/v1/1/random.php');
|
||||
if (!response.data.meals) {
|
||||
throw new Error('No se pudo obtener una receta aleatoria.');
|
||||
}
|
||||
return response.data.meals[0];
|
||||
} catch (error) {
|
||||
throw new Error(`Error al obtener una receta aleatoria: ${error.message}`);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Filtra recetas por ingrediente principal utilizando la API de TheMealDB.
|
||||
* @param {String} ingredient - Ingrediente principal para filtrar recetas.
|
||||
* @returns {Array} - Lista de recetas que contienen el ingrediente especificado.
|
||||
* @throws {Error} - Si no se encuentran recetas o hay un error en la solicitud.
|
||||
*/
|
||||
const filterByIngredient = async (ingredient) => {
|
||||
try {
|
||||
const response = await axios.get('https://www.themealdb.com/api/json/v1/1/filter.php', {
|
||||
params: {
|
||||
i: ingredient
|
||||
}
|
||||
});
|
||||
|
||||
if (!response.data.meals) {
|
||||
throw new Error('No se encontraron recetas con ese ingrediente.');
|
||||
}
|
||||
|
||||
return response.data.meals;
|
||||
} catch (error) {
|
||||
throw new Error(`Error al filtrar por ingrediente: ${error.message}`);
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
searchMealByName,
|
||||
getRandomMeal,
|
||||
filterByIngredient
|
||||
};
|
49
utils/recipe_utils.js
Normal file
49
utils/recipe_utils.js
Normal file
@ -0,0 +1,49 @@
|
||||
/**
|
||||
* Formatea la información de una receta para enviarla como mensaje.
|
||||
* @param {Object} recipe - Objeto de receta obtenido de TheMealDB.
|
||||
* @returns {String} - Mensaje formateado con la información de la receta.
|
||||
*/
|
||||
const formatRecipeInfo = (recipe) => {
|
||||
return `
|
||||
🍽️ *${recipe.strMeal}*
|
||||
|
||||
📄 *Categoría:* ${recipe.strCategory || 'No disponible'}
|
||||
🌍 *Área:* ${recipe.strArea || 'No disponible'}
|
||||
|
||||
📝 *Instrucciones:*
|
||||
${recipe.strInstructions || 'No hay instrucciones disponibles.'}
|
||||
|
||||
🔗 *Fuente:*
|
||||
${recipe.strSource || 'No disponible'}
|
||||
|
||||
🌐 *Video:*
|
||||
${recipe.strYoutube || 'No disponible'}
|
||||
|
||||
🌐 *Imagen:*
|
||||
${recipe.strMealThumb}
|
||||
|
||||
🛒 *Ingredientes:*
|
||||
${getIngredientsList(recipe)}
|
||||
`.trim();
|
||||
};
|
||||
|
||||
/**
|
||||
* Genera una lista de ingredientes y sus medidas.
|
||||
* @param {Object} recipe - Objeto de receta obtenido de TheMealDB.
|
||||
* @returns {String} - Lista formateada de ingredientes.
|
||||
*/
|
||||
const getIngredientsList = (recipe) => {
|
||||
let ingredients = '';
|
||||
for (let i = 1; i <= 20; i++) {
|
||||
const ingredient = recipe[`strIngredient${i}`];
|
||||
const measure = recipe[`strMeasure${i}`];
|
||||
if (ingredient && ingredient.trim() !== '') {
|
||||
ingredients += `- ${ingredient} - ${measure}\n`;
|
||||
}
|
||||
}
|
||||
return ingredients || 'No hay ingredientes disponibles.';
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
formatRecipeInfo
|
||||
};
|
Loading…
Reference in New Issue
Block a user