push notifications
authorJan Szejko <janek37@gmail.com>
Thu, 30 Aug 2018 10:38:08 +0000 (12:38 +0200)
committerJan Szejko <janek37@gmail.com>
Fri, 31 Aug 2018 09:58:53 +0000 (11:58 +0200)
16 files changed:
requirements/requirements.txt
src/push/__init__.py [new file with mode: 0644]
src/push/admin.py [new file with mode: 0644]
src/push/forms.py [new file with mode: 0644]
src/push/migrations/0001_initial.py [new file with mode: 0644]
src/push/migrations/0002_auto_20180830_1627.py [new file with mode: 0644]
src/push/migrations/0003_auto_20180831_1135.py [new file with mode: 0644]
src/push/migrations/__init__.py [new file with mode: 0644]
src/push/models.py [new file with mode: 0644]
src/push/templates/push/notification_form.html [new file with mode: 0644]
src/push/templates/push/notification_sent.html [new file with mode: 0644]
src/push/urls.py [new file with mode: 0644]
src/push/utils.py [new file with mode: 0644]
src/push/views.py [new file with mode: 0644]
src/wolnelektury/settings/apps.py
src/wolnelektury/urls.py

index 05e0a8f..62c6180 100644 (file)
@@ -71,4 +71,6 @@ paypalrestsdk
 django-haystack<2.8.0
 django-migdal>=0.8.3
 
-python-slugify
\ No newline at end of file
+python-slugify
+
+firebase-admin
diff --git a/src/push/__init__.py b/src/push/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/src/push/admin.py b/src/push/admin.py
new file mode 100644 (file)
index 0000000..339e2e7
--- /dev/null
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later.
+# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
+#
+from django.contrib import admin
+
+from .models import Notification
+
+
+admin.site.register(Notification)
diff --git a/src/push/forms.py b/src/push/forms.py
new file mode 100644 (file)
index 0000000..b49096d
--- /dev/null
@@ -0,0 +1,23 @@
+# -*- coding: utf-8 -*-
+# This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later.
+# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
+#
+from django import forms
+from django.contrib.sites.models import Site
+
+from push.models import Notification
+from push.utils import send_fcm_push
+
+
+class NotificationForm(forms.ModelForm):
+
+    class Meta:
+        model = Notification
+        exclude = ('timestamp', 'message_id')
+
+    def save(self, commit=True):
+        notification = super(NotificationForm, self).save(commit=commit)
+        wl_base = u'https://' + Site.objects.get_current().domain
+        notification.message_id = send_fcm_push(notification.title, notification.body, wl_base + notification.image.url)
+        if commit:
+            notification.save()
diff --git a/src/push/migrations/0001_initial.py b/src/push/migrations/0001_initial.py
new file mode 100644 (file)
index 0000000..86a33dc
--- /dev/null
@@ -0,0 +1,24 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name='Notification',
+            fields=[
+                ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+                ('timestamp', models.DateTimeField(auto_now_add=True)),
+                ('title', models.CharField(max_length=256)),
+                ('body', models.CharField(max_length=2048)),
+                ('image_url', models.URLField()),
+                ('message_id', models.CharField(max_length=2048)),
+            ],
+        ),
+    ]
diff --git a/src/push/migrations/0002_auto_20180830_1627.py b/src/push/migrations/0002_auto_20180830_1627.py
new file mode 100644 (file)
index 0000000..bb22b65
--- /dev/null
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('push', '0001_initial'),
+    ]
+
+    operations = [
+        migrations.AlterModelOptions(
+            name='notification',
+            options={'ordering': ['-timestamp']},
+        ),
+        migrations.RemoveField(
+            model_name='notification',
+            name='image_url',
+        ),
+        migrations.AddField(
+            model_name='notification',
+            name='image',
+            field=models.FileField(upload_to=b'push/img', verbose_name='image', blank=True),
+        ),
+        migrations.AlterField(
+            model_name='notification',
+            name='body',
+            field=models.CharField(max_length=2048, verbose_name='content'),
+        ),
+        migrations.AlterField(
+            model_name='notification',
+            name='title',
+            field=models.CharField(max_length=256, verbose_name='title'),
+        ),
+    ]
diff --git a/src/push/migrations/0003_auto_20180831_1135.py b/src/push/migrations/0003_auto_20180831_1135.py
new file mode 100644 (file)
index 0000000..40da3fe
--- /dev/null
@@ -0,0 +1,19 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('push', '0002_auto_20180830_1627'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='notification',
+            name='image',
+            field=models.ImageField(upload_to=b'push/img', verbose_name='image', blank=True),
+        ),
+    ]
diff --git a/src/push/migrations/__init__.py b/src/push/migrations/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/src/push/models.py b/src/push/models.py
new file mode 100644 (file)
index 0000000..79e5551
--- /dev/null
@@ -0,0 +1,20 @@
+# -*- coding: utf-8 -*-
+# This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later.
+# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
+#
+from django.db import models
+from django.utils.translation import ugettext_lazy as _
+
+
+class Notification(models.Model):
+    timestamp = models.DateTimeField(auto_now_add=True)
+    title = models.CharField(max_length=256, verbose_name=_(u'title'))
+    body = models.CharField(max_length=2048, verbose_name=_(u'content'))
+    image = models.ImageField(verbose_name=_(u'image'), blank=True, upload_to='push/img')
+    message_id = models.CharField(max_length=2048)
+
+    class Meta:
+        ordering = ['-timestamp']
+
+    def __unicode__(self):
+        return '%s: %s' % (self.timestamp, self.title)
diff --git a/src/push/templates/push/notification_form.html b/src/push/templates/push/notification_form.html
new file mode 100644 (file)
index 0000000..e926c92
--- /dev/null
@@ -0,0 +1,17 @@
+{% extends "base/base.html" %}
+{% load i18n %}
+
+{% block titleextra %}{% trans "Notifications" %}{% endblock %}
+
+
+{% block body %}
+  <h1>Wyślij powiadomienie</h1>
+
+  <form method="post" class="submit-form" action="" enctype="multipart/form-data">
+    {% csrf_token %}
+    <table>
+      {{ form.as_table }}
+      <tr><td></td><td><button type="submit">Wyślij</button></td></tr>
+    </table>
+  </form>
+{% endblock %}
\ No newline at end of file
diff --git a/src/push/templates/push/notification_sent.html b/src/push/templates/push/notification_sent.html
new file mode 100644 (file)
index 0000000..44c29c3
--- /dev/null
@@ -0,0 +1,10 @@
+{% extends "base/base.html" %}
+{% load i18n %}
+
+{% block titleextra %}{% trans "Notifications" %}{% endblock %}
+
+
+{% block body %}
+  <h1>Wysłano powiadomienie</h1>
+  <p>Gratulacje!</p>
+{% endblock %}
\ No newline at end of file
diff --git a/src/push/urls.py b/src/push/urls.py
new file mode 100644 (file)
index 0000000..70a8487
--- /dev/null
@@ -0,0 +1,12 @@
+# -*- coding: utf-8 -*-
+# This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later.
+# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
+#
+from django.conf.urls import patterns, url
+
+from push import views
+
+urlpatterns = (
+    url(r'^wyslij/$', views.notification_form, name='notification_form'),
+    url(r'^wyslane/$', views.notification_sent, name='notification_sent'),
+)
diff --git a/src/push/utils.py b/src/push/utils.py
new file mode 100644 (file)
index 0000000..98f0359
--- /dev/null
@@ -0,0 +1,29 @@
+# -*- coding: utf-8 -*-
+# This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later.
+# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
+#
+import firebase_admin
+from firebase_admin import credentials, messaging
+from django.conf import settings
+
+cred = credentials.Certificate(settings.FCM_PRIVATE_KEY_PATH)
+firebase_admin.initialize_app(cred)
+
+TOPIC = 'wolnelektury'
+
+
+def send_fcm_push(title, body, image_url=None):
+    # See documentation on defining a message payload.
+    data = {}
+    if image_url:
+        data['imageUrl'] = image_url
+    message = messaging.Message(
+        notification=messaging.Notification(
+            title=title,
+            body=body,
+        ),
+        data=data,
+        topic=TOPIC,
+    )
+    message_id = messaging.send(message)
+    return message_id
diff --git a/src/push/views.py b/src/push/views.py
new file mode 100644 (file)
index 0000000..bbcf89d
--- /dev/null
@@ -0,0 +1,26 @@
+# -*- coding: utf-8 -*-
+# This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later.
+# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
+#
+from django.contrib.auth.decorators import permission_required
+from django.core.urlresolvers import reverse
+from django.http.response import HttpResponseRedirect
+from django.shortcuts import render
+
+from push.forms import NotificationForm
+
+
+@permission_required('push.change_notification')
+def notification_form(request):
+    if request.method == 'POST':
+        form = NotificationForm(data=request.POST, files=request.FILES or None)
+        if form.is_valid():
+            form.save()
+            return HttpResponseRedirect(reverse('notification_sent'))
+    else:
+        form = NotificationForm()
+    return render(request, 'push/notification_form.html', {'form': form})
+
+
+def notification_sent(request):
+    return render(request, 'push/notification_sent.html')
\ No newline at end of file
index 7e293d3..87286d5 100644 (file)
@@ -32,6 +32,7 @@ INSTALLED_APPS_OUR = [
     'contact',
     'isbn',
     'paypal',
+    'push',
 ]
 
 INSTALLED_APPS_CONTRIB = [
index 97002d1..403cc1f 100644 (file)
@@ -52,6 +52,7 @@ urlpatterns += [
     url(r'^formularz/', include('contact.urls')),
     url(r'^isbn/', include('isbn.urls')),
     url(r'^paypal/', include('paypal.urls')),
+    url(r'^powiadomienie/', include('push.urls')),
 
     # Admin panel
     url(r'^admin/catalogue/book/import$', catalogue.views.import_book, name='import_book'),