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