diff --git a/frontend_tests/node_tests/lib/events.js b/frontend_tests/node_tests/lib/events.js index f83f688f9e..8ae424893e 100644 --- a/frontend_tests/node_tests/lib/events.js +++ b/frontend_tests/node_tests/lib/events.js @@ -84,6 +84,7 @@ exports.test_realm_emojis = { author_id: 222, deactivated: false, source_url: "/some/path/to/emoji", + still_url: null, }, }; diff --git a/templates/zerver/api/changelog.md b/templates/zerver/api/changelog.md index f82904a642..13390d7102 100644 --- a/templates/zerver/api/changelog.md +++ b/templates/zerver/api/changelog.md @@ -20,6 +20,14 @@ format used by the Zulip server that they are interacting with. ## Changes in Zulip 5.0 +**Feature level 113** + +* `GET /realm/emoji`, `POST /realm/emoji/{emoji_name}`, [`GET + /events`](/api/get-events), [`POST /register`](/api/register-queue): + The `still_url` field for custom emoji objects is now always + present, with a value of null for non-animated emoji. Previously, it + only was present for animated emoji. + **Feature level 112** * [`GET /events`](/api/get-events): Updated `update_message` event type diff --git a/version.py b/version.py index d2ab230469..e0f34f4319 100644 --- a/version.py +++ b/version.py @@ -33,7 +33,7 @@ DESKTOP_WARNING_VERSION = "5.4.3" # Changes should be accompanied by documentation explaining what the # new level means in templates/zerver/api/changelog.md, as well as # "**Changes**" entries in the endpoint's documentation in `zulip.yaml`. -API_FEATURE_LEVEL = 112 +API_FEATURE_LEVEL = 113 # 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 diff --git a/zerver/lib/event_schema.py b/zerver/lib/event_schema.py index dcff713c3a..7dc4d2c5ec 100644 --- a/zerver/lib/event_schema.py +++ b/zerver/lib/event_schema.py @@ -712,9 +712,7 @@ realm_emoji_type = DictType( ("source_url", str), ("deactivated", bool), ("author_id", int), - ], - optional_keys=[ - ("still_url", str), + ("still_url", OptionalType(str)), ], ) diff --git a/zerver/lib/markdown/__init__.py b/zerver/lib/markdown/__init__.py index 5a5ca00513..2b3c47f49c 100644 --- a/zerver/lib/markdown/__init__.py +++ b/zerver/lib/markdown/__init__.py @@ -1503,7 +1503,7 @@ class Emoji(markdown.inlinepatterns.Pattern): orig_syntax = match.group("syntax") name = orig_syntax[1:-1] - active_realm_emoji: Dict[str, Dict[str, str]] = {} + active_realm_emoji: Dict[str, EmojiInfo] = {} db_data = self.md.zulip_db_data if db_data is not None: active_realm_emoji = db_data["active_realm_emoji"] diff --git a/zerver/models.py b/zerver/models.py index 3e7deee120..3173782d47 100644 --- a/zerver/models.py +++ b/zerver/models.py @@ -37,6 +37,7 @@ from django.utils.timezone import now as timezone_now from django.utils.translation import gettext as _ from django.utils.translation import gettext_lazy from django_cte import CTEManager +from typing_extensions import TypedDict from confirmation import settings as confirmation_settings from zerver.lib import cache @@ -100,6 +101,15 @@ MAX_LANGUAGE_ID_LENGTH: int = 50 STREAM_NAMES = TypeVar("STREAM_NAMES", Sequence[str], AbstractSet[str]) +class EmojiInfo(TypedDict): + id: str + name: str + source_url: str + deactivated: bool + author_id: Optional[int] + still_url: Optional[str] + + def query_for_ids(query: QuerySet, user_ids: List[int], field: str) -> QuerySet: """ This function optimizes searches of the form @@ -726,11 +736,11 @@ class Realm(models.Model): return f"" @cache_with_key(get_realm_emoji_cache_key, timeout=3600 * 24 * 7) - def get_emoji(self) -> Dict[str, Dict[str, Any]]: + def get_emoji(self) -> Dict[str, EmojiInfo]: return get_realm_emoji_uncached(self) @cache_with_key(get_active_realm_emoji_cache_key, timeout=3600 * 24 * 7) - def get_active_emoji(self) -> Dict[str, Dict[str, Any]]: + def get_active_emoji(self) -> Dict[str, EmojiInfo]: return get_active_realm_emoji_uncached(self) def get_admin_users_and_bots( @@ -1058,9 +1068,7 @@ class RealmEmoji(models.Model): ] -def get_realm_emoji_dicts( - realm: Realm, only_active_emojis: bool = False -) -> Dict[str, Dict[str, Any]]: +def get_realm_emoji_dicts(realm: Realm, only_active_emojis: bool = False) -> Dict[str, EmojiInfo]: query = RealmEmoji.objects.filter(realm=realm).select_related("author") if only_active_emojis: query = query.filter(deactivated=False) @@ -1073,12 +1081,13 @@ def get_realm_emoji_dicts( author_id = realm_emoji.author_id emoji_url = get_emoji_url(realm_emoji.file_name, realm_emoji.realm_id) - emoji_dict = dict( + emoji_dict: EmojiInfo = dict( id=str(realm_emoji.id), name=realm_emoji.name, source_url=emoji_url, deactivated=realm_emoji.deactivated, author_id=author_id, + still_url=None, ) if realm_emoji.is_animated: @@ -1095,11 +1104,11 @@ def get_realm_emoji_dicts( return d -def get_realm_emoji_uncached(realm: Realm) -> Dict[str, Dict[str, Any]]: +def get_realm_emoji_uncached(realm: Realm) -> Dict[str, EmojiInfo]: return get_realm_emoji_dicts(realm) -def get_active_realm_emoji_uncached(realm: Realm) -> Dict[str, Dict[str, Any]]: +def get_active_realm_emoji_uncached(realm: Realm) -> Dict[str, EmojiInfo]: realm_emojis = get_realm_emoji_dicts(realm, only_active_emojis=True) d = {} for emoji_id, emoji_dict in realm_emojis.items(): diff --git a/zerver/openapi/zulip.yaml b/zerver/openapi/zulip.yaml index e4e1b27288..d3027a77db 100644 --- a/zerver/openapi/zulip.yaml +++ b/zerver/openapi/zulip.yaml @@ -13931,8 +13931,9 @@ components: emoji's image can be found. still_url: type: string + nullable: true description: | - Only present when the emoji's image is animated. + Only non-null when the emoji's image is animated. The path relative to the organization's URL where a still (not animated) version of the emoji can be found. (This is @@ -13942,7 +13943,9 @@ components: where continuously animating it would be a bad user experience (E.g. because it would be distracting). - **Changes**: New in Zulip 5.0 (feature level 97). + **Changes**: New in Zulip 5.0 (added as optional field in + feature level 97 and then made mandatory, but nullable, in + feature level 113). deactivated: type: boolean description: |