main functions commit
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
2025-10-19 19:50:00 +09:00
parent ce72785184
commit 3050e084fa
39 changed files with 7149 additions and 186 deletions

247
tests/test_fatsecret_api_v2.py Executable file
View File

@@ -0,0 +1,247 @@
#!/usr/bin/env python3
"""
Скрипт для тестирования API FatSecret
Выполняет тестовые запросы к API FatSecret с использованием ключей из конфигурации приложения
"""
import os
import json
import time
import base64
import requests
import urllib.parse
from dotenv import load_dotenv
# Загружаем .env файл
current_dir = os.path.dirname(os.path.abspath(__file__))
env_path = os.path.join(current_dir, ".env")
load_dotenv(env_path)
print(f"✅ Loaded .env from: {env_path}")
# Получаем API ключи из переменных окружения
FATSECRET_CLIENT_ID = os.environ.get("FATSECRET_CLIENT_ID")
FATSECRET_CLIENT_SECRET = os.environ.get("FATSECRET_CLIENT_SECRET")
if not FATSECRET_CLIENT_ID or not FATSECRET_CLIENT_SECRET:
raise ValueError("FatSecret API keys not found in .env file")
print(f"🔑 Using FatSecret API keys: CLIENT_ID={FATSECRET_CLIENT_ID[:8]}...")
customer_key = os.environ.get("FATSECRET_CUSTOMER_KEY")
if customer_key:
print(f"🔑 Using CUSTOMER_KEY={customer_key[:8]}...")
def get_oauth_token():
"""Получение OAuth 2.0 токена для доступа к API"""
print("🔄 Getting OAuth token...")
# Создаем заголовок авторизации с Base64-кодированными ID и секретом
auth_string = f"{FATSECRET_CLIENT_ID}:{FATSECRET_CLIENT_SECRET}"
auth_header = base64.b64encode(auth_string.encode()).decode()
# Полный вывод учетных данных для диагностики
print(f"🔑 CLIENT_ID: {FATSECRET_CLIENT_ID}")
if FATSECRET_CLIENT_SECRET:
print(f"🔑 CLIENT_SECRET (first few chars): {FATSECRET_CLIENT_SECRET[:5]}...")
else:
print("⚠️ CLIENT_SECRET is missing!")
print(f"🔑 Authorization header: Basic {auth_header}")
# Выполняем запрос на получение токена
token_url = "https://oauth.fatsecret.com/connect/token"
headers = {
"Authorization": f"Basic {auth_header}",
"Content-Type": "application/x-www-form-urlencoded"
}
data = {
"grant_type": "client_credentials",
"scope": "basic"
}
print("📤 Sending request with headers:")
for key, value in headers.items():
print(f" {key}: {value if key != 'Authorization' else value[:30]}...")
print("📤 Sending request with data:")
for key, value in data.items():
print(f" {key}: {value}")
try:
response = requests.post(token_url, headers=headers, data=data)
# Дополнительная информация о запросе
print(f"📥 Response status code: {response.status_code}")
print(f"📥 Response headers: {dict(response.headers)}")
# Проверяем успешность запроса
if response.status_code == 200:
token_data = response.json()
access_token = token_data.get("access_token")
expires_in = token_data.get("expires_in")
print(f"✅ Got token, expires in {expires_in} seconds")
return access_token
else:
print(f"❌ Error getting token: {response.status_code}")
print(f"❌ Error response: {response.text}")
return None
except Exception as e:
print(f"❌ Exception getting token: {e}")
return None
def search_food(token, query, max_results=5):
"""Поиск продуктов по названию"""
if not token:
print("⚠️ No token available, cannot search")
return None
print(f"🔍 Searching for '{query}'...")
api_url = "https://platform.fatsecret.com/rest/server.api"
headers = {
"Authorization": f"Bearer {token}",
"Content-Type": "application/json"
}
params = {
"method": "foods.search",
"search_expression": query,
"max_results": max_results,
"format": "json"
}
try:
response = requests.post(api_url, headers=headers, json=params)
if response.status_code == 200:
print(f"✅ Search successful")
result = response.json()
return result
else:
print(f"❌ Error searching: {response.status_code}")
print(response.text)
return None
except Exception as e:
print(f"❌ Exception during search: {e}")
return None
def get_food_details(token, food_id):
"""Получение информации о продукте по ID"""
if not token:
print("⚠️ No token available, cannot get food details")
return None
print(f"🔍 Getting details for food ID: {food_id}")
api_url = "https://platform.fatsecret.com/rest/server.api"
headers = {
"Authorization": f"Bearer {token}",
"Content-Type": "application/json"
}
params = {
"method": "food.get",
"food_id": food_id,
"format": "json"
}
try:
response = requests.post(api_url, headers=headers, json=params)
if response.status_code == 200:
print(f"✅ Got food details")
result = response.json()
return result
else:
print(f"❌ Error getting food details: {response.status_code}")
print(response.text)
return None
except Exception as e:
print(f"❌ Exception getting food details: {e}")
return None
def main():
"""Основная функция для тестирования API FatSecret"""
print("\n🚀 Starting FatSecret API test...\n")
# Получаем токен доступа
token = get_oauth_token()
if not token:
print("❌ Failed to get OAuth token, exiting")
return
# Тестируем поиск продуктов
print("\n--- 📋 Testing Food Search ---")
search_queries = ["apple", "bread", "chicken breast", "молоко"]
first_food_id = None
for query in search_queries:
result = search_food(token, query)
if result and "foods" in result:
foods_data = result["foods"]
if "food" not in foods_data:
print(f"⚠️ No results found for '{query}'")
continue
food_list = foods_data["food"]
if not isinstance(food_list, list):
food_list = [food_list] # Если только один результат, оборачиваем в список
print(f"📊 Found {len(food_list)} results")
# Выводим первые 3 результата
for i, food in enumerate(food_list[:3]):
food_name = food.get("food_name", "Unknown")
food_id = food.get("food_id", "Unknown")
food_desc = food.get("food_description", "No description")
print(f" {i+1}. [{food_id}] {food_name}")
print(f" {food_desc}")
# Сохраняем ID первого продукта для следующего теста
if not first_food_id and food_list:
first_food_id = food_list[0].get("food_id")
# Тестируем получение информации о продукте
if first_food_id:
print("\n--- 🍎 Testing Food Details ---")
food_details = get_food_details(token, first_food_id)
if food_details and "food" in food_details:
food = food_details["food"]
food_name = food.get("food_name", "Unknown")
brand = food.get("brand_name", "Generic")
print(f"📝 Details for: {food_name} [{brand}]")
# Выводим информацию о пищевой ценности
if "servings" in food:
servings = food["servings"]
if "serving" in servings:
serving_data = servings["serving"]
if not isinstance(serving_data, list):
serving_data = [serving_data]
print("\n📊 Nutrition info per serving:")
for i, serving in enumerate(serving_data[:2]): # Выводим до 2 видов порций
serving_desc = serving.get("serving_description", "Standard")
calories = serving.get("calories", "N/A")
protein = serving.get("protein", "N/A")
carbs = serving.get("carbohydrate", "N/A")
fat = serving.get("fat", "N/A")
print(f" Serving {i+1}: {serving_desc}")
print(f" Calories: {calories}")
print(f" Protein: {protein}g")
print(f" Carbohydrates: {carbs}g")
print(f" Fat: {fat}g")
print("\n✅ Test completed!")
if __name__ == "__main__":
main()