195 lines
6.4 KiB
Python
195 lines
6.4 KiB
Python
import logging
|
|
from typing import Dict, Optional
|
|
|
|
from blender_id_oauth_client import signals as bid_signals
|
|
from django import urls
|
|
from django.conf import settings
|
|
from django.contrib.auth.models import User
|
|
from django.contrib.sites.models import Site
|
|
from django.core.mail import send_mail
|
|
from django.db.models.signals import post_save, post_delete, pre_delete, pre_save
|
|
from django.dispatch import receiver
|
|
|
|
from conference_main.models import (
|
|
Event,
|
|
FestivalEntry,
|
|
Message,
|
|
MessageExchange,
|
|
Edition,
|
|
SiteSettings,
|
|
FlatFile,
|
|
)
|
|
|
|
log = logging.getLogger(__name__)
|
|
|
|
|
|
def clear_site_cache(sender: object, instance: Edition, **kwargs: object) -> None:
|
|
"""
|
|
Clear the cache for `Site.objects.get_current`.
|
|
|
|
This is needed because otherwise changes to e.g. Editions or SiteSettings
|
|
would not be taken into account when using `Site.object.get_current`.
|
|
"""
|
|
Site.objects.clear_cache()
|
|
|
|
|
|
post_save.connect(clear_site_cache, sender=Edition)
|
|
post_save.connect(clear_site_cache, sender=SiteSettings)
|
|
post_delete.connect(clear_site_cache, sender=Edition)
|
|
post_delete.connect(clear_site_cache, sender=SiteSettings)
|
|
|
|
|
|
@receiver(bid_signals.user_created)
|
|
def set_profile_fullname(
|
|
sender: object, instance: User, oauth_info: Dict[str, str], **kwargs: object
|
|
) -> None:
|
|
"""Create a Profile when a new User is created via OAuth"""
|
|
my_log = log.getChild('create_profile')
|
|
if not instance.profile:
|
|
my_log.info('NOT updating user full_name of user %s, as they have no Profile')
|
|
return
|
|
|
|
my_log.info('Updating Profile full_name as result of OAuth login of %s', instance.pk)
|
|
instance.profile.full_name = oauth_info['full_name']
|
|
instance.profile.save()
|
|
|
|
|
|
@receiver(post_save, sender=User)
|
|
def create_profile(
|
|
sender: object, instance: User, raw: bool, created: bool, **kwargs: object
|
|
) -> None:
|
|
from conference_main.models import Profile
|
|
|
|
if raw:
|
|
return
|
|
|
|
if not created:
|
|
return
|
|
|
|
my_log = log.getChild('create_profile')
|
|
try:
|
|
profile = instance.profile
|
|
except Profile.DoesNotExist:
|
|
pass
|
|
else:
|
|
my_log.debug(
|
|
'Newly created User %d already has a Profile %d, not creating new one',
|
|
instance.pk,
|
|
profile.pk,
|
|
)
|
|
return
|
|
|
|
my_log.info('Creating new Profile due to creation of user %s', instance.pk)
|
|
Profile.objects.create(user=instance)
|
|
|
|
|
|
@receiver(post_save, sender=MessageExchange)
|
|
def message_created(
|
|
sender: object, instance: MessageExchange, raw: bool, created: bool, **kwargs: object
|
|
) -> None:
|
|
if raw:
|
|
return
|
|
|
|
if not created:
|
|
return
|
|
|
|
# TODO(fsiddi) Send email asynchronously
|
|
# TODO(fsiddi) Extend logging
|
|
log.debug('Sending email notification about new message')
|
|
|
|
# If object belongs to staff, skip notifications
|
|
# TODO(fsiddi) enable once we are happy with the look of mails
|
|
# if instance.content_object.user.is_staff:
|
|
# return
|
|
|
|
if isinstance(instance.content_object, Event):
|
|
send_email_notification_for_event_message(instance.content_object, instance.message)
|
|
elif isinstance(instance.content_object, FestivalEntry):
|
|
send_email_notification_for_festival_entry_message(
|
|
instance.content_object, instance.message
|
|
)
|
|
|
|
|
|
def send_email_notification_for_event_message(event: Event, message: Message) -> None:
|
|
presentation_url = urls.reverse(
|
|
'presentation_detail', kwargs={'edition_path': event.edition.path, 'pk': event.pk}
|
|
)
|
|
|
|
# Build URL pointing directly to the message
|
|
current_site = Site.objects.get_current()
|
|
presentation_url = f'http://{current_site}{presentation_url}review/#message-{message.id}'
|
|
|
|
# If staff posted a message, notify speaker (unless speaker is staff)
|
|
if message.user.is_staff:
|
|
# TODO(fsiddi) Improve content and layout of the message
|
|
send_mail(
|
|
f'New comment on your {event.edition.title} presentation',
|
|
'Hi,\n\n'
|
|
f'There is a new comment on your Blender Conference presentation. \n'
|
|
f'Check it out at {presentation_url} \n\n'
|
|
f'{event.edition.title} team',
|
|
settings.DEFAULT_FROM_EMAIL,
|
|
[event.user.email],
|
|
fail_silently=False,
|
|
)
|
|
# In any other case, notify staff
|
|
else:
|
|
send_mail(
|
|
f'New comment on presentation "{event.name}"',
|
|
'Hi, \n\n'
|
|
f'There is a new comment on presentation "{event.name}". \n'
|
|
f'Check it out at {presentation_url} \n\n',
|
|
settings.DEFAULT_FROM_EMAIL,
|
|
[settings.DEFAULT_REPLY_TO_EMAIL],
|
|
fail_silently=False,
|
|
)
|
|
|
|
|
|
def send_email_notification_for_festival_entry_message(
|
|
festival_entry: FestivalEntry, message: Message
|
|
) -> None:
|
|
festival_entry_url = urls.reverse(
|
|
'festival_entry_detail',
|
|
kwargs={'edition_path': festival_entry.edition.path, 'pk': festival_entry.pk},
|
|
)
|
|
festival_entry_url = f'https://conference.blender.org{festival_entry_url}'
|
|
|
|
if message.user.is_staff:
|
|
# If staff posted a message, notify speaker.
|
|
send_mail(
|
|
'New comment on your Suzanne Awards festival entry',
|
|
'Hi,\n\n'
|
|
f'There is a new comment on your Blender Conference festival entry. \n'
|
|
f'Check it out at {festival_entry_url} \n\n'
|
|
f'Blender Conference 2019 team',
|
|
settings.DEFAULT_FROM_EMAIL,
|
|
[festival_entry.user.email],
|
|
fail_silently=False,
|
|
)
|
|
else:
|
|
# If owner posted a message, notify staff.
|
|
send_mail(
|
|
f'New comment on festival entry "{festival_entry.title}"',
|
|
'Hi, \n\n'
|
|
f'There is a new comment on festival entry "{festival_entry.title}". \n'
|
|
f'Check it out at {festival_entry_url} \n\n',
|
|
settings.DEFAULT_FROM_EMAIL,
|
|
[settings.DEFAULT_REPLY_TO_EMAIL],
|
|
fail_silently=False,
|
|
)
|
|
|
|
|
|
@receiver(pre_delete, sender=FlatFile)
|
|
def delete_flatfile_on_delete(sender: object, instance: FlatFile, **kwargs: object) -> None:
|
|
instance.file.delete(save=False)
|
|
|
|
|
|
@receiver(pre_save, sender=FlatFile)
|
|
def delete_flatfile_on_change(sender: object, instance: FlatFile, **kwargs: object) -> None:
|
|
if kwargs.get('raw', False):
|
|
return
|
|
|
|
original_flatfile: Optional[FlatFile] = FlatFile.objects.filter(pk=instance.pk).first()
|
|
if original_flatfile and original_flatfile.file != instance.file:
|
|
original_flatfile.file.delete(save=False)
|