finished primitive email notifications.
This commit is contained in:
@@ -1,6 +1,10 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
# E-Mails
|
||||
EMAIL_SENDER = 'Jens Kleineheismann <kleineheismann@kit.edu>'
|
||||
BASE_URL = 'http://localhost:8000'
|
||||
|
||||
# Auth Config
|
||||
MANAGE_ALL_GROUP = 'Tourenreferenten'
|
||||
MANAGE_W_GROUP = 'Wanderreferenten'
|
||||
|
||||
@@ -1,11 +1,17 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import logging
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.contrib.auth.models import Group
|
||||
from django.core.mail import EmailMessage
|
||||
from django.template.loader import get_template
|
||||
|
||||
from . import config
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class AbstractMail(object):
|
||||
_sender = config.EMAIL_SENDER
|
||||
_subject = 'Generic Mail'
|
||||
|
||||
def _get_subject(self, **kwargs):
|
||||
@@ -20,41 +26,67 @@ class AbstractMail(object):
|
||||
def send(self):
|
||||
subject = self._get_subject()
|
||||
body = self._get_body()
|
||||
sender = self._sender
|
||||
recipients = self._get_recipients()
|
||||
|
||||
emo = EmailMessage(subject=subject, body=body, to=recipients)
|
||||
emo = EmailMessage(subject=subject, body=body, from_email=sender, to=recipients)
|
||||
logger.debug('sending mail to %s', recipients)
|
||||
emo.send()
|
||||
|
||||
|
||||
class AbstractEventMail(AbstractMail):
|
||||
_subject = 'DAV Events'
|
||||
_subject = u'[DAV Veranstaltungen]'
|
||||
_template_name = 'dav_events/emails/default.txt'
|
||||
|
||||
def __init__(self, event):
|
||||
self._event = event
|
||||
|
||||
def _get_body(self):
|
||||
template_name = self._template_name
|
||||
template = get_template(template_name)
|
||||
context = {
|
||||
'base_url': config.BASE_URL,
|
||||
}
|
||||
context.update(self._event.get_template_context())
|
||||
return template.render(context)
|
||||
|
||||
|
||||
class NewEventMail(AbstractEventMail):
|
||||
def get_recipients(self):
|
||||
r = '{fullname} <{email}>'.format(fullname=self._event.owner.get_fullname(),
|
||||
_template_name = 'dav_events/emails/new_event.txt'
|
||||
|
||||
def _get_subject(self, **kwargs):
|
||||
s = super(NewEventMail, self)._get_subject(**kwargs)
|
||||
s += u' Neue Veranstaltung angelegt'
|
||||
return s
|
||||
|
||||
def _get_recipients(self):
|
||||
r = '{fullname} <{email}>'.format(fullname=self._event.owner.get_full_name(),
|
||||
email=self._event.owner.email)
|
||||
return [r]
|
||||
|
||||
|
||||
class NewEventToAcceptMail(AbstractEventMail):
|
||||
def get_recipients(self):
|
||||
class EventToAcceptMail(AbstractEventMail):
|
||||
_template_name = 'dav_events/emails/event_to_accept.txt'
|
||||
|
||||
def _get_subject(self, **kwargs):
|
||||
s = super(EventToAcceptMail, self)._get_subject(**kwargs)
|
||||
s += u' Neue Veranstaltung freigeben'
|
||||
return s
|
||||
|
||||
def _get_recipients(self):
|
||||
recipients = []
|
||||
|
||||
sport = self._event.sport
|
||||
group_var_name = 'MANAGE_{K}_GROUP'.format(sport)
|
||||
group_var_name = 'MANAGE_{}_GROUP'.format(sport)
|
||||
group_name = getattr(config, group_var_name, None)
|
||||
if group_name:
|
||||
try:
|
||||
group = Group.objects.get(name=group_name)
|
||||
for user in group.user_set:
|
||||
r = '{fullname} <{email}>'.format(fullname=user.get_fullname(),
|
||||
for user in group.user_set.all():
|
||||
r = '{fullname} <{email}>'.format(fullname=user.get_full_name(),
|
||||
email=user.email)
|
||||
recipients.append(r)
|
||||
except Group.DoesNotExists:
|
||||
except Group.DoesNotExist:
|
||||
pass
|
||||
|
||||
group_var_name = 'MANAGE_ALL_GROUP'
|
||||
@@ -62,25 +94,39 @@ class NewEventToAcceptMail(AbstractEventMail):
|
||||
if group_name:
|
||||
try:
|
||||
group = Group.objects.get(name=group_name)
|
||||
for user in group.user_set:
|
||||
r = '{fullname} <{email}>'.format(fullname=user.get_fullname(),
|
||||
for user in group.user_set.all():
|
||||
r = '{fullname} <{email}>'.format(fullname=user.get_full_name(),
|
||||
email=user.email)
|
||||
recipients.append(r)
|
||||
except Group.DoesNotExists:
|
||||
except Group.DoesNotExist:
|
||||
pass
|
||||
|
||||
return recipients
|
||||
|
||||
|
||||
class EventAcceptedMail(AbstractEventMail):
|
||||
def get_recipients(self):
|
||||
r = '{fullname} <{email}>'.format(fullname=self._event.owner.get_fullname(),
|
||||
_template_name = 'dav_events/emails/event_accepted.txt'
|
||||
|
||||
def _get_subject(self, **kwargs):
|
||||
s = super(EventAcceptedMail, self)._get_subject(**kwargs)
|
||||
s += u' Veranstaltung wurde freigegeben'
|
||||
return s
|
||||
|
||||
def _get_recipients(self):
|
||||
r = '{fullname} <{email}>'.format(fullname=self._event.owner.get_full_name(),
|
||||
email=self._event.owner.email)
|
||||
return [r]
|
||||
|
||||
|
||||
class NewEventToPublishMail(AbstractEventMail):
|
||||
def get_recipients(self):
|
||||
class EventToPublishMail(AbstractEventMail):
|
||||
_template_name = 'dav_events/emails/event_to_publish.txt'
|
||||
|
||||
def _get_subject(self, **kwargs):
|
||||
s = super(EventToPublishMail, self)._get_subject(**kwargs)
|
||||
s += u' Veranstaltung veröffentlichen'
|
||||
return s
|
||||
|
||||
def _get_recipients(self):
|
||||
recipients = []
|
||||
|
||||
group_var_name = 'INCREMENTAL_PUBLISHER_GROUP'
|
||||
@@ -88,12 +134,11 @@ class NewEventToPublishMail(AbstractEventMail):
|
||||
if group_name:
|
||||
try:
|
||||
group = Group.objects.get(name=group_name)
|
||||
for user in group.user_set:
|
||||
r = '{fullname} <{email}>'.format(fullname=user.get_fullname(),
|
||||
for user in group.user_set.all():
|
||||
r = '{fullname} <{email}>'.format(fullname=user.get_full_name(),
|
||||
email=user.email)
|
||||
recipients.append(r)
|
||||
except Group.DoesNotExists:
|
||||
except Group.DoesNotExist:
|
||||
pass
|
||||
|
||||
return recipients
|
||||
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import os
|
||||
from babel.dates import format_date
|
||||
from django.conf import settings
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.db import models
|
||||
from django.template.loader import get_template
|
||||
from django.utils import timezone
|
||||
@@ -10,6 +12,7 @@ from django_countries.fields import CountryField
|
||||
|
||||
from . import choices
|
||||
from . import config
|
||||
from . import emails
|
||||
|
||||
CHOICE_FIELD_MAX_LENGTH = 25
|
||||
|
||||
@@ -136,10 +139,13 @@ class Event(models.Model):
|
||||
sport=self.sport,
|
||||
first_day=self.first_day)
|
||||
|
||||
def save(self, notify=None, **kwargs):
|
||||
def get_absolute_url(self):
|
||||
return reverse('dav_events:event_detail', kwargs={'pk': self.pk})
|
||||
|
||||
def save(self, **kwargs):
|
||||
emails_to_send = []
|
||||
|
||||
if not self.id:
|
||||
if notify is None:
|
||||
notify = True
|
||||
user_model = get_user_model()
|
||||
try:
|
||||
owner = user_model.objects.get(username=self.trainer_email.lower())
|
||||
@@ -151,19 +157,24 @@ class Event(models.Model):
|
||||
)
|
||||
owner.save()
|
||||
self.owner = owner
|
||||
emails_to_send.append(emails.NewEventMail(event=self))
|
||||
emails_to_send.append(emails.EventToAcceptMail(event=self))
|
||||
|
||||
super(Event, self).save(**kwargs)
|
||||
if notify:
|
||||
self.send_notification()
|
||||
|
||||
def send_notification(self):
|
||||
pass
|
||||
for email in emails_to_send:
|
||||
email.send()
|
||||
|
||||
def accept(self):
|
||||
if not self.accepted:
|
||||
self.accepted = True
|
||||
self.accepted_at = timezone.now()
|
||||
self.save(notify=True)
|
||||
self.save()
|
||||
emails_to_send = [
|
||||
emails.EventAcceptedMail(event=self),
|
||||
emails.EventToPublishMail(event=self)
|
||||
]
|
||||
for email in emails_to_send:
|
||||
email.send()
|
||||
|
||||
def get_short_date(self, begin_date=None, end_date=None):
|
||||
if begin_date is None:
|
||||
@@ -195,7 +206,7 @@ class Event(models.Model):
|
||||
else:
|
||||
return None
|
||||
|
||||
def _get_context(self):
|
||||
def get_template_context(self):
|
||||
context = {
|
||||
'event': self,
|
||||
'mode': self.mode,
|
||||
@@ -248,7 +259,12 @@ class Event(models.Model):
|
||||
}
|
||||
return context
|
||||
|
||||
def render_as_text(self):
|
||||
template_name = os.path.join('dav_events', 'event.txt')
|
||||
template = get_template(template_name)
|
||||
return template.render(self.get_template_context())
|
||||
|
||||
def render_as_html(self):
|
||||
template_name = os.path.join('dav_events', 'event.html')
|
||||
template = get_template(template_name)
|
||||
return template.render(self._get_context())
|
||||
return template.render(self.get_template_context())
|
||||
|
||||
1
dav_events/templates/dav_events/emails/default.txt
Normal file
1
dav_events/templates/dav_events/emails/default.txt
Normal file
@@ -0,0 +1 @@
|
||||
{{ event.render_as_text }}
|
||||
@@ -0,0 +1,9 @@
|
||||
Hallo {{ trainer_firstname }},
|
||||
|
||||
deine folgende Veranstaltung wurde von einem Tourenreferent freigegeben:
|
||||
|
||||
-----
|
||||
{{ event.render_as_text }}-----
|
||||
|
||||
URL: {{ base_url }}{{ event.get_absolute_url }}
|
||||
Die Redaktion wurden informiert, um deine Veranstaltung zu veröffentlichen.
|
||||
@@ -0,0 +1,9 @@
|
||||
Hallo Tourenreferenten,
|
||||
|
||||
{{ trainer_firstname }} {{ trainer_familyname }} hat eine neue Veranstaltung angelegt:
|
||||
|
||||
-----
|
||||
{{ event.render_as_text }}-----
|
||||
|
||||
Ihr könnt die Veranstaltung unter folgender URL freigeben:
|
||||
{{ base_url }}{{ event.get_absolute_url }}
|
||||
56
dav_events/templates/dav_events/emails/event_to_publish.txt
Normal file
56
dav_events/templates/dav_events/emails/event_to_publish.txt
Normal file
@@ -0,0 +1,56 @@
|
||||
{% load i18n %}Hallo Redaktionsteam,
|
||||
|
||||
{{ trainer_firstname }} {{ trainer_familyname }} hat eine neue Veranstaltung angelegt:
|
||||
|
||||
-----
|
||||
{{ event.render_as_text }}-----
|
||||
|
||||
Die Veranstaltung wurde zur Veröffentlichung frei gegeben.
|
||||
|
||||
----- HTML Joomla -----
|
||||
{{ sport|upper }}**/{{ first_day|date:'y' }} - {{ title }}
|
||||
|
||||
<h6>{{ short_date }}{% if alt_short_date %}<br />
|
||||
({% trans 'Ersatztermin' %}: {{ alt_short_date }})
|
||||
{% endif %}</h6>
|
||||
<p>{{ description|linebreaksbr }}</p>
|
||||
{% if mode == 'training' %}
|
||||
<p>{% trans 'Kursinhalte' %}:</p>
|
||||
{% if course_topic_2 %}<ul>
|
||||
<li>{{ course_topic_1 }}</li>
|
||||
<li>{{ course_topic_2 }}</li>
|
||||
{% if course_topic_3 %} <li>{{ course_topic_3 }}</li>
|
||||
{% endif %}{% if course_topic_4 %} <li>{{ course_topic_4 }}</li>
|
||||
{% endif %}{% if course_topic_5 %} <li>{{ course_topic_5 }}</li>
|
||||
{% endif %}{% if course_topic_6 %} <li>{{ course_topic_6 }}</li>
|
||||
{% endif %}</ul>
|
||||
{% else %}<p>{{ course_topic_1|linebreaksbr }}</p>{% endif %}
|
||||
<p>{% trans 'Kursziele' %}:</p>
|
||||
{% if course_goal_2 %}<ul>
|
||||
<li>{{ course_goal_1 }}</li>
|
||||
<li>{{ course_goal_2 }}</li>
|
||||
{% if course_goal_3 %} <li>{{ course_goal_3 }}</li>
|
||||
{% endif %}{% if course_goal_4 %} <li>{{ course_goal_4 }}</li>
|
||||
{% endif %}{% if course_goal_5 %} <li>{{ course_goal_5 }}</li>
|
||||
{% endif %}{% if course_goal_6 %} <li>{{ course_goal_6 }}</li>
|
||||
{% endif %}</ul>
|
||||
{% else %}<p>{{ course_goal_1|linebreaksbr }}</p>{% endif %}
|
||||
{% endif %}<hr id="system-readmore" />
|
||||
|
||||
{% if requirements %}<strong>{% trans 'Anforderungen' %}:</strong> {{ requirements }}<br />
|
||||
{% endif %}{% if equipment %}<strong>{% trans 'Ausrüstung' %}:</strong> {{ equipment }}<br />
|
||||
{% endif %}{% if location %}<strong>{% trans 'Ort' %}:</strong> {{ location }}<br />
|
||||
{% endif %}{% if basecamp %}<strong>{% trans 'Stützpunkt' %}:</strong> {{ basecamp }}<br />
|
||||
{% endif %}{% if accommodation and accommodation != 'NONE' %}<strong>{% trans 'Unterkunft' %}:</strong> {% if accommodation == 'OTHER' %}{{ accommodation_other }}{% else %}{{ event.get_accommodation_display }}{% endif %}<br />
|
||||
{% endif %}{% if meals and meals != 'NONE' %}<strong>{% trans 'Verpflegung' %}:</strong> {% if meals == 'OTHER' %}{{ meals_other }}{% else %}{{ event.get_meals_display }}{% endif %}<br />
|
||||
{% endif %}{% if transport and transport != 'NONE' %}<strong>{% trans 'Anfahrt' %}:</strong> {% if transport == 'OTHER' %}{{ transport_other }}{% else %}{{ event.get_transport_display }}{% endif %}<br />
|
||||
{% endif %}{% if meeting_point and meeting_point != 'NONE' %}<strong>{% trans 'Treffpunkt' %}:</strong> {% if meeting_time %}{{ meeting_time|time:'G:i'|cut:':00' }} Uhr, {% endif %}{% if meeting_point == 'OTHER' %}{{ meeting_point_other }}{% else %}{{ event.get_meeting_point_display }}{% endif %}<br />
|
||||
{% endif %}{% if pre_meeting_1 %}{% if pre_meeting_2 %}<strong>{% trans 'Vortreffen' %} 1:</strong> {{ pre_meeting_1|date:'l, d. F Y, G:i'|cut:':00' }} {% trans 'Uhr' %}, DAV {% trans 'Sektionszentrum' %}<br />
|
||||
<strong>{% trans 'Vortreffen' %} 2:</strong> {{ pre_meeting_2|date:'l, d. F Y, G:i'|cut:':00' }} {% trans 'Uhr' %}, DAV {% trans 'Sektionszentrum' %}<br />
|
||||
{% else %}<strong>{% trans 'Vortreffen' %}:</strong> {{ pre_meeting_1|date:'l, d. F Y, G:i'|cut:':00' }} {% trans 'Uhr' %}, DAV {% trans 'Sektionszentrum' %}<br />{% endif %}
|
||||
{% endif %}{% if min_participants > 0 or max_participants > 0 %}<strong>{% trans 'Teilnehmerzahl' %}:</strong> {% if min_participants > 0 and max_participants > 0 %}{{ min_participants }} - {{ max_participants }} {% trans 'Teilnehmer' %}{% elif min_participants > 0 %}min. {{ min_participants }} {% trans 'Teilnehmer' %}{% else %}max. {{ max_participants }} {% trans 'Teilnehmer' %}{% endif %}<br />
|
||||
{% endif %}{% if charge > 0 or additional_costs %}<strong>{% trans 'Kosten' %}:</strong> {% if charge > 0 %}{{ charge|floatformat:'-2' }} € {% trans 'Teilnahmegebühr' %}{% endif %}{% if additional_costs %}{% if charge > 0 %}{% trans 'zzgl.' %}{% endif %}{{ additional_costs }}{% endif %}<br />
|
||||
{% endif %}{% if deadline %}<strong>{% trans 'Anmeldeschluss' %}:</strong> {{ deadline|date:'l, d. F Y' }}<br />
|
||||
{% endif %}{% if trainer_2_fullname %}{% if mode == 'training' %}<strong>{% trans 'Ausbildungsteam' %}:</strong>{% else %}<strong>{% trans 'Team' %}:</strong>{% endif %} XXX <br />
|
||||
{% endif %}{% if trainer_familyname %}<strong>{% trans 'Leitung' %}:</strong> {{ trainer_firstname }} {{ trainer_familyname }}{% if trainer_email %} (<a href="mailto:{{ trainer_email }}">{{ trainer_email }}</a>){% endif %}{% if trainer_phone %} {{ trainer_phone }}{% endif %}
|
||||
{% endif %}-----
|
||||
9
dav_events/templates/dav_events/emails/new_event.txt
Normal file
9
dav_events/templates/dav_events/emails/new_event.txt
Normal file
@@ -0,0 +1,9 @@
|
||||
Hallo {{ trainer_firstname }},
|
||||
|
||||
du hast die folgende Veranstaltung angelegt:
|
||||
|
||||
-----
|
||||
{{ event.render_as_text }}-----
|
||||
|
||||
URL: {{ base_url }}{{ event.get_absolute_url }}
|
||||
Die entsprechenden Referenten wurden informiert, um deine Veranstaltung frei zu geben.
|
||||
46
dav_events/templates/dav_events/event.txt
Normal file
46
dav_events/templates/dav_events/event.txt
Normal file
@@ -0,0 +1,46 @@
|
||||
{% load i18n %}{{ sport|upper }}**/{{ first_day|date:'y' }} - {{ title }}
|
||||
|
||||
{{ short_date }}
|
||||
{% if alt_short_date %}({% trans 'Ersatztermin' %}: {{ alt_short_date }})
|
||||
{% endif %}
|
||||
{{ description }}
|
||||
{% if mode == 'training' %}
|
||||
{% trans 'Kursinhalte' %}:
|
||||
{% if course_topic_2 %}
|
||||
- {{ course_topic_1 }}
|
||||
- {{ course_topic_2 }}
|
||||
{% if course_topic_3 %} - {{ course_topic_3 }}
|
||||
{% endif %}{% if course_topic_4 %} - {{ course_topic_4 }}
|
||||
{% endif %}{% if course_topic_5 %} - {{ course_topic_5 }}
|
||||
{% endif %}{% if course_topic_6 %} - {{ course_topic_6 }}
|
||||
{% endif %}{% else %}
|
||||
{{ course_topic_1 }}
|
||||
{% endif %}
|
||||
{% trans 'Kursziele' %}:
|
||||
{% if course_goal_2 %}
|
||||
- {{ course_goal_1 }}
|
||||
- {{ course_goal_2 }}
|
||||
{% if course_goal_3 %} - {{ course_goal_3 }}
|
||||
{% endif %}{% if course_goal_4 %} - {{ course_goal_4 }}
|
||||
{% endif %}{% if course_goal_5 %} - {{ course_goal_5 }}
|
||||
{% endif %}{% if course_goal_6 %} - {{ course_goal_6 }}
|
||||
{% endif %}{% else %}
|
||||
{{ course_goal_1 }}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% if requirements %}{% trans 'Anforderungen' %}: {{ requirements }}
|
||||
{% endif %}{% if equipment %}{% trans 'Ausrüstung' %}: {{ equipment }}
|
||||
{% endif %}{% if location %}{% trans 'Ort' %}: {{ location }}
|
||||
{% endif %}{% if basecamp %}{% trans 'Stützpunkt' %}: {{ basecamp }}
|
||||
{% endif %}{% if accommodation and accommodation != 'NONE' %}{% trans 'Unterkunft' %}: {% if accommodation == 'OTHER' %}{{ accommodation_other }}{% else %}{{ event.get_accommodation_display }}{% endif %}
|
||||
{% endif %}{% if meals and meals != 'NONE' %}{% trans 'Verpflegung' %}: {% if meals == 'OTHER' %}{{ meals_other }}{% else %}{{ event.get_meals_display }}{% endif %}
|
||||
{% endif %}{% if transport and transport != 'NONE' %}{% trans 'Anfahrt' %}: {% if transport == 'OTHER' %}{{ transport_other }}{% else %}{{ event.get_transport_display }}{% endif %}
|
||||
{% endif %}{% if meeting_point and meeting_point != 'NONE' %}{% trans 'Treffpunkt' %}: {% if meeting_time %}{{ meeting_time|time:'G:i'|cut:':00' }} Uhr, {% endif %}{% if meeting_point == 'OTHER' %}{{ meeting_point_other }}{% else %}{{ event.get_meeting_point_display }}{% endif %}
|
||||
{% endif %}{% if pre_meeting_1 %}{% if pre_meeting_2 %}{% trans 'Vortreffen' %} 1: {{ pre_meeting_1|date:'l, d. F Y, G:i'|cut:':00' }} {% trans 'Uhr' %}, DAV {% trans 'Sektionszentrum' %}
|
||||
{% trans 'Vortreffen' %} 2: {{ pre_meeting_2|date:'l, d. F Y, G:i'|cut:':00' }} {% trans 'Uhr' %}, DAV {% trans 'Sektionszentrum' %}{% else %}{% trans 'Vortreffen' %}: {{ pre_meeting_1|date:'l, d. F Y, G:i'|cut:':00' }} {% trans 'Uhr' %}, DAV {% trans 'Sektionszentrum' %}{% endif %}
|
||||
{% endif %}{% if min_participants > 0 or max_participants > 0 %}{% trans 'Teilnehmerzahl' %}: {% if min_participants > 0 and max_participants > 0 %}{{ min_participants }} - {{ max_participants }} {% trans 'Teilnehmer' %}{% elif min_participants > 0 %}min. {{ min_participants }} {% trans 'Teilnehmer' %}{% else %}max. {{ max_participants }} {% trans 'Teilnehmer' %}{% endif %}
|
||||
{% endif %}{% if charge > 0 or additional_costs %}{% trans 'Kosten' %}: {% if charge > 0 %}{{ charge|floatformat:'-2' }} € {% trans 'Teilnahmegebühr' %}{% endif %}{% if additional_costs %}{% if charge > 0 %} {% trans 'zzgl.' %} {% endif %}{{ additional_costs }}{% endif %}
|
||||
{% endif %}{% if deadline %}{% trans 'Anmeldeschluss' %}: {{ deadline|date:'l, d. F Y' }}
|
||||
{% endif %}{% if trainer_2_fullname %}{% if mode == 'training' %}{% trans 'Ausbildungsteam' %}:{% else %}{% trans 'Team' %}:{% endif %} XXX
|
||||
{% endif %}{% if trainer_familyname %}{% trans 'Leitung' %}: {{ trainer_firstname }} {{ trainer_familyname }}{% if trainer_email %} ({{ trainer_email }}){% endif %}{% if trainer_phone %} {{ trainer_phone }}{% endif %}
|
||||
{% endif %}
|
||||
Reference in New Issue
Block a user