Files
chat/docs/FATSECRET_API.md
Andrew K. Choi 537e7b363f
All checks were successful
continuous-integration/drone/push Build is passing
main commit
2025-10-16 16:30:25 +09:00

9.1 KiB
Raw Permalink Blame History

Работа с 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

Поиск продуктов питания

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

Получение информации о продукте

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 подписи

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:

{
  "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:

{
  "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 можно использовать готовый тестовый скрипт, который находится в корне проекта:

# Активировать виртуальное окружение
source venv/bin/activate

# Запустить тестовый скрипт
python test_fatsecret_api_oauth1.py

Вы также можете использовать этот скрипт как шаблон для написания собственных тестов. Примеры использования:

# Импортировать функции из тестового скрипта
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 можно использовать следующие команды:

# Поиск продуктов через 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. Использовать английские запросы для поиска, так как база данных в основном на английском языке