Implement flexible recipe search and add healthy meal retrieval functionality

This commit is contained in:
David Vargas 2024-11-05 23:17:42 -06:00
parent 4c9455f644
commit c79ebcf9ff
2 changed files with 118 additions and 15 deletions

View File

@ -1,6 +1,49 @@
const axios = require('axios');
const { MessageMedia } = require('whatsapp-web.js');
const recipesService = require('../services/recipes_service');
const recipeUtils = require('../utils/recipe_utils');
/**
* Selecciona una receta aleatoria de una lista.
* @param {Array} recipes - Lista de recetas.
* @returns {Object} - Una receta aleatoria de la lista.
*/
const getRandomRecipe = (recipes) => {
return recipes[Math.floor(Math.random() * recipes.length)];
};
/**
* Realiza una búsqueda flexible utilizando varias estrategias.
* @param {String} query - La consulta de búsqueda introducida por el usuario.
* @returns {Object|null} - Objeto de receta encontrado o null si no hay coincidencias.
*/
const flexibleSearch = async (query) => {
const words = query.split(' ');
let recipes;
// 1. Intentar búsqueda exacta
recipes = await recipesService.searchMealByName(query);
if (recipes && recipes.length > 0) return getRandomRecipe(recipes);
// 2. Intentar con palabras clave parciales
for (let i = words.length; i > 0; i--) {
const partialQuery = words.slice(0, i).join(' ');
recipes = await recipesService.searchMealByName(partialQuery);
if (recipes && recipes.length > 0) return getRandomRecipe(recipes);
}
// 3. Intentar con cada palabra como filtro de ingrediente
for (const word of words) {
recipes = await recipesService.filterByIngredient(word);
if (recipes && recipes.length > 0) {
const randomRecipe = await recipesService.lookupMealById(getRandomRecipe(recipes).idMeal);
if (randomRecipe) return randomRecipe;
}
}
return null;
};
/**
* Maneja el comando de recetas.
* @param {Object} client - Instancia del cliente de WhatsApp.
@ -15,19 +58,30 @@ const handleRecipeCommand = async (client, message) => {
let recipe;
if (subCommand === '!receta') {
if (query) {
// Buscar receta por nombre
recipe = await recipesService.searchMealByName(query);
if (query === 'saludable') {
recipe = await recipesService.getRandomHealthyMeal();
} else if (query) {
recipe = await flexibleSearch(query);
} else {
// Obtener receta aleatoria
recipe = await recipesService.getRandomMeal();
}
if (!recipe) {
throw new Error('No se encontraron recetas para tu búsqueda.');
}
const recipeInfo = recipeUtils.formatRecipeInfo(recipe);
await client.sendMessage(message.from, recipeInfo);
// Descargar la imagen de la receta
const imageUrl = recipe.strMealThumb;
const response = await axios.get(imageUrl, { responseType: 'arraybuffer' });
const imageBase64 = Buffer.from(response.data, 'binary').toString('base64');
const media = new MessageMedia('image/jpeg', imageBase64, 'receta.jpg');
// Enviar la imagen con la información de la receta como leyenda
await client.sendMessage(message.from, media, { caption: 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) {

View File

@ -1,24 +1,22 @@
const axios = require('axios');
/**
* Busca una receta por nombre utilizando la API de TheMealDB.
* Busca recetas 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.
* @returns {Array} - Lista de recetas encontradas.
* @throws {Error} - Si no se encuentran recetas 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
}
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
return response.data.meals; // Devuelve todas las recetas encontradas
} catch (error) {
throw new Error(`Error al buscar la receta: ${error.message}`);
}
@ -65,8 +63,59 @@ const filterByIngredient = async (ingredient) => {
}
};
/*
* Categorías saludables para filtrar recetas.
*/
const healthyCategories = ['Salad', 'Chicken', 'Eggs', 'Fish', 'Seafood', 'Pasta', 'Rice', 'Beef', 'Pork', 'Lamb'];
/**
* Obtiene una receta aleatoria de categorías saludables.
* @returns {Object} - Objeto de receta aleatoria saludable.
* @throws {Error} - Si no se encuentra una receta o hay un error en la solicitud.
*/
const getRandomHealthyMeal = async () => {
try {
// Escoge una categoría saludable al azar
const randomCategory = healthyCategories[Math.floor(Math.random() * healthyCategories.length)];
// Filtra las recetas por la categoría saludable seleccionada
const response = await axios.get('https://www.themealdb.com/api/json/v1/1/filter.php', {
params: { c: randomCategory }
});
if (!response.data.meals || response.data.meals.length === 0) {
throw new Error('No se encontraron recetas saludables.');
}
// Escoge una receta aleatoria dentro de las recetas saludables
const randomMeal = response.data.meals[Math.floor(Math.random() * response.data.meals.length)];
return await lookupMealById(randomMeal.idMeal);
} catch (error) {
throw new Error(`Error al obtener una receta saludable: ${error.message}`);
}
};
/**
* Busca los detalles completos de una receta por ID.
* @param {String} id - ID de la receta.
* @returns {Object} - Objeto de receta con detalles completos.
*/
const lookupMealById = async (id) => {
try {
const response = await axios.get(`https://www.themealdb.com/api/json/v1/1/lookup.php?i=${id}`);
if (!response.data.meals) {
throw new Error('No se encontraron detalles para la receta.');
}
return response.data.meals[0];
} catch (error) {
throw new Error(`Error al obtener detalles de la receta: ${error.message}`);
}
};
module.exports = {
searchMealByName,
getRandomMeal,
filterByIngredient
filterByIngredient,
getRandomHealthyMeal,
lookupMealById
};