Fix #5435 - Bad comment links cause server error
[mediagoblin.git] / mediagoblin / notifications / __init__.py
1 # GNU MediaGoblin -- federated, autonomous media hosting
2 # Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
3 #
4 # This program is free software: you can redistribute it and/or modify
5 # it under the terms of the GNU Affero General Public License as published by
6 # the Free Software Foundation, either version 3 of the License, or
7 # (at your option) any later version.
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU Affero General Public License for more details.
13 #
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16
17 import logging
18
19 from mediagoblin.db.models import Notification, CommentSubscription, User, \
20 Comment, GenericModelReference
21 from mediagoblin.notifications.task import email_notification_task
22 from mediagoblin.notifications.tools import generate_comment_message
23
24 _log = logging.getLogger(__name__)
25
26 def trigger_notification(comment, media_entry, request):
27 '''
28 Send out notifications about a new comment.
29 '''
30 # Verify we have the Comment object and not any other type e.g. TextComment
31 if not isinstance(comment, Comment):
32 raise ValueError("Must provide Comment to trigger_notification")
33
34 # Get the associated object associated to the Comment wrapper.
35 comment_object = comment.comment()
36
37 subscriptions = CommentSubscription.query.filter_by(
38 media_entry_id=media_entry.id).all()
39
40 for subscription in subscriptions:
41 # Check the user wants to be notified, if not, skip.
42 if not subscription.notify:
43 continue
44
45 # If the subscriber is the current actor, don't bother.
46 if comment_object.get_actor == subscription.user:
47 continue
48
49 cn = Notification(
50 user_id=subscription.user_id,
51 )
52 cn.obj = comment
53 cn.save()
54
55 if subscription.send_email:
56 message = generate_comment_message(
57 subscription.user,
58 comment,
59 media_entry,
60 request)
61
62 from mediagoblin.notifications.task import email_notification_task
63 email_notification_task.apply_async([cn.id, message])
64
65
66 def mark_notification_seen(notification):
67 if notification:
68 notification.seen = True
69 notification.save()
70
71
72 def mark_comment_notification_seen(comment_id, user):
73 comment = Comment.query.get(comment_id)
74
75 # If there is no comment, there is no notification
76 if comment == None:
77 return
78
79 comment_gmr = GenericModelReference.query.filter_by(
80 obj_pk=comment.id,
81 model_type=comment.__tablename__
82 ).first()
83
84 # If there is no GMR, there is no notification
85 if comment_gmr == None:
86 return
87
88 notification = Notification.query.filter_by(
89 user_id=user.id,
90 object_id=comment_gmr.id
91 ).first()
92
93 _log.debug(u'Marking {0} as seen.'.format(notification))
94
95 mark_notification_seen(notification)
96
97
98 def get_comment_subscription(user_id, media_entry_id):
99 return CommentSubscription.query.filter_by(
100 user_id=user_id,
101 media_entry_id=media_entry_id).first()
102
103 def add_comment_subscription(user, media_entry):
104 '''
105 Create a comment subscription for a User on a MediaEntry.
106
107 Uses the User's wants_comment_notification to set email notifications for
108 the subscription to enabled/disabled.
109 '''
110 cn = get_comment_subscription(user.id, media_entry.id)
111
112 if not cn:
113 cn = CommentSubscription(
114 user_id=user.id,
115 media_entry_id=media_entry.id)
116
117 cn.notify = True
118
119 if not user.wants_comment_notification:
120 cn.send_email = False
121
122 cn.save()
123
124
125 def silence_comment_subscription(user, media_entry):
126 '''
127 Silence a subscription so that the user is never notified in any way about
128 new comments on an entry
129 '''
130 cn = get_comment_subscription(user.id, media_entry.id)
131
132 if cn:
133 cn.notify = False
134 cn.send_email = False
135 cn.save()
136
137
138 def remove_comment_subscription(user, media_entry):
139 cn = get_comment_subscription(user.id, media_entry.id)
140
141 if cn:
142 cn.delete()
143
144
145 NOTIFICATION_FETCH_LIMIT = 100
146
147
148 def get_notifications(user_id, only_unseen=True):
149 query = Notification.query.filter_by(user_id=user_id)
150 wants_notifications = User.query.filter_by(id=user_id).first()\
151 .wants_notifications
152
153 # If the user does not want notifications, don't return any
154 if not wants_notifications:
155 return None
156
157 if only_unseen:
158 query = query.filter_by(seen=False)
159
160 notifications = query.limit(
161 NOTIFICATION_FETCH_LIMIT).all()
162
163 return notifications
164
165
166 def get_notification_count(user_id, only_unseen=True):
167 query = Notification.query.filter_by(user_id=user_id)
168 wants_notifications = User.query.filter_by(id=user_id).first()\
169 .wants_notifications
170
171 if only_unseen:
172 query = query.filter_by(seen=False)
173
174 # If the user doesn't want notifications, don't show any
175 if not wants_notifications:
176 count = None
177 else:
178 count = query.count()
179
180 return count