djangoldp-notification/djangoldp_notification/models.py

154 lines
5.5 KiB
Python
Raw Normal View History

2019-02-20 03:18:46 +00:00
import logging
import requests
from django.conf import settings
2019-03-18 11:57:57 +00:00
from django.core.mail import send_mail
2019-01-09 09:27:54 +00:00
from django.db import models
from django.db.models.signals import post_save
from django.dispatch import receiver
from django.template import loader
2019-04-30 15:07:20 +00:00
from django.urls import NoReverseMatch
from django.utils.translation import ugettext_lazy as _
2019-02-28 01:21:03 +00:00
from djangoldp.fields import LDPUrlField
2019-02-20 03:18:46 +00:00
from djangoldp.models import Model
from threading import Thread
from djangoldp_notification.middlewares import MODEL_MODIFICATION_USER_FIELD
from djangoldp_notification.permissions import InboxPermissions, SubscriptionsPermissions
class Notification(Model):
2019-04-30 15:07:20 +00:00
user = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='inbox', on_delete=models.deletion.CASCADE)
2019-05-07 09:01:26 +00:00
author = LDPUrlField()
2019-03-01 04:20:21 +00:00
object = LDPUrlField()
2019-01-09 09:27:54 +00:00
type = models.CharField(max_length=255)
summary = models.TextField()
date = models.DateTimeField(auto_now_add=True)
2019-04-04 10:18:24 +00:00
unread = models.BooleanField(default=True)
class Meta(Model.Meta):
2019-08-07 13:57:57 +00:00
owner_field = 'user'
2019-06-17 01:34:38 +00:00
ordering = ['-date']
permission_classes = [InboxPermissions]
2019-08-01 12:03:00 +00:00
anonymous_perms = ['add']
2019-08-07 13:57:57 +00:00
authenticated_perms = ['inherit']
owner_perms = ['view', 'change', 'control']
2019-01-09 09:27:54 +00:00
def __str__(self):
return '{}'.format(self.type)
2019-01-31 09:44:41 +00:00
2020-02-04 14:44:11 +00:00
def save(self, *args, **kwargs):
# I cannot send a notification to myself
if self.author.startswith(settings.SITE_URL):
try:
# author is a WebID.. convert to local representation
author = Model.resolve(self.author.replace(settings.SITE_URL, ''))[1]
except NoReverseMatch:
author = None
if author == self.user:
return
super(Notification, self).save(*args, **kwargs)
class Subscription(Model):
2019-01-31 09:44:41 +00:00
object = models.URLField()
inbox = models.URLField()
def __str__(self):
return '{}'.format(self.object)
class Meta(Model.Meta):
anonymous_perms = []
authenticated_perms = ["add", "view", "delete"]
permission_classes = [SubscriptionsPermissions]
2019-01-31 09:44:41 +00:00
# --- SUBSCRIPTION SYSTEM ---
2019-02-20 03:18:46 +00:00
@receiver(post_save, dispatch_uid="callback_notif")
def send_notification(sender, instance, created, **kwargs):
2019-04-24 08:20:11 +00:00
if sender != Notification:
2019-02-20 03:18:46 +00:00
threads = []
2019-04-24 08:20:11 +00:00
try:
url_container = settings.BASE_URL + Model.container_id(instance)
url_resource = settings.BASE_URL + Model.resource_id(instance)
2019-04-24 08:20:11 +00:00
except NoReverseMatch:
return
2020-02-04 14:44:11 +00:00
# dispatch a notification for every Subscription on this resource
for subscription in Subscription.objects.filter(models.Q(object=url_resource) | models.Q(object=url_container)):
process = Thread(target=send_request, args=[subscription.inbox, url_resource, instance, created])
2019-02-20 03:18:46 +00:00
process.start()
threads.append(process)
def send_request(target, object_iri, instance, created):
unknown = _("Unknown author")
author = getattr(getattr(instance, MODEL_MODIFICATION_USER_FIELD, unknown), "urlid", unknown)
request_type = "creation" if created else "update"
2019-02-20 03:18:46 +00:00
try:
2020-02-04 14:44:11 +00:00
# local inbox
if target.startswith(settings.SITE_URL):
user = Model.resolve_parent(target.replace(settings.SITE_URL, ''))
Notification.objects.create(user=user, object=object_iri, type=request_type, author=author)
2020-02-04 14:44:11 +00:00
# external inbox
else:
json = {
"@context": settings.LDP_RDF_CONTEXT,
"object": object_iri,
"author": author,
"type": request_type
}
requests.post(target, json=json, headers={"Content-Type": "application/ld+json"})
except Exception as e:
logging.error('Djangoldp_notifications: Error with request: {}'.format(e))
return True
2019-03-18 11:57:57 +00:00
@receiver(post_save, sender=Notification)
def send_email_on_notification(sender, instance, created, **kwargs):
if created and instance.summary and settings.JABBER_DEFAULT_HOST and instance.user.email:
2020-02-04 14:44:11 +00:00
# get author name, and store in who
2019-10-21 15:35:37 +00:00
try:
2020-02-04 14:44:11 +00:00
# local author
2019-10-21 15:35:37 +00:00
if instance.author.startswith(settings.SITE_URL):
who = str(Model.resolve_id(instance.author.replace(settings.SITE_URL, '')))
2020-02-04 14:44:11 +00:00
# external author
2019-10-21 15:35:37 +00:00
else:
who = requests.get(instance.author).json()['name']
except:
who = "Unknown Person"
2020-02-04 14:44:11 +00:00
# get identifier for resource triggering notification, and store in where
2019-10-21 15:35:37 +00:00
try:
if instance.object.startswith(settings.SITE_URL):
where = str(Model.resolve_id(instance.object.replace(settings.SITE_URL, '')))
2019-10-02 14:08:05 +00:00
else:
2019-10-21 15:35:37 +00:00
where = requests.get(instance.object).json()['name']
2019-10-02 14:08:05 +00:00
except:
2019-10-21 15:35:37 +00:00
where = "Unknown place"
if who == where:
2019-10-21 15:35:37 +00:00
where = "has sent you a private message"
else:
2020-02-04 14:44:11 +00:00
where = "mentioned you on " + where
2019-10-21 15:35:37 +00:00
html_message = loader.render_to_string(
'email.html',
{
'on': settings.JABBER_DEFAULT_HOST,
'instance': instance,
'author': who,
'object': where
}
)
send_mail(
'Notification on ' + settings.JABBER_DEFAULT_HOST,
instance.summary,
settings.EMAIL_HOST_USER or "noreply@" + settings.JABBER_DEFAULT_HOST,
[instance.user.email],
fail_silently=True,
html_message=html_message
)