|
|
@ -0,0 +1,73 @@ |
|
|
|
|
|
"""Web API endpoints related to comment notifications.""" |
|
|
|
|
|
|
|
|
|
|
|
from datetime import datetime |
|
|
|
|
|
|
|
|
|
|
|
from marshmallow.fields import DateTime |
|
|
|
|
|
from pyramid.request import Request |
|
|
|
|
|
from pyramid.response import Response |
|
|
|
|
|
from sqlalchemy.dialects.postgresql import insert |
|
|
|
|
|
from webargs.pyramidparser import use_kwargs |
|
|
|
|
|
from zope.sqlalchemy import mark_changed |
|
|
|
|
|
|
|
|
|
|
|
from tildes.lib.datetime import utc_now |
|
|
|
|
|
from tildes.models.comment import CommentNotification |
|
|
|
|
|
from tildes.models.topic import TopicVisit |
|
|
|
|
|
from tildes.views.decorators import ic_view_config |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ic_view_config( |
|
|
|
|
|
route_name='mark_notifications_read_before', request_method='PUT', |
|
|
|
|
|
) |
|
|
|
|
|
@use_kwargs( |
|
|
|
|
|
{'last_notification_seen': DateTime(required=True)}, |
|
|
|
|
|
locations=('matchdict',), |
|
|
|
|
|
) |
|
|
|
|
|
def put_notifications_read_before( |
|
|
|
|
|
request: Request, |
|
|
|
|
|
last_notification_seen: datetime, |
|
|
|
|
|
) -> Response: |
|
|
|
|
|
"""Clear all user comment notifications before the latest displayed.""" |
|
|
|
|
|
notifications = ( |
|
|
|
|
|
request.query(CommentNotification) |
|
|
|
|
|
.join_all_relationships() |
|
|
|
|
|
.filter( |
|
|
|
|
|
CommentNotification.user == request.user, |
|
|
|
|
|
CommentNotification.is_unread == True, # noqa |
|
|
|
|
|
CommentNotification.created_time <= last_notification_seen, |
|
|
|
|
|
) |
|
|
|
|
|
.all() |
|
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
# If the user has the "track comment visits" feature enabled, we want to |
|
|
|
|
|
# increment the number of comments they've seen in the thread that the |
|
|
|
|
|
# comment came from, so that they don't *both* get a notification as well |
|
|
|
|
|
# as have the thread highlight with "(1 new)". This should only happen if |
|
|
|
|
|
# their last visit was before the comment was posted, however. |
|
|
|
|
|
# Below, this is implemented as a INSERT ... ON CONFLICT DO UPDATE so that |
|
|
|
|
|
# it will insert a new topic visit with 1 comment if they didn't previously |
|
|
|
|
|
# have one at all. |
|
|
|
|
|
if request.user.track_comment_visits: |
|
|
|
|
|
for notification in notifications: |
|
|
|
|
|
statement = ( |
|
|
|
|
|
insert(TopicVisit.__table__) |
|
|
|
|
|
.values( |
|
|
|
|
|
user_id=request.user.user_id, |
|
|
|
|
|
topic_id=notification.comment.topic_id, |
|
|
|
|
|
visit_time=utc_now(), |
|
|
|
|
|
num_comments=1, |
|
|
|
|
|
) |
|
|
|
|
|
.on_conflict_do_update( |
|
|
|
|
|
constraint=TopicVisit.__table__.primary_key, |
|
|
|
|
|
set_={'num_comments': TopicVisit.num_comments + 1}, |
|
|
|
|
|
where=TopicVisit.visit_time < |
|
|
|
|
|
notification.comment.created_time, |
|
|
|
|
|
) |
|
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
request.db_session.execute(statement) |
|
|
|
|
|
mark_changed(request.db_session) |
|
|
|
|
|
|
|
|
|
|
|
for notification in notifications: |
|
|
|
|
|
notification.is_unread = False |
|
|
|
|
|
|
|
|
|
|
|
return Response('Your comment notifications have been cleared.') |