Skip to content

Commit 0c170c9

Browse files
committed
feat: allow discussion notification customization
1 parent c3e235a commit 0c170c9

10 files changed

+375
-31
lines changed

udata/core/discussions/tasks.py

+74-13
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,18 @@
1+
import fnmatch
2+
3+
from urllib.parse import urlparse
4+
5+
from flask import current_app
6+
17
from udata import mail
28
from udata.i18n import lazy_gettext as _
39
from udata.core.dataset.models import Dataset
4-
from udata.core.reuse.models import Reuse
510
from udata.core.post.models import Post
11+
from udata.core.reuse.models import Reuse
12+
from udata.core.topic.models import Topic
613
from udata.tasks import connect, get_logger
714

8-
from .models import Discussion, Message
15+
from .models import Discussion
916
from .signals import (
1017
on_new_discussion, on_new_discussion_comment, on_discussion_closed
1118
)
@@ -22,15 +29,48 @@ def owner_recipients(discussion):
2229
return []
2330

2431

32+
def get_external_url(discussion):
33+
url = None
34+
if (meta_url := discussion.extras.get('notification', {}).get('external_url')):
35+
meta_url_parsed = urlparse(meta_url)
36+
if any(
37+
fnmatch.fnmatch(meta_url_parsed.netloc, pattern)
38+
for pattern in current_app.config['DISCUSSION_ALLOWED_EXTERNAL_DOMAINS']
39+
):
40+
url = f'{meta_url}#discussion-{discussion.id}'
41+
if not url:
42+
url = getattr(discussion, 'external_url', None)
43+
return url
44+
45+
46+
def get_subject_type(discussion):
47+
if (meta_name := discussion.extras.get('notification', {}).get('model_name')):
48+
if meta_name in current_app.config['DISCUSSION_ALTERNATE_MODEL_NAMES']:
49+
return meta_name
50+
return discussion.subject.verbose_name
51+
52+
2553
@connect(on_new_discussion, by_id=True)
2654
def notify_new_discussion(discussion_id):
2755
discussion = Discussion.objects.get(pk=discussion_id)
28-
if isinstance(discussion.subject, (Dataset, Reuse, Post)):
56+
if isinstance(discussion.subject, (Dataset, Reuse, Post, Topic)):
2957
recipients = owner_recipients(discussion)
58+
subject_type = get_subject_type(discussion)
3059
subject = _('Your %(type)s have a new discussion',
31-
type=discussion.subject.verbose_name)
32-
mail.send(subject, recipients, 'new_discussion',
33-
discussion=discussion, message=discussion.discussion[0])
60+
type=subject_type)
61+
external_url = get_external_url(discussion)
62+
if external_url:
63+
mail.send(
64+
subject,
65+
recipients,
66+
'new_discussion',
67+
discussion=discussion,
68+
message=discussion.discussion[0],
69+
external_url=external_url,
70+
subject_type=subject_type
71+
)
72+
else:
73+
log.warning(f'No external url could be computed for discussion {discussion.id}')
3474
else:
3575
log.warning('Unrecognized discussion subject type %s',
3676
type(discussion.subject))
@@ -40,15 +80,25 @@ def notify_new_discussion(discussion_id):
4080
def notify_new_discussion_comment(discussion_id, message=None):
4181
discussion = Discussion.objects.get(pk=discussion_id)
4282
message = discussion.discussion[message]
43-
if isinstance(discussion.subject, (Dataset, Reuse, Post)):
83+
if isinstance(discussion.subject, (Dataset, Reuse, Post, Topic)):
4484
recipients = owner_recipients(discussion) + [
4585
m.posted_by for m in discussion.discussion]
4686
recipients = list({u.id: u for u in recipients if u != message.posted_by}.values())
4787
subject = _('%(user)s commented your discussion',
4888
user=message.posted_by.fullname)
49-
50-
mail.send(subject, recipients, 'new_discussion_comment',
51-
discussion=discussion, message=message)
89+
external_url = get_external_url(discussion)
90+
if external_url:
91+
mail.send(
92+
subject,
93+
recipients,
94+
'new_discussion_comment',
95+
discussion=discussion,
96+
message=message,
97+
external_url=external_url,
98+
subject_type=get_subject_type(discussion)
99+
)
100+
else:
101+
log.warning(f'No external url could be computed for discussion {discussion.id}')
52102
else:
53103
log.warning('Unrecognized discussion subject type %s',
54104
type(discussion.subject))
@@ -58,13 +108,24 @@ def notify_new_discussion_comment(discussion_id, message=None):
58108
def notify_discussion_closed(discussion_id, message=None):
59109
discussion = Discussion.objects.get(pk=discussion_id)
60110
message = discussion.discussion[message]
61-
if isinstance(discussion.subject, (Dataset, Reuse, Post)):
111+
if isinstance(discussion.subject, (Dataset, Reuse, Post, Topic)):
62112
recipients = owner_recipients(discussion) + [
63113
m.posted_by for m in discussion.discussion]
64114
recipients = list({u.id: u for u in recipients if u != message.posted_by}.values())
65115
subject = _('A discussion has been closed')
66-
mail.send(subject, recipients, 'discussion_closed',
67-
discussion=discussion, message=message)
116+
external_url = get_external_url(discussion)
117+
if external_url:
118+
mail.send(
119+
subject,
120+
recipients,
121+
'discussion_closed',
122+
discussion=discussion,
123+
message=message,
124+
external_url=external_url,
125+
subject_type=get_subject_type(discussion),
126+
)
127+
else:
128+
log.warning(f'No external url could be computed for discussion {discussion.id}')
68129
else:
69130
log.warning('Unrecognized discussion subject type %s',
70131
type(discussion.subject))

udata/core/topic/models.py

+3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from flask import url_for
22
from mongoengine.signals import pre_save
3+
from udata.i18n import lazy_gettext as _
34
from udata.models import db, SpatialCoverage
45
from udata.search import reindex
56
from udata.tasks import as_task_param
@@ -40,6 +41,8 @@ class Topic(db.Document, Owned, db.Datetimed):
4041
'queryset_class': OwnedQuerySet,
4142
}
4243

44+
verbose_name = _('topic')
45+
4346
def __str__(self):
4447
return self.name
4548

udata/settings.py

+7-2
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,7 @@ class Defaults(object):
232232
# A list of tuples, each tuple describing a group with its title and
233233
# a list of licenses associated. Translations are not supported.
234234
# Example:
235-
# LICENSE_GROUPS = [
235+
# LICENSE_GROUPS = [
236236
# ("Autorités administratives", [
237237
# {"value": "lov2", "recommended": True, "description": "Recommandée", "code": "etalab-2.0"},
238238
# {"value": "notspecified", "description": "Le Code des relations entre le public et l’administration ne s’applique pas"}]),
@@ -264,7 +264,7 @@ class Defaults(object):
264264

265265
HARVEST_VALIDATION_CONTACT_FORM = None
266266

267-
HARVEST_MAX_CATALOG_SIZE_IN_MONGO = None # Defaults to the size of a MongoDB document
267+
HARVEST_MAX_CATALOG_SIZE_IN_MONGO = None # Defaults to the size of a MongoDB document
268268
HARVEST_GRAPHS_S3_BUCKET = None # If the catalog is bigger than `HARVEST_MAX_CATALOG_SIZE_IN_MONGO` store the graph inside S3 instead of MongoDB
269269
HARVEST_GRAPHS_S3_FILENAME_PREFIX = '' # Useful to store the graphs inside a subfolder of the bucket. For example by setting `HARVEST_GRAPHS_S3_FILENAME_PREFIX = 'graphs/'`
270270

@@ -473,6 +473,11 @@ class Defaults(object):
473473
###########################################################################
474474
MATTERMOST_WEBHOOK = None
475475

476+
# Discussion settings
477+
###########################################################################
478+
DISCUSSION_ALLOWED_EXTERNAL_DOMAINS = ['*.data.gouv.fr']
479+
DISCUSSION_ALTERNATE_MODEL_NAMES = []
480+
476481

477482
class Testing(object):
478483
'''Sane values for testing. Should be applied as override'''

udata/templates/mail/discussion_closed.html

+3-3
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
{% block body %}
55
<p style="margin: 0;padding: 0;">{{
66
_('%(user)s closed an discussion on your %(type)s %(subject)s',
7-
type=discussion.subject.verbose_name,
7+
type=subject_type,
88
user=(
99
'<a href="'|safe
1010
+ url_for('api.user', user=message.posted_by, _external=True)
@@ -14,7 +14,7 @@
1414
),
1515
subject=(
1616
'<a href="'|safe
17-
+ discussion.external_url
17+
+ external_url
1818
+ '">'|safe
1919
+ discussion.subject|string
2020
+ '</a>'|safe
@@ -38,7 +38,7 @@
3838
<td align="center">
3939
{{ mail_button(
4040
_('See the discussion'),
41-
discussion.external_url
41+
external_url
4242
) }}
4343
</td>
4444
</tr>

udata/templates/mail/discussion_closed.txt

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
{% block body %}
44
{{ _('%(user)s closed an discussion on your %(type)s %(subject)s',
5-
type=discussion.subject.verbose_name,
5+
type=subject_type,
66
user=message.posted_by.fullname,
77
subject=discussion.subject|string
88
) }}.
@@ -12,5 +12,5 @@
1212

1313

1414
{{ _('You can see the discussion on this page:') }}
15-
{{ discussion.external_url }}
15+
{{ external_url }}
1616
{% endblock %}

udata/templates/mail/new_discussion.html

+3-3
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
{% block body %}
55
<p style="margin: 0;padding: 0;">{{
66
_('%(user)s submitted a new discussion on your %(type)s %(subject)s',
7-
type=discussion.subject.verbose_name,
7+
type=subject_type,
88
user=(
99
'<a href="'|safe
1010
+ url_for('api.user', user=discussion.user, _external=True)
@@ -14,7 +14,7 @@
1414
),
1515
subject=(
1616
'<a href="'|safe
17-
+ discussion.external_url
17+
+ external_url
1818
+ '">'|safe
1919
+ discussion.subject|string
2020
+ '</a>'|safe
@@ -36,7 +36,7 @@
3636
<td align="center">
3737
{{ mail_button(
3838
_('See the discussion'),
39-
discussion.external_url
39+
external_url
4040
) }}
4141
</td>
4242
</tr>

udata/templates/mail/new_discussion.txt

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
{% block body %}
44
{{ _('%(user)s submitted a new discussion on your %(type)s %(subject)s',
5-
type=discussion.subject.verbose_name,
5+
type=subject_type,
66
user=discussion.user.fullname,
77
subject=discussion.subject|string
88
) }}.
@@ -11,5 +11,5 @@
1111
{{ _('Title') }}: {{ discussion.title }}
1212

1313
{{ _('You can see the discussion on this page:') }}
14-
{{ discussion.subject.external_url }}
14+
{{ external_url }}
1515
{% endblock %}

udata/templates/mail/new_discussion_comment.html

+3-3
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
{% block body %}
55
<p style="margin: 0;padding: 0;">{{
66
_('%(user)s commented an discussion on your %(type)s %(subject)s',
7-
type=discussion.subject.verbose_name,
7+
type=subject_type,
88
user=(
99
'<a href="'|safe
1010
+ url_for('api.user', user=message.posted_by, _external=True)
@@ -14,7 +14,7 @@
1414
),
1515
subject=(
1616
'<a href="'|safe
17-
+ discussion.external_url
17+
+ external_url
1818
+ '">'|safe
1919
+ discussion.subject|string
2020
+ '</a>'|safe
@@ -37,7 +37,7 @@
3737
<td align="center">
3838
{{ mail_button(
3939
_('See the discussion'),
40-
discussion.external_url
40+
external_url
4141
) }}
4242
</td>
4343
</tr>

udata/templates/mail/new_discussion_comment.txt

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
{% block body %}
44
{{ _('%(user)s commented an discussion on your %(type)s %(subject)s',
5-
type=discussion.subject.verbose_name,
5+
type=subject_type,
66
user=message.posted_by.fullname,
77
subject=discussion.subject|string
88
) }}.
@@ -12,5 +12,5 @@
1212

1313

1414
{{ _('You can see the discussion on this page:') }}
15-
{{ discussion.external_url }}
15+
{{ external_url }}
1616
{% endblock %}

0 commit comments

Comments
 (0)