mirror of
				https://github.com/zulip/zulip.git
				synced 2025-11-04 05:53:43 +00:00 
			
		
		
		
	emoji: Add which emoji are supported to the /register call.
Fixes #21037. This is part of fixing #19371. To bulk-add new emoji regularly, mobile needs to know which servers support which emoji. `staticfiles_storage.url` generates a unique URL with a hash based on the file content, which lets mobile know if it needs to update its locally stored data.
This commit is contained in:
		@@ -20,6 +20,11 @@ format used by the Zulip server that they are interacting with.
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
## Changes in Zulip 6.0
 | 
					## Changes in Zulip 6.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					**Feature level 140**
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* [`POST /register`](/api/register-queue): Added string field `server_emoji_data_url`
 | 
				
			||||||
 | 
					  to the response.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
**Feature level 139**
 | 
					**Feature level 139**
 | 
				
			||||||
 | 
					
 | 
				
			||||||
* [`GET /get-events`](/api/get-events): When a user mutes or unmutes
 | 
					* [`GET /get-events`](/api/get-events): When a user mutes or unmutes
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -15,6 +15,7 @@ from emoji_setup_utils import (
 | 
				
			|||||||
    REMAPPED_EMOJIS,
 | 
					    REMAPPED_EMOJIS,
 | 
				
			||||||
    emoji_names_for_picker,
 | 
					    emoji_names_for_picker,
 | 
				
			||||||
    generate_codepoint_to_name_map,
 | 
					    generate_codepoint_to_name_map,
 | 
				
			||||||
 | 
					    generate_codepoint_to_names_map,
 | 
				
			||||||
    generate_emoji_catalog,
 | 
					    generate_emoji_catalog,
 | 
				
			||||||
    generate_name_to_codepoint_map,
 | 
					    generate_name_to_codepoint_map,
 | 
				
			||||||
    get_emoji_code,
 | 
					    get_emoji_code,
 | 
				
			||||||
@@ -332,7 +333,7 @@ def setup_old_emoji_farm(
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def generate_map_files(cache_path: str, emoji_catalog: Dict[str, List[str]]) -> None:
 | 
					def generate_map_files(cache_path: str, emoji_catalog: Dict[str, List[str]]) -> None:
 | 
				
			||||||
    # This function generates the main data file about emoji that are
 | 
					    # This function generates the main data files about emoji that are
 | 
				
			||||||
    # consumed by the web app, mobile apps, Markdown processor, etc.
 | 
					    # consumed by the web app, mobile apps, Markdown processor, etc.
 | 
				
			||||||
    names = emoji_names_for_picker(EMOJI_NAME_MAPS)
 | 
					    names = emoji_names_for_picker(EMOJI_NAME_MAPS)
 | 
				
			||||||
    codepoint_to_name = generate_codepoint_to_name_map(EMOJI_NAME_MAPS)
 | 
					    codepoint_to_name = generate_codepoint_to_name_map(EMOJI_NAME_MAPS)
 | 
				
			||||||
@@ -352,6 +353,24 @@ def generate_map_files(cache_path: str, emoji_catalog: Dict[str, List[str]]) ->
 | 
				
			|||||||
            )
 | 
					            )
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # This is the more official API for mobile to fetch data about emoji.
 | 
				
			||||||
 | 
					    # emoji_codes.json has a lot of goo, and we're creating this new file
 | 
				
			||||||
 | 
					    # as a cleaner data format to move towards. We could add the rest of
 | 
				
			||||||
 | 
					    # the data into this API-described data, and then the web client could
 | 
				
			||||||
 | 
					    # switch to that which would allow us to drop the existing file. But
 | 
				
			||||||
 | 
					    # we'll probably instead do #18121 which will make this file obsolete.
 | 
				
			||||||
 | 
					    # So this is a temporary solution. CZO discussion:
 | 
				
			||||||
 | 
					    # https://chat.zulip.org/#narrow/stream/378-api-design/topic/currently.20supported.20emoji/near/1394598
 | 
				
			||||||
 | 
					    EMOJI_API_FILE_PATH = os.path.join(cache_path, "emoji_api.json")
 | 
				
			||||||
 | 
					    with open(EMOJI_API_FILE_PATH, "wb") as emoji_api_file:
 | 
				
			||||||
 | 
					        emoji_api_file.write(
 | 
				
			||||||
 | 
					            orjson.dumps(
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    "code_to_names": generate_codepoint_to_names_map(EMOJI_NAME_MAPS),
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def dump_emojis(cache_path: str) -> None:
 | 
					def dump_emojis(cache_path: str) -> None:
 | 
				
			||||||
    with open("emoji_map.json", "rb") as emoji_map_file:
 | 
					    with open("emoji_map.json", "rb") as emoji_map_file:
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -116,6 +116,19 @@ def generate_codepoint_to_name_map(emoji_name_maps: Dict[str, Dict[str, Any]]) -
 | 
				
			|||||||
    return codepoint_to_name
 | 
					    return codepoint_to_name
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def generate_codepoint_to_names_map(
 | 
				
			||||||
 | 
					    emoji_name_maps: Dict[str, Dict[str, Any]]
 | 
				
			||||||
 | 
					) -> Dict[str, List[str]]:
 | 
				
			||||||
 | 
					    codepoint_to_names: Dict[str, List[str]] = {}
 | 
				
			||||||
 | 
					    for emoji_code, name_info in emoji_name_maps.items():
 | 
				
			||||||
 | 
					        # The first element of the names list is always the canonical name.
 | 
				
			||||||
 | 
					        names = [name_info["canonical_name"]]
 | 
				
			||||||
 | 
					        for alias in name_info["aliases"]:
 | 
				
			||||||
 | 
					            names.append(alias)
 | 
				
			||||||
 | 
					        codepoint_to_names[emoji_code] = names
 | 
				
			||||||
 | 
					    return codepoint_to_names
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def generate_name_to_codepoint_map(emoji_name_maps: Dict[str, Dict[str, Any]]) -> Dict[str, str]:
 | 
					def generate_name_to_codepoint_map(emoji_name_maps: Dict[str, Dict[str, Any]]) -> Dict[str, str]:
 | 
				
			||||||
    name_to_codepoint = {}
 | 
					    name_to_codepoint = {}
 | 
				
			||||||
    for emoji_code, name_info in emoji_name_maps.items():
 | 
					    for emoji_code, name_info in emoji_name_maps.items():
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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 = 139
 | 
					API_FEATURE_LEVEL = 140
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# 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
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,6 +3,7 @@ import re
 | 
				
			|||||||
from typing import Tuple
 | 
					from typing import Tuple
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import orjson
 | 
					import orjson
 | 
				
			||||||
 | 
					from django.contrib.staticfiles.storage import staticfiles_storage
 | 
				
			||||||
from django.utils.translation import gettext as _
 | 
					from django.utils.translation import gettext as _
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from zerver.lib.exceptions import JsonableError
 | 
					from zerver.lib.exceptions import JsonableError
 | 
				
			||||||
@@ -35,6 +36,15 @@ EMOTICON_RE = (
 | 
				
			|||||||
    + f"))(?![^{terminal_symbols}])"
 | 
					    + f"))(?![^{terminal_symbols}])"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def data_url() -> str:
 | 
				
			||||||
 | 
					    # This bakes a hash into the URL, which looks something like
 | 
				
			||||||
 | 
					    # static/webpack-bundles/files/64.0cdafdf0b6596657a9be.png
 | 
				
			||||||
 | 
					    # This is how Django deals with serving static files in a cacheable way.
 | 
				
			||||||
 | 
					    # See PR #22275 for details.
 | 
				
			||||||
 | 
					    return staticfiles_storage.url("generated/emoji/emoji_api.json")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Translates emoticons to their colon syntax, e.g. `:smiley:`.
 | 
					# Translates emoticons to their colon syntax, e.g. `:smiley:`.
 | 
				
			||||||
def translate_emoticons(text: str) -> str:
 | 
					def translate_emoticons(text: str) -> str:
 | 
				
			||||||
    translated = text
 | 
					    translated = text
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -14,6 +14,7 @@ from zerver.actions.default_streams import (
 | 
				
			|||||||
    streams_to_dicts_sorted,
 | 
					    streams_to_dicts_sorted,
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
from zerver.actions.users import get_owned_bot_dicts
 | 
					from zerver.actions.users import get_owned_bot_dicts
 | 
				
			||||||
 | 
					from zerver.lib import emoji
 | 
				
			||||||
from zerver.lib.alert_words import user_alert_words
 | 
					from zerver.lib.alert_words import user_alert_words
 | 
				
			||||||
from zerver.lib.avatar import avatar_url
 | 
					from zerver.lib.avatar import avatar_url
 | 
				
			||||||
from zerver.lib.bot_config import load_bot_config_template
 | 
					from zerver.lib.bot_config import load_bot_config_template
 | 
				
			||||||
@@ -308,6 +309,8 @@ def fetch_initial_state_data(
 | 
				
			|||||||
        state["server_web_public_streams_enabled"] = settings.WEB_PUBLIC_STREAMS_ENABLED
 | 
					        state["server_web_public_streams_enabled"] = settings.WEB_PUBLIC_STREAMS_ENABLED
 | 
				
			||||||
        state["giphy_rating_options"] = realm.GIPHY_RATING_OPTIONS
 | 
					        state["giphy_rating_options"] = realm.GIPHY_RATING_OPTIONS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        state["server_emoji_data_url"] = emoji.data_url()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        state["server_needs_upgrade"] = is_outdated_server(user_profile)
 | 
					        state["server_needs_upgrade"] = is_outdated_server(user_profile)
 | 
				
			||||||
        state[
 | 
					        state[
 | 
				
			||||||
            "event_queue_longpoll_timeout_seconds"
 | 
					            "event_queue_longpoll_timeout_seconds"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -12166,6 +12166,26 @@ paths:
 | 
				
			|||||||
                          (`realm_enable_spectator_access`).
 | 
					                          (`realm_enable_spectator_access`).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                          **Changes**: New in Zulip 5.0 (feature level 110).
 | 
					                          **Changes**: New in Zulip 5.0 (feature level 110).
 | 
				
			||||||
 | 
					                      server_emoji_data_url:
 | 
				
			||||||
 | 
					                        type: string
 | 
				
			||||||
 | 
					                        description: |
 | 
				
			||||||
 | 
					                          Present if `realm` is present in `fetch_event_types`.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                          The URL to a JSON file that describes which emoji names map to which
 | 
				
			||||||
 | 
					                          emoji codes, for all Unicode emoji this Zulip server accepts.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                          The data at the given URL is a JSON object with one property, `code_to_names`.
 | 
				
			||||||
 | 
					                          The value of that property is a JSON object where each key is an
 | 
				
			||||||
 | 
					                          [emoji code](/api/add-reaction#parameter-emoji_code) for an available
 | 
				
			||||||
 | 
					                          Unicode emoji, and each value is the corresponding
 | 
				
			||||||
 | 
					                          [emoji names](/api/add-reaction#parameter-emoji_name) for this emoji,
 | 
				
			||||||
 | 
					                          with the canonical name for the emoji always appearing first.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                          The HTTP response at that URL will have appropriate HTTP caching headers, such
 | 
				
			||||||
 | 
					                          any HTTP implementation should get a cached version if emoji haven't changed
 | 
				
			||||||
 | 
					                          since the last request.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                          **Changes**: New in Zulip 6.0 (feature level 140).
 | 
				
			||||||
                      event_queue_longpoll_timeout_seconds:
 | 
					                      event_queue_longpoll_timeout_seconds:
 | 
				
			||||||
                        type: integer
 | 
					                        type: integer
 | 
				
			||||||
                        description: |
 | 
					                        description: |
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -190,6 +190,7 @@ class HomeTest(ZulipTestCase):
 | 
				
			|||||||
        "request_language",
 | 
					        "request_language",
 | 
				
			||||||
        "search_pills_enabled",
 | 
					        "search_pills_enabled",
 | 
				
			||||||
        "server_avatar_changes_disabled",
 | 
					        "server_avatar_changes_disabled",
 | 
				
			||||||
 | 
					        "server_emoji_data_url",
 | 
				
			||||||
        "server_generation",
 | 
					        "server_generation",
 | 
				
			||||||
        "server_inline_image_preview",
 | 
					        "server_inline_image_preview",
 | 
				
			||||||
        "server_inline_url_embed_preview",
 | 
					        "server_inline_url_embed_preview",
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user