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