mirror of
https://github.com/zulip/zulip.git
synced 2025-11-03 13:33:24 +00:00
muting: Record DateTime when a Topic is muted.
This includes the necessary migration to add the date_muted field to the MutedTopic class and populates it with a hard coded value.
This commit is contained in:
@@ -5286,8 +5286,11 @@ def do_set_alert_words(user_profile: UserProfile, alert_words: List[str]) -> Non
|
||||
set_user_alert_words(user_profile, alert_words)
|
||||
notify_alert_words(user_profile, alert_words)
|
||||
|
||||
def do_mute_topic(user_profile: UserProfile, stream: Stream, recipient: Recipient, topic: str) -> None:
|
||||
add_topic_mute(user_profile, stream.id, recipient.id, topic)
|
||||
def do_mute_topic(user_profile: UserProfile, stream: Stream, recipient: Recipient, topic: str,
|
||||
date_muted: Optional[datetime.datetime]=None) -> None:
|
||||
if date_muted is None:
|
||||
date_muted = timezone_now()
|
||||
add_topic_mute(user_profile, stream.id, recipient.id, topic, date_muted)
|
||||
event = dict(type="muted_topics", muted_topics=get_topic_mutes(user_profile))
|
||||
send_event(user_profile.realm, event, [user_profile.id])
|
||||
|
||||
|
||||
@@ -247,6 +247,7 @@ ANALYTICS_TABLES = {
|
||||
DATE_FIELDS = {
|
||||
'zerver_attachment': ['create_time'],
|
||||
'zerver_message': ['last_edit_time', 'date_sent'],
|
||||
'zerver_mutedtopic': ['date_muted'],
|
||||
'zerver_realm': ['date_created'],
|
||||
'zerver_stream': ['date_created'],
|
||||
'zerver_useractivity': ['last_visit'],
|
||||
|
||||
@@ -914,6 +914,7 @@ def do_import_realm(import_dir: Path, subdomain: str, processes: int=1) -> Realm
|
||||
bulk_import_model(data, UserHotspot)
|
||||
|
||||
if 'zerver_mutedtopic' in data:
|
||||
fix_datetime_fields(data, 'zerver_mutedtopic')
|
||||
re_map_foreign_keys(data, 'zerver_mutedtopic', 'user_profile', related_table='user_profile')
|
||||
re_map_foreign_keys(data, 'zerver_mutedtopic', 'stream', related_table='stream')
|
||||
re_map_foreign_keys(data, 'zerver_mutedtopic', 'recipient', related_table='recipient')
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
from typing import Any, Callable, Dict, List, Optional
|
||||
import datetime
|
||||
|
||||
from zerver.lib.topic import (
|
||||
topic_match_sa,
|
||||
@@ -17,6 +18,8 @@ from sqlalchemy.sql import (
|
||||
Selectable
|
||||
)
|
||||
|
||||
from django.utils.timezone import now as timezone_now
|
||||
|
||||
def get_topic_mutes(user_profile: UserProfile) -> List[List[str]]:
|
||||
rows = MutedTopic.objects.filter(
|
||||
user_profile=user_profile,
|
||||
@@ -29,7 +32,8 @@ def get_topic_mutes(user_profile: UserProfile) -> List[List[str]]:
|
||||
for row in rows
|
||||
]
|
||||
|
||||
def set_topic_mutes(user_profile: UserProfile, muted_topics: List[List[str]]) -> None:
|
||||
def set_topic_mutes(user_profile: UserProfile, muted_topics: List[List[str]],
|
||||
date_muted: Optional[datetime.datetime]=None) -> None:
|
||||
|
||||
'''
|
||||
This is only used in tests.
|
||||
@@ -39,6 +43,8 @@ def set_topic_mutes(user_profile: UserProfile, muted_topics: List[List[str]]) ->
|
||||
user_profile=user_profile,
|
||||
).delete()
|
||||
|
||||
if date_muted is None:
|
||||
date_muted = timezone_now()
|
||||
for stream_name, topic_name in muted_topics:
|
||||
stream = get_stream(stream_name, user_profile.realm)
|
||||
recipient = get_stream_recipient(stream.id)
|
||||
@@ -48,14 +54,19 @@ def set_topic_mutes(user_profile: UserProfile, muted_topics: List[List[str]]) ->
|
||||
stream_id=stream.id,
|
||||
recipient_id=recipient.id,
|
||||
topic_name=topic_name,
|
||||
date_muted=date_muted,
|
||||
)
|
||||
|
||||
def add_topic_mute(user_profile: UserProfile, stream_id: int, recipient_id: int, topic_name: str) -> None:
|
||||
def add_topic_mute(user_profile: UserProfile, stream_id: int, recipient_id: int, topic_name: str,
|
||||
date_muted: Optional[datetime.datetime]=None) -> None:
|
||||
if date_muted is None:
|
||||
date_muted = timezone_now()
|
||||
MutedTopic.objects.create(
|
||||
user_profile=user_profile,
|
||||
stream_id=stream_id,
|
||||
recipient_id=recipient_id,
|
||||
topic_name=topic_name,
|
||||
date_muted=date_muted,
|
||||
)
|
||||
|
||||
def remove_topic_mute(user_profile: UserProfile, stream_id: int, topic_name: str) -> None:
|
||||
|
||||
21
zerver/migrations/0262_mutedtopic_date_muted.py
Normal file
21
zerver/migrations/0262_mutedtopic_date_muted.py
Normal file
@@ -0,0 +1,21 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.11.26 on 2020-01-17 15:26
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import datetime
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('zerver', '0261_realm_private_message_policy'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='mutedtopic',
|
||||
name='date_muted',
|
||||
field=models.DateTimeField(default=datetime.datetime(2020, 1, 1, 0, 0)),
|
||||
),
|
||||
]
|
||||
@@ -1457,12 +1457,19 @@ class MutedTopic(models.Model):
|
||||
stream = models.ForeignKey(Stream, on_delete=CASCADE)
|
||||
recipient = models.ForeignKey(Recipient, on_delete=CASCADE)
|
||||
topic_name = models.CharField(max_length=MAX_TOPIC_NAME_LENGTH)
|
||||
# The default value for date_muted is a few weeks before tracking
|
||||
# of when topics were muted was first introduced. It's designed
|
||||
# to be obviously incorrect so that users can tell it's backfilled data.
|
||||
date_muted = models.DateTimeField(default=datetime.datetime(2020, 1, 1, 0, 0, 0, 0))
|
||||
|
||||
class Meta:
|
||||
unique_together = ('user_profile', 'stream', 'topic_name')
|
||||
|
||||
def __str__(self) -> str:
|
||||
return "<MutedTopic: (%s, %s, %s)>" % (self.user_profile.email, self.stream.name, self.topic_name)
|
||||
return ("<MutedTopic: (%s, %s, %s, %s)>" % (self.user_profile.email,
|
||||
self.stream.name,
|
||||
self.topic_name,
|
||||
self.date_muted))
|
||||
|
||||
class Client(models.Model):
|
||||
name = models.CharField(max_length=30, db_index=True, unique=True) # type: str
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
from django.utils.timezone import now as timezone_now
|
||||
from datetime import timedelta
|
||||
from typing import Any, Dict
|
||||
|
||||
from zerver.lib.test_classes import ZulipTestCase
|
||||
@@ -7,6 +9,7 @@ from zerver.models import (
|
||||
get_stream,
|
||||
get_stream_recipient,
|
||||
UserProfile,
|
||||
MutedTopic
|
||||
)
|
||||
|
||||
from zerver.lib.topic_mutes import (
|
||||
@@ -39,15 +42,20 @@ class MutedTopicsTests(ZulipTestCase):
|
||||
stream_id=stream.id,
|
||||
recipient_id=recipient.id,
|
||||
topic_name='test TOPIC',
|
||||
date_muted=timezone_now(),
|
||||
)
|
||||
|
||||
mute_user(hamlet)
|
||||
user_ids = stream_topic_target.user_ids_muting_topic()
|
||||
self.assertEqual(user_ids, {hamlet.id})
|
||||
hamlet_date_muted = MutedTopic.objects.filter(user_profile=hamlet)[0].date_muted
|
||||
self.assertTrue(timezone_now() - hamlet_date_muted <= timedelta(seconds=100))
|
||||
|
||||
mute_user(cordelia)
|
||||
user_ids = stream_topic_target.user_ids_muting_topic()
|
||||
self.assertEqual(user_ids, {hamlet.id, cordelia.id})
|
||||
cordelia_date_muted = MutedTopic.objects.filter(user_profile=cordelia)[0].date_muted
|
||||
self.assertTrue(timezone_now() - cordelia_date_muted <= timedelta(seconds=100))
|
||||
|
||||
def test_add_muted_topic(self) -> None:
|
||||
user = self.example_user('hamlet')
|
||||
@@ -98,6 +106,7 @@ class MutedTopicsTests(ZulipTestCase):
|
||||
stream_id=stream.id,
|
||||
recipient_id=recipient.id,
|
||||
topic_name='Verona3',
|
||||
date_muted=timezone_now(),
|
||||
)
|
||||
self.assertIn([stream.name, 'Verona3'], get_topic_mutes(user))
|
||||
|
||||
@@ -120,6 +129,7 @@ class MutedTopicsTests(ZulipTestCase):
|
||||
stream_id=stream.id,
|
||||
recipient_id=recipient.id,
|
||||
topic_name=u'Verona3',
|
||||
date_muted=timezone_now(),
|
||||
)
|
||||
|
||||
url = '/api/v1/users/me/subscriptions/muted_topics'
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
from django.http import HttpResponse, HttpRequest
|
||||
from typing import Optional
|
||||
import datetime
|
||||
|
||||
from django.utils.timezone import now as timezone_now
|
||||
from django.utils.translation import ugettext as _
|
||||
from zerver.lib.actions import do_mute_topic, do_unmute_topic
|
||||
from zerver.lib.request import has_request_variables, REQ
|
||||
@@ -19,7 +21,8 @@ from zerver.models import UserProfile
|
||||
def mute_topic(user_profile: UserProfile,
|
||||
stream_id: Optional[int],
|
||||
stream_name: Optional[str],
|
||||
topic_name: str) -> HttpResponse:
|
||||
topic_name: str,
|
||||
date_muted: datetime.datetime) -> HttpResponse:
|
||||
if stream_name is not None:
|
||||
(stream, recipient, sub) = access_stream_by_name(user_profile, stream_name)
|
||||
else:
|
||||
@@ -29,7 +32,7 @@ def mute_topic(user_profile: UserProfile,
|
||||
if topic_is_muted(user_profile, stream.id, topic_name):
|
||||
return json_error(_("Topic already muted"))
|
||||
|
||||
do_mute_topic(user_profile, stream, recipient, topic_name)
|
||||
do_mute_topic(user_profile, stream, recipient, topic_name, date_muted)
|
||||
return json_success()
|
||||
|
||||
def unmute_topic(user_profile: UserProfile,
|
||||
@@ -66,6 +69,7 @@ def update_muted_topic(request: HttpRequest,
|
||||
stream_id=stream_id,
|
||||
stream_name=stream,
|
||||
topic_name=topic,
|
||||
date_muted=timezone_now(),
|
||||
)
|
||||
elif op == 'remove':
|
||||
return unmute_topic(
|
||||
|
||||
Reference in New Issue
Block a user