mirror of https://github.com/zulip/zulip.git
stream: Add do_change_can_remove_subscribers_group and field to objects.
This commit adds do_change_can_remove_subscriber_group function for changing can_remove_subscribers_group field of a stream. We also add can_remove_subscribers_group_id field to stream and subscription objects. This function will be helpful for writing tests in next commit. We would add API and UI support to change this setting in further commits.
This commit is contained in:
parent
86c2f6881e
commit
b9248c75f4
|
@ -50,6 +50,7 @@ exports.test_streams = {
|
||||||
is_web_public: false,
|
is_web_public: false,
|
||||||
message_retention_days: null,
|
message_retention_days: null,
|
||||||
stream_post_policy: 1,
|
stream_post_policy: 1,
|
||||||
|
can_remove_subscribers_group_id: 2,
|
||||||
},
|
},
|
||||||
test: {
|
test: {
|
||||||
name: "test",
|
name: "test",
|
||||||
|
@ -64,6 +65,7 @@ exports.test_streams = {
|
||||||
is_announcement_only: false,
|
is_announcement_only: false,
|
||||||
message_retention_days: null,
|
message_retention_days: null,
|
||||||
stream_post_policy: 1,
|
stream_post_policy: 1,
|
||||||
|
can_remove_subscribers_group_id: 2,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,13 @@ format used by the Zulip server that they are interacting with.
|
||||||
|
|
||||||
## Changes in Zulip 6.0
|
## Changes in Zulip 6.0
|
||||||
|
|
||||||
|
**Feature level 142**
|
||||||
|
|
||||||
|
* [`GET users/me/subscriptions`](/api/get-subscriptions), [`GET
|
||||||
|
/streams`](/api/get-streams), [`POST /register`](/api/register-queue),
|
||||||
|
[`GET /events`](/api/get-events): Added `can_remove_subscribers_group_id`
|
||||||
|
field to Stream and Subscription objects.
|
||||||
|
|
||||||
**Feature level 141**
|
**Feature level 141**
|
||||||
|
|
||||||
* [`POST /register`](/api/register-queue), [`PATCH
|
* [`POST /register`](/api/register-queue), [`PATCH
|
||||||
|
|
|
@ -33,7 +33,7 @@ DESKTOP_WARNING_VERSION = "5.4.3"
|
||||||
# Changes should be accompanied by documentation explaining what the
|
# Changes should be accompanied by documentation explaining what the
|
||||||
# new level means in templates/zerver/api/changelog.md, as well as
|
# new level means in templates/zerver/api/changelog.md, as well as
|
||||||
# "**Changes**" entries in the endpoint's documentation in `zulip.yaml`.
|
# "**Changes**" entries in the endpoint's documentation in `zulip.yaml`.
|
||||||
API_FEATURE_LEVEL = 141
|
API_FEATURE_LEVEL = 142
|
||||||
|
|
||||||
# Bump the minor PROVISION_VERSION to indicate that folks should provision
|
# Bump the minor PROVISION_VERSION to indicate that folks should provision
|
||||||
# only when going from an old version of the code to a newer version. Bump
|
# only when going from an old version of the code to a newer version. Bump
|
||||||
|
|
|
@ -68,6 +68,7 @@ from zerver.models import (
|
||||||
Recipient,
|
Recipient,
|
||||||
Stream,
|
Stream,
|
||||||
Subscription,
|
Subscription,
|
||||||
|
UserGroup,
|
||||||
UserProfile,
|
UserProfile,
|
||||||
active_non_guest_user_ids,
|
active_non_guest_user_ids,
|
||||||
get_system_bot,
|
get_system_bot,
|
||||||
|
@ -289,6 +290,7 @@ def send_subscription_add_events(
|
||||||
stream_weekly_traffic=stream_info.stream_weekly_traffic,
|
stream_weekly_traffic=stream_info.stream_weekly_traffic,
|
||||||
subscribers=stream_info.subscribers,
|
subscribers=stream_info.subscribers,
|
||||||
# Fields from Stream.API_FIELDS
|
# Fields from Stream.API_FIELDS
|
||||||
|
can_remove_subscribers_group_id=stream_dict["can_remove_subscribers_group_id"],
|
||||||
date_created=stream_dict["date_created"],
|
date_created=stream_dict["date_created"],
|
||||||
description=stream_dict["description"],
|
description=stream_dict["description"],
|
||||||
first_message_id=stream_dict["first_message_id"],
|
first_message_id=stream_dict["first_message_id"],
|
||||||
|
@ -1317,3 +1319,39 @@ def do_change_stream_message_retention_days(
|
||||||
old_value=old_message_retention_days_value,
|
old_value=old_message_retention_days_value,
|
||||||
new_value=message_retention_days,
|
new_value=message_retention_days,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def do_change_can_remove_subscribers_group(
|
||||||
|
stream: Stream, user_group: UserGroup, *, acting_user: Optional[UserProfile] = None
|
||||||
|
) -> None:
|
||||||
|
old_user_group = stream.can_remove_subscribers_group
|
||||||
|
old_user_group_id = None
|
||||||
|
if old_user_group is not None:
|
||||||
|
old_user_group_id = old_user_group.id
|
||||||
|
|
||||||
|
stream.can_remove_subscribers_group = user_group
|
||||||
|
stream.save()
|
||||||
|
RealmAuditLog.objects.create(
|
||||||
|
realm=stream.realm,
|
||||||
|
acting_user=acting_user,
|
||||||
|
modified_stream=stream,
|
||||||
|
event_type=RealmAuditLog.STREAM_CAN_REMOVE_SUBSCRIBERS_GROUP_CHANGED,
|
||||||
|
event_time=timezone_now(),
|
||||||
|
extra_data=orjson.dumps(
|
||||||
|
{
|
||||||
|
RealmAuditLog.OLD_VALUE: old_user_group_id,
|
||||||
|
RealmAuditLog.NEW_VALUE: user_group.id,
|
||||||
|
}
|
||||||
|
).decode(),
|
||||||
|
)
|
||||||
|
event = dict(
|
||||||
|
op="update",
|
||||||
|
type="stream",
|
||||||
|
property="can_remove_subscribers_group_id",
|
||||||
|
value=user_group.id,
|
||||||
|
stream_id=stream.id,
|
||||||
|
name=stream.name,
|
||||||
|
)
|
||||||
|
transaction.on_commit(
|
||||||
|
lambda: send_event(stream.realm, event, can_access_stream_user_ids(stream))
|
||||||
|
)
|
||||||
|
|
|
@ -50,6 +50,7 @@ from zerver.models import Realm, RealmUserDefault, Stream, UserProfile
|
||||||
# These fields are used for "stream" events, and are included in the
|
# These fields are used for "stream" events, and are included in the
|
||||||
# larger "subscription" events that also contain personal settings.
|
# larger "subscription" events that also contain personal settings.
|
||||||
basic_stream_fields = [
|
basic_stream_fields = [
|
||||||
|
("can_remove_subscribers_group_id", int),
|
||||||
("date_created", int),
|
("date_created", int),
|
||||||
("description", str),
|
("description", str),
|
||||||
("first_message_id", OptionalType(int)),
|
("first_message_id", OptionalType(int)),
|
||||||
|
@ -1287,6 +1288,9 @@ def check_stream_update(
|
||||||
elif prop == "stream_post_policy":
|
elif prop == "stream_post_policy":
|
||||||
assert extra_keys == set()
|
assert extra_keys == set()
|
||||||
assert value in Stream.STREAM_POST_POLICY_TYPES
|
assert value in Stream.STREAM_POST_POLICY_TYPES
|
||||||
|
elif prop == "can_remove_subscribers_group_id":
|
||||||
|
assert extra_keys == set()
|
||||||
|
assert isinstance(value, int)
|
||||||
else:
|
else:
|
||||||
raise AssertionError(f"Unknown property: {prop}")
|
raise AssertionError(f"Unknown property: {prop}")
|
||||||
|
|
||||||
|
|
|
@ -40,6 +40,7 @@ def get_web_public_subs(realm: Realm) -> SubscriptionInfo:
|
||||||
subscribed = []
|
subscribed = []
|
||||||
for stream in get_web_public_streams_queryset(realm):
|
for stream in get_web_public_streams_queryset(realm):
|
||||||
# Add Stream fields.
|
# Add Stream fields.
|
||||||
|
can_remove_subscribers_group_id = stream.can_remove_subscribers_group_id
|
||||||
date_created = datetime_to_timestamp(stream.date_created)
|
date_created = datetime_to_timestamp(stream.date_created)
|
||||||
description = stream.description
|
description = stream.description
|
||||||
first_message_id = stream.first_message_id
|
first_message_id = stream.first_message_id
|
||||||
|
@ -71,6 +72,7 @@ def get_web_public_subs(realm: Realm) -> SubscriptionInfo:
|
||||||
|
|
||||||
sub = SubscriptionStreamDict(
|
sub = SubscriptionStreamDict(
|
||||||
audible_notifications=audible_notifications,
|
audible_notifications=audible_notifications,
|
||||||
|
can_remove_subscribers_group_id=can_remove_subscribers_group_id,
|
||||||
color=color,
|
color=color,
|
||||||
date_created=date_created,
|
date_created=date_created,
|
||||||
description=description,
|
description=description,
|
||||||
|
@ -110,6 +112,7 @@ def build_stream_dict_for_sub(
|
||||||
recent_traffic: Dict[int, int],
|
recent_traffic: Dict[int, int],
|
||||||
) -> SubscriptionStreamDict:
|
) -> SubscriptionStreamDict:
|
||||||
# Handle Stream.API_FIELDS
|
# Handle Stream.API_FIELDS
|
||||||
|
can_remove_subscribers_group_id = raw_stream_dict["can_remove_subscribers_group_id"]
|
||||||
date_created = datetime_to_timestamp(raw_stream_dict["date_created"])
|
date_created = datetime_to_timestamp(raw_stream_dict["date_created"])
|
||||||
description = raw_stream_dict["description"]
|
description = raw_stream_dict["description"]
|
||||||
first_message_id = raw_stream_dict["first_message_id"]
|
first_message_id = raw_stream_dict["first_message_id"]
|
||||||
|
@ -153,6 +156,7 @@ def build_stream_dict_for_sub(
|
||||||
# Our caller may add a subscribers field.
|
# Our caller may add a subscribers field.
|
||||||
return SubscriptionStreamDict(
|
return SubscriptionStreamDict(
|
||||||
audible_notifications=audible_notifications,
|
audible_notifications=audible_notifications,
|
||||||
|
can_remove_subscribers_group_id=can_remove_subscribers_group_id,
|
||||||
color=color,
|
color=color,
|
||||||
date_created=date_created,
|
date_created=date_created,
|
||||||
description=description,
|
description=description,
|
||||||
|
@ -182,6 +186,7 @@ def build_stream_dict_for_never_sub(
|
||||||
raw_stream_dict: RawStreamDict,
|
raw_stream_dict: RawStreamDict,
|
||||||
recent_traffic: Dict[int, int],
|
recent_traffic: Dict[int, int],
|
||||||
) -> NeverSubscribedStreamDict:
|
) -> NeverSubscribedStreamDict:
|
||||||
|
can_remove_subscribers_group_id = raw_stream_dict["can_remove_subscribers_group_id"]
|
||||||
date_created = datetime_to_timestamp(raw_stream_dict["date_created"])
|
date_created = datetime_to_timestamp(raw_stream_dict["date_created"])
|
||||||
description = raw_stream_dict["description"]
|
description = raw_stream_dict["description"]
|
||||||
first_message_id = raw_stream_dict["first_message_id"]
|
first_message_id = raw_stream_dict["first_message_id"]
|
||||||
|
@ -202,6 +207,7 @@ def build_stream_dict_for_never_sub(
|
||||||
|
|
||||||
# Our caller may add a subscribers field.
|
# Our caller may add a subscribers field.
|
||||||
return NeverSubscribedStreamDict(
|
return NeverSubscribedStreamDict(
|
||||||
|
can_remove_subscribers_group_id=can_remove_subscribers_group_id,
|
||||||
date_created=date_created,
|
date_created=date_created,
|
||||||
description=description,
|
description=description,
|
||||||
first_message_id=first_message_id,
|
first_message_id=first_message_id,
|
||||||
|
|
|
@ -177,6 +177,7 @@ class RawStreamDict(TypedDict):
|
||||||
are needed to encode the stream for the API.
|
are needed to encode the stream for the API.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
can_remove_subscribers_group_id: int
|
||||||
date_created: datetime.datetime
|
date_created: datetime.datetime
|
||||||
description: str
|
description: str
|
||||||
email_token: str
|
email_token: str
|
||||||
|
@ -216,6 +217,7 @@ class SubscriptionStreamDict(TypedDict):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
audible_notifications: Optional[bool]
|
audible_notifications: Optional[bool]
|
||||||
|
can_remove_subscribers_group_id: int
|
||||||
color: str
|
color: str
|
||||||
date_created: int
|
date_created: int
|
||||||
description: str
|
description: str
|
||||||
|
@ -242,6 +244,7 @@ class SubscriptionStreamDict(TypedDict):
|
||||||
|
|
||||||
|
|
||||||
class NeverSubscribedStreamDict(TypedDict):
|
class NeverSubscribedStreamDict(TypedDict):
|
||||||
|
can_remove_subscribers_group_id: int
|
||||||
date_created: int
|
date_created: int
|
||||||
description: str
|
description: str
|
||||||
first_message_id: Optional[int]
|
first_message_id: Optional[int]
|
||||||
|
@ -264,6 +267,7 @@ class APIStreamDict(TypedDict):
|
||||||
with few exceptions and possible additional fields.
|
with few exceptions and possible additional fields.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
can_remove_subscribers_group_id: int
|
||||||
date_created: int
|
date_created: int
|
||||||
description: str
|
description: str
|
||||||
first_message_id: Optional[int]
|
first_message_id: Optional[int]
|
||||||
|
|
|
@ -2552,6 +2552,7 @@ class Stream(models.Model):
|
||||||
"name",
|
"name",
|
||||||
"rendered_description",
|
"rendered_description",
|
||||||
"stream_post_policy",
|
"stream_post_policy",
|
||||||
|
"can_remove_subscribers_group_id",
|
||||||
]
|
]
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
@ -2561,6 +2562,7 @@ class Stream(models.Model):
|
||||||
|
|
||||||
def to_dict(self) -> APIStreamDict:
|
def to_dict(self) -> APIStreamDict:
|
||||||
return APIStreamDict(
|
return APIStreamDict(
|
||||||
|
can_remove_subscribers_group_id=self.can_remove_subscribers_group_id,
|
||||||
date_created=datetime_to_timestamp(self.date_created),
|
date_created=datetime_to_timestamp(self.date_created),
|
||||||
description=self.description,
|
description=self.description,
|
||||||
first_message_id=self.first_message_id,
|
first_message_id=self.first_message_id,
|
||||||
|
@ -4364,6 +4366,7 @@ class AbstractRealmAuditLog(models.Model):
|
||||||
STREAM_REACTIVATED = 604
|
STREAM_REACTIVATED = 604
|
||||||
STREAM_MESSAGE_RETENTION_DAYS_CHANGED = 605
|
STREAM_MESSAGE_RETENTION_DAYS_CHANGED = 605
|
||||||
STREAM_PROPERTY_CHANGED = 607
|
STREAM_PROPERTY_CHANGED = 607
|
||||||
|
STREAM_CAN_REMOVE_SUBSCRIBERS_GROUP_CHANGED = 608
|
||||||
|
|
||||||
# The following values are only for RemoteZulipServerAuditLog
|
# The following values are only for RemoteZulipServerAuditLog
|
||||||
# Values should be exactly 10000 greater than the corresponding
|
# Values should be exactly 10000 greater than the corresponding
|
||||||
|
|
|
@ -644,6 +644,7 @@ paths:
|
||||||
"in_home_view": true,
|
"in_home_view": true,
|
||||||
"email_address": "test_stream.af64447e9e39374841063747ade8e6b0.show-sender@testserver",
|
"email_address": "test_stream.af64447e9e39374841063747ade8e6b0.show-sender@testserver",
|
||||||
"stream_weekly_traffic": null,
|
"stream_weekly_traffic": null,
|
||||||
|
"can_remove_subscribers_group_id": 2,
|
||||||
"subscribers": [10],
|
"subscribers": [10],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -1143,6 +1144,7 @@ paths:
|
||||||
"first_message_id": null,
|
"first_message_id": null,
|
||||||
"message_retention_days": null,
|
"message_retention_days": null,
|
||||||
"is_announcement_only": false,
|
"is_announcement_only": false,
|
||||||
|
"can_remove_subscribers_group_id": 2,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
"id": 0,
|
"id": 0,
|
||||||
|
@ -1188,6 +1190,7 @@ paths:
|
||||||
"first_message_id": null,
|
"first_message_id": null,
|
||||||
"message_retention_days": null,
|
"message_retention_days": null,
|
||||||
"is_announcement_only": false,
|
"is_announcement_only": false,
|
||||||
|
"can_remove_subscribers_group_id": 2,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
"id": 0,
|
"id": 0,
|
||||||
|
@ -1745,6 +1748,7 @@ paths:
|
||||||
"first_message_id": 1,
|
"first_message_id": 1,
|
||||||
"message_retention_days": null,
|
"message_retention_days": null,
|
||||||
"is_announcement_only": false,
|
"is_announcement_only": false,
|
||||||
|
"can_remove_subscribers_group_id": 2,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Denmark",
|
"name": "Denmark",
|
||||||
|
@ -1758,6 +1762,7 @@ paths:
|
||||||
"first_message_id": 4,
|
"first_message_id": 4,
|
||||||
"message_retention_days": null,
|
"message_retention_days": null,
|
||||||
"is_announcement_only": false,
|
"is_announcement_only": false,
|
||||||
|
"can_remove_subscribers_group_id": 2,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Verona",
|
"name": "Verona",
|
||||||
|
@ -1771,6 +1776,7 @@ paths:
|
||||||
"first_message_id": 6,
|
"first_message_id": 6,
|
||||||
"message_retention_days": null,
|
"message_retention_days": null,
|
||||||
"is_announcement_only": false,
|
"is_announcement_only": false,
|
||||||
|
"can_remove_subscribers_group_id": 2,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
@ -1815,6 +1821,7 @@ paths:
|
||||||
"first_message_id": 1,
|
"first_message_id": 1,
|
||||||
"message_retention_days": null,
|
"message_retention_days": null,
|
||||||
"is_announcement_only": false,
|
"is_announcement_only": false,
|
||||||
|
"can_remove_subscribers_group_id": 2,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
"id": 0,
|
"id": 0,
|
||||||
|
@ -10089,6 +10096,7 @@ paths:
|
||||||
first_message_id:
|
first_message_id:
|
||||||
nullable: true
|
nullable: true
|
||||||
is_announcement_only: {}
|
is_announcement_only: {}
|
||||||
|
can_remove_subscribers_group_id: {}
|
||||||
stream_weekly_traffic:
|
stream_weekly_traffic:
|
||||||
type: integer
|
type: integer
|
||||||
nullable: true
|
nullable: true
|
||||||
|
@ -13879,6 +13887,7 @@ paths:
|
||||||
first_message_id:
|
first_message_id:
|
||||||
nullable: true
|
nullable: true
|
||||||
is_announcement_only: {}
|
is_announcement_only: {}
|
||||||
|
can_remove_subscribers_group_id: {}
|
||||||
is_default:
|
is_default:
|
||||||
type: boolean
|
type: boolean
|
||||||
description: |
|
description: |
|
||||||
|
@ -13989,6 +13998,7 @@ paths:
|
||||||
"rendered_description": "<p>A Scandinavian country</p>",
|
"rendered_description": "<p>A Scandinavian country</p>",
|
||||||
"stream_id": 7,
|
"stream_id": 7,
|
||||||
"stream_post_policy": 1,
|
"stream_post_policy": 1,
|
||||||
|
"can_remove_subscribers_group_id": 2,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
"400":
|
"400":
|
||||||
|
@ -15075,6 +15085,7 @@ components:
|
||||||
first_message_id:
|
first_message_id:
|
||||||
nullable: true
|
nullable: true
|
||||||
is_announcement_only: {}
|
is_announcement_only: {}
|
||||||
|
can_remove_subscribers_group_id: {}
|
||||||
BasicStreamBase:
|
BasicStreamBase:
|
||||||
type: object
|
type: object
|
||||||
description: |
|
description: |
|
||||||
|
@ -15176,6 +15187,13 @@ components:
|
||||||
|
|
||||||
**Changes**: Deprecated in Zulip 3.0 (feature level 1). Clients
|
**Changes**: Deprecated in Zulip 3.0 (feature level 1). Clients
|
||||||
should use `stream_post_policy` instead.
|
should use `stream_post_policy` instead.
|
||||||
|
can_remove_subscribers_group_id:
|
||||||
|
type: integer
|
||||||
|
description: |
|
||||||
|
ID of the user group whose members are allowed to unsubscribe others
|
||||||
|
from the stream.
|
||||||
|
|
||||||
|
**Changes**: New in Zulip 6.0 (feature level 142).
|
||||||
BasicBot:
|
BasicBot:
|
||||||
allOf:
|
allOf:
|
||||||
- $ref: "#/components/schemas/BasicBotBase"
|
- $ref: "#/components/schemas/BasicBotBase"
|
||||||
|
@ -15792,6 +15810,13 @@ components:
|
||||||
|
|
||||||
Null means the stream was recently created and there is
|
Null means the stream was recently created and there is
|
||||||
insufficient data to estimate the average traffic.
|
insufficient data to estimate the average traffic.
|
||||||
|
can_remove_subscribers_group_id:
|
||||||
|
type: integer
|
||||||
|
description: |
|
||||||
|
ID of the user group whose members are allowed to unsubscribe others
|
||||||
|
from the stream.
|
||||||
|
|
||||||
|
**Changes**: New in Zulip 6.0 (feature level 142).
|
||||||
DefaultStreamGroup:
|
DefaultStreamGroup:
|
||||||
type: object
|
type: object
|
||||||
description: |
|
description: |
|
||||||
|
|
|
@ -79,6 +79,7 @@ from zerver.actions.realm_settings import (
|
||||||
from zerver.actions.streams import (
|
from zerver.actions.streams import (
|
||||||
bulk_add_subscriptions,
|
bulk_add_subscriptions,
|
||||||
bulk_remove_subscriptions,
|
bulk_remove_subscriptions,
|
||||||
|
do_change_can_remove_subscribers_group,
|
||||||
do_change_stream_description,
|
do_change_stream_description,
|
||||||
do_change_stream_message_retention_days,
|
do_change_stream_message_retention_days,
|
||||||
do_change_stream_permission,
|
do_change_stream_permission,
|
||||||
|
@ -2885,6 +2886,17 @@ class SubscribeActionTest(BaseAction):
|
||||||
events = self.verify_action(action, include_subscribers=include_subscribers, num_events=2)
|
events = self.verify_action(action, include_subscribers=include_subscribers, num_events=2)
|
||||||
check_stream_update("events[0]", events[0])
|
check_stream_update("events[0]", events[0])
|
||||||
|
|
||||||
|
moderators_group = UserGroup.objects.get(
|
||||||
|
name=UserGroup.MODERATORS_GROUP_NAME,
|
||||||
|
is_system_group=True,
|
||||||
|
realm=self.user_profile.realm,
|
||||||
|
)
|
||||||
|
action = lambda: do_change_can_remove_subscribers_group(
|
||||||
|
stream, moderators_group, acting_user=self.example_user("hamlet")
|
||||||
|
)
|
||||||
|
events = self.verify_action(action, include_subscribers=include_subscribers, num_events=1)
|
||||||
|
check_stream_update("events[0]", events[0])
|
||||||
|
|
||||||
# Subscribe to a totally new invite-only stream, so it's just Hamlet on it
|
# Subscribe to a totally new invite-only stream, so it's just Hamlet on it
|
||||||
stream = self.make_stream("private", self.user_profile.realm, invite_only=True)
|
stream = self.make_stream("private", self.user_profile.realm, invite_only=True)
|
||||||
stream.message_retention_days = 10
|
stream.message_retention_days = 10
|
||||||
|
|
Loading…
Reference in New Issue