feat: extend Apprise JSON notification functionality with programmatic data (#1355)

* Fixed incorrect generic deleted notification text

* Added custom "event_source" header for json notifs

* Added internal reference data to event notifs

* Added event listeners to shopping list items

* Fixed type issues

* moved JSON event source k:v pairs to message body

* added hook for all supported custom endpoints
fixed bug that excluded non-custom notification types

* created event_source class to replace loosely-typed dict

* fixed silent error when dispatching a null task

* moved url updates to static function

* added unit tests for event_source url manipulation

* removed array from event bus (it's unsupported)
This commit is contained in:
Michael Genson
2022-06-15 14:49:42 -05:00
committed by GitHub
parent 3030e3e7f4
commit 754e77c9cb
42 changed files with 296 additions and 54 deletions

View File

@@ -8,7 +8,7 @@ from mealie.routes._base import BaseUserController, controller
from mealie.routes._base.mixins import HttpRepo
from mealie.schema import mapper
from mealie.schema.cookbook import CreateCookBook, ReadCookBook, RecipeCookBook, SaveCookBook, UpdateCookBook
from mealie.services.event_bus_service.event_bus_service import EventBusService
from mealie.services.event_bus_service.event_bus_service import EventBusService, EventSource
from mealie.services.event_bus_service.message_types import EventTypes
router = APIRouter(prefix="/groups/cookbooks", tags=["Groups: Cookbooks"])
@@ -53,6 +53,7 @@ class GroupCookbookController(BaseUserController):
self.deps.acting_user.group_id,
EventTypes.cookbook_created,
msg=self.t("notifications.generic-created", name=val.name),
event_source=EventSource(event_type="create", item_type="cookbook", item_id=val.id, slug=val.slug),
)
return val
@@ -94,6 +95,7 @@ class GroupCookbookController(BaseUserController):
self.deps.acting_user.group_id,
EventTypes.cookbook_updated,
msg=self.t("notifications.generic-updated", name=val.name),
event_source=EventSource(event_type="update", item_type="cookbook", item_id=val.id, slug=val.slug),
)
return val
@@ -106,5 +108,6 @@ class GroupCookbookController(BaseUserController):
self.deps.acting_user.group_id,
EventTypes.cookbook_deleted,
msg=self.t("notifications.generic-deleted", name=val.name),
event_source=EventSource(event_type="delete", item_type="cookbook", item_id=val.id, slug=val.slug),
)
return val

View File

@@ -19,7 +19,7 @@ from mealie.schema.group.group_shopping_list import (
from mealie.schema.mapper import cast
from mealie.schema.query import GetAll
from mealie.schema.response.responses import SuccessResponse
from mealie.services.event_bus_service.event_bus_service import EventBusService
from mealie.services.event_bus_service.event_bus_service import EventBusService, EventSource
from mealie.services.event_bus_service.message_types import EventTypes
from mealie.services.group_services.shopping_lists import ShoppingListService
@@ -75,7 +75,25 @@ class ShoppingListItemController(BaseUserController):
@item_router.post("", response_model=ShoppingListItemOut, status_code=201)
def create_one(self, data: ShoppingListItemCreate):
return self.mixins.create_one(data)
shopping_list_item = self.mixins.create_one(data)
if shopping_list_item:
self.event_bus.dispatch(
self.deps.acting_user.group_id,
EventTypes.shopping_list_updated,
msg=self.t(
"notifications.generic-created",
name=f"An item on shopping list {shopping_list_item.shopping_list_id}",
),
event_source=EventSource(
event_type="create",
item_type="shopping-list-item",
item_id=shopping_list_item.id,
shopping_list_id=shopping_list_item.shopping_list_id,
),
)
return shopping_list_item
@item_router.get("/{item_id}", response_model=ShoppingListItemOut)
def get_one(self, item_id: UUID4):
@@ -83,11 +101,47 @@ class ShoppingListItemController(BaseUserController):
@item_router.put("/{item_id}", response_model=ShoppingListItemOut)
def update_one(self, item_id: UUID4, data: ShoppingListItemUpdate):
return self.mixins.update_one(data, item_id)
shopping_list_item = self.mixins.update_one(data, item_id)
if shopping_list_item:
self.event_bus.dispatch(
self.deps.acting_user.group_id,
EventTypes.shopping_list_updated,
msg=self.t(
"notifications.generic-updated",
name=f"An item on shopping list {shopping_list_item.shopping_list_id}",
),
event_source=EventSource(
event_type="update",
item_type="shopping-list-item",
item_id=shopping_list_item.id,
shopping_list_id=shopping_list_item.shopping_list_id,
),
)
return shopping_list_item
@item_router.delete("/{item_id}", response_model=ShoppingListItemOut)
def delete_one(self, item_id: UUID4):
return self.mixins.delete_one(item_id) # type: ignore
shopping_list_item = self.mixins.delete_one(item_id) # type: ignore
if shopping_list_item:
self.event_bus.dispatch(
self.deps.acting_user.group_id,
EventTypes.shopping_list_updated,
msg=self.t(
"notifications.generic-deleted",
name=f"An item on shopping list {shopping_list_item.shopping_list_id}",
),
event_source=EventSource(
event_type="delete",
item_type="shopping-list-item",
item_id=shopping_list_item.id,
shopping_list_id=shopping_list_item.shopping_list_id,
),
)
return shopping_list_item
router = APIRouter(prefix="/groups/shopping/lists", tags=["Group: Shopping Lists"])
@@ -126,6 +180,11 @@ class ShoppingListController(BaseUserController):
self.deps.acting_user.group_id,
EventTypes.shopping_list_created,
msg=self.t("notifications.generic-created", name=val.name),
event_source=EventSource(
event_type="create",
item_type="shopping-list",
item_id=val.id,
),
)
return val
@@ -142,6 +201,11 @@ class ShoppingListController(BaseUserController):
self.deps.acting_user.group_id,
EventTypes.shopping_list_updated,
msg=self.t("notifications.generic-updated", name=data.name),
event_source=EventSource(
event_type="update",
item_type="shopping-list",
item_id=data.id,
),
)
return data
@@ -151,8 +215,13 @@ class ShoppingListController(BaseUserController):
if data:
self.event_bus.dispatch(
self.deps.acting_user.group_id,
EventTypes.shopping_list_updated,
EventTypes.shopping_list_deleted,
msg=self.t("notifications.generic-deleted", name=data.name),
event_source=EventSource(
event_type="delete",
item_type="shopping-list",
item_id=data.id,
),
)
return data
@@ -161,8 +230,40 @@ class ShoppingListController(BaseUserController):
@router.post("/{item_id}/recipe/{recipe_id}", response_model=ShoppingListOut)
def add_recipe_ingredients_to_list(self, item_id: UUID4, recipe_id: UUID4):
return self.service.add_recipe_ingredients_to_list(item_id, recipe_id)
shopping_list = self.service.add_recipe_ingredients_to_list(item_id, recipe_id)
if shopping_list:
self.event_bus.dispatch(
self.deps.acting_user.group_id,
EventTypes.shopping_list_updated,
msg=self.t(
"notifications.generic-updated",
name=shopping_list.name,
),
event_source=EventSource(
event_type="bulk-updated-items",
item_type="shopping-list",
item_id=shopping_list.id,
),
)
return shopping_list
@router.delete("/{item_id}/recipe/{recipe_id}", response_model=ShoppingListOut)
def remove_recipe_ingredients_from_list(self, item_id: UUID4, recipe_id: UUID4):
return self.service.remove_recipe_ingredients_from_list(item_id, recipe_id)
shopping_list = self.service.remove_recipe_ingredients_from_list(item_id, recipe_id)
if shopping_list:
self.event_bus.dispatch(
self.deps.acting_user.group_id,
EventTypes.shopping_list_updated,
msg=self.t(
"notifications.generic-updated",
name=shopping_list.name,
),
event_source=EventSource(
event_type="bulk-updated-items",
item_type="shopping-list",
item_id=shopping_list.id,
),
)
return shopping_list