# Работа с FatSecret API в проекте Этот документ описывает, как используется API FatSecret для получения данных о продуктах питания и их пищевой ценности в нашем проекте. ## Настройка API ### Ключи API Для работы с FatSecret API необходимы следующие ключи: - `FATSECRET_CLIENT_ID` - ID клиента - `FATSECRET_CLIENT_SECRET` - секрет клиента - `FATSECRET_CUSTOMER_KEY` - ключ пользователя (используется как альтернатива CLIENT_ID) Эти ключи хранятся в `.env` файле проекта и загружаются в конфигурацию через модуль `shared/config.py`. ### Методы аутентификации FatSecret API поддерживает два метода аутентификации: 1. **OAuth 2.0** - требует прокси-сервер с белым списком IP для запроса токенов (не работает в нашем тестовом окружении) 2. **OAuth 1.0** - работает напрямую и подписывает каждый запрос (рекомендуется использовать) ## Примеры использования API ### Поиск продуктов питания ```python def search_food(query, max_results=5): """Поиск продуктов по названию""" # URL для API url = "https://platform.fatsecret.com/rest/server.api" # Параметры запроса params = { 'method': 'foods.search', 'search_expression': query, 'max_results': max_results, 'format': 'json' } # Подписываем запрос с помощью OAuth 1.0 oauth_params = generate_oauth_params("GET", url, params) # Отправляем запрос response = requests.get(url, params=oauth_params) if response.status_code == 200: return response.json() return None ``` ### Получение информации о продукте ```python def get_food_details(food_id): """Получение подробной информации о продукте по ID""" # URL для API url = "https://platform.fatsecret.com/rest/server.api" # Параметры запроса params = { 'method': 'food.get', 'food_id': food_id, 'format': 'json' } # Подписываем запрос с помощью OAuth 1.0 oauth_params = generate_oauth_params("GET", url, params) # Отправляем запрос response = requests.get(url, params=oauth_params) if response.status_code == 200: return response.json() return None ``` ## Генерация OAuth 1.0 подписи ```python def generate_oauth_params(http_method, url, params): """Создание и подписание OAuth 1.0 параметров""" # Текущее время в секундах timestamp = str(int(time.time())) # Случайная строка для nonce nonce = ''.join([str(random.randint(0, 9)) for _ in range(8)]) # Базовый набор параметров OAuth oauth_params = { 'oauth_consumer_key': FATSECRET_KEY, 'oauth_nonce': nonce, 'oauth_signature_method': 'HMAC-SHA1', 'oauth_timestamp': timestamp, 'oauth_version': '1.0' } # Объединяем с параметрами запроса all_params = {**params, **oauth_params} # Сортируем параметры по ключу sorted_params = sorted(all_params.items()) # Создаем строку параметров для подписи param_string = "&".join([f"{urllib.parse.quote(str(k), safe='')}={urllib.parse.quote(str(v), safe='')}" for k, v in sorted_params]) # Создаем строку для подписи signature_base = f"{http_method}&{urllib.parse.quote(url, safe='')}&{urllib.parse.quote(param_string, safe='')}" # Создаем ключ для подписи signing_key = f"{urllib.parse.quote(str(FATSECRET_SECRET), safe='')}&" # Создаем HMAC-SHA1 подпись signature = base64.b64encode( hmac.new( signing_key.encode(), signature_base.encode(), hashlib.sha1 ).digest() ).decode() # Добавляем подпись к параметрам OAuth all_params['oauth_signature'] = signature return all_params ``` ## Формат ответа API ### Поиск продуктов Структура ответа от метода `foods.search`: ```json { "foods": { "max_results": "5", "total_results": "1000", "page_number": "0", "food": [ { "food_id": "35718", "food_name": "Apples", "food_description": "Per 100g - Calories: 52kcal | Fat: 0.17g | Carbs: 13.81g | Protein: 0.26g", "food_url": "https://www.fatsecret.com/calories-nutrition/usda/apples?portionid=34128" }, // ...другие продукты ] } } ``` ### Информация о продукте Структура ответа от метода `food.get`: ```json { "food": { "food_id": "35718", "food_name": "Apples", "food_type": "Generic", "servings": { "serving": [ { "serving_id": "34128", "serving_description": "100g", "calories": "52", "carbohydrate": "13.81", "protein": "0.26", "fat": "0.17", // другие пищевые вещества }, // другие варианты порций ] } } } ``` ## Ограничения API 1. Функциональность поиска на русском языке может быть недоступна в базовой версии API 2. Ограничение на количество запросов в месяц (зависит от уровня доступа) 3. OAuth 2.0 требует прокси-сервера, настроенного на определенные IP-адреса ## Тестирование API Для тестирования API можно использовать готовый тестовый скрипт, который находится в корне проекта: ```bash # Активировать виртуальное окружение source venv/bin/activate # Запустить тестовый скрипт python test_fatsecret_api_oauth1.py ``` Вы также можете использовать этот скрипт как шаблон для написания собственных тестов. Примеры использования: ```python # Импортировать функции из тестового скрипта from test_fatsecret_api_oauth1 import search_food, process_search_results # Поиск продуктов на английском result = search_food("chicken breast") process_search_results(result) # Поиск продуктов на русском result = search_food("яблоко", locale="ru_RU") process_search_results(result) ``` ### Примеры команд для тестирования через cURL Для тестирования API через cURL можно использовать следующие команды: ```bash # Поиск продуктов через nutrition service (требуется авторизация) curl -X POST http://localhost:8006/api/v1/nutrition/search \ -H "Content-Type: application/json" \ -H "Authorization: Bearer YOUR_JWT_TOKEN" \ -d '{"query": "apple", "max_results": 5}' # Прямое тестирование FatSecret API (OAuth 1.0) curl -X GET "https://platform.fatsecret.com/rest/server.api?method=foods.search&search_expression=apple&max_results=5&format=json&oauth_consumer_key=YOUR_CONSUMER_KEY&oauth_signature_method=HMAC-SHA1&oauth_timestamp=TIMESTAMP&oauth_nonce=NONCE&oauth_version=1.0&oauth_signature=YOUR_SIGNATURE" ``` > **Примечание:** Для выполнения прямого запроса к FatSecret API через cURL необходимо сгенерировать правильную OAuth 1.0 подпись. Рекомендуется использовать скрипт `test_fatsecret_api_oauth1.py` вместо этого. ## Рекомендации по использованию 1. Использовать OAuth 1.0 для аутентификации, так как он работает без дополнительной инфраструктуры 2. Кэшировать результаты запросов, чтобы снизить нагрузку на API 3. Обрабатывать возможные ошибки API и предоставлять пользователям понятные сообщения 4. Использовать английские запросы для поиска, так как база данных в основном на английском языке