combo-plugin-gnm/combo_plugin_gnm/push.py

68 lines
2.7 KiB
Python

# -*- coding: utf-8 -*-
# combo-plugin-gnm - Combo WebPush App
# Copyright (C) 2018 Entr'ouvert
#
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from django.conf import settings
from django.db import transaction
from django.utils.timezone import is_naive, make_aware
from pywebpush import WebPushException
from retrying import retry
from webpush.utils import _send_notification
from .models import WebPushRecord
def retry_if_webpush_exception(exception):
'''Return True if we should retry'''
return isinstance(exception, WebPushException)
@retry(wait_exponential_multiplier=1000,
wait_exponential_max=getattr(settings, 'WEBPUSH_BACKOFF_MAXMILLISECS', 10000),
retry_on_exception=retry_if_webpush_exception)
def send_web_push(notification, since=None):
'''Get all the user subscriptions (every browsers with authoorized notifications)
and send a push mesg to each one
'''
if is_naive(since):
since = make_aware(since)
user_subscription_list = notification.user.webpush_info.select_related("subscription")
responses = []
for sub_info in user_subscription_list:
with transaction.atomic():
web_push_record, created = WebPushRecord.objects.select_for_update().get_or_create(
notification=notification,
subscription=sub_info)
if web_push_record.status == WebPushRecord.DEFAULT_STATUS and \
web_push_record.creation_date >= since:
# check the user's subscription and send the request to the endpoint
req = _send_notification(sub_info, web_push_record.payload, web_push_record.ttl)
# requests.Response object
if req.status_code <= 201:
web_push_record.status = web_push_record.OK_STATUS
web_push_record.save()
responses += [req]
else:
web_push_record.status = web_push_record.ERR_STATUS
web_push_record.save()
else:
web_push_record.set_status_err()
return responses