1
0
Fork 0
mirror of https://github.com/mealie-recipes/mealie.git synced 2025-08-06 05:55:23 +02:00

api documentation

This commit is contained in:
Hayden 2021-01-07 19:54:49 -09:00
parent 53b4717810
commit 36db9f2e86
8 changed files with 175 additions and 41 deletions

View file

@ -1,4 +1,3 @@
# from datetime import datetime
from typing import List, Optional from typing import List, Optional
from pydantic import BaseModel from pydantic import BaseModel

View file

@ -0,0 +1,12 @@
from pydantic.main import BaseModel
class ChowdownURL(BaseModel):
url: str
class Config:
schema_extra = {
"example": {
"url": "https://chowdownrepo.com/repo",
}
}

View file

@ -0,0 +1,56 @@
from typing import List, Optional
import pydantic
from pydantic.main import BaseModel
class RecipeResponse(BaseModel):
class Config:
schema_extra = {
"example": [
{
"slug": "crockpot-buffalo-chicken",
"image": "crockpot-buffalo-chicken.jpg",
"name": "Crockpot Buffalo Chicken",
},
{
"slug": "downtown-marinade",
"image": "downtown-marinade.jpg",
"name": "Downtown Marinade",
},
{
"slug": "detroit-style-pepperoni-pizza",
"image": "detroit-style-pepperoni-pizza.jpg",
"name": "Detroit-Style Pepperoni Pizza",
},
{
"slug": "crispy-carrots",
"image": "crispy-carrots.jpg",
"name": "Crispy Carrots",
},
]
}
class AllRecipeRequest(BaseModel):
properties: List[str]
limit: Optional[int]
class Config:
schema_extra = {
"example": {
"properties": ["name", "slug", "image"],
"limit": 100,
}
}
class RecipeURLIn(BaseModel):
class Config:
schema_extra = {"example": {"url": "https://myfavoriterecipes.com/recipes"}}
class SlugResponse(BaseModel):
class Config:
schema_extra = {
"example": "adult-mac-and-cheese"
}

View file

@ -1,22 +1,23 @@
from pprint import pprint from typing import List
from fastapi import APIRouter, HTTPException from fastapi import APIRouter, HTTPException
from models.recipe_models import SlugResponse
from services.meal_services import MealPlan from services.meal_services import MealPlan
from utils.snackbar import SnackResponse from utils.snackbar import SnackResponse
router = APIRouter() router = APIRouter()
@router.get("/api/meal-plan/all/", tags=["Meal Plan"]) @router.get("/api/meal-plan/all/", tags=["Meal Plan"], response_model=List[MealPlan])
async def get_all_meals(): async def get_all_meals():
""" Returns a list of all available meal plans """ """ Returns a list of all available Meal Plan """
return MealPlan.get_all() return MealPlan.get_all()
@router.post("/api/meal-plan/create/", tags=["Meal Plan"]) @router.post("/api/meal-plan/create/", tags=["Meal Plan"])
async def set_meal_plan(data: MealPlan): async def set_meal_plan(data: MealPlan):
""" Creates a mealplan database entry""" """ Creates a meal plan database entry """
data.process_meals() data.process_meals()
data.save_to_db() data.save_to_db()
@ -30,7 +31,7 @@ async def set_meal_plan(data: MealPlan):
@router.post("/api/meal-plan/{plan_id}/update/", tags=["Meal Plan"]) @router.post("/api/meal-plan/{plan_id}/update/", tags=["Meal Plan"])
async def update_meal_plan(plan_id: str, meal_plan: MealPlan): async def update_meal_plan(plan_id: str, meal_plan: MealPlan):
""" Updates a Meal Plan Based off ID """ """ Updates a meal plan based off ID """
try: try:
meal_plan.process_meals() meal_plan.process_meals()
@ -46,21 +47,24 @@ async def update_meal_plan(plan_id: str, meal_plan: MealPlan):
@router.delete("/api/meal-plan/{plan_id}/delete/", tags=["Meal Plan"]) @router.delete("/api/meal-plan/{plan_id}/delete/", tags=["Meal Plan"])
async def delete_meal_plan(plan_id): async def delete_meal_plan(plan_id):
""" Doc Str """ """ Removes a meal plan from the database """
MealPlan.delete(plan_id) MealPlan.delete(plan_id)
return SnackResponse.success("Mealplan Deleted") return SnackResponse.success("Mealplan Deleted")
@router.get("/api/meal-plan/today/", tags=["Meal Plan"]) @router.get("/api/meal-plan/today/", tags=["Meal Plan"], response_model=SlugResponse)
async def get_today(): async def get_today():
""" Returns the meal plan data for today """ """
Returns the recipe slug for the meal scheduled for today.
If no meal is scheduled nothing is returned
"""
return MealPlan.today() return MealPlan.today()
@router.get("/api/meal-plan/this-week/", tags=["Meal Plan"]) @router.get("/api/meal-plan/this-week/", tags=["Meal Plan"], response_model=MealPlan)
async def get_this_week(): async def get_this_week():
""" Returns the meal plan data for this week """ """ Returns the meal plan data for this week """

View file

@ -1,5 +1,6 @@
from fastapi import APIRouter, HTTPException from fastapi import APIRouter, HTTPException
from models.backup_models import BackupJob from models.backup_models import BackupJob
from models.migration_models import ChowdownURL
from services.migrations.chowdown import chowdown_migrate as chowdow_migrate from services.migrations.chowdown import chowdown_migrate as chowdow_migrate
from utils.snackbar import SnackResponse from utils.snackbar import SnackResponse
@ -7,10 +8,10 @@ router = APIRouter()
@router.post("/api/migration/chowdown/repo/", tags=["Migration"]) @router.post("/api/migration/chowdown/repo/", tags=["Migration"])
async def import_chowdown_recipes(repo: dict): async def import_chowdown_recipes(repo: ChowdownURL):
""" Import Chowsdown Recipes from Repo URL """ """ Import Chowsdown Recipes from Repo URL """
try: try:
report = chowdow_migrate(repo.get("url")) report = chowdow_migrate(repo.url)
return SnackResponse.success( return SnackResponse.success(
"Recipes Imported from Git Repo, see report for failures.", "Recipes Imported from Git Repo, see report for failures.",
additional_data=report, additional_data=report,

View file

@ -2,6 +2,12 @@ from typing import List, Optional
from fastapi import APIRouter, File, Form, HTTPException, Query from fastapi import APIRouter, File, Form, HTTPException, Query
from fastapi.responses import FileResponse from fastapi.responses import FileResponse
from models.recipe_models import (
AllRecipeRequest,
RecipeResponse,
RecipeURLIn,
SlugResponse,
)
from services.image_services import read_image, write_image from services.image_services import read_image, write_image
from services.recipe_services import Recipe, read_requested_values from services.recipe_services import Recipe, read_requested_values
from services.scrape_services import create_from_url from services.scrape_services import create_from_url
@ -10,17 +16,42 @@ from utils.snackbar import SnackResponse
router = APIRouter() router = APIRouter()
@router.get("/api/all-recipes/", tags=["Recipes"]) @router.get("/api/all-recipes/", tags=["Recipes"], response_model=RecipeResponse)
async def get_all_recipes( async def get_all_recipes(
keys: Optional[List[str]] = Query(...), num: Optional[int] = 100 keys: Optional[List[str]] = Query(...), num: Optional[int] = 100
) -> Optional[List[str]]: ):
""" Returns key data for all recipes """ """
Returns key data for all recipes based off the query paramters provided.
For example, if slug, image, and name are provided you will recieve a list of
recipes containing the slug, image, and name property. By default, responses
are limited to 100.
**Note:** You may experience problems with with query parameters. As an alternative
you may also use the post method and provide a body.
See the *Post* method for more details.
"""
all_recipes = read_requested_values(keys, num) all_recipes = read_requested_values(keys, num)
return all_recipes return all_recipes
@router.get("/api/recipe/{recipe_slug}/", tags=["Recipes"]) @router.post("/api/all-recipes/", tags=["Recipes"], response_model=RecipeResponse)
async def get_all_recipes_post(body: AllRecipeRequest):
"""
Returns key data for all recipes based off the body data provided.
For example, if slug, image, and name are provided you will recieve a list of
recipes containing the slug, image, and name property.
Refer to the body example for data formats.
"""
all_recipes = read_requested_values(body.properties, body.limit)
return all_recipes
@router.get("/api/recipe/{recipe_slug}/", tags=["Recipes"], response_model=Recipe)
async def get_recipe(recipe_slug: str): async def get_recipe(recipe_slug: str):
""" Takes in a recipe slug, returns all data for a recipe """ """ Takes in a recipe slug, returns all data for a recipe """
recipe = Recipe.get_by_slug(recipe_slug) recipe = Recipe.get_by_slug(recipe_slug)
@ -37,24 +68,21 @@ async def get_recipe_img(recipe_slug: str):
# Recipe Creations # Recipe Creations
@router.post("/api/recipe/create-url/", tags=["Recipes"], status_code=201) @router.post(
async def get_recipe_url(url: dict): "/api/recipe/create-url/",
""" Takes in a URL and Attempts to scrape data and load it into the database """ tags=["Recipes"],
status_code=201,
response_model=SlugResponse,
)
async def parse_recipe_url(url: RecipeURLIn):
""" Takes in a URL and attempts to scrape data and load it into the database """
url = url.get("url") slug = create_from_url(url.url)
slug = create_from_url(url)
# try:
# slug = create_from_url(url)
# except:
# raise HTTPException(
# status_code=400, detail=SnackResponse.error("Unable to Parse URL")
# )
return slug return slug
@router.post("/api/recipe/create/", tags=["Recipes"]) @router.post("/api/recipe/create/", tags=["Recipes"], response_model=SlugResponse)
async def create_from_json(data: Recipe) -> str: async def create_from_json(data: Recipe) -> str:
""" Takes in a JSON string and loads data into the database as a new entry""" """ Takes in a JSON string and loads data into the database as a new entry"""
created_recipe = data.save_to_db() created_recipe = data.save_to_db()
@ -63,7 +91,7 @@ async def create_from_json(data: Recipe) -> str:
@router.post("/api/recipe/{recipe_slug}/update/image/", tags=["Recipes"]) @router.post("/api/recipe/{recipe_slug}/update/image/", tags=["Recipes"])
def update_image( def update_recipe_image(
recipe_slug: str, image: bytes = File(...), extension: str = Form(...) recipe_slug: str, image: bytes = File(...), extension: str = Form(...)
): ):
""" Removes an existing image and replaces it with the incoming file. """ """ Removes an existing image and replaces it with the incoming file. """
@ -73,7 +101,7 @@ def update_image(
@router.post("/api/recipe/{recipe_slug}/update/", tags=["Recipes"]) @router.post("/api/recipe/{recipe_slug}/update/", tags=["Recipes"])
async def update(recipe_slug: str, data: Recipe): async def update_recipe(recipe_slug: str, data: Recipe):
""" Updates a recipe by existing slug and data. Data should containt """ """ Updates a recipe by existing slug and data. Data should containt """
data.update(recipe_slug) data.update(recipe_slug)
@ -82,7 +110,7 @@ async def update(recipe_slug: str, data: Recipe):
@router.delete("/api/recipe/{recipe_slug}/delete/", tags=["Recipes"]) @router.delete("/api/recipe/{recipe_slug}/delete/", tags=["Recipes"])
async def delete(recipe_slug: str): async def delete_recipe(recipe_slug: str):
""" Deletes a recipe by slug """ """ Deletes a recipe by slug """
try: try:

View file

@ -1,3 +1,5 @@
from typing import List
from db.mongo_setup import global_init from db.mongo_setup import global_init
from fastapi import APIRouter, HTTPException from fastapi import APIRouter, HTTPException
from services.scheduler_services import Scheduler, post_webhooks from services.scheduler_services import Scheduler, post_webhooks
@ -11,16 +13,16 @@ scheduler = Scheduler()
scheduler.startup_scheduler() scheduler.startup_scheduler()
@router.get("/api/site-settings/", tags=["Settings"]) @router.get("/api/site-settings/", tags=["Settings"], response_model=SiteSettings)
async def get_main_settings(): async def get_main_settings():
""" Returns basic site Settings """ """ Returns basic site settings """
return SiteSettings.get_site_settings() return SiteSettings.get_site_settings()
@router.post("/api/site-settings/webhooks/test/", tags=["Settings"]) @router.post("/api/site-settings/webhooks/test/", tags=["Settings"])
async def test_webhooks(): async def test_webhooks():
""" Test Webhooks """ """ Run the function to test your webhooks """
return post_webhooks() return post_webhooks()
@ -40,22 +42,26 @@ async def update_settings(data: SiteSettings):
return SnackResponse.success("Settings Updated") return SnackResponse.success("Settings Updated")
@router.get("/api/site-settings/themes/", tags=["Themes"]) @router.get(
"/api/site-settings/themes/", tags=["Themes"], response_model=List[SiteTheme]
)
async def get_all_themes(): async def get_all_themes():
""" Returns all site themes """ """ Returns all site themes """
return SiteTheme.get_all() return SiteTheme.get_all()
@router.get("/api/site-settings/themes/{theme_name}/", tags=["Themes"]) @router.get(
"/api/site-settings/themes/{theme_name}/", tags=["Themes"], response_model=SiteTheme
)
async def get_single_theme(theme_name: str): async def get_single_theme(theme_name: str):
""" Returns basic site Settings """ """ Returns a named theme """
return SiteTheme.get_by_name(theme_name) return SiteTheme.get_by_name(theme_name)
@router.post("/api/site-settings/themes/create/", tags=["Themes"]) @router.post("/api/site-settings/themes/create/", tags=["Themes"])
async def create_theme(data: SiteTheme): async def create_theme(data: SiteTheme):
""" Creates a Site Color Theme """ """ Creates a site color theme database entry """
try: try:
data.save_to_db() data.save_to_db()
@ -69,7 +75,7 @@ async def create_theme(data: SiteTheme):
@router.post("/api/site-settings/themes/{theme_name}/update/", tags=["Themes"]) @router.post("/api/site-settings/themes/{theme_name}/update/", tags=["Themes"])
async def update_theme(theme_name: str, data: SiteTheme): async def update_theme(theme_name: str, data: SiteTheme):
""" Returns basic site Settings """ """ Update a theme database entry """
try: try:
data.update_document() data.update_document()
except: except:
@ -82,7 +88,7 @@ async def update_theme(theme_name: str, data: SiteTheme):
@router.delete("/api/site-settings/themes/{theme_name}/delete/", tags=["Themes"]) @router.delete("/api/site-settings/themes/{theme_name}/delete/", tags=["Themes"])
async def delete_theme(theme_name: str): async def delete_theme(theme_name: str):
""" Returns basic site Settings """ """ Deletes theme from the database """
try: try:
SiteTheme.delete_theme(theme_name) SiteTheme.delete_theme(theme_name)
except: except:

View file

@ -24,6 +24,18 @@ class SiteSettings(BaseModel):
name: str = "main" name: str = "main"
webhooks: Webhooks webhooks: Webhooks
class Config:
schema_extra = {
"example": {
"name": "main",
"webhooks": {
"webhookTime": "00:00",
"webhookURLs": ["https://mywebhookurl.com/webhook"],
"enable": False,
},
}
}
@staticmethod @staticmethod
def _unpack_doc(document: SiteSettingsDocument): def _unpack_doc(document: SiteSettingsDocument):
document = json.loads(document.to_json()) document = json.loads(document.to_json())
@ -65,6 +77,22 @@ class SiteTheme(BaseModel):
name: str name: str
colors: Colors colors: Colors
class Config:
schema_extra = {
"example": {
"name": "default",
"colors": {
"primary": "#E58325",
"accent": "#00457A",
"secondary": "#973542",
"success": "#5AB1BB",
"info": "#4990BA",
"warning": "#FF4081",
"error": "#EF5350",
},
}
}
@staticmethod @staticmethod
def get_by_name(theme_name): def get_by_name(theme_name):
document = SiteThemeDocument.objects.get(name=theme_name) document = SiteThemeDocument.objects.get(name=theme_name)