summaryrefslogtreecommitdiff
path: root/postgresqleu/util/messaging/util.py
blob: b78e8ae1b53e96ff2b853cb58641a2cad408d8c2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
from django.utils import timezone

from datetime import timedelta
import time

from postgresqleu.confreg.models import NotificationQueue
from postgresqleu.util.db import exec_no_result
from postgresqleu.util.messaging import get_messaging_class

#
# This file holds methods callable from outside the "messaging framework"
#


class _Notifier(object):
    def __enter__(self):
        self.notified = False
        return self

    def notify(self):
        self.notified = True

    def __exit__(self, *args):
        if self.notified:
            exec_no_result('NOTIFY pgeu_notification')


def send_reg_direct_message(reg, msg, expiry=timedelta(hours=1)):
    with _Notifier() as n:
        if reg.messaging and reg.messaging.provider.active:
            NotificationQueue(
                time=timezone.now(),
                expires=timezone.now() + expiry,
                messaging=reg.messaging,
                reg=reg,
                channel=None,
                msg=msg,
            ).save()
            n.notify()


def send_private_broadcast(conference, msg, expiry=timedelta(hours=1)):
    with _Notifier() as n:
        for messaging in conference.conferencemessaging_set.filter(privatebcast=True, provider__active=True):
            NotificationQueue(
                time=timezone.now(),
                expires=timezone.now() + expiry,
                messaging=messaging,
                reg=None,
                channel="privatebcast",
                msg=msg,
            ).save()
            n.notify()


def send_org_notification(conference, msg, expiry=timedelta(hours=1)):
    with _Notifier() as n:
        for messaging in conference.conferencemessaging_set.filter(orgnotification=True, provider__active=True):
            NotificationQueue(
                time=timezone.now(),
                expires=timezone.now() + expiry,
                messaging=messaging,
                reg=None,
                channel="orgnotification",
                msg=msg,
            ).save()
            n.notify()


def send_channel_message(messaging, channel, msg, expiry=timedelta(hours=1)):
    with _Notifier() as n:
        NotificationQueue(
            time=timezone.now(),
            expires=timezone.now() + expiry,
            messaging=messaging,
            reg=None,
            channel=channel,
            msg=msg,
        ).save()
        n.notify()


def notify_twitter_moderation(tweet, completed, approved):
    for messaging in tweet.conference.conferencemessaging_set.filter(socialmediamanagement=True, provider__active=True):
        get_messaging_class(messaging.provider.classname)(messaging.provider.id, messaging.provider.config).notify_twitter_moderation(messaging, tweet, completed, approved)


# Some Mastodon servers have started doing rate limiting at the TCP level, it seems. So
# we create a generic rate limiting class. Note that it will only rate limit within the
# same process, but this problem only shows up in batch jobs so it should be fine.
class _RateLimiter:
    def __init__(self):
        self.lastcalls = {}

    def limit(self, baseurl):
        if baseurl in self.lastcalls:
            # Space calls out by 15 seconds per baseurl
            s = 15 + self.lastcalls[baseurl] - time.time()
            if s > 0:
                time.sleep(s)

        self.lastcalls[baseurl] = time.time()


ratelimiter = _RateLimiter()