theme + settings refactor

This commit is contained in:
hay-kot 2021-02-09 22:17:11 -09:00
commit 866e7de498
19 changed files with 236 additions and 262 deletions

View file

@ -12,7 +12,6 @@ from routes import (
setting_routes, setting_routes,
static_routes, static_routes,
theme_routes, theme_routes,
user_routes,
) )
from routes.recipe import ( from routes.recipe import (
all_recipe_routes, all_recipe_routes,
@ -22,18 +21,6 @@ from routes.recipe import (
) )
from utils.logger import logger from utils.logger import logger
"""
TODO:
- [x] Fix Duplicate Category
- [x] Fix category overflow
- [ ] Enable Database Name Versioning
- [ ] Finish Frontend Category Management
- [x] Delete Category
- [ ] Sort Sidebar A-Z
- [ ] Refactor Test Endpoints - Abstract to fixture?
"""
app = FastAPI( app = FastAPI(
title="Mealie", title="Mealie",
description="A place for all your recipes", description="A place for all your recipes",
@ -51,6 +38,10 @@ def start_scheduler():
import services.scheduler.scheduled_jobs import services.scheduler.scheduled_jobs
def init_settings():
import services.theme_services
def api_routers(): def api_routers():
# Recipes # Recipes
app.include_router(all_recipe_routes.router) app.include_router(all_recipe_routes.router)
@ -64,8 +55,6 @@ def api_routers():
app.include_router(theme_routes.router) app.include_router(theme_routes.router)
# Backups/Imports Routes # Backups/Imports Routes
app.include_router(backup_routes.router) app.include_router(backup_routes.router)
# User Routes
app.include_router(user_routes.router)
# Migration Routes # Migration Routes
app.include_router(migration_routes.router) app.include_router(migration_routes.router)
app.include_router(debug_routes.router) app.include_router(debug_routes.router)
@ -90,6 +79,7 @@ app.include_router(static_routes.router)
# generate_api_docs(app) # generate_api_docs(app)
start_scheduler() start_scheduler()
init_settings()
if __name__ == "__main__": if __name__ == "__main__":
logger.info("-----SYSTEM STARTUP-----") logger.info("-----SYSTEM STARTUP-----")

View file

@ -9,7 +9,6 @@ from db.sql.theme_models import SiteThemeModel
""" """
# TODO # TODO
- [ ] Abstract Classes to use save_new, and update from base models - [ ] Abstract Classes to use save_new, and update from base models
- [x] Create Category and Tags Table with Many to Many relationship
""" """
@ -49,7 +48,7 @@ class _Settings(BaseDocument):
self.primary_key = "name" self.primary_key = "name"
self.sql_model = SiteSettingsModel self.sql_model = SiteSettingsModel
def save_new(self, session: Session, main: dict, webhooks: dict) -> str: def create(self, session: Session, main: dict, webhooks: dict) -> str:
new_settings = self.sql_model(main.get("name"), webhooks) new_settings = self.sql_model(main.get("name"), webhooks)
session.add(new_settings) session.add(new_settings)

View file

@ -106,7 +106,7 @@ class BaseDocument:
return db_entry return db_entry
def save_new(self, session: Session, document: dict) -> dict: def create(self, session: Session, document: dict) -> dict:
"""Creates a new database entry for the given SQL Alchemy Model. """Creates a new database entry for the given SQL Alchemy Model.
Args: \n Args: \n

View file

@ -0,0 +1,38 @@
from datetime import date
from typing import List, Optional
from pydantic import BaseModel
class Meal(BaseModel):
slug: Optional[str]
name: Optional[str]
date: date
dateText: str
image: Optional[str]
description: Optional[str]
class MealData(BaseModel):
name: Optional[str]
slug: str
dateText: str
class MealPlan(BaseModel):
uid: Optional[str]
startDate: date
endDate: date
meals: List[Meal]
class Config:
schema_extra = {
"example": {
"startDate": date.today(),
"endDate": date.today(),
"meals": [
{"slug": "Packed Mac and Cheese", "date": date.today()},
{"slug": "Eggs and Toast", "date": date.today()},
],
}
}

View file

@ -1,38 +1,79 @@
from typing import List, Optional import datetime
from pydantic.main import BaseModel from typing import Any, List, Optional
from pydantic import BaseModel, validator
from slugify import slugify
class RecipeNote(BaseModel):
title: str
text: str
class RecipeStep(BaseModel):
text: str
class AllRecipeResponse(BaseModel):
class Recipe(BaseModel):
# Standard Schema
name: str
description: Optional[str]
image: Optional[Any]
recipeYield: Optional[str]
recipeIngredient: Optional[list]
recipeInstructions: Optional[list]
totalTime: Optional[str] = None
prepTime: Optional[str] = None
performTime: Optional[str] = None
# Mealie Specific
slug: Optional[str] = ""
categories: Optional[List[str]] = []
tags: Optional[List[str]] = []
dateAdded: Optional[datetime.date]
notes: Optional[List[RecipeNote]] = []
rating: Optional[int]
orgURL: Optional[str]
extras: Optional[dict] = {}
class Config: class Config:
schema_extra = { schema_extra = {
"example": [ "example": {
"name": "Chicken and Rice With Leeks and Salsa Verde",
"description": "This one-skillet dinner gets deep oniony flavor from lots of leeks cooked down to jammy tenderness.",
"image": "chicken-and-rice-with-leeks-and-salsa-verde.jpg",
"recipeYield": "4 Servings",
"recipeIngredient": [
"1 1/2 lb. skinless, boneless chicken thighs (4-8 depending on size)",
"Kosher salt, freshly ground pepper",
"3 Tbsp. unsalted butter, divided",
],
"recipeInstructions": [
{ {
"slug": "crockpot-buffalo-chicken", "text": "Season chicken with salt and pepper.",
"image": "crockpot-buffalo-chicken.jpg",
"name": "Crockpot Buffalo Chicken",
}, },
{ ],
"slug": "downtown-marinade", "slug": "chicken-and-rice-with-leeks-and-salsa-verde",
"image": "downtown-marinade.jpg", "tags": ["favorite", "yummy!"],
"name": "Downtown Marinade", "categories": ["Dinner", "Pasta"],
}, "notes": [{"title": "Watch Out!", "text": "Prep the day before!"}],
{ "orgURL": "https://www.bonappetit.com/recipe/chicken-and-rice-with-leeks-and-salsa-verde",
"slug": "detroit-style-pepperoni-pizza", "rating": 3,
"image": "detroit-style-pepperoni-pizza.jpg", "extras": {"message": "Don't forget to defrost the chicken!"},
"name": "Detroit-Style Pepperoni Pizza",
},
{
"slug": "crispy-carrots",
"image": "crispy-carrots.jpg",
"name": "Crispy Carrots",
},
]
} }
}
@validator("slug", always=True, pre=True)
def validate_slug(slug: str, values):
name: str = values["name"]
calc_slug: str = slugify(name)
if slug == calc_slug:
return slug
else:
slug = calc_slug
return slug
class AllRecipeRequest(BaseModel): class AllRecipeRequest(BaseModel):

View file

@ -0,0 +1,26 @@
from typing import List, Optional
from pydantic import BaseModel
class Webhooks(BaseModel):
webhookTime: str = "00:00"
webhookURLs: Optional[List[str]] = []
enabled: bool = False
class SiteSettings(BaseModel):
name: str = "main"
webhooks: Webhooks
class Config:
schema_extra = {
"example": {
"name": "main",
"webhooks": {
"webhookTime": "00:00",
"webhookURLs": ["https://mywebhookurl.com/webhook"],
"enable": False,
},
}
}

View file

@ -0,0 +1,31 @@
from pydantic import BaseModel
class Colors(BaseModel):
primary: str
accent: str
secondary: str
success: str
info: str
warning: str
error: str
class SiteTheme(BaseModel):
name: str
colors: Colors
class Config:
schema_extra = {
"example": {
"name": "default",
"colors": {
"primary": "#E58325",
"accent": "#00457A",
"secondary": "#973542",
"success": "#5AB1BB",
"info": "#4990BA",
"warning": "#FF4081",
"error": "#EF5350",
},
}
}

View file

@ -1,10 +0,0 @@
from typing import Optional
from pydantic import BaseModel
class User(BaseModel):
username: str
email: Optional[str] = None
full_name: Optional[str] = None
disabled: Optional[bool] = None

View file

@ -1,6 +1,7 @@
from db.database import db
from db.db_setup import generate_session from db.db_setup import generate_session
from fastapi import APIRouter, Depends from fastapi import APIRouter, Depends
from services.settings_services import SiteSettings from models.settings_models import SiteSettings
from sqlalchemy.orm.session import Session from sqlalchemy.orm.session import Session
from utils.post_webhooks import post_webhooks from utils.post_webhooks import post_webhooks
from utils.snackbar import SnackResponse from utils.snackbar import SnackResponse
@ -12,7 +13,7 @@ router = APIRouter(prefix="/api/site-settings", tags=["Settings"])
def get_main_settings(session: Session = Depends(generate_session)): def get_main_settings(session: Session = Depends(generate_session)):
""" Returns basic site settings """ """ Returns basic site settings """
return SiteSettings.get_site_settings(session) return db.settings.get(session, "main")
@router.post("/webhooks/test") @router.post("/webhooks/test")
@ -25,6 +26,6 @@ def test_webhooks():
@router.put("") @router.put("")
def update_settings(data: SiteSettings, session: Session = Depends(generate_session)): def update_settings(data: SiteSettings, session: Session = Depends(generate_session)):
""" Returns Site Settings """ """ Returns Site Settings """
data.update(session) db.settings.update(session, "main", data.dict())
return SnackResponse.success("Settings Updated") return SnackResponse.success("Settings Updated")

View file

@ -1,8 +1,9 @@
from db.db_setup import generate_session from db.db_setup import generate_session
from fastapi import APIRouter, Depends from fastapi import APIRouter, Depends
from services.settings_services import SiteTheme from models.theme_models import SiteTheme
from sqlalchemy.orm.session import Session from sqlalchemy.orm.session import Session
from utils.snackbar import SnackResponse from utils.snackbar import SnackResponse
from db.database import db
router = APIRouter(prefix="/api", tags=["Themes"]) router = APIRouter(prefix="/api", tags=["Themes"])
@ -11,13 +12,13 @@ router = APIRouter(prefix="/api", tags=["Themes"])
def get_all_themes(session: Session = Depends(generate_session)): def get_all_themes(session: Session = Depends(generate_session)):
""" Returns all site themes """ """ Returns all site themes """
return SiteTheme.get_all(session) return db.themes.get_all(session)
@router.post("/themes/create") @router.post("/themes/create")
def create_theme(data: SiteTheme, session: Session = Depends(generate_session)): def create_theme(data: SiteTheme, session: Session = Depends(generate_session)):
""" Creates a site color theme database entry """ """ Creates a site color theme database entry """
data.save_to_db(session) db.themes.create(session, data.dict())
return SnackResponse.success("Theme Saved") return SnackResponse.success("Theme Saved")
@ -25,7 +26,7 @@ def create_theme(data: SiteTheme, session: Session = Depends(generate_session)):
@router.get("/themes/{theme_name}") @router.get("/themes/{theme_name}")
def get_single_theme(theme_name: str, session: Session = Depends(generate_session)): def get_single_theme(theme_name: str, session: Session = Depends(generate_session)):
""" Returns a named theme """ """ Returns a named theme """
return SiteTheme.get_by_name(session, theme_name) return db.themes.get(session, theme_name)
@router.put("/themes/{theme_name}") @router.put("/themes/{theme_name}")
@ -33,7 +34,7 @@ def update_theme(
theme_name: str, data: SiteTheme, session: Session = Depends(generate_session) theme_name: str, data: SiteTheme, session: Session = Depends(generate_session)
): ):
""" Update a theme database entry """ """ Update a theme database entry """
data.update_document(session) db.themes.update(session, theme_name, data.dict())
return SnackResponse.info(f"Theme Updated: {theme_name}") return SnackResponse.info(f"Theme Updated: {theme_name}")
@ -41,6 +42,6 @@ def update_theme(
@router.delete("/themes/{theme_name}") @router.delete("/themes/{theme_name}")
def delete_theme(theme_name: str, session: Session = Depends(generate_session)): def delete_theme(theme_name: str, session: Session = Depends(generate_session)):
""" Deletes theme from the database """ """ Deletes theme from the database """
SiteTheme.delete_theme(session, theme_name) db.themes.delete(session, theme_name)
return SnackResponse.error(f"Theme Deleted: {theme_name}") return SnackResponse.error(f"Theme Deleted: {theme_name}")

View file

@ -1,33 +0,0 @@
from fastapi import APIRouter, Depends
from fastapi.security import OAuth2PasswordRequestForm
# from fastapi_login import LoginManager
# from fastapi_login.exceptions import InvalidCredentialsException
router = APIRouter()
# SECRET = "876cfb59db03d9c17cefec967b00255d3f7d93a823e5dc2a"
# manager = LoginManager(SECRET, tokenUrl="/api/auth/token")
# fake_db = {"johndoe@e.mail": {"password": "hunter2"}}
# @manager.user_loader
# def load_user(email: str): # could also be an asynchronous function
# user = fake_db.get(email)
# return user
# @router.post("/api/auth/token", tags=["User Gen"])
# def login(data: OAuth2PasswordRequestForm = Depends()):
# email = data.username
# password = data.password
# user = load_user(email) # we are using the same function to retrieve the user
# if not user:
# raise InvalidCredentialsException # you can also use your own HTTPException
# elif password != user["password"]:
# raise InvalidCredentialsException
# access_token = manager.create_access_token(data=dict(sub=email))
# return {"access_token": access_token, "token_type": "bearer"}

View file

@ -4,11 +4,11 @@ from datetime import datetime
from pathlib import Path from pathlib import Path
from app_config import BACKUP_DIR, IMG_DIR, TEMP_DIR, TEMPLATE_DIR from app_config import BACKUP_DIR, IMG_DIR, TEMP_DIR, TEMPLATE_DIR
from db.database import db
from db.db_setup import create_session from db.db_setup import create_session
from jinja2 import Template from jinja2 import Template
from services.meal_services import MealPlan from services.meal_services import MealPlan
from services.recipe_services import Recipe from services.recipe_services import Recipe
from services.settings_services import SiteSettings, SiteTheme
from utils.logger import logger from utils.logger import logger
@ -88,20 +88,18 @@ class ExportDatabase:
shutil.copy(file, self.img_dir.joinpath(file.name)) shutil.copy(file, self.img_dir.joinpath(file.name))
def export_settings(self): def export_settings(self):
all_settings = SiteSettings.get_site_settings(self.session) all_settings = db.settings.get(self.session, "main")
out_file = self.settings_dir.joinpath("settings.json") out_file = self.settings_dir.joinpath("settings.json")
ExportDatabase._write_json_file(all_settings.dict(), out_file) ExportDatabase._write_json_file(all_settings, out_file)
def export_themes(self): def export_themes(self):
all_themes = SiteTheme.get_all(self.session) all_themes = db.themes.get_all(self.session)
if all_themes: if all_themes:
all_themes = [x.dict() for x in all_themes]
out_file = self.themes_dir.joinpath("themes.json") out_file = self.themes_dir.joinpath("themes.json")
ExportDatabase._write_json_file(all_themes, out_file) ExportDatabase._write_json_file(all_themes, out_file)
def export_meals( def export_meals(self):
self, #! Problem Parseing Datetime Objects... May come back to this
): #! Problem Parseing Datetime Objects... May come back to this
meal_plans = MealPlan.get_all(self.session) meal_plans = MealPlan.get_all(self.session)
if meal_plans: if meal_plans:
meal_plans = [x.dict() for x in meal_plans] meal_plans = [x.dict() for x in meal_plans]

View file

@ -1,12 +1,15 @@
import json import json
import shutil import shutil
import zipfile import zipfile
from logging import error
from pathlib import Path from pathlib import Path
from typing import List from typing import List
from app_config import BACKUP_DIR, IMG_DIR, TEMP_DIR from app_config import BACKUP_DIR, IMG_DIR, TEMP_DIR
from db.database import db
from models.theme_models import SiteTheme
from services.recipe_services import Recipe from services.recipe_services import Recipe
from services.settings_services import SiteSettings, SiteTheme from services.settings_services import SiteSettings
from sqlalchemy.orm.session import Session from sqlalchemy.orm.session import Session
from utils.logger import logger from utils.logger import logger
@ -54,6 +57,7 @@ class ImportDatabase:
raise Exception("Import file does not exist") raise Exception("Import file does not exist")
def run(self): def run(self):
report = {}
if self.imp_recipes: if self.imp_recipes:
report = self.import_recipes() report = self.import_recipes()
if self.imp_settings: if self.imp_settings:
@ -128,11 +132,13 @@ class ImportDatabase:
themes_file = self.import_dir.joinpath("themes", "themes.json") themes_file = self.import_dir.joinpath("themes", "themes.json")
with open(themes_file, "r") as f: with open(themes_file, "r") as f:
themes: list = json.loads(f.read()) themes: list[dict] = json.loads(f.read())
for theme in themes: for theme in themes:
if theme.get("name") == "default":
continue
new_theme = SiteTheme(**theme) new_theme = SiteTheme(**theme)
try: try:
new_theme.save_to_db(self.session) db.themes.create(self.session, new_theme.dict())
except: except:
logger.info(f"Unable Import Theme {new_theme.name}") logger.info(f"Unable Import Theme {new_theme.name}")
@ -142,9 +148,7 @@ class ImportDatabase:
with open(settings_file, "r") as f: with open(settings_file, "r") as f:
settings: dict = json.loads(f.read()) settings: dict = json.loads(f.read())
settings = SiteSettings(**settings) db.settings.update(self.session, settings)
settings.update(self.session)
def clean_up(self): def clean_up(self):
shutil.rmtree(TEMP_DIR) shutil.rmtree(TEMP_DIR)

View file

@ -8,19 +8,6 @@ from sqlalchemy.orm.session import Session
from services.recipe_services import Recipe from services.recipe_services import Recipe
CWD = Path(__file__).parent
THIS_WEEK = CWD.parent.joinpath("data", "meal_plan", "this_week.json")
NEXT_WEEK = CWD.parent.joinpath("data", "meal_plan", "next_week.json")
WEEKDAYS = [
"monday",
"tuesday",
"wednesday",
"thursday",
"friday",
"saturday",
"sunday",
]
class Meal(BaseModel): class Meal(BaseModel):
slug: Optional[str] slug: Optional[str]
@ -81,7 +68,7 @@ class MealPlan(BaseModel):
self.meals = meals self.meals = meals
def save_to_db(self, session: Session): def save_to_db(self, session: Session):
db.meals.save_new(session, self.dict()) db.meals.create(session, self.dict())
@staticmethod @staticmethod
def get_all(session: Session) -> List: def get_all(session: Session) -> List:

View file

@ -1,5 +1,4 @@
import datetime import datetime
import json
from pathlib import Path from pathlib import Path
from typing import Any, List, Optional from typing import Any, List, Optional
@ -98,7 +97,7 @@ class Recipe(BaseModel):
except: except:
recipe_dict["image"] = "no image" recipe_dict["image"] = "no image"
recipe_doc = db.recipes.save_new(session, recipe_dict) recipe_doc = db.recipes.create(session, recipe_dict)
recipe = Recipe(**recipe_doc) recipe = Recipe(**recipe_doc)
return recipe.slug return recipe.slug

View file

@ -3,8 +3,9 @@ from db.db_setup import create_session
from services.backups.exports import auto_backup_job from services.backups.exports import auto_backup_job
from services.scheduler.global_scheduler import scheduler from services.scheduler.global_scheduler import scheduler
from services.scheduler.scheduler_utils import Cron, cron_parser from services.scheduler.scheduler_utils import Cron, cron_parser
from services.settings_services import SiteSettings
from utils.logger import logger from utils.logger import logger
from models.settings_models import SiteSettings
from db.database import db
from utils.post_webhooks import post_webhooks from utils.post_webhooks import post_webhooks
@ -15,7 +16,8 @@ def update_webhook_schedule():
poll the database for changes and reschedule the webhook time poll the database for changes and reschedule the webhook time
""" """
session = create_session() session = create_session()
settings = SiteSettings.get_site_settings(session=session) settings = db.settings.get(session, "main")
settings = SiteSettings(**settings)
time = cron_parser(settings.webhooks.webhookTime) time = cron_parser(settings.webhooks.webhookTime)
job = JOB_STORE.get("webhooks") job = JOB_STORE.get("webhooks")

View file

@ -1,135 +1,6 @@
from typing import List, Optional
from db.database import db from db.database import db
from db.db_setup import create_session, sql_exists from db.db_setup import create_session, sql_exists
from pydantic import BaseModel from models.settings_models import SiteSettings, Webhooks
from sqlalchemy.orm.session import Session
from utils.logger import logger
class Webhooks(BaseModel):
webhookTime: str = "00:00"
webhookURLs: Optional[List[str]] = []
enabled: bool = False
class SiteSettings(BaseModel):
name: str = "main"
webhooks: Webhooks
class Config:
schema_extra = {
"example": {
"name": "main",
"webhooks": {
"webhookTime": "00:00",
"webhookURLs": ["https://mywebhookurl.com/webhook"],
"enable": False,
},
}
}
@staticmethod
def get_all(session: Session):
db.settings.get_all(session)
@classmethod
def get_site_settings(cls, session: Session):
try:
document = db.settings.get(session=session, match_value="main")
except:
webhooks = Webhooks()
default_entry = SiteSettings(name="main", webhooks=webhooks)
document = db.settings.save_new(
session, default_entry.dict(), webhooks.dict()
)
return cls(**document)
def update(self, session: Session):
db.settings.update(session, "main", new_data=self.dict())
class Colors(BaseModel):
primary: str
accent: str
secondary: str
success: str
info: str
warning: str
error: str
class SiteTheme(BaseModel):
name: str
colors: Colors
class Config:
schema_extra = {
"example": {
"name": "default",
"colors": {
"primary": "#E58325",
"accent": "#00457A",
"secondary": "#973542",
"success": "#5AB1BB",
"info": "#4990BA",
"warning": "#FF4081",
"error": "#EF5350",
},
}
}
@classmethod
def get_by_name(cls, session: Session, theme_name):
db_entry = db.themes.get(session, theme_name)
name = db_entry.get("name")
colors = Colors(**db_entry.get("colors"))
return cls(name=name, colors=colors)
@staticmethod
def get_all(session: Session):
all_themes = db.themes.get_all(session)
for index, theme in enumerate(all_themes):
name = theme.get("name")
colors = Colors(**theme.get("colors"))
all_themes[index] = SiteTheme(name=name, colors=colors)
return all_themes
def save_to_db(self, session: Session):
db.themes.save_new(session, self.dict())
def update_document(self, session: Session):
db.themes.update(session, self.name, self.dict())
@staticmethod
def delete_theme(session: Session, theme_name: str) -> str:
""" Removes the theme by name """
db.themes.delete(session, theme_name)
def default_theme_init():
default_colors = {
"primary": "#E58325",
"accent": "#00457A",
"secondary": "#973542",
"success": "#5AB1BB",
"info": "#4990BA",
"warning": "#FF4081",
"error": "#EF5350",
}
session = create_session()
try:
SiteTheme.get_by_name(session, "default")
logger.info("Default theme exists... skipping generation")
except:
logger.info("Generating Default Theme")
colors = Colors(**default_colors)
default_theme = SiteTheme(name="default", colors=colors)
default_theme.save_to_db(session)
def default_settings_init(): def default_settings_init():
@ -139,11 +10,10 @@ def default_settings_init():
except: except:
webhooks = Webhooks() webhooks = Webhooks()
default_entry = SiteSettings(name="main", webhooks=webhooks) default_entry = SiteSettings(name="main", webhooks=webhooks)
document = db.settings.save_new(session, default_entry.dict(), webhooks.dict()) document = db.settings.create(session, default_entry.dict(), webhooks.dict())
session.close() session.close()
if not sql_exists: if not sql_exists:
default_settings_init() default_settings_init()
default_theme_init()

View file

@ -0,0 +1,28 @@
from db.database import db
from db.db_setup import create_session, sql_exists
from utils.logger import logger
def default_theme_init():
default_theme = {
"name": "default",
"colors": {
"primary": "#E58325",
"accent": "#00457A",
"secondary": "#973542",
"success": "#5AB1BB",
"info": "#4990BA",
"warning": "#FF4081",
"error": "#EF5350",
},
}
session = create_session()
try:
db.themes.create(session, default_theme)
logger.info("Generating default theme...")
except:
logger.info("Default Theme Exists.. skipping generation")
if not sql_exists:
default_theme_init()

View file

@ -1,15 +1,17 @@
import json import json
import requests import requests
from db.database import db
from db.db_setup import create_session from db.db_setup import create_session
from models.settings_models import SiteSettings
from services.meal_services import MealPlan from services.meal_services import MealPlan
from services.recipe_services import Recipe from services.recipe_services import Recipe
from services.settings_services import SiteSettings
def post_webhooks(): def post_webhooks():
session = create_session() session = create_session()
all_settings = SiteSettings.get_site_settings(session) all_settings = db.get(session, "main")
all_settings = SiteSettings(**all_settings)
if all_settings.webhooks.enabled: if all_settings.webhooks.enabled:
todays_meal = Recipe.get_by_slug(MealPlan.today()).dict() todays_meal = Recipe.get_by_slug(MealPlan.today()).dict()