gitscope
← marzneshin / v0.1.2 / app/tasks/send_notifications.py
https://dev.kronoz.win/r/marzneshin.git
app/tasks/send_notifications.py · Python
Blame Raw
 1import logging
 2from datetime import datetime as dt
 3from datetime import timedelta as td
 4from typing import Any, Dict, List
 5
 6import aiohttp
 7from fastapi.encoders import jsonable_encoder
 8from requests import Session
 9
10import config
11from app.db.models import NotificationReminder
12from app.utils.notification import queue
13from app.db import GetDB
14
15logger = logging.getLogger(__name__)
16
17session = Session()
18
19headers = {"x-webhook-secret": config.WEBHOOK_SECRET} if config.WEBHOOK_SECRET else None
20
21
22async def send(data: List[Dict[Any, Any]]) -> bool:
23    """Send the notification to the webhook address provided by config.WEBHOOK_ADDRESS
24
25    Args:
26        data (List[Dict[Any, Any]]): list of json encoded notifications
27
28    Returns:
29        bool: returns True if an ok response received
30    """
31    try:
32        logger.debug(f"Sending {len(data)} webhook updates to {config.WEBHOOK_ADDRESS}")
33
34        r = await aiohttp.request("post", config.WEBHOOK_ADDRESS, json=data, headers=headers)
35        if r.ok:
36            return True
37        logger.error(r)
38    except Exception as err:
39        logger.error(err)
40    return False
41
42
43async def send_notifications():
44    if not queue:
45        return
46
47    notifications_to_send = list()
48    try:
49        while (notification := queue.popleft()):
50            if (notification.tries > config.NUMBER_OF_RECURRENT_NOTIFICATIONS):
51                continue
52            if notification.send_at > dt.utcnow().timestamp():
53                queue.append(notification)  # add it to the queue again for the next check
54                continue
55            notifications_to_send.append(notification)
56    except IndexError:  # if the queue is empty
57        pass
58
59    if not notifications_to_send:
60        return
61    if not await send([jsonable_encoder(notif) for notif in notifications_to_send]):
62        for notification in notifications_to_send:
63            if (notification.tries + 1) > config.NUMBER_OF_RECURRENT_NOTIFICATIONS:
64                continue
65            notification.tries += 1
66            notification.send_at = (  # schedule notification for n seconds later
67                dt.utcnow() + td(seconds=config.RECURRENT_NOTIFICATIONS_TIMEOUT)).timestamp()
68            queue.append(notification)
69
70
71def delete_expired_reminders() -> None:
72    with GetDB() as db:
73        db.query(NotificationReminder).filter(NotificationReminder.expires_at < dt.utcnow()).delete()
74        db.commit()
75