get-your-recipes / api /edamam_api.py
Dieu-Sang's picture
add meal type
591adee
import requests
import json
import os
from dataclasses import dataclass
from typing import List
READ_KEY_FROM_FILE = True
def read_json_to_dict(file_path) -> dict:
try:
with open(file_path, 'r') as file:
data = json.load(file)
return data
except FileNotFoundError:
print("File not found at the specified path.")
return {}
except json.JSONDecodeError:
print("Error decoding JSON file.")
return {}
DietChoices = [
None,
"balanced",
"high-fiber",
"high-protein",
"low-carb",
"low-fat",
"low-sodium"]
HealthChoices = [
None,
"alcohol-cocktail",
"alcohol-free",
"celery-free",
"crustacean-free",
"dairy-free",
"DASH",
"egg-free",
"fish-free",
"fodmap-free",
"gluten-free",
"immuno-supportive",
"keto-friendly",
"kidney-friendly",
"kosher",
"low-fat-abs",
"low-potassium",
"low-sugar",
"lupine-free",
"Mediterranean",
"mollusk-free",
"mustard-free",
"no-oil-added",
"paleo",
"peanut-free",
"pescatarian",
"pork-free",
"red-meat-free",
"sesame-free",
"shellfish-free",
"soy-free",
"sugar-conscious",
"sulfite-free",
"tree-nut-free",
"vegan",
"vegetarian",
"wheat-free"]
CuisineTypeChoices = [
None,
"American",
"Asian",
"British",
"Caribbean",
"Central Europe",
"Chinese",
"Eastern Europe",
"French",
"Indian",
"Italian",
"Japanese",
"Kosher",
"Mediterranean",
"Mexican",
"Middle Eastern",
"Nordic",
"South American",
"South East Asian"]
MealTypeChoices = [
None,
"Breakfast",
"Dinner",
"Lunch",
"Snack",
"Teatime"]
ParamQueryString = [
{"param": 'calories', "param_query_string": 'calories'},
{"param": 'protein', "param_query_string": 'nutrients[PROCNT]'},
{"param": 'carbs', "param_query_string": 'nutrients[CHOCDF.net]'},
{"param": 'fat', "param_query_string": 'nutrients[FAT]'},
{"param": 'added_sugar', "param_query_string": 'nutrients[SUGAR.added]'},
{"param": 'sodium', "param_query_string": 'nutrients[NA]'},
{"param": 'saturated_fat', "param_query_string": 'nutrients[FASAT]'},
{"param": 'fiber', "param_query_string": 'nutrients[FIBTG]'},
]
@dataclass
class Recipe:
name: str
cuisine_type: list
calories: int
protein_g: int
carbs_g: int
fat_g: int
servings: int
ingredients: list
edamam_url: str
source_url: str
def get_param_query_string(param, param_query_string_list) -> str:
for item in param_query_string_list:
if item['param'] == param:
return item['param_query_string']
return ""
def update_params(params, param_to_update, min_val, max_val):
param_query_string = get_param_query_string(param_to_update, ParamQueryString)
if not bool(param_query_string):
print("Error: could not update params")
return
if min_val!=None and max_val==None:
params.update({param_query_string: f"{str(min_val)}+"})
if min_val==None and max_val!=None:
params.update({param_query_string: f"{str(max_val)}"})
if min_val!=None and max_val!=None:
params.update({param_query_string: f"{str(min_val)}-{str(max_val)}"})
def get_recipes(
edamam_app_id: str,
edamam_app_key: str,
calories_min: float | None = None,
calories_max: float | None = None,
protein_min_g: float | None = None,
protein_max_g: float | None = None,
carbs_min_g: float | None = None,
carbs_max_g: float | None = None,
fat_min_g: float | None = None,
fat_max_g: float | None = None,
included: str | None = None,
excluded: List[str] | None = None,
added_sugar_min_g: float | None = None,
added_sugar_max_g: float | None = None,
sodium_min_mg: float | None = None,
sodium_max_mg: float | None = None,
saturated_fat_min_g: float | None = None,
saturated_fat_max_g: float | None = None,
fiber_min_g: float | None = None,
fiber_max_g: float | None = None,
cuisine_type: List[str] | None = None,
meal_type: List[str] | None = None,
diet: List[str] | None = None,
health: List[str] | None = None,
nb_recipes: int = 1,
) -> list:
if not edamam_app_id or not edamam_app_key:
return []
params = {
'type': 'any',
'app_id': edamam_app_id,
'app_key': edamam_app_key,
'calories': f"{str(calories_min)}-{str(calories_max)}",
'q': included,
'excluded': excluded,
'diet': diet,
'health': health,
'cuisineType': cuisine_type,
'mealType': meal_type,
}
update_params(params, 'calories', calories_min, calories_max)
update_params(params, 'protein', protein_min_g, protein_max_g)
update_params(params, 'carbs', carbs_min_g, carbs_max_g)
update_params(params, 'fat', fat_min_g, fat_max_g)
update_params(params, 'added_sugar', added_sugar_min_g, added_sugar_max_g)
update_params(params, 'sodium', sodium_min_mg, sodium_max_mg)
update_params(params, 'saturated_fat', saturated_fat_min_g, saturated_fat_max_g)
update_params(params, 'fiber', fiber_min_g, fiber_max_g)
"""Get raw recipes from edamam"""
response = requests.get(url='https://api.edamam.com/api/recipes/v2', params=params)
"""Convert to list of Recipe objects"""
recipes = []
if response.status_code == 200:
results = response.json()['hits']
if results:
for item in results:
if (len(recipes) < nb_recipes):
recipe = item['recipe']
servings = int(recipe['yield'])
recipes.append(
Recipe(
name=recipe['label'],
cuisine_type=recipe['cuisineType'],
calories=round(recipe['totalNutrients']['ENERC_KCAL']['quantity']/servings),
protein_g=round(recipe['totalNutrients']['PROCNT']['quantity']/servings),
carbs_g=round(recipe['totalNutrients']['CHOCDF']['quantity']/servings),
fat_g=round(recipe['totalNutrients']['FAT']['quantity']/servings),
servings=servings,
ingredients=recipe['ingredientLines'],
edamam_url=recipe['shareAs'],
source_url=recipe['url'],
)
)
else:
break
return recipes
else:
return []
else:
print(f"Error {response.status_code}: {response.text}")
return []
"""Print Recipe object information to string"""
def print2string_recipe(recipe: Recipe) -> str:
string = f""
if recipe:
string += f"********\n"
string += f"Recipe: {recipe.name}\n"
string += f"Calories: {recipe.calories}kcal\n"
string += f"Protein: {recipe.protein_g}g\n"
string += f"Carbs: {recipe.carbs_g}g\n"
string += f"Fat: {recipe.fat_g}g\n"
string += f"Ingredients for {recipe.servings} servings:\n"
for ingredient in recipe.ingredients:
string += f"- {ingredient}\n"
string += f"URL: {recipe.edamam_url}\n"
else:
string += "No recipe found\n"
return string
if __name__ == "__main__":
if READ_KEY_FROM_FILE:
CURRENT_DIR = os.path.dirname(os.path.realpath(__file__))
edamam_app_id = read_json_to_dict(file_path=f"{CURRENT_DIR}/api_key.json")['edamam_app_id']
edamam_app_key = read_json_to_dict(file_path=f"{CURRENT_DIR}/api_key.json")['edamam_app_key']
else:
edamam_app_id = input('Enter your edamam app id: ')
edamam_app_key = input('Enter your edamam app key: ')
"""Compute macronutrients in grams from percent"""
calories = 700
protein_min_percent = 10
protein_max_percent = 35
carbs_min_percent = 45
carbs_max_percent = 65
fat_min_percent = 10
fat_max_percent = 25
calories_div_100_div_4 = calories / 100.0 / 4.0
calories_div_100_div_9 = calories / 100.0 / 9.0
protein_min_g = round(protein_min_percent * calories_div_100_div_4)
protein_max_g = round(protein_max_percent * calories_div_100_div_4)
carbs_min_g = round(carbs_min_percent * calories_div_100_div_4)
carbs_max_g = round(carbs_max_percent * calories_div_100_div_4)
fat_min_g = round(fat_min_percent * calories_div_100_div_9)
fat_max_g = round(fat_max_percent * calories_div_100_div_9)
recipes = get_recipes(
edamam_app_id=edamam_app_id,
edamam_app_key=edamam_app_key,
calories_min=None,
calories_max=calories,
protein_min_g=protein_min_g,
protein_max_g=protein_max_g,
carbs_min_g=carbs_min_g,
carbs_max_g=carbs_max_g,
fat_min_g=fat_min_g,
fat_max_g=fat_max_g,
included="chicken",
excluded=["sesame"],
nb_recipes=5)
for recipe in recipes:
print()
print(print2string_recipe(recipe))