mirror of
https://github.com/hay-kot/mealie.git
synced 2025-08-22 14:33:33 -07:00
test notification
This commit is contained in:
parent
566e947ffc
commit
c4d1a9ff9a
10 changed files with 117 additions and 59 deletions
1
frontend/public/static/discord.svg
Normal file
1
frontend/public/static/discord.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 245 240"><style>.st0{fill:#7289DA;}</style><path class="st0" d="M104.4 103.9c-5.7 0-10.2 5-10.2 11.1s4.6 11.1 10.2 11.1c5.7 0 10.2-5 10.2-11.1.1-6.1-4.5-11.1-10.2-11.1zM140.9 103.9c-5.7 0-10.2 5-10.2 11.1s4.6 11.1 10.2 11.1c5.7 0 10.2-5 10.2-11.1s-4.5-11.1-10.2-11.1z"/><path class="st0" d="M189.5 20h-134C44.2 20 35 29.2 35 40.6v135.2c0 11.4 9.2 20.6 20.5 20.6h113.4l-5.3-18.5 12.8 11.9 12.1 11.2 21.5 19V40.6c0-11.4-9.2-20.6-20.5-20.6zm-38.6 130.6s-3.6-4.3-6.6-8.1c13.1-3.7 18.1-11.9 18.1-11.9-4.1 2.7-8 4.6-11.5 5.9-5 2.1-9.8 3.5-14.5 4.3-9.6 1.8-18.4 1.3-25.9-.1-5.7-1.1-10.6-2.7-14.7-4.3-2.3-.9-4.8-2-7.3-3.4-.3-.2-.6-.3-.9-.5-.2-.1-.3-.2-.4-.3-1.8-1-2.8-1.7-2.8-1.7s4.8 8 17.5 11.8c-3 3.8-6.7 8.3-6.7 8.3-22.1-.7-30.5-15.2-30.5-15.2 0-32.2 14.4-58.3 14.4-58.3 14.4-10.8 28.1-10.5 28.1-10.5l1 1.2c-18 5.2-26.3 13.1-26.3 13.1s2.2-1.2 5.9-2.9c10.7-4.7 19.2-6 22.7-6.3.6-.1 1.1-.2 1.7-.2 6.1-.8 13-1 20.2-.2 9.5 1.1 19.7 3.9 30.1 9.6 0 0-7.9-7.5-24.9-12.7l1.4-1.6s13.7-.3 28.1 10.5c0 0 14.4 26.1 14.4 58.3 0 0-8.5 14.5-30.6 15.2z"/></svg>
|
After Width: | Height: | Size: 1.1 KiB |
BIN
frontend/public/static/home-assistant.png
Normal file
BIN
frontend/public/static/home-assistant.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 17 KiB |
BIN
frontend/public/static/matrix.png
Normal file
BIN
frontend/public/static/matrix.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.4 KiB |
7
frontend/public/static/pushover.svg
Normal file
7
frontend/public/static/pushover.svg
Normal file
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<svg width="602px" height="602px" viewBox="57 57 602 602" version="1.1" xmlns="http://www.w3.org/2000/svg">
|
||||
<g id="layer1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" transform="translate(58.964119, 58.887520)" opacity="0.91">
|
||||
<ellipse style="fill: rgb(36, 157, 241); fill-rule: evenodd; stroke: rgb(255, 255, 255); stroke-width: 0;" transform="matrix(-0.674571, 0.73821, -0.73821, -0.674571, 556.833239, 241.613465)" cx="216.308" cy="152.076" rx="296.855" ry="296.855"/>
|
||||
<path d="M 280.949 172.514 L 355.429 162.714 L 282.909 326.374 L 282.909 326.374 C 295.649 325.394 308.142 321.067 320.389 313.394 L 320.389 313.394 L 320.389 313.394 C 332.642 305.714 343.916 296.077 354.209 284.484 L 354.209 284.484 L 354.209 284.484 C 364.496 272.884 373.396 259.981 380.909 245.774 L 380.909 245.774 L 380.909 245.774 C 388.422 231.561 393.812 217.594 397.079 203.874 L 397.079 203.874 L 397.079 203.874 C 399.039 195.381 399.939 187.214 399.779 179.374 L 399.779 179.374 L 399.779 179.374 C 399.612 171.534 397.569 164.674 393.649 158.794 L 393.649 158.794 L 393.649 158.794 C 389.729 152.914 383.766 148.177 375.759 144.584 L 375.759 144.584 L 375.759 144.584 C 367.759 140.991 356.899 139.194 343.179 139.194 L 343.179 139.194 L 343.179 139.194 C 327.172 139.194 311.409 141.807 295.889 147.034 L 295.889 147.034 L 295.889 147.034 C 280.376 152.261 266.002 159.857 252.769 169.824 L 252.769 169.824 L 252.769 169.824 C 239.542 179.784 228.029 192.197 218.229 207.064 L 218.229 207.064 L 218.229 207.064 C 208.429 221.924 201.406 238.827 197.159 257.774 L 197.159 257.774 L 197.159 257.774 C 195.526 263.981 194.546 268.961 194.219 272.714 L 194.219 272.714 L 194.219 272.714 C 193.892 276.474 193.812 279.577 193.979 282.024 L 193.979 282.024 L 193.979 282.024 C 194.139 284.477 194.462 286.357 194.949 287.664 L 194.949 287.664 L 194.949 287.664 C 195.442 288.971 195.852 290.277 196.179 291.584 L 196.179 291.584 L 196.179 291.584 C 179.519 291.584 167.349 288.234 159.669 281.534 L 159.669 281.534 L 159.669 281.534 C 151.996 274.841 150.119 263.164 154.039 246.504 L 154.039 246.504 L 154.039 246.504 C 157.959 229.191 166.862 212.694 180.749 197.014 L 180.749 197.014 L 180.749 197.014 C 194.629 181.334 211.122 167.531 230.229 155.604 L 230.229 155.604 L 230.229 155.604 C 249.342 143.684 270.249 134.214 292.949 127.194 L 292.949 127.194 L 292.949 127.194 C 315.656 120.167 337.789 116.654 359.349 116.654 L 359.349 116.654 L 359.349 116.654 C 378.296 116.654 394.219 119.347 407.119 124.734 L 407.119 124.734 L 407.119 124.734 C 420.026 130.127 430.072 137.234 437.259 146.054 L 437.259 146.054 L 437.259 146.054 C 444.446 154.874 448.936 165.164 450.729 176.924 L 450.729 176.924 L 450.729 176.924 C 452.529 188.684 451.959 200.934 449.019 213.674 L 449.019 213.674 L 449.019 213.674 C 445.426 229.027 438.646 244.464 428.679 259.984 L 428.679 259.984 L 428.679 259.984 C 418.719 275.497 406.226 289.544 391.199 302.124 L 391.199 302.124 L 391.199 302.124 C 376.172 314.697 358.939 324.904 339.499 332.744 L 339.499 332.744 L 339.499 332.744 C 320.066 340.584 299.406 344.504 277.519 344.504 L 277.519 344.504 L 275.069 344.504 L 212.839 484.154 L 142.279 484.154 L 280.949 172.514 Z" transform="matrix(1, 0, 0, 1, 0, 0)" style="fill: rgb(255, 255, 255); fill-rule: nonzero; white-space: pre;"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 3.3 KiB |
|
@ -14,6 +14,7 @@ const aboutURLs = {
|
|||
event: id => `${prefix}/events/${id}`,
|
||||
|
||||
allNotifications: `${prefix}/events/notifications`,
|
||||
testNotifications: `${prefix}/events/notifications/test`,
|
||||
notification: id => `${prefix}/events/notifications/${id}`,
|
||||
};
|
||||
|
||||
|
@ -45,6 +46,14 @@ export const aboutAPI = {
|
|||
const response = await apiReq.delete(aboutURLs.notification(id));
|
||||
return response.data;
|
||||
},
|
||||
async testNotificationByID(id) {
|
||||
const response = await apiReq.post(aboutURLs.testNotifications, { id: id });
|
||||
return response.data;
|
||||
},
|
||||
async testNotificationByURL(url) {
|
||||
const response = await apiReq.post(aboutURLs.testNotifications, { test_url: url });
|
||||
return response.data;
|
||||
},
|
||||
// async getAppInfo() {
|
||||
// const response = await apiReq.get(aboutURLs.version);
|
||||
// return response.data;
|
||||
|
|
|
@ -14,9 +14,9 @@
|
|||
</template>
|
||||
<v-card-text class="mt-2">
|
||||
We use the <a href="https://github.com/caronc/apprise/wiki" target="_blanks"> Apprise </a> library to
|
||||
generate notifications. They offer many options for services to use. Refer to their wiki for a comprehensive
|
||||
guide on how to create the URL for your service. If available, selecting the type of your notification can
|
||||
include extra features Here are some common choices.
|
||||
generate notifications. They offer many options for services to use for notifications. Refer to their wiki
|
||||
for a comprehensive guide on how to create the URL for your service. If available, selecting the type of
|
||||
your notification can include extra features Here are some common choices.
|
||||
|
||||
<div class="d-flex justify-space-around mt-1">
|
||||
<a href="https://github.com/caronc/apprise/wiki/Notify_gotify" target="_blanks"> Gotify </a>
|
||||
|
@ -33,6 +33,10 @@
|
|||
</v-select>
|
||||
<v-text-field label="Name" v-model="newNotification.name"> </v-text-field>
|
||||
<v-text-field label="Notification URL" v-model="newNotification.notificationUrl"> </v-text-field>
|
||||
<v-btn class="d-flex ml-auto" small color="info" @click="testByURL(newNotification.notificationUrl)">
|
||||
<v-icon left> mdi-test-tube</v-icon>
|
||||
Test
|
||||
</v-btn>
|
||||
<v-subheader class="pa-0 mb-0">
|
||||
Select the events you would like to recieve notifications for on this URL
|
||||
</v-subheader>
|
||||
|
@ -55,31 +59,31 @@
|
|||
<template v-slot:default>
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="text-left">
|
||||
<th class="text-center">
|
||||
Type
|
||||
</th>
|
||||
<th class="text-left">
|
||||
<th class="text-center">
|
||||
Name
|
||||
</th>
|
||||
<th class="text-left">
|
||||
<th class="text-center">
|
||||
General
|
||||
</th>
|
||||
<th class="text-left">
|
||||
<th class="text-center">
|
||||
Recipe
|
||||
</th>
|
||||
<th class="text-left">
|
||||
<th class="text-center">
|
||||
Backup
|
||||
</th>
|
||||
<th class="text-left">
|
||||
<th class="text-center">
|
||||
Scheduled
|
||||
</th>
|
||||
<th class="text-left">
|
||||
<th class="text-center">
|
||||
Migration
|
||||
</th>
|
||||
<th class="text-left">
|
||||
<th class="text-center">
|
||||
Group
|
||||
</th>
|
||||
<th class="text-left">
|
||||
<th class="text-center">
|
||||
User
|
||||
</th>
|
||||
</tr>
|
||||
|
@ -87,7 +91,7 @@
|
|||
<tbody>
|
||||
<tr v-for="(item, index) in notifications" :key="index">
|
||||
<td>
|
||||
<v-avatar size="35" class="ma-1" color="primary">
|
||||
<v-avatar size="35" class="ma-1" :color="getIcon(item.type).icon ? 'primary' : undefined">
|
||||
<v-icon dark v-if="getIcon(item.type).icon"> {{ getIcon(item.type).icon }}</v-icon>
|
||||
<v-img v-else :src="getIcon(item.type).image"> </v-img>
|
||||
</v-avatar>
|
||||
|
@ -96,30 +100,35 @@
|
|||
<td>
|
||||
{{ item.name }}
|
||||
</td>
|
||||
<td>
|
||||
<td class="text-center">
|
||||
<v-icon color="success"> {{ item.general ? "mdi-check" : "" }} </v-icon>
|
||||
</td>
|
||||
<td>
|
||||
<td class="text-center">
|
||||
<v-icon color="success"> {{ item.recipe ? "mdi-check" : "" }} </v-icon>
|
||||
</td>
|
||||
<td>
|
||||
<td class="text-center">
|
||||
<v-icon color="success"> {{ item.backup ? "mdi-check" : "" }} </v-icon>
|
||||
</td>
|
||||
<td>
|
||||
<td class="text-center">
|
||||
<v-icon color="success"> {{ item.scheduled ? "mdi-check" : "" }} </v-icon>
|
||||
</td>
|
||||
<td>
|
||||
<td class="text-center">
|
||||
<v-icon color="success"> {{ item.migration ? "mdi-check" : "" }} </v-icon>
|
||||
</td>
|
||||
<td>
|
||||
<td class="text-center">
|
||||
<v-icon color="success"> {{ item.group ? "mdi-check" : "" }} </v-icon>
|
||||
</td>
|
||||
<td>
|
||||
<td class="text-center">
|
||||
<v-icon color="success"> {{ item.user ? "mdi-check" : "" }} </v-icon>
|
||||
</td>
|
||||
<td>
|
||||
<v-btn small icon color="error" @click="deleteNotification(item.id)">
|
||||
<v-btn class="mx-1" small color="error" @click="deleteNotification(item.id)">
|
||||
<v-icon> mdi-delete </v-icon>
|
||||
Delete
|
||||
</v-btn>
|
||||
<v-btn small color="info" @click="testByID(item.id)">
|
||||
<v-icon left> mdi-test-tube</v-icon>
|
||||
Test
|
||||
</v-btn>
|
||||
</td>
|
||||
</tr>
|
||||
|
@ -162,12 +171,20 @@ export default {
|
|||
},
|
||||
{
|
||||
text: "Discord",
|
||||
icon: "mdi-discord",
|
||||
image: "./static/discord.svg",
|
||||
},
|
||||
{
|
||||
text: "Gotify",
|
||||
image: "./static/gotify.png",
|
||||
},
|
||||
{
|
||||
text: "Home Assistant",
|
||||
image: "./static/home-assistant.png",
|
||||
},
|
||||
{
|
||||
text: "Pushover",
|
||||
image: "./static/pushover.svg",
|
||||
},
|
||||
],
|
||||
};
|
||||
},
|
||||
|
@ -190,6 +207,12 @@ export default {
|
|||
await api.about.deleteNotification(id);
|
||||
this.getAllNotifications();
|
||||
},
|
||||
async testByID(id) {
|
||||
await api.about.testNotificationByID(id);
|
||||
},
|
||||
async testByURL(url) {
|
||||
await api.about.testNotificationByURL(url);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
|
@ -1,14 +1,20 @@
|
|||
from fastapi import APIRouter, Depends
|
||||
from http.client import HTTPException
|
||||
|
||||
from fastapi import APIRouter, Depends, status
|
||||
from mealie.core.root_logger import get_logger
|
||||
from mealie.db.database import db
|
||||
from mealie.db.db_setup import generate_session
|
||||
from mealie.routes.deps import get_current_user
|
||||
from mealie.schema.event_notifications import EventNotificationIn, EventNotificationOut
|
||||
from mealie.schema.events import EventsOut
|
||||
from mealie.schema.events import Event, EventCategory, EventsOut, TestEvent
|
||||
from mealie.schema.user import UserInDB
|
||||
from mealie.services.events import post_notifications
|
||||
from sqlalchemy.orm.session import Session
|
||||
|
||||
router = APIRouter(prefix="/events", tags=["App Events"])
|
||||
|
||||
logger = get_logger()
|
||||
|
||||
|
||||
@router.get("", response_model=EventsOut)
|
||||
async def get_events(session: Session = Depends(generate_session), current_user: UserInDB = Depends(get_current_user)):
|
||||
|
@ -41,10 +47,35 @@ async def create_event_notification(
|
|||
current_user: UserInDB = Depends(get_current_user),
|
||||
):
|
||||
""" Create event_notification in the Database """
|
||||
|
||||
|
||||
return db.event_notifications.create(session, event_data)
|
||||
|
||||
|
||||
@router.post("/notifications/test")
|
||||
async def test_notification(
|
||||
test_data: TestEvent,
|
||||
session: Session = Depends(generate_session),
|
||||
current_user: UserInDB = Depends(get_current_user),
|
||||
):
|
||||
""" Create event_notification in the Database """
|
||||
|
||||
if test_data.id:
|
||||
print("TEST ID")
|
||||
event_obj: EventNotificationIn = db.event_notifications.get(session, test_data.id)
|
||||
test_data.test_url = event_obj.notification_url
|
||||
|
||||
test_event = Event(
|
||||
title="Test Notification",
|
||||
text="This is a test message from the Mealie API server",
|
||||
category=EventCategory.general.value,
|
||||
)
|
||||
try:
|
||||
post_notifications(test_event, [test_data.test_url])
|
||||
except Exception as e:
|
||||
logger.error(e)
|
||||
raise HTTPException(status.HTTP_500_INTERNAL_SERVER_ERROR)
|
||||
|
||||
|
||||
@router.get("/notifications", response_model=list[EventNotificationOut])
|
||||
async def get_all_event_notification(
|
||||
session: Session = Depends(generate_session), current_user: UserInDB = Depends(get_current_user)
|
||||
|
|
|
@ -30,3 +30,8 @@ class Event(CamelModel):
|
|||
class EventsOut(CamelModel):
|
||||
total: int
|
||||
events: list[Event]
|
||||
|
||||
|
||||
class TestEvent(CamelModel):
|
||||
id: Optional[int]
|
||||
test_url: Optional[str]
|
||||
|
|
|
@ -1,32 +0,0 @@
|
|||
import apprise
|
||||
from mealie.schema.event_notifications import EventNotificationIn
|
||||
from mealie.schema.events import Event
|
||||
|
||||
|
||||
def post_notifications(event: Event, notification_dests=list[EventNotificationIn]):
|
||||
# Create an Apprise instance
|
||||
|
||||
# discord = Discord(
|
||||
# webhook_id="840358511842295829",
|
||||
# webhook_token="EtcH6ACFM-qpHRkPw1TUTc_r8AiVMlKYhGEzlANvXj7SlGGFZt18dkYy96ayZHZ8HaI9",
|
||||
# )
|
||||
# Create our asset object
|
||||
asset = apprise.AppriseAsset(async_mode=False)
|
||||
|
||||
# Create our object
|
||||
apobj = apprise.Apprise(asset=asset)
|
||||
|
||||
# Add all of the notification services by their server url.
|
||||
# A sample email notification:
|
||||
|
||||
for dest in notification_dests:
|
||||
dest: EventNotificationIn
|
||||
apobj.add(dest.notification_url)
|
||||
|
||||
# A sample pushbullet notification
|
||||
# Then notify these services any time you desire. The below would
|
||||
# notify all of the services loaded into our Apprise object.
|
||||
apobj.notify(
|
||||
body=event.text,
|
||||
title=event.title,
|
||||
)
|
|
@ -1,17 +1,31 @@
|
|||
import apprise
|
||||
from mealie.db.database import db
|
||||
from mealie.db.db_setup import create_session
|
||||
from mealie.schema.events import Event, EventCategory
|
||||
from mealie.services.event_notifications import post_notifications
|
||||
from sqlalchemy.orm.session import Session
|
||||
|
||||
|
||||
def post_notifications(event: Event, notification_urls=list[str]):
|
||||
asset = apprise.AppriseAsset(async_mode=False)
|
||||
apobj = apprise.Apprise(asset=asset)
|
||||
|
||||
for dest in notification_urls:
|
||||
apobj.add(dest)
|
||||
|
||||
apobj.notify(
|
||||
body=event.text,
|
||||
title=event.title,
|
||||
)
|
||||
|
||||
|
||||
def save_event(title, text, category, session: Session):
|
||||
event = Event(title=title, text=text, category=category)
|
||||
session = session or create_session()
|
||||
db.events.create(session, event.dict())
|
||||
|
||||
notification_objects = db.event_notifications.get(session=session, match_value=True, match_key=category, limit=9999)
|
||||
post_notifications(event, notification_objects)
|
||||
notification_urls = [x.notification_url for x in notification_objects]
|
||||
post_notifications(event, notification_urls)
|
||||
|
||||
|
||||
def create_general_event(title, text, session=None):
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue