#!/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()