def test_null_value_and_rendered_value(self) -> None: self.login("iago") realm = get_realm("zulip") quote = try_add_realm_custom_profile_field( realm=realm, name="Quote", hint="Saying or phrase which you known for.", field_type=CustomProfileField.SHORT_TEXT, ) iago = self.example_user("iago") iago_profile_quote = iago.profile_data()[-1] value = iago_profile_quote["value"] rendered_value = iago_profile_quote["rendered_value"] self.assertIsNone(value) self.assertIsNone(rendered_value) update_dict: Dict[str, Union[int, str, List[int]]] = { "id": quote.id, "value": "***beware*** of jealousy...", } do_update_user_custom_profile_data_if_changed(iago, [update_dict]) iago_profile_quote = self.example_user("iago").profile_data()[-1] value = iago_profile_quote["value"] rendered_value = iago_profile_quote["rendered_value"] self.assertIsNotNone(value) self.assertIsNotNone(rendered_value) self.assertEqual( "<p><strong><em>beware</em></strong> of jealousy...</p>", rendered_value)
def update_user_custom_profile_data( request: HttpRequest, user_profile: UserProfile, data: List[Dict[str, Union[int, ProfileDataElementValue]]] = REQ( json_validator=check_list( check_dict_only([ ("id", check_int), ("value", check_union([check_string, check_list(check_int)])), ]), )), ) -> HttpResponse: validate_user_custom_profile_data(user_profile.realm.id, data) do_update_user_custom_profile_data_if_changed(user_profile, data) # We need to call this explicitly otherwise constraints are not check return json_success(request)
def test_delete_field_value(self) -> None: iago = self.example_user("iago") self.login_user(iago) realm = get_realm("zulip") invalid_field_id = 1234 result = self.client_delete( "/json/users/me/profile_data", { "data": orjson.dumps([invalid_field_id]).decode(), }, ) self.assert_json_error(result, f"Field id {invalid_field_id} not found.") field = CustomProfileField.objects.get(name="Mentor", realm=realm) data: List[Dict[str, Union[int, str, List[int]]]] = [ { "id": field.id, "value": [self.example_user("aaron").id] }, ] do_update_user_custom_profile_data_if_changed(iago, data) iago_value = CustomProfileFieldValue.objects.get(user_profile=iago, field=field) converter = field.FIELD_CONVERTERS[field.field_type] self.assertEqual([self.example_user("aaron").id], converter(iago_value.value)) result = self.client_delete( "/json/users/me/profile_data", { "data": orjson.dumps([field.id]).decode(), }, ) self.assert_json_success(result) # Don't throw an exception here result = self.client_delete( "/json/users/me/profile_data", { "data": orjson.dumps([field.id]).decode(), }, ) self.assert_json_success(result)
def test_do_update_value_not_changed(self) -> None: iago = self.example_user("iago") self.login_user(iago) realm = get_realm("zulip") # Set field value: field = CustomProfileField.objects.get(name="Mentor", realm=realm) data: List[Dict[str, Union[int, str, List[int]]]] = [ { "id": field.id, "value": [self.example_user("aaron").id] }, ] do_update_user_custom_profile_data_if_changed(iago, data) with mock.patch( "zerver.actions.custom_profile_fields.notify_user_update_custom_profile_data" ) as mock_notify: # Attempting to "update" the field value, when it wouldn't actually change, # shouldn't trigger notify. do_update_user_custom_profile_data_if_changed(iago, data) mock_notify.assert_not_called()
def test_delete_internals(self) -> None: user_profile = self.example_user("iago") realm = user_profile.realm field = CustomProfileField.objects.get(name="Phone number", realm=realm) data: List[Dict[str, Union[int, str, List[int]]]] = [ { "id": field.id, "value": "123456" }, ] do_update_user_custom_profile_data_if_changed(user_profile, data) self.assertTrue(self.custom_field_exists_in_realm(field.id)) self.assertEqual(user_profile.customprofilefieldvalue_set.count(), self.original_count) do_remove_realm_custom_profile_field(realm, field) self.assertFalse(self.custom_field_exists_in_realm(field.id)) self.assertEqual(user_profile.customprofilefieldvalue_set.count(), self.original_count - 1)
def update_user_backend( request: HttpRequest, user_profile: UserProfile, user_id: int, full_name: Optional[str] = REQ(default=None), role: Optional[int] = REQ( default=None, json_validator=check_int_in(UserProfile.ROLE_TYPES, ), ), profile_data: Optional[List[Dict[str, Optional[Union[ int, ProfileDataElementValue]]]]] = REQ( default=None, json_validator=check_profile_data, ), ) -> HttpResponse: target = access_user_by_id(user_profile, user_id, allow_deactivated=True, allow_bots=True, for_admin=True) if role is not None and target.role != role: # Require that the current user has permissions to # grant/remove the role in question. access_user_by_id has # already verified we're an administrator; here we enforce # that only owners can toggle the is_realm_owner flag. # # Logic replicated in patch_bot_backend. if UserProfile.ROLE_REALM_OWNER in [ role, target.role ] and not user_profile.is_realm_owner: raise OrganizationOwnerRequired() if target.role == UserProfile.ROLE_REALM_OWNER and check_last_owner( target): raise JsonableError( _("The owner permission cannot be removed from the only organization owner." )) do_change_user_role(target, role, acting_user=user_profile) if full_name is not None and target.full_name != full_name and full_name.strip( ) != "": # We don't respect `name_changes_disabled` here because the request # is on behalf of the administrator. check_change_full_name(target, full_name, user_profile) if profile_data is not None: clean_profile_data = [] for entry in profile_data: assert isinstance(entry["id"], int) if entry["value"] is None or not entry["value"]: field_id = entry["id"] check_remove_custom_profile_field_value(target, field_id) else: clean_profile_data.append({ "id": entry["id"], "value": entry["value"], }) validate_user_custom_profile_data(target.realm.id, clean_profile_data) do_update_user_custom_profile_data_if_changed(target, clean_profile_data) return json_success(request)
def handle(self, *args: Any, **options: Any) -> None: # Suppress spammy output from the push notifications logger push_notifications_logger.disabled = True if options["percent_huddles"] + options["percent_personals"] > 100: self.stderr.write("Error! More than 100% of messages allocated.\n") return # Get consistent data for backend tests. if options["test_suite"]: random.seed(0) with connection.cursor() as cursor: # Sometimes bugs relating to confusing recipient.id for recipient.type_id # or <object>.id for <object>.recipient_id remain undiscovered by the test suite # due to these numbers happening to coincide in such a way that it makes tests # accidentally pass. By bumping the Recipient.id sequence by a large enough number, # we can have those ids in a completely different range of values than object ids, # eliminating the possibility of such coincidences. cursor.execute("SELECT setval('zerver_recipient_id_seq', 100)") if options["max_topics"] is None: # If max_topics is not set, we use a default that's big # enough "more topics" should appear, and scales slowly # with the number of messages. options["max_topics"] = 8 + options["num_messages"] // 1000 if options["delete"]: # Start by clearing all the data in our database clear_database() # Create our three default realms # Could in theory be done via zerver.actions.create_realm.do_create_realm, but # welcome-bot (needed for do_create_realm) hasn't been created yet create_internal_realm() zulip_realm = do_create_realm( string_id="zulip", name="Zulip Dev", emails_restricted_to_domains=False, email_address_visibility=Realm.EMAIL_ADDRESS_VISIBILITY_ADMINS, description="The Zulip development environment default organization." " It's great for testing!", invite_required=False, plan_type=Realm.PLAN_TYPE_SELF_HOSTED, org_type=Realm.ORG_TYPES["business"]["id"], enable_spectator_access=True, ) RealmDomain.objects.create(realm=zulip_realm, domain="zulip.com") assert zulip_realm.notifications_stream is not None zulip_realm.notifications_stream.name = "Verona" zulip_realm.notifications_stream.description = "A city in Italy" zulip_realm.notifications_stream.save(update_fields=["name", "description"]) realm_user_default = RealmUserDefault.objects.get(realm=zulip_realm) realm_user_default.enter_sends = True realm_user_default.save() if options["test_suite"]: mit_realm = do_create_realm( string_id="zephyr", name="MIT", emails_restricted_to_domains=True, invite_required=False, plan_type=Realm.PLAN_TYPE_SELF_HOSTED, org_type=Realm.ORG_TYPES["business"]["id"], ) RealmDomain.objects.create(realm=mit_realm, domain="mit.edu") lear_realm = do_create_realm( string_id="lear", name="Lear & Co.", emails_restricted_to_domains=False, invite_required=False, plan_type=Realm.PLAN_TYPE_SELF_HOSTED, org_type=Realm.ORG_TYPES["business"]["id"], ) # Default to allowing all members to send mentions in # large streams for the test suite to keep # mention-related tests simple. zulip_realm.wildcard_mention_policy = Realm.WILDCARD_MENTION_POLICY_MEMBERS zulip_realm.save(update_fields=["wildcard_mention_policy"]) # Create test Users (UserProfiles are automatically created, # as are subscriptions to the ability to receive personals). names = [ ("Zoe", "*****@*****.**"), ("Othello, the Moor of Venice", "*****@*****.**"), ("Iago", "*****@*****.**"), ("Prospero from The Tempest", "*****@*****.**"), ("Cordelia, Lear's daughter", "*****@*****.**"), ("King Hamlet", "*****@*****.**"), ("aaron", "*****@*****.**"), ("Polonius", "*****@*****.**"), ("Desdemona", "*****@*****.**"), ("शिव", "*****@*****.**"), ] # For testing really large batches: # Create extra users with semi realistic names to make search # functions somewhat realistic. We'll still create 1000 users # like Extra222 User for some predictability. num_names = options["extra_users"] num_boring_names = 300 for i in range(min(num_names, num_boring_names)): full_name = f"Extra{i:03} User" names.append((full_name, f"extrauser{i}@zulip.com")) if num_names > num_boring_names: fnames = [ "Amber", "Arpita", "Bob", "Cindy", "Daniela", "Dan", "Dinesh", "Faye", "François", "George", "Hank", "Irene", "James", "Janice", "Jenny", "Jill", "John", "Kate", "Katelyn", "Kobe", "Lexi", "Manish", "Mark", "Matt", "Mayna", "Michael", "Pete", "Peter", "Phil", "Phillipa", "Preston", "Sally", "Scott", "Sandra", "Steve", "Stephanie", "Vera", ] mnames = ["de", "van", "von", "Shaw", "T."] lnames = [ "Adams", "Agarwal", "Beal", "Benson", "Bonita", "Davis", "George", "Harden", "James", "Jones", "Johnson", "Jordan", "Lee", "Leonard", "Singh", "Smith", "Patel", "Towns", "Wall", ] non_ascii_names = [ "Günter", "أحمد", "Magnús", "आशी", "イツキ", "语嫣", "அருண்", "Александр", "José", ] # to imitate emoji insertions in usernames raw_emojis = ["😎", "😂", "🐱👤"] for i in range(num_boring_names, num_names): fname = random.choice(fnames) + str(i) full_name = fname if random.random() < 0.7: if random.random() < 0.3: full_name += " " + random.choice(non_ascii_names) else: full_name += " " + random.choice(mnames) if random.random() < 0.1: full_name += f" {random.choice(raw_emojis)} " else: full_name += " " + random.choice(lnames) email = fname.lower() + "@zulip.com" names.append((full_name, email)) create_users(zulip_realm, names, tos_version=settings.TERMS_OF_SERVICE_VERSION) # Add time zones to some users. Ideally, this would be # done in the initial create_users calls, but the # tuple-based interface for that function doesn't support # doing so. def assign_time_zone_by_delivery_email(delivery_email: str, new_time_zone: str) -> None: u = get_user_by_delivery_email(delivery_email, zulip_realm) u.timezone = new_time_zone u.save(update_fields=["timezone"]) # Note: Hamlet keeps default time zone of "". assign_time_zone_by_delivery_email("*****@*****.**", "US/Pacific") assign_time_zone_by_delivery_email("*****@*****.**", "US/Pacific") assign_time_zone_by_delivery_email("*****@*****.**", "US/Eastern") assign_time_zone_by_delivery_email("*****@*****.**", "US/Eastern") assign_time_zone_by_delivery_email("*****@*****.**", "Canada/Newfoundland") assign_time_zone_by_delivery_email("*****@*****.**", "Asia/Shanghai") # China assign_time_zone_by_delivery_email("*****@*****.**", "Asia/Kolkata") # India assign_time_zone_by_delivery_email("*****@*****.**", "UTC") users = UserProfile.objects.filter(realm=zulip_realm) # All users in development environment are full members initially because # waiting period threshold is 0. Groups of Iago, Dedemona, Shiva and # Polonius will be updated according to their role in do_change_user_role. full_members_user_group = UserGroup.objects.get( realm=zulip_realm, name="@role:fullmembers", is_system_group=True ) members_user_group = UserGroup.objects.get( realm=zulip_realm, name="@role:members", is_system_group=True ) user_group_memberships = [] for user_profile in list(users): for group in [full_members_user_group, members_user_group]: user_group_membership = UserGroupMembership( user_group=group, user_profile=user_profile ) user_group_memberships.append(user_group_membership) UserGroupMembership.objects.bulk_create(user_group_memberships) iago = get_user_by_delivery_email("*****@*****.**", zulip_realm) do_change_user_role(iago, UserProfile.ROLE_REALM_ADMINISTRATOR, acting_user=None) iago.is_staff = True iago.save(update_fields=["is_staff"]) # We need to create at least two test draft for Iago for the sake # of the cURL tests. Two since one will be deleted. Draft.objects.create( user_profile=iago, recipient=None, topic="Release Notes", content="Release 4.0 will contain ...", last_edit_time=timezone_now(), ) Draft.objects.create( user_profile=iago, recipient=None, topic="Release Notes", content="Release 4.0 will contain many new features such as ... ", last_edit_time=timezone_now(), ) desdemona = get_user_by_delivery_email("*****@*****.**", zulip_realm) do_change_user_role(desdemona, UserProfile.ROLE_REALM_OWNER, acting_user=None) shiva = get_user_by_delivery_email("*****@*****.**", zulip_realm) do_change_user_role(shiva, UserProfile.ROLE_MODERATOR, acting_user=None) polonius = get_user_by_delivery_email("*****@*****.**", zulip_realm) do_change_user_role(polonius, UserProfile.ROLE_GUEST, acting_user=None) # These bots are directly referenced from code and thus # are needed for the test suite. zulip_realm_bots = [ ("Zulip Error Bot", "*****@*****.**"), ("Zulip Default Bot", "*****@*****.**"), ] for i in range(options["extra_bots"]): zulip_realm_bots.append((f"Extra Bot {i}", f"extrabot{i}@zulip.com")) create_users( zulip_realm, zulip_realm_bots, bot_type=UserProfile.DEFAULT_BOT, bot_owner=desdemona ) zoe = get_user_by_delivery_email("*****@*****.**", zulip_realm) zulip_webhook_bots = [ ("Zulip Webhook Bot", "*****@*****.**"), ] # If a stream is not supplied in the webhook URL, the webhook # will (in some cases) send the notification as a PM to the # owner of the webhook bot, so bot_owner can't be None create_users( zulip_realm, zulip_webhook_bots, bot_type=UserProfile.INCOMING_WEBHOOK_BOT, bot_owner=zoe, ) aaron = get_user_by_delivery_email("*****@*****.**", zulip_realm) zulip_outgoing_bots = [ ("Outgoing Webhook", "*****@*****.**"), ] create_users( zulip_realm, zulip_outgoing_bots, bot_type=UserProfile.OUTGOING_WEBHOOK_BOT, bot_owner=aaron, ) outgoing_webhook = get_user("*****@*****.**", zulip_realm) add_service( "outgoing-webhook", user_profile=outgoing_webhook, interface=Service.GENERIC, base_url="http://127.0.0.1:5002", token=generate_api_key(), ) # Add the realm internal bots to each realm. create_if_missing_realm_internal_bots() # Create public streams. signups_stream = Realm.INITIAL_PRIVATE_STREAM_NAME stream_list = [ "Verona", "Denmark", "Scotland", "Venice", "Rome", signups_stream, ] stream_dict: Dict[str, Dict[str, Any]] = { "Denmark": {"description": "A Scandinavian country"}, "Scotland": {"description": "Located in the United Kingdom"}, "Venice": {"description": "A northeastern Italian city"}, "Rome": {"description": "Yet another Italian city", "is_web_public": True}, } bulk_create_streams(zulip_realm, stream_dict) recipient_streams: List[int] = [ Stream.objects.get(name=name, realm=zulip_realm).id for name in stream_list ] # Create subscriptions to streams. The following # algorithm will give each of the users a different but # deterministic subset of the streams (given a fixed list # of users). For the test suite, we have a fixed list of # subscriptions to make sure test data is consistent # across platforms. subscriptions_list: List[Tuple[UserProfile, Recipient]] = [] profiles: Sequence[UserProfile] = list( UserProfile.objects.select_related().filter(is_bot=False).order_by("email") ) if options["test_suite"]: subscriptions_map = { "*****@*****.**": ["Verona"], "*****@*****.**": ["Verona"], "*****@*****.**": ["Verona", "Denmark", signups_stream], "*****@*****.**": [ "Verona", "Denmark", "Scotland", signups_stream, ], "*****@*****.**": ["Verona", "Denmark", "Scotland"], "*****@*****.**": ["Verona", "Denmark", "Scotland", "Venice"], "*****@*****.**": ["Verona", "Denmark", "Scotland", "Venice", "Rome"], "*****@*****.**": ["Verona"], "*****@*****.**": [ "Verona", "Denmark", "Venice", signups_stream, ], "*****@*****.**": ["Verona", "Denmark", "Scotland"], } for profile in profiles: email = profile.delivery_email if email not in subscriptions_map: raise Exception(f"Subscriptions not listed for user {email}") for stream_name in subscriptions_map[email]: stream = Stream.objects.get(name=stream_name, realm=zulip_realm) r = Recipient.objects.get(type=Recipient.STREAM, type_id=stream.id) subscriptions_list.append((profile, r)) else: num_streams = len(recipient_streams) num_users = len(profiles) for i, profile in enumerate(profiles): # Subscribe to some streams. fraction = float(i) / num_users num_recips = int(num_streams * fraction) + 1 for type_id in recipient_streams[:num_recips]: r = Recipient.objects.get(type=Recipient.STREAM, type_id=type_id) subscriptions_list.append((profile, r)) subscriptions_to_add: List[Subscription] = [] event_time = timezone_now() all_subscription_logs: (List[RealmAuditLog]) = [] i = 0 for profile, recipient in subscriptions_list: i += 1 color = STREAM_ASSIGNMENT_COLORS[i % len(STREAM_ASSIGNMENT_COLORS)] s = Subscription( recipient=recipient, user_profile=profile, is_user_active=profile.is_active, color=color, ) subscriptions_to_add.append(s) log = RealmAuditLog( realm=profile.realm, modified_user=profile, modified_stream_id=recipient.type_id, event_last_message_id=0, event_type=RealmAuditLog.SUBSCRIPTION_CREATED, event_time=event_time, ) all_subscription_logs.append(log) Subscription.objects.bulk_create(subscriptions_to_add) RealmAuditLog.objects.bulk_create(all_subscription_logs) # Create custom profile field data phone_number = try_add_realm_custom_profile_field( zulip_realm, "Phone number", CustomProfileField.SHORT_TEXT, hint="" ) biography = try_add_realm_custom_profile_field( zulip_realm, "Biography", CustomProfileField.LONG_TEXT, hint="What are you known for?", ) favorite_food = try_add_realm_custom_profile_field( zulip_realm, "Favorite food", CustomProfileField.SHORT_TEXT, hint="Or drink, if you'd prefer", ) field_data: ProfileFieldData = { "vim": {"text": "Vim", "order": "1"}, "emacs": {"text": "Emacs", "order": "2"}, } favorite_editor = try_add_realm_custom_profile_field( zulip_realm, "Favorite editor", CustomProfileField.SELECT, field_data=field_data ) birthday = try_add_realm_custom_profile_field( zulip_realm, "Birthday", CustomProfileField.DATE ) favorite_website = try_add_realm_custom_profile_field( zulip_realm, "Favorite website", CustomProfileField.URL, hint="Or your personal blog's URL", ) mentor = try_add_realm_custom_profile_field( zulip_realm, "Mentor", CustomProfileField.USER ) github_profile = try_add_realm_default_custom_profile_field(zulip_realm, "github") # Fill in values for Iago and Hamlet hamlet = get_user_by_delivery_email("*****@*****.**", zulip_realm) do_update_user_custom_profile_data_if_changed( iago, [ {"id": phone_number.id, "value": "+1-234-567-8901"}, {"id": biography.id, "value": "Betrayer of Othello."}, {"id": favorite_food.id, "value": "Apples"}, {"id": favorite_editor.id, "value": "emacs"}, {"id": birthday.id, "value": "2000-01-01"}, {"id": favorite_website.id, "value": "https://zulip.readthedocs.io/en/latest/"}, {"id": mentor.id, "value": [hamlet.id]}, {"id": github_profile.id, "value": "zulip"}, ], ) do_update_user_custom_profile_data_if_changed( hamlet, [ {"id": phone_number.id, "value": "+0-11-23-456-7890"}, { "id": biography.id, "value": "I am:\n* The prince of Denmark\n* Nephew to the usurping Claudius", }, {"id": favorite_food.id, "value": "Dark chocolate"}, {"id": favorite_editor.id, "value": "vim"}, {"id": birthday.id, "value": "1900-01-01"}, {"id": favorite_website.id, "value": "https://blog.zulig.org"}, {"id": mentor.id, "value": [iago.id]}, {"id": github_profile.id, "value": "zulipbot"}, ], ) else: zulip_realm = get_realm("zulip") recipient_streams = [ klass.type_id for klass in Recipient.objects.filter(type=Recipient.STREAM) ] # Extract a list of all users user_profiles: List[UserProfile] = list(UserProfile.objects.filter(is_bot=False)) # Create a test realm emoji. IMAGE_FILE_PATH = static_path("images/test-images/checkbox.png") with open(IMAGE_FILE_PATH, "rb") as fp: check_add_realm_emoji(zulip_realm, "green_tick", iago, File(fp)) if not options["test_suite"]: # Populate users with some bar data for user in user_profiles: status: int = UserPresence.ACTIVE date = timezone_now() client = get_client("website") if user.full_name[0] <= "H": client = get_client("ZulipAndroid") UserPresence.objects.get_or_create( user_profile=user, realm_id=user.realm_id, client=client, timestamp=date, status=status, ) user_profiles_ids = [user_profile.id for user_profile in user_profiles] # Create several initial huddles for i in range(options["num_huddles"]): get_huddle(random.sample(user_profiles_ids, random.randint(3, 4))) # Create several initial pairs for personals personals_pairs = [ random.sample(user_profiles_ids, 2) for i in range(options["num_personals"]) ] create_alert_words(zulip_realm.id) # Generate a new set of test data. create_test_data() if options["delete"]: if options["test_suite"]: # Create test users; the MIT ones are needed to test # the Zephyr mirroring codepaths. event_time = timezone_now() testsuite_mit_users = [ ("Fred Sipb (MIT)", "*****@*****.**"), ("Athena Consulting Exchange User (MIT)", "*****@*****.**"), ("Esp Classroom (MIT)", "*****@*****.**"), ] create_users( mit_realm, testsuite_mit_users, tos_version=settings.TERMS_OF_SERVICE_VERSION ) mit_user = get_user_by_delivery_email("*****@*****.**", mit_realm) mit_signup_stream = Stream.objects.get( name=Realm.INITIAL_PRIVATE_STREAM_NAME, realm=mit_realm ) bulk_add_subscriptions(mit_realm, [mit_signup_stream], [mit_user], acting_user=None) testsuite_lear_users = [ ("King Lear", "*****@*****.**"), ("Cordelia, Lear's daughter", "*****@*****.**"), ] create_users( lear_realm, testsuite_lear_users, tos_version=settings.TERMS_OF_SERVICE_VERSION ) lear_user = get_user_by_delivery_email("*****@*****.**", lear_realm) lear_signup_stream = Stream.objects.get( name=Realm.INITIAL_PRIVATE_STREAM_NAME, realm=lear_realm ) bulk_add_subscriptions( lear_realm, [lear_signup_stream], [lear_user], acting_user=None ) if not options["test_suite"]: # To keep the messages.json fixtures file for the test # suite fast, don't add these users and subscriptions # when running populate_db for the test suite # to imitate emoji insertions in stream names raw_emojis = ["😎", "😂", "🐱👤"] zulip_stream_dict: Dict[str, Dict[str, Any]] = { "devel": {"description": "For developing"}, # ビデオゲーム - VideoGames (japanese) "ビデオゲーム": {"description": f"Share your favorite video games! {raw_emojis[2]}"}, "announce": { "description": "For announcements", "stream_post_policy": Stream.STREAM_POST_POLICY_ADMINS, }, "design": {"description": "For design"}, "support": {"description": "For support"}, "social": {"description": "For socializing"}, "test": {"description": "For testing `code`"}, "errors": {"description": "For errors"}, # 조리법 - Recipes (Korean) , Пельмени - Dumplings (Russian) "조리법 " + raw_emojis[0]: {"description": "Everything cooking, from pasta to Пельмени"}, } extra_stream_names = [ "802.11a", "Ad Hoc Network", "Augmented Reality", "Cycling", "DPI", "FAQ", "FiFo", "commits", "Control panel", "desktop", "компьютеры", "Data security", "desktop", "काम", "discussions", "Cloud storage", "GCI", "Vaporware", "Recent Trends", "issues", "live", "Health", "mobile", "空間", "provision", "hidrógeno", "HR", "アニメ", ] # Add stream names and stream descriptions for i in range(options["extra_streams"]): extra_stream_name = random.choice(extra_stream_names) + " " + str(i) # to imitate emoji insertions in stream names if random.random() <= 0.15: extra_stream_name += random.choice(raw_emojis) zulip_stream_dict[extra_stream_name] = { "description": "Auto-generated extra stream.", } bulk_create_streams(zulip_realm, zulip_stream_dict) # Now that we've created the notifications stream, configure it properly. zulip_realm.notifications_stream = get_stream("announce", zulip_realm) zulip_realm.save(update_fields=["notifications_stream"]) # Add a few default streams for default_stream_name in ["design", "devel", "social", "support"]: DefaultStream.objects.create( realm=zulip_realm, stream=get_stream(default_stream_name, zulip_realm) ) # Now subscribe everyone to these streams subscribe_users_to_streams(zulip_realm, zulip_stream_dict) create_user_groups() if not options["test_suite"]: # We populate the analytics database here for # development purpose only call_command("populate_analytics_db") threads = options["threads"] jobs: List[Tuple[int, List[List[int]], Dict[str, Any], int]] = [] for i in range(threads): count = options["num_messages"] // threads if i < options["num_messages"] % threads: count += 1 jobs.append((count, personals_pairs, options, random.randint(0, 10**10))) for job in jobs: generate_and_send_messages(job) if options["delete"]: if not options["test_suite"]: # These bots are not needed by the test suite # Also, we don't want interacting with each other # in dev setup. internal_zulip_users_nosubs = [ ("Zulip Commit Bot", "*****@*****.**"), ("Zulip Trac Bot", "*****@*****.**"), ("Zulip Nagios Bot", "*****@*****.**"), ] create_users( zulip_realm, internal_zulip_users_nosubs, bot_type=UserProfile.DEFAULT_BOT, bot_owner=desdemona, ) mark_all_messages_as_read() self.stdout.write("Successfully populated test database.\n") push_notifications_logger.disabled = False