diff --git a/CHANGELOG.md b/CHANGELOG.md index ceff4f07a..6aaeeec50 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -63,6 +63,8 @@ If you depend on these features, please raise your voice in * Improve readability of SHA256 fingerprint. (@wrekone) * Metadata and Replay Flow Filters: Flows may be filtered based on metadata and replay status. (@rbdixon) * Flow control: don't read connection data faster than it can be forwarded. (@hazcod) +* Customize markers with emoji, and filters: The `flow.mark` command may be used to mark a flow with either the default + "red ball" marker, a single character, or an emoji like `:grapes:`. Use the `~marker` filter to filter on marker characters. (@rbdixon) * --- TODO: add new PRs above this line --- * ... and various other fixes, documentation improvements, dependency version bumps, etc. diff --git a/examples/contrib/all_markers.py b/examples/contrib/all_markers.py new file mode 100644 index 000000000..4e9043f33 --- /dev/null +++ b/examples/contrib/all_markers.py @@ -0,0 +1,10 @@ +from mitmproxy import ctx, command +from mitmproxy.utils import emoji + + +@command.command('all.markers') +def all_markers(): + 'Create a new flow showing all marker values' + for marker in emoji.emoji: + ctx.master.commands.call('view.flows.create', 'get', f'https://example.com/{marker}') + ctx.master.commands.call('flow.mark', [ctx.master.view.focus.flow], marker) diff --git a/mitmproxy/addons/core.py b/mitmproxy/addons/core.py index 072eedb32..73e64d168 100644 --- a/mitmproxy/addons/core.py +++ b/mitmproxy/addons/core.py @@ -2,7 +2,7 @@ import typing import os -from mitmproxy.utils import human +from mitmproxy.utils import emoji, human from mitmproxy import ctx, hooks from mitmproxy import exceptions from mitmproxy import command @@ -103,15 +103,17 @@ class Core: # FIXME: this will become view.mark later @command.command("flow.mark") - def mark(self, flows: typing.Sequence[flow.Flow], boolean: bool) -> None: + def mark(self, flows: typing.Sequence[flow.Flow], marker: mitmproxy.types.Marker) -> None: """ Mark flows. """ updated = [] + if marker not in emoji.emoji: + raise exceptions.CommandError(f"invalid marker value") + for i in flows: - if i.marked != boolean: - i.marked = boolean - updated.append(i) + i.marked = marker + updated.append(i) ctx.master.addons.trigger(hooks.UpdateHook(updated)) # FIXME: this will become view.mark.toggle later @@ -121,7 +123,10 @@ class Core: Toggle mark for flows. """ for i in flows: - i.marked = not i.marked + if i.marked: + i.marked = "" + else: + i.marked = ":default:" ctx.master.addons.trigger(hooks.UpdateHook(flows)) @command.command("flow.kill") diff --git a/mitmproxy/flow.py b/mitmproxy/flow.py index d33f637fa..61dec3f8f 100644 --- a/mitmproxy/flow.py +++ b/mitmproxy/flow.py @@ -82,9 +82,18 @@ class Flow(stateobject.StateObject): We're waiting for a user action to forward the flow to its destination. """ - marked: bool + marked: str = "" """ - If `True`, this flow has been marked by the user. + If this attribute is a non-empty string the flow has been marked by the user. + + A string value will be used as the marker annotation. May either be a single character or a Unicode emoji name. + + For example `:grapes:` becomes `๐Ÿ‡` in views that support emoji rendering. + Consult the [Github API Emoji List](https://api.github.com/emojis) for a list of emoji that may be used. + Not all emoji, especially [emoji modifiers](https://en.wikipedia.org/wiki/Miscellaneous_Symbols_and_Pictographs#Emoji_modifiers) + will render consistently. + + The default marker for the view will be used if the Unicode emoji name can not be interpreted. """ is_replay: typing.Optional[str] @@ -111,7 +120,7 @@ class Flow(stateobject.StateObject): self.intercepted: bool = False self._backup: typing.Optional[Flow] = None self.reply: typing.Optional[controller.Reply] = None - self.marked: bool = False + self.marked: str = "" self.is_replay: typing.Optional[str] = None self.metadata: typing.Dict[str, typing.Any] = dict() @@ -123,7 +132,7 @@ class Flow(stateobject.StateObject): type=str, intercepted=bool, is_replay=str, - marked=bool, + marked=str, metadata=typing.Dict[str, typing.Any], ) diff --git a/mitmproxy/flowfilter.py b/mitmproxy/flowfilter.py index 6435a73fe..00641fa9b 100644 --- a/mitmproxy/flowfilter.py +++ b/mitmproxy/flowfilter.py @@ -86,7 +86,7 @@ class FMarked(_Action): help = "Match marked flows" def __call__(self, f): - return f.marked + return bool(f.marked) class FHTTP(_Action): @@ -416,6 +416,15 @@ class FMeta(_Rex): return self.re.search(m) +class FMarker(_Rex): + code = "marker" + help = "Match marked flows with specified marker" + is_binary = False + + def __call__(self, f): + return self.re.search(f.marked) + + class _Int(_Action): def __init__(self, num): @@ -502,6 +511,7 @@ filter_rex: Sequence[Type[_Rex]] = [ FSrc, FUrl, FMeta, + FMarker, ] filter_int = [ FCode diff --git a/mitmproxy/io/compat.py b/mitmproxy/io/compat.py index 795dda8af..c7e7b76ae 100644 --- a/mitmproxy/io/compat.py +++ b/mitmproxy/io/compat.py @@ -300,6 +300,15 @@ def convert_11_12(data): return data +def convert_12_13(data): + data["version"] = 13 + if data["marked"]: + data["marked"] = ":default:" + else: + data["marked"] = "" + return data + + def _convert_dict_keys(o: Any) -> Any: if isinstance(o, dict): return {strutils.always_str(k): _convert_dict_keys(v) for k, v in o.items()} @@ -359,6 +368,7 @@ converters = { 9: convert_9_10, 10: convert_10_11, 11: convert_11_12, + 12: convert_12_13, } diff --git a/mitmproxy/tools/console/common.py b/mitmproxy/tools/console/common.py index edb4a0d1e..f807ae17c 100644 --- a/mitmproxy/tools/console/common.py +++ b/mitmproxy/tools/console/common.py @@ -10,7 +10,7 @@ import urwid.util from mitmproxy import flow from mitmproxy.http import HTTPFlow -from mitmproxy.utils import human +from mitmproxy.utils import human, emoji from mitmproxy.tcp import TCPFlow # Detect Windows Subsystem for Linux and Windows @@ -161,6 +161,16 @@ def fixlen_r(s: str, maxlen: int) -> str: return SYMBOL_ELLIPSIS + s[len(s) - maxlen + len(SYMBOL_ELLIPSIS):] +def render_marker(marker: str) -> str: + rendered = emoji.emoji.get(marker, SYMBOL_MARK) + + # The marker can only be one glyph. Some emoji that use zero-width joiners (ZWJ) + # will not be rendered as a single glyph and instead will show + # multiple glyphs. Just use the first glyph as a fallback. + # https://emojipedia.org/emoji-zwj-sequence/ + return rendered[0] + + class TruncatedText(urwid.Widget): def __init__(self, text, attr, align='left'): self.text = text @@ -359,18 +369,18 @@ def format_left_indicators( def format_right_indicators( *, replay: bool, - marked: bool + marked: str, ): indicators: typing.List[typing.Union[str, typing.Tuple[str, str]]] = [] if replay: indicators.append(("replay", SYMBOL_REPLAY)) else: indicators.append(" ") - if marked: - indicators.append(("mark", SYMBOL_MARK)) + if bool(marked): + indicators.append(("mark", render_marker(marked))) else: - indicators.append(" ") - return "fixed", 2, urwid.Text(indicators) + indicators.append(" ") + return "fixed", 3, urwid.Text(indicators) @lru_cache(maxsize=800) @@ -378,7 +388,7 @@ def format_http_flow_list( *, render_mode: RenderMode, focused: bool, - marked: bool, + marked: str, is_replay: bool, request_method: str, request_scheme: str, @@ -479,7 +489,7 @@ def format_http_flow_table( *, render_mode: RenderMode, focused: bool, - marked: bool, + marked: str, is_replay: typing.Optional[str], request_method: str, request_scheme: str, @@ -574,7 +584,7 @@ def format_http_flow_table( items.append(format_right_indicators( replay=bool(is_replay), - marked=marked + marked=marked, )) return urwid.Columns(items, dividechars=1, min_width=15) @@ -585,7 +595,7 @@ def format_tcp_flow( render_mode: RenderMode, focused: bool, timestamp_start: float, - marked: bool, + marked: str, client_address, server_address, total_size: int, diff --git a/mitmproxy/types.py b/mitmproxy/types.py index 0a16c5657..e02a1f670 100644 --- a/mitmproxy/types.py +++ b/mitmproxy/types.py @@ -4,6 +4,7 @@ import typing from mitmproxy import exceptions from mitmproxy import flow +from mitmproxy.utils import emoji if typing.TYPE_CHECKING: # pragma: no cover from mitmproxy.command import CommandManager @@ -37,6 +38,10 @@ class Data(typing.Sequence[typing.Sequence[typing.Union[str, bytes]]]): pass +class Marker(str): + pass + + class Choice: def __init__(self, options_command): self.options_command = options_command @@ -406,6 +411,29 @@ class _ChoiceType(_BaseType): return val in opts +ALL_MARKERS = ['true', 'false'] + list(emoji.emoji) + + +class _MarkerType(_BaseType): + typ = Marker + display = "marker" + + def completion(self, manager: "CommandManager", t: Choice, s: str) -> typing.Sequence[str]: + return ALL_MARKERS + + def parse(self, manager: "CommandManager", t: Choice, s: str) -> str: + if s not in ALL_MARKERS: + raise exceptions.TypeError("Invalid choice.") + if s == 'true': + return ":default:" + elif s == 'false': + return "" + return s + + def is_valid(self, manager: "CommandManager", typ: typing.Any, val: str) -> bool: + return val in ALL_MARKERS + + class TypeManager: def __init__(self, *types): self.typemap = {} @@ -428,6 +456,7 @@ CommandTypes = TypeManager( _FlowType, _FlowsType, _IntType, + _MarkerType, _PathType, _StrType, _StrSeqType, diff --git a/mitmproxy/utils/emoji.py b/mitmproxy/utils/emoji.py new file mode 100644 index 000000000..35832b85d --- /dev/null +++ b/mitmproxy/utils/emoji.py @@ -0,0 +1,1887 @@ +#!/usr/bin/env python3 +""" +All of the emoji and characters that can be used as flow markers. +""" + +# auto-generated. run this file to refresh. + +emoji = { + ":+1:": "๐Ÿ‘", + ":-1:": "๐Ÿ‘Ž", + ":100:": "๐Ÿ’ฏ", + ":1234:": "๐Ÿ”ข", + ":1st_place_medal:": "๐Ÿฅ‡", + ":2nd_place_medal:": "๐Ÿฅˆ", + ":3rd_place_medal:": "๐Ÿฅ‰", + ":8ball:": "๐ŸŽฑ", + ":a:": "๐Ÿ…ฐ", + ":ab:": "๐Ÿ†Ž", + ":abacus:": "๐Ÿงฎ", + ":abc:": "๐Ÿ”ค", + ":abcd:": "๐Ÿ”ก", + ":accept:": "๐Ÿ‰‘", + ":adhesive_bandage:": "๐Ÿฉน", + ":adult:": "๐Ÿง‘", + ":aerial_tramway:": "๐Ÿšก", + ":afghanistan:": "๐Ÿ‡ฆโ€๐Ÿ‡ซ", + ":airplane:": "โœˆ", + ":aland_islands:": "๐Ÿ‡ฆโ€๐Ÿ‡ฝ", + ":alarm_clock:": "โฐ", + ":albania:": "๐Ÿ‡ฆโ€๐Ÿ‡ฑ", + ":alembic:": "โš—", + ":algeria:": "๐Ÿ‡ฉโ€๐Ÿ‡ฟ", + ":alien:": "๐Ÿ‘ฝ", + ":ambulance:": "๐Ÿš‘", + ":american_samoa:": "๐Ÿ‡ฆโ€๐Ÿ‡ธ", + ":amphora:": "๐Ÿบ", + ":anchor:": "โš“", + ":andorra:": "๐Ÿ‡ฆโ€๐Ÿ‡ฉ", + ":angel:": "๐Ÿ‘ผ", + ":anger:": "๐Ÿ’ข", + ":angola:": "๐Ÿ‡ฆโ€๐Ÿ‡ด", + ":angry:": "๐Ÿ˜ ", + ":anguilla:": "๐Ÿ‡ฆโ€๐Ÿ‡ฎ", + ":anguished:": "๐Ÿ˜ง", + ":ant:": "๐Ÿœ", + ":antarctica:": "๐Ÿ‡ฆโ€๐Ÿ‡ถ", + ":antigua_barbuda:": "๐Ÿ‡ฆโ€๐Ÿ‡ฌ", + ":apple:": "๐ŸŽ", + ":aquarius:": "โ™’", + ":argentina:": "๐Ÿ‡ฆโ€๐Ÿ‡ท", + ":aries:": "โ™ˆ", + ":armenia:": "๐Ÿ‡ฆโ€๐Ÿ‡ฒ", + ":arrow_backward:": "โ—€", + ":arrow_double_down:": "โฌ", + ":arrow_double_up:": "โซ", + ":arrow_down:": "โฌ‡", + ":arrow_down_small:": "๐Ÿ”ฝ", + ":arrow_forward:": "โ–ถ", + ":arrow_heading_down:": "โคต", + ":arrow_heading_up:": "โคด", + ":arrow_left:": "โฌ…", + ":arrow_lower_left:": "โ†™", + ":arrow_lower_right:": "โ†˜", + ":arrow_right:": "โžก", + ":arrow_right_hook:": "โ†ช", + ":arrow_up:": "โฌ†", + ":arrow_up_down:": "โ†•", + ":arrow_up_small:": "๐Ÿ”ผ", + ":arrow_upper_left:": "โ†–", + ":arrow_upper_right:": "โ†—", + ":arrows_clockwise:": "๐Ÿ”ƒ", + ":arrows_counterclockwise:": "๐Ÿ”„", + ":art:": "๐ŸŽจ", + ":articulated_lorry:": "๐Ÿš›", + ":artificial_satellite:": "๐Ÿ›ฐ", + ":artist:": "๐Ÿง‘โ€๐ŸŽจ", + ":aruba:": "๐Ÿ‡ฆโ€๐Ÿ‡ผ", + ":ascension_island:": "๐Ÿ‡ฆโ€๐Ÿ‡จ", + ":asterisk:": "*โ€โƒฃ", + ":astonished:": "๐Ÿ˜ฒ", + ":astronaut:": "๐Ÿง‘โ€๐Ÿš€", + ":athletic_shoe:": "๐Ÿ‘Ÿ", + ":atm:": "๐Ÿง", + ":atom_symbol:": "โš›", + ":australia:": "๐Ÿ‡ฆโ€๐Ÿ‡บ", + ":austria:": "๐Ÿ‡ฆโ€๐Ÿ‡น", + ":auto_rickshaw:": "๐Ÿ›บ", + ":avocado:": "๐Ÿฅ‘", + ":axe:": "๐Ÿช“", + ":azerbaijan:": "๐Ÿ‡ฆโ€๐Ÿ‡ฟ", + ":b:": "๐Ÿ…ฑ", + ":baby:": "๐Ÿ‘ถ", + ":baby_bottle:": "๐Ÿผ", + ":baby_chick:": "๐Ÿค", + ":baby_symbol:": "๐Ÿšผ", + ":back:": "๐Ÿ”™", + ":bacon:": "๐Ÿฅ“", + ":badger:": "๐Ÿฆก", + ":badminton:": "๐Ÿธ", + ":bagel:": "๐Ÿฅฏ", + ":baggage_claim:": "๐Ÿ›„", + ":baguette_bread:": "๐Ÿฅ–", + ":bahamas:": "๐Ÿ‡งโ€๐Ÿ‡ธ", + ":bahrain:": "๐Ÿ‡งโ€๐Ÿ‡ญ", + ":balance_scale:": "โš–", + ":bald_man:": "๐Ÿ‘จโ€๐Ÿฆฒ", + ":bald_woman:": "๐Ÿ‘ฉโ€๐Ÿฆฒ", + ":ballet_shoes:": "๐Ÿฉฐ", + ":balloon:": "๐ŸŽˆ", + ":ballot_box:": "๐Ÿ—ณ", + ":ballot_box_with_check:": "โ˜‘", + ":bamboo:": "๐ŸŽ", + ":banana:": "๐ŸŒ", + ":bangbang:": "โ€ผ", + ":bangladesh:": "๐Ÿ‡งโ€๐Ÿ‡ฉ", + ":banjo:": "๐Ÿช•", + ":bank:": "๐Ÿฆ", + ":bar_chart:": "๐Ÿ“Š", + ":barbados:": "๐Ÿ‡งโ€๐Ÿ‡ง", + ":barber:": "๐Ÿ’ˆ", + ":baseball:": "โšพ", + ":basket:": "๐Ÿงบ", + ":basketball:": "๐Ÿ€", + ":basketball_man:": "โ›นโ€โ™‚", + ":basketball_woman:": "โ›นโ€โ™€", + ":bat:": "๐Ÿฆ‡", + ":bath:": "๐Ÿ›€", + ":bathtub:": "๐Ÿ›", + ":battery:": "๐Ÿ”‹", + ":beach_umbrella:": "๐Ÿ–", + ":bear:": "๐Ÿป", + ":bearded_person:": "๐Ÿง”", + ":bed:": "๐Ÿ›", + ":bee:": "๐Ÿ", + ":beer:": "๐Ÿบ", + ":beers:": "๐Ÿป", + ":beetle:": "๐Ÿž", + ":beginner:": "๐Ÿ”ฐ", + ":belarus:": "๐Ÿ‡งโ€๐Ÿ‡พ", + ":belgium:": "๐Ÿ‡งโ€๐Ÿ‡ช", + ":belize:": "๐Ÿ‡งโ€๐Ÿ‡ฟ", + ":bell:": "๐Ÿ””", + ":bellhop_bell:": "๐Ÿ›Ž", + ":benin:": "๐Ÿ‡งโ€๐Ÿ‡ฏ", + ":bento:": "๐Ÿฑ", + ":bermuda:": "๐Ÿ‡งโ€๐Ÿ‡ฒ", + ":beverage_box:": "๐Ÿงƒ", + ":bhutan:": "๐Ÿ‡งโ€๐Ÿ‡น", + ":bicyclist:": "๐Ÿšด", + ":bike:": "๐Ÿšฒ", + ":biking_man:": "๐Ÿšดโ€โ™‚", + ":biking_woman:": "๐Ÿšดโ€โ™€", + ":bikini:": "๐Ÿ‘™", + ":billed_cap:": "๐Ÿงข", + ":biohazard:": "โ˜ฃ", + ":bird:": "๐Ÿฆ", + ":birthday:": "๐ŸŽ‚", + ":black_circle:": "โšซ", + ":black_flag:": "๐Ÿด", + ":black_heart:": "๐Ÿ–ค", + ":black_joker:": "๐Ÿƒ", + ":black_large_square:": "โฌ›", + ":black_medium_small_square:": "โ—พ", + ":black_medium_square:": "โ—ผ", + ":black_nib:": "โœ’", + ":black_small_square:": "โ–ช", + ":black_square_button:": "๐Ÿ”ฒ", + ":blond_haired_man:": "๐Ÿ‘ฑโ€โ™‚", + ":blond_haired_person:": "๐Ÿ‘ฑ", + ":blond_haired_woman:": "๐Ÿ‘ฑโ€โ™€", + ":blonde_woman:": "๐Ÿ‘ฑโ€โ™€", + ":blossom:": "๐ŸŒผ", + ":blowfish:": "๐Ÿก", + ":blue_book:": "๐Ÿ“˜", + ":blue_car:": "๐Ÿš™", + ":blue_heart:": "๐Ÿ’™", + ":blue_square:": "๐ŸŸฆ", + ":blush:": "๐Ÿ˜Š", + ":boar:": "๐Ÿ—", + ":boat:": "โ›ต", + ":bolivia:": "๐Ÿ‡งโ€๐Ÿ‡ด", + ":bomb:": "๐Ÿ’ฃ", + ":bone:": "๐Ÿฆด", + ":book:": "๐Ÿ“–", + ":bookmark:": "๐Ÿ”–", + ":bookmark_tabs:": "๐Ÿ“‘", + ":books:": "๐Ÿ“š", + ":boom:": "๐Ÿ’ฅ", + ":boot:": "๐Ÿ‘ข", + ":bosnia_herzegovina:": "๐Ÿ‡งโ€๐Ÿ‡ฆ", + ":botswana:": "๐Ÿ‡งโ€๐Ÿ‡ผ", + ":bouncing_ball_man:": "โ›นโ€โ™‚", + ":bouncing_ball_person:": "โ›น", + ":bouncing_ball_woman:": "โ›นโ€โ™€", + ":bouquet:": "๐Ÿ’", + ":bouvet_island:": "๐Ÿ‡งโ€๐Ÿ‡ป", + ":bow:": "๐Ÿ™‡", + ":bow_and_arrow:": "๐Ÿน", + ":bowing_man:": "๐Ÿ™‡โ€โ™‚", + ":bowing_woman:": "๐Ÿ™‡โ€โ™€", + ":bowl_with_spoon:": "๐Ÿฅฃ", + ":bowling:": "๐ŸŽณ", + ":boxing_glove:": "๐ŸฅŠ", + ":boy:": "๐Ÿ‘ฆ", + ":brain:": "๐Ÿง ", + ":brazil:": "๐Ÿ‡งโ€๐Ÿ‡ท", + ":bread:": "๐Ÿž", + ":breast_feeding:": "๐Ÿคฑ", + ":bricks:": "๐Ÿงฑ", + ":bride_with_veil:": "๐Ÿ‘ฐ", + ":bridge_at_night:": "๐ŸŒ‰", + ":briefcase:": "๐Ÿ’ผ", + ":british_indian_ocean_territory:": "๐Ÿ‡ฎโ€๐Ÿ‡ด", + ":british_virgin_islands:": "๐Ÿ‡ปโ€๐Ÿ‡ฌ", + ":broccoli:": "๐Ÿฅฆ", + ":broken_heart:": "๐Ÿ’”", + ":broom:": "๐Ÿงน", + ":brown_circle:": "๐ŸŸค", + ":brown_heart:": "๐ŸคŽ", + ":brown_square:": "๐ŸŸซ", + ":brunei:": "๐Ÿ‡งโ€๐Ÿ‡ณ", + ":bug:": "๐Ÿ›", + ":building_construction:": "๐Ÿ—", + ":bulb:": "๐Ÿ’ก", + ":bulgaria:": "๐Ÿ‡งโ€๐Ÿ‡ฌ", + ":bullettrain_front:": "๐Ÿš…", + ":bullettrain_side:": "๐Ÿš„", + ":burkina_faso:": "๐Ÿ‡งโ€๐Ÿ‡ซ", + ":burrito:": "๐ŸŒฏ", + ":burundi:": "๐Ÿ‡งโ€๐Ÿ‡ฎ", + ":bus:": "๐ŸšŒ", + ":business_suit_levitating:": "๐Ÿ•ด", + ":busstop:": "๐Ÿš", + ":bust_in_silhouette:": "๐Ÿ‘ค", + ":busts_in_silhouette:": "๐Ÿ‘ฅ", + ":butter:": "๐Ÿงˆ", + ":butterfly:": "๐Ÿฆ‹", + ":cactus:": "๐ŸŒต", + ":cake:": "๐Ÿฐ", + ":calendar:": "๐Ÿ“†", + ":call_me_hand:": "๐Ÿค™", + ":calling:": "๐Ÿ“ฒ", + ":cambodia:": "๐Ÿ‡ฐโ€๐Ÿ‡ญ", + ":camel:": "๐Ÿซ", + ":camera:": "๐Ÿ“ท", + ":camera_flash:": "๐Ÿ“ธ", + ":cameroon:": "๐Ÿ‡จโ€๐Ÿ‡ฒ", + ":camping:": "๐Ÿ•", + ":canada:": "๐Ÿ‡จโ€๐Ÿ‡ฆ", + ":canary_islands:": "๐Ÿ‡ฎโ€๐Ÿ‡จ", + ":cancer:": "โ™‹", + ":candle:": "๐Ÿ•ฏ", + ":candy:": "๐Ÿฌ", + ":canned_food:": "๐Ÿฅซ", + ":canoe:": "๐Ÿ›ถ", + ":cape_verde:": "๐Ÿ‡จโ€๐Ÿ‡ป", + ":capital_abcd:": "๐Ÿ” ", + ":capricorn:": "โ™‘", + ":car:": "๐Ÿš—", + ":card_file_box:": "๐Ÿ—ƒ", + ":card_index:": "๐Ÿ“‡", + ":card_index_dividers:": "๐Ÿ—‚", + ":caribbean_netherlands:": "๐Ÿ‡งโ€๐Ÿ‡ถ", + ":carousel_horse:": "๐ŸŽ ", + ":carrot:": "๐Ÿฅ•", + ":cartwheeling:": "๐Ÿคธ", + ":cat:": "๐Ÿฑ", + ":cat2:": "๐Ÿˆ", + ":cayman_islands:": "๐Ÿ‡ฐโ€๐Ÿ‡พ", + ":cd:": "๐Ÿ’ฟ", + ":central_african_republic:": "๐Ÿ‡จโ€๐Ÿ‡ซ", + ":ceuta_melilla:": "๐Ÿ‡ชโ€๐Ÿ‡ฆ", + ":chad:": "๐Ÿ‡นโ€๐Ÿ‡ฉ", + ":chains:": "โ›“", + ":chair:": "๐Ÿช‘", + ":champagne:": "๐Ÿพ", + ":chart:": "๐Ÿ’น", + ":chart_with_downwards_trend:": "๐Ÿ“‰", + ":chart_with_upwards_trend:": "๐Ÿ“ˆ", + ":checkered_flag:": "๐Ÿ", + ":cheese:": "๐Ÿง€", + ":cherries:": "๐Ÿ’", + ":cherry_blossom:": "๐ŸŒธ", + ":chess_pawn:": "โ™Ÿ", + ":chestnut:": "๐ŸŒฐ", + ":chicken:": "๐Ÿ”", + ":child:": "๐Ÿง’", + ":children_crossing:": "๐Ÿšธ", + ":chile:": "๐Ÿ‡จโ€๐Ÿ‡ฑ", + ":chipmunk:": "๐Ÿฟ", + ":chocolate_bar:": "๐Ÿซ", + ":chopsticks:": "๐Ÿฅข", + ":christmas_island:": "๐Ÿ‡จโ€๐Ÿ‡ฝ", + ":christmas_tree:": "๐ŸŽ„", + ":church:": "โ›ช", + ":cinema:": "๐ŸŽฆ", + ":circus_tent:": "๐ŸŽช", + ":city_sunrise:": "๐ŸŒ‡", + ":city_sunset:": "๐ŸŒ†", + ":cityscape:": "๐Ÿ™", + ":cl:": "๐Ÿ†‘", + ":clamp:": "๐Ÿ—œ", + ":clap:": "๐Ÿ‘", + ":clapper:": "๐ŸŽฌ", + ":classical_building:": "๐Ÿ›", + ":climbing:": "๐Ÿง—", + ":climbing_man:": "๐Ÿง—โ€โ™‚", + ":climbing_woman:": "๐Ÿง—โ€โ™€", + ":clinking_glasses:": "๐Ÿฅ‚", + ":clipboard:": "๐Ÿ“‹", + ":clipperton_island:": "๐Ÿ‡จโ€๐Ÿ‡ต", + ":clock1:": "๐Ÿ•", + ":clock10:": "๐Ÿ•™", + ":clock1030:": "๐Ÿ•ฅ", + ":clock11:": "๐Ÿ•š", + ":clock1130:": "๐Ÿ•ฆ", + ":clock12:": "๐Ÿ•›", + ":clock1230:": "๐Ÿ•ง", + ":clock130:": "๐Ÿ•œ", + ":clock2:": "๐Ÿ•‘", + ":clock230:": "๐Ÿ•", + ":clock3:": "๐Ÿ•’", + ":clock330:": "๐Ÿ•ž", + ":clock4:": "๐Ÿ•“", + ":clock430:": "๐Ÿ•Ÿ", + ":clock5:": "๐Ÿ•”", + ":clock530:": "๐Ÿ• ", + ":clock6:": "๐Ÿ••", + ":clock630:": "๐Ÿ•ก", + ":clock7:": "๐Ÿ•–", + ":clock730:": "๐Ÿ•ข", + ":clock8:": "๐Ÿ•—", + ":clock830:": "๐Ÿ•ฃ", + ":clock9:": "๐Ÿ•˜", + ":clock930:": "๐Ÿ•ค", + ":closed_book:": "๐Ÿ“•", + ":closed_lock_with_key:": "๐Ÿ”", + ":closed_umbrella:": "๐ŸŒ‚", + ":cloud:": "โ˜", + ":cloud_with_lightning:": "๐ŸŒฉ", + ":cloud_with_lightning_and_rain:": "โ›ˆ", + ":cloud_with_rain:": "๐ŸŒง", + ":cloud_with_snow:": "๐ŸŒจ", + ":clown_face:": "๐Ÿคก", + ":clubs:": "โ™ฃ", + ":cn:": "๐Ÿ‡จโ€๐Ÿ‡ณ", + ":coat:": "๐Ÿงฅ", + ":cocktail:": "๐Ÿธ", + ":coconut:": "๐Ÿฅฅ", + ":cocos_islands:": "๐Ÿ‡จโ€๐Ÿ‡จ", + ":coffee:": "โ˜•", + ":coffin:": "โšฐ", + ":cold_face:": "๐Ÿฅถ", + ":cold_sweat:": "๐Ÿ˜ฐ", + ":collision:": "๐Ÿ’ฅ", + ":colombia:": "๐Ÿ‡จโ€๐Ÿ‡ด", + ":comet:": "โ˜„", + ":comoros:": "๐Ÿ‡ฐโ€๐Ÿ‡ฒ", + ":compass:": "๐Ÿงญ", + ":computer:": "๐Ÿ’ป", + ":computer_mouse:": "๐Ÿ–ฑ", + ":confetti_ball:": "๐ŸŽŠ", + ":confounded:": "๐Ÿ˜–", + ":confused:": "๐Ÿ˜•", + ":congo_brazzaville:": "๐Ÿ‡จโ€๐Ÿ‡ฌ", + ":congo_kinshasa:": "๐Ÿ‡จโ€๐Ÿ‡ฉ", + ":congratulations:": "ใŠ—", + ":construction:": "๐Ÿšง", + ":construction_worker:": "๐Ÿ‘ท", + ":construction_worker_man:": "๐Ÿ‘ทโ€โ™‚", + ":construction_worker_woman:": "๐Ÿ‘ทโ€โ™€", + ":control_knobs:": "๐ŸŽ›", + ":convenience_store:": "๐Ÿช", + ":cook:": "๐Ÿง‘โ€๐Ÿณ", + ":cook_islands:": "๐Ÿ‡จโ€๐Ÿ‡ฐ", + ":cookie:": "๐Ÿช", + ":cool:": "๐Ÿ†’", + ":cop:": "๐Ÿ‘ฎ", + ":copyright:": "ยฉ", + ":corn:": "๐ŸŒฝ", + ":costa_rica:": "๐Ÿ‡จโ€๐Ÿ‡ท", + ":cote_divoire:": "๐Ÿ‡จโ€๐Ÿ‡ฎ", + ":couch_and_lamp:": "๐Ÿ›‹", + ":couple:": "๐Ÿ‘ซ", + ":couple_with_heart:": "๐Ÿ’‘", + ":couple_with_heart_man_man:": "๐Ÿ‘จโ€โคโ€๐Ÿ‘จ", + ":couple_with_heart_woman_man:": "๐Ÿ‘ฉโ€โคโ€๐Ÿ‘จ", + ":couple_with_heart_woman_woman:": "๐Ÿ‘ฉโ€โคโ€๐Ÿ‘ฉ", + ":couplekiss:": "๐Ÿ’", + ":couplekiss_man_man:": "๐Ÿ‘จโ€โคโ€๐Ÿ’‹โ€๐Ÿ‘จ", + ":couplekiss_man_woman:": "๐Ÿ‘ฉโ€โคโ€๐Ÿ’‹โ€๐Ÿ‘จ", + ":couplekiss_woman_woman:": "๐Ÿ‘ฉโ€โคโ€๐Ÿ’‹โ€๐Ÿ‘ฉ", + ":cow:": "๐Ÿฎ", + ":cow2:": "๐Ÿ„", + ":cowboy_hat_face:": "๐Ÿค ", + ":crab:": "๐Ÿฆ€", + ":crayon:": "๐Ÿ–", + ":credit_card:": "๐Ÿ’ณ", + ":crescent_moon:": "๐ŸŒ™", + ":cricket:": "๐Ÿฆ—", + ":cricket_game:": "๐Ÿ", + ":croatia:": "๐Ÿ‡ญโ€๐Ÿ‡ท", + ":crocodile:": "๐ŸŠ", + ":croissant:": "๐Ÿฅ", + ":crossed_fingers:": "๐Ÿคž", + ":crossed_flags:": "๐ŸŽŒ", + ":crossed_swords:": "โš”", + ":crown:": "๐Ÿ‘‘", + ":cry:": "๐Ÿ˜ข", + ":crying_cat_face:": "๐Ÿ˜ฟ", + ":crystal_ball:": "๐Ÿ”ฎ", + ":cuba:": "๐Ÿ‡จโ€๐Ÿ‡บ", + ":cucumber:": "๐Ÿฅ’", + ":cup_with_straw:": "๐Ÿฅค", + ":cupcake:": "๐Ÿง", + ":cupid:": "๐Ÿ’˜", + ":curacao:": "๐Ÿ‡จโ€๐Ÿ‡ผ", + ":curling_stone:": "๐ŸฅŒ", + ":curly_haired_man:": "๐Ÿ‘จโ€๐Ÿฆฑ", + ":curly_haired_woman:": "๐Ÿ‘ฉโ€๐Ÿฆฑ", + ":curly_loop:": "โžฐ", + ":currency_exchange:": "๐Ÿ’ฑ", + ":curry:": "๐Ÿ›", + ":cursing_face:": "๐Ÿคฌ", + ":custard:": "๐Ÿฎ", + ":customs:": "๐Ÿ›ƒ", + ":cut_of_meat:": "๐Ÿฅฉ", + ":cyclone:": "๐ŸŒ€", + ":cyprus:": "๐Ÿ‡จโ€๐Ÿ‡พ", + ":czech_republic:": "๐Ÿ‡จโ€๐Ÿ‡ฟ", + ":dagger:": "๐Ÿ—ก", + ":dancer:": "๐Ÿ’ƒ", + ":dancers:": "๐Ÿ‘ฏ", + ":dancing_men:": "๐Ÿ‘ฏโ€โ™‚", + ":dancing_women:": "๐Ÿ‘ฏโ€โ™€", + ":dango:": "๐Ÿก", + ":dark_sunglasses:": "๐Ÿ•ถ", + ":dart:": "๐ŸŽฏ", + ":dash:": "๐Ÿ’จ", + ":date:": "๐Ÿ“…", + ":de:": "๐Ÿ‡ฉโ€๐Ÿ‡ช", + ":deaf_man:": "๐Ÿงโ€โ™‚", + ":deaf_person:": "๐Ÿง", + ":deaf_woman:": "๐Ÿงโ€โ™€", + ":deciduous_tree:": "๐ŸŒณ", + ":deer:": "๐ŸฆŒ", + ":denmark:": "๐Ÿ‡ฉโ€๐Ÿ‡ฐ", + ":department_store:": "๐Ÿฌ", + ":derelict_house:": "๐Ÿš", + ":desert:": "๐Ÿœ", + ":desert_island:": "๐Ÿ", + ":desktop_computer:": "๐Ÿ–ฅ", + ":detective:": "๐Ÿ•ต", + ":diamond_shape_with_a_dot_inside:": "๐Ÿ’ ", + ":diamonds:": "โ™ฆ", + ":diego_garcia:": "๐Ÿ‡ฉโ€๐Ÿ‡ฌ", + ":disappointed:": "๐Ÿ˜ž", + ":disappointed_relieved:": "๐Ÿ˜ฅ", + ":diving_mask:": "๐Ÿคฟ", + ":diya_lamp:": "๐Ÿช”", + ":dizzy:": "๐Ÿ’ซ", + ":dizzy_face:": "๐Ÿ˜ต", + ":djibouti:": "๐Ÿ‡ฉโ€๐Ÿ‡ฏ", + ":dna:": "๐Ÿงฌ", + ":do_not_litter:": "๐Ÿšฏ", + ":dog:": "๐Ÿถ", + ":dog2:": "๐Ÿ•", + ":dollar:": "๐Ÿ’ต", + ":dolls:": "๐ŸŽŽ", + ":dolphin:": "๐Ÿฌ", + ":dominica:": "๐Ÿ‡ฉโ€๐Ÿ‡ฒ", + ":dominican_republic:": "๐Ÿ‡ฉโ€๐Ÿ‡ด", + ":door:": "๐Ÿšช", + ":doughnut:": "๐Ÿฉ", + ":dove:": "๐Ÿ•Š", + ":dragon:": "๐Ÿ‰", + ":dragon_face:": "๐Ÿฒ", + ":dress:": "๐Ÿ‘—", + ":dromedary_camel:": "๐Ÿช", + ":drooling_face:": "๐Ÿคค", + ":drop_of_blood:": "๐Ÿฉธ", + ":droplet:": "๐Ÿ’ง", + ":drum:": "๐Ÿฅ", + ":duck:": "๐Ÿฆ†", + ":dumpling:": "๐ŸฅŸ", + ":dvd:": "๐Ÿ“€", + ":e-mail:": "๐Ÿ“ง", + ":eagle:": "๐Ÿฆ…", + ":ear:": "๐Ÿ‘‚", + ":ear_of_rice:": "๐ŸŒพ", + ":ear_with_hearing_aid:": "๐Ÿฆป", + ":earth_africa:": "๐ŸŒ", + ":earth_americas:": "๐ŸŒŽ", + ":earth_asia:": "๐ŸŒ", + ":ecuador:": "๐Ÿ‡ชโ€๐Ÿ‡จ", + ":egg:": "๐Ÿฅš", + ":eggplant:": "๐Ÿ†", + ":egypt:": "๐Ÿ‡ชโ€๐Ÿ‡ฌ", + ":eight:": "8โ€โƒฃ", + ":eight_pointed_black_star:": "โœด", + ":eight_spoked_asterisk:": "โœณ", + ":eject_button:": "โ", + ":el_salvador:": "๐Ÿ‡ธโ€๐Ÿ‡ป", + ":electric_plug:": "๐Ÿ”Œ", + ":elephant:": "๐Ÿ˜", + ":elf:": "๐Ÿง", + ":elf_man:": "๐Ÿงโ€โ™‚", + ":elf_woman:": "๐Ÿงโ€โ™€", + ":email:": "โœ‰", + ":end:": "๐Ÿ”š", + ":england:": "๐Ÿดโ€๓ งโ€๓ ขโ€๓ ฅโ€๓ ฎโ€๓ งโ€๓ ฟ", + ":envelope:": "โœ‰", + ":envelope_with_arrow:": "๐Ÿ“ฉ", + ":equatorial_guinea:": "๐Ÿ‡ฌโ€๐Ÿ‡ถ", + ":eritrea:": "๐Ÿ‡ชโ€๐Ÿ‡ท", + ":es:": "๐Ÿ‡ชโ€๐Ÿ‡ธ", + ":estonia:": "๐Ÿ‡ชโ€๐Ÿ‡ช", + ":ethiopia:": "๐Ÿ‡ชโ€๐Ÿ‡น", + ":eu:": "๐Ÿ‡ชโ€๐Ÿ‡บ", + ":euro:": "๐Ÿ’ถ", + ":european_castle:": "๐Ÿฐ", + ":european_post_office:": "๐Ÿค", + ":european_union:": "๐Ÿ‡ชโ€๐Ÿ‡บ", + ":evergreen_tree:": "๐ŸŒฒ", + ":exclamation:": "โ—", + ":exploding_head:": "๐Ÿคฏ", + ":expressionless:": "๐Ÿ˜‘", + ":eye:": "๐Ÿ‘", + ":eye_speech_bubble:": "๐Ÿ‘โ€๐Ÿ—จ", + ":eyeglasses:": "๐Ÿ‘“", + ":eyes:": "๐Ÿ‘€", + ":face_with_head_bandage:": "๐Ÿค•", + ":face_with_thermometer:": "๐Ÿค’", + ":facepalm:": "๐Ÿคฆ", + ":facepunch:": "๐Ÿ‘Š", + ":factory:": "๐Ÿญ", + ":factory_worker:": "๐Ÿง‘โ€๐Ÿญ", + ":fairy:": "๐Ÿงš", + ":fairy_man:": "๐Ÿงšโ€โ™‚", + ":fairy_woman:": "๐Ÿงšโ€โ™€", + ":falafel:": "๐Ÿง†", + ":falkland_islands:": "๐Ÿ‡ซโ€๐Ÿ‡ฐ", + ":fallen_leaf:": "๐Ÿ‚", + ":family:": "๐Ÿ‘ช", + ":family_man_boy:": "๐Ÿ‘จโ€๐Ÿ‘ฆ", + ":family_man_boy_boy:": "๐Ÿ‘จโ€๐Ÿ‘ฆโ€๐Ÿ‘ฆ", + ":family_man_girl:": "๐Ÿ‘จโ€๐Ÿ‘ง", + ":family_man_girl_boy:": "๐Ÿ‘จโ€๐Ÿ‘งโ€๐Ÿ‘ฆ", + ":family_man_girl_girl:": "๐Ÿ‘จโ€๐Ÿ‘งโ€๐Ÿ‘ง", + ":family_man_man_boy:": "๐Ÿ‘จโ€๐Ÿ‘จโ€๐Ÿ‘ฆ", + ":family_man_man_boy_boy:": "๐Ÿ‘จโ€๐Ÿ‘จโ€๐Ÿ‘ฆโ€๐Ÿ‘ฆ", + ":family_man_man_girl:": "๐Ÿ‘จโ€๐Ÿ‘จโ€๐Ÿ‘ง", + ":family_man_man_girl_boy:": "๐Ÿ‘จโ€๐Ÿ‘จโ€๐Ÿ‘งโ€๐Ÿ‘ฆ", + ":family_man_man_girl_girl:": "๐Ÿ‘จโ€๐Ÿ‘จโ€๐Ÿ‘งโ€๐Ÿ‘ง", + ":family_man_woman_boy:": "๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘ฆ", + ":family_man_woman_boy_boy:": "๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘ฆโ€๐Ÿ‘ฆ", + ":family_man_woman_girl:": "๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘ง", + ":family_man_woman_girl_boy:": "๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ฆ", + ":family_man_woman_girl_girl:": "๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ง", + ":family_woman_boy:": "๐Ÿ‘ฉโ€๐Ÿ‘ฆ", + ":family_woman_boy_boy:": "๐Ÿ‘ฉโ€๐Ÿ‘ฆโ€๐Ÿ‘ฆ", + ":family_woman_girl:": "๐Ÿ‘ฉโ€๐Ÿ‘ง", + ":family_woman_girl_boy:": "๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ฆ", + ":family_woman_girl_girl:": "๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ง", + ":family_woman_woman_boy:": "๐Ÿ‘ฉโ€๐Ÿ‘ฉโ€๐Ÿ‘ฆ", + ":family_woman_woman_boy_boy:": "๐Ÿ‘ฉโ€๐Ÿ‘ฉโ€๐Ÿ‘ฆโ€๐Ÿ‘ฆ", + ":family_woman_woman_girl:": "๐Ÿ‘ฉโ€๐Ÿ‘ฉโ€๐Ÿ‘ง", + ":family_woman_woman_girl_boy:": "๐Ÿ‘ฉโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ฆ", + ":family_woman_woman_girl_girl:": "๐Ÿ‘ฉโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ง", + ":farmer:": "๐Ÿง‘โ€๐ŸŒพ", + ":faroe_islands:": "๐Ÿ‡ซโ€๐Ÿ‡ด", + ":fast_forward:": "โฉ", + ":fax:": "๐Ÿ“ ", + ":fearful:": "๐Ÿ˜จ", + ":feet:": "๐Ÿพ", + ":female_detective:": "๐Ÿ•ตโ€โ™€", + ":female_sign:": "โ™€", + ":ferris_wheel:": "๐ŸŽก", + ":ferry:": "โ›ด", + ":field_hockey:": "๐Ÿ‘", + ":fiji:": "๐Ÿ‡ซโ€๐Ÿ‡ฏ", + ":file_cabinet:": "๐Ÿ—„", + ":file_folder:": "๐Ÿ“", + ":film_projector:": "๐Ÿ“ฝ", + ":film_strip:": "๐ŸŽž", + ":finland:": "๐Ÿ‡ซโ€๐Ÿ‡ฎ", + ":fire:": "๐Ÿ”ฅ", + ":fire_engine:": "๐Ÿš’", + ":fire_extinguisher:": "๐Ÿงฏ", + ":firecracker:": "๐Ÿงจ", + ":firefighter:": "๐Ÿง‘โ€๐Ÿš’", + ":fireworks:": "๐ŸŽ†", + ":first_quarter_moon:": "๐ŸŒ“", + ":first_quarter_moon_with_face:": "๐ŸŒ›", + ":fish:": "๐ŸŸ", + ":fish_cake:": "๐Ÿฅ", + ":fishing_pole_and_fish:": "๐ŸŽฃ", + ":fist:": "โœŠ", + ":fist_left:": "๐Ÿค›", + ":fist_oncoming:": "๐Ÿ‘Š", + ":fist_raised:": "โœŠ", + ":fist_right:": "๐Ÿคœ", + ":five:": "5โ€โƒฃ", + ":flags:": "๐ŸŽ", + ":flamingo:": "๐Ÿฆฉ", + ":flashlight:": "๐Ÿ”ฆ", + ":flat_shoe:": "๐Ÿฅฟ", + ":fleur_de_lis:": "โšœ", + ":flight_arrival:": "๐Ÿ›ฌ", + ":flight_departure:": "๐Ÿ›ซ", + ":flipper:": "๐Ÿฌ", + ":floppy_disk:": "๐Ÿ’พ", + ":flower_playing_cards:": "๐ŸŽด", + ":flushed:": "๐Ÿ˜ณ", + ":flying_disc:": "๐Ÿฅ", + ":flying_saucer:": "๐Ÿ›ธ", + ":fog:": "๐ŸŒซ", + ":foggy:": "๐ŸŒ", + ":foot:": "๐Ÿฆถ", + ":football:": "๐Ÿˆ", + ":footprints:": "๐Ÿ‘ฃ", + ":fork_and_knife:": "๐Ÿด", + ":fortune_cookie:": "๐Ÿฅ ", + ":fountain:": "โ›ฒ", + ":fountain_pen:": "๐Ÿ–‹", + ":four:": "4โ€โƒฃ", + ":four_leaf_clover:": "๐Ÿ€", + ":fox_face:": "๐ŸฆŠ", + ":fr:": "๐Ÿ‡ซโ€๐Ÿ‡ท", + ":framed_picture:": "๐Ÿ–ผ", + ":free:": "๐Ÿ†“", + ":french_guiana:": "๐Ÿ‡ฌโ€๐Ÿ‡ซ", + ":french_polynesia:": "๐Ÿ‡ตโ€๐Ÿ‡ซ", + ":french_southern_territories:": "๐Ÿ‡นโ€๐Ÿ‡ซ", + ":fried_egg:": "๐Ÿณ", + ":fried_shrimp:": "๐Ÿค", + ":fries:": "๐ŸŸ", + ":frog:": "๐Ÿธ", + ":frowning:": "๐Ÿ˜ฆ", + ":frowning_face:": "โ˜น", + ":frowning_man:": "๐Ÿ™โ€โ™‚", + ":frowning_person:": "๐Ÿ™", + ":frowning_woman:": "๐Ÿ™โ€โ™€", + ":fu:": "๐Ÿ–•", + ":fuelpump:": "โ›ฝ", + ":full_moon:": "๐ŸŒ•", + ":full_moon_with_face:": "๐ŸŒ", + ":funeral_urn:": "โšฑ", + ":gabon:": "๐Ÿ‡ฌโ€๐Ÿ‡ฆ", + ":gambia:": "๐Ÿ‡ฌโ€๐Ÿ‡ฒ", + ":game_die:": "๐ŸŽฒ", + ":garlic:": "๐Ÿง„", + ":gb:": "๐Ÿ‡ฌโ€๐Ÿ‡ง", + ":gear:": "โš™", + ":gem:": "๐Ÿ’Ž", + ":gemini:": "โ™Š", + ":genie:": "๐Ÿงž", + ":genie_man:": "๐Ÿงžโ€โ™‚", + ":genie_woman:": "๐Ÿงžโ€โ™€", + ":georgia:": "๐Ÿ‡ฌโ€๐Ÿ‡ช", + ":ghana:": "๐Ÿ‡ฌโ€๐Ÿ‡ญ", + ":ghost:": "๐Ÿ‘ป", + ":gibraltar:": "๐Ÿ‡ฌโ€๐Ÿ‡ฎ", + ":gift:": "๐ŸŽ", + ":gift_heart:": "๐Ÿ’", + ":giraffe:": "๐Ÿฆ’", + ":girl:": "๐Ÿ‘ง", + ":globe_with_meridians:": "๐ŸŒ", + ":gloves:": "๐Ÿงค", + ":goal_net:": "๐Ÿฅ…", + ":goat:": "๐Ÿ", + ":goggles:": "๐Ÿฅฝ", + ":golf:": "โ›ณ", + ":golfing:": "๐ŸŒ", + ":golfing_man:": "๐ŸŒโ€โ™‚", + ":golfing_woman:": "๐ŸŒโ€โ™€", + ":gorilla:": "๐Ÿฆ", + ":grapes:": "๐Ÿ‡", + ":greece:": "๐Ÿ‡ฌโ€๐Ÿ‡ท", + ":green_apple:": "๐Ÿ", + ":green_book:": "๐Ÿ“—", + ":green_circle:": "๐ŸŸข", + ":green_heart:": "๐Ÿ’š", + ":green_salad:": "๐Ÿฅ—", + ":green_square:": "๐ŸŸฉ", + ":greenland:": "๐Ÿ‡ฌโ€๐Ÿ‡ฑ", + ":grenada:": "๐Ÿ‡ฌโ€๐Ÿ‡ฉ", + ":grey_exclamation:": "โ•", + ":grey_question:": "โ”", + ":grimacing:": "๐Ÿ˜ฌ", + ":grin:": "๐Ÿ˜", + ":grinning:": "๐Ÿ˜€", + ":guadeloupe:": "๐Ÿ‡ฌโ€๐Ÿ‡ต", + ":guam:": "๐Ÿ‡ฌโ€๐Ÿ‡บ", + ":guard:": "๐Ÿ’‚", + ":guardsman:": "๐Ÿ’‚โ€โ™‚", + ":guardswoman:": "๐Ÿ’‚โ€โ™€", + ":guatemala:": "๐Ÿ‡ฌโ€๐Ÿ‡น", + ":guernsey:": "๐Ÿ‡ฌโ€๐Ÿ‡ฌ", + ":guide_dog:": "๐Ÿฆฎ", + ":guinea:": "๐Ÿ‡ฌโ€๐Ÿ‡ณ", + ":guinea_bissau:": "๐Ÿ‡ฌโ€๐Ÿ‡ผ", + ":guitar:": "๐ŸŽธ", + ":gun:": "๐Ÿ”ซ", + ":guyana:": "๐Ÿ‡ฌโ€๐Ÿ‡พ", + ":haircut:": "๐Ÿ’‡", + ":haircut_man:": "๐Ÿ’‡โ€โ™‚", + ":haircut_woman:": "๐Ÿ’‡โ€โ™€", + ":haiti:": "๐Ÿ‡ญโ€๐Ÿ‡น", + ":hamburger:": "๐Ÿ”", + ":hammer:": "๐Ÿ”จ", + ":hammer_and_pick:": "โš’", + ":hammer_and_wrench:": "๐Ÿ› ", + ":hamster:": "๐Ÿน", + ":hand:": "โœ‹", + ":hand_over_mouth:": "๐Ÿคญ", + ":handbag:": "๐Ÿ‘œ", + ":handball_person:": "๐Ÿคพ", + ":handshake:": "๐Ÿค", + ":hankey:": "๐Ÿ’ฉ", + ":hash:": "#โ€โƒฃ", + ":hatched_chick:": "๐Ÿฅ", + ":hatching_chick:": "๐Ÿฃ", + ":headphones:": "๐ŸŽง", + ":health_worker:": "๐Ÿง‘โ€โš•", + ":hear_no_evil:": "๐Ÿ™‰", + ":heard_mcdonald_islands:": "๐Ÿ‡ญโ€๐Ÿ‡ฒ", + ":heart:": "โค", + ":heart_decoration:": "๐Ÿ’Ÿ", + ":heart_eyes:": "๐Ÿ˜", + ":heart_eyes_cat:": "๐Ÿ˜ป", + ":heartbeat:": "๐Ÿ’“", + ":heartpulse:": "๐Ÿ’—", + ":hearts:": "โ™ฅ", + ":heavy_check_mark:": "โœ”", + ":heavy_division_sign:": "โž—", + ":heavy_dollar_sign:": "๐Ÿ’ฒ", + ":heavy_exclamation_mark:": "โ—", + ":heavy_heart_exclamation:": "โฃ", + ":heavy_minus_sign:": "โž–", + ":heavy_multiplication_x:": "โœ–", + ":heavy_plus_sign:": "โž•", + ":hedgehog:": "๐Ÿฆ”", + ":helicopter:": "๐Ÿš", + ":herb:": "๐ŸŒฟ", + ":hibiscus:": "๐ŸŒบ", + ":high_brightness:": "๐Ÿ”†", + ":high_heel:": "๐Ÿ‘ ", + ":hiking_boot:": "๐Ÿฅพ", + ":hindu_temple:": "๐Ÿ›•", + ":hippopotamus:": "๐Ÿฆ›", + ":hocho:": "๐Ÿ”ช", + ":hole:": "๐Ÿ•ณ", + ":honduras:": "๐Ÿ‡ญโ€๐Ÿ‡ณ", + ":honey_pot:": "๐Ÿฏ", + ":honeybee:": "๐Ÿ", + ":hong_kong:": "๐Ÿ‡ญโ€๐Ÿ‡ฐ", + ":horse:": "๐Ÿด", + ":horse_racing:": "๐Ÿ‡", + ":hospital:": "๐Ÿฅ", + ":hot_face:": "๐Ÿฅต", + ":hot_pepper:": "๐ŸŒถ", + ":hotdog:": "๐ŸŒญ", + ":hotel:": "๐Ÿจ", + ":hotsprings:": "โ™จ", + ":hourglass:": "โŒ›", + ":hourglass_flowing_sand:": "โณ", + ":house:": "๐Ÿ ", + ":house_with_garden:": "๐Ÿก", + ":houses:": "๐Ÿ˜", + ":hugs:": "๐Ÿค—", + ":hungary:": "๐Ÿ‡ญโ€๐Ÿ‡บ", + ":hushed:": "๐Ÿ˜ฏ", + ":ice_cream:": "๐Ÿจ", + ":ice_cube:": "๐ŸงŠ", + ":ice_hockey:": "๐Ÿ’", + ":ice_skate:": "โ›ธ", + ":icecream:": "๐Ÿฆ", + ":iceland:": "๐Ÿ‡ฎโ€๐Ÿ‡ธ", + ":id:": "๐Ÿ†”", + ":ideograph_advantage:": "๐Ÿ‰", + ":imp:": "๐Ÿ‘ฟ", + ":inbox_tray:": "๐Ÿ“ฅ", + ":incoming_envelope:": "๐Ÿ“จ", + ":india:": "๐Ÿ‡ฎโ€๐Ÿ‡ณ", + ":indonesia:": "๐Ÿ‡ฎโ€๐Ÿ‡ฉ", + ":infinity:": "โ™พ", + ":information_desk_person:": "๐Ÿ’", + ":information_source:": "โ„น", + ":innocent:": "๐Ÿ˜‡", + ":interrobang:": "โ‰", + ":iphone:": "๐Ÿ“ฑ", + ":iran:": "๐Ÿ‡ฎโ€๐Ÿ‡ท", + ":iraq:": "๐Ÿ‡ฎโ€๐Ÿ‡ถ", + ":ireland:": "๐Ÿ‡ฎโ€๐Ÿ‡ช", + ":isle_of_man:": "๐Ÿ‡ฎโ€๐Ÿ‡ฒ", + ":israel:": "๐Ÿ‡ฎโ€๐Ÿ‡ฑ", + ":it:": "๐Ÿ‡ฎโ€๐Ÿ‡น", + ":izakaya_lantern:": "๐Ÿฎ", + ":jack_o_lantern:": "๐ŸŽƒ", + ":jamaica:": "๐Ÿ‡ฏโ€๐Ÿ‡ฒ", + ":japan:": "๐Ÿ—พ", + ":japanese_castle:": "๐Ÿฏ", + ":japanese_goblin:": "๐Ÿ‘บ", + ":japanese_ogre:": "๐Ÿ‘น", + ":jeans:": "๐Ÿ‘–", + ":jersey:": "๐Ÿ‡ฏโ€๐Ÿ‡ช", + ":jigsaw:": "๐Ÿงฉ", + ":jordan:": "๐Ÿ‡ฏโ€๐Ÿ‡ด", + ":joy:": "๐Ÿ˜‚", + ":joy_cat:": "๐Ÿ˜น", + ":joystick:": "๐Ÿ•น", + ":jp:": "๐Ÿ‡ฏโ€๐Ÿ‡ต", + ":judge:": "๐Ÿง‘โ€โš–", + ":juggling_person:": "๐Ÿคน", + ":kaaba:": "๐Ÿ•‹", + ":kangaroo:": "๐Ÿฆ˜", + ":kazakhstan:": "๐Ÿ‡ฐโ€๐Ÿ‡ฟ", + ":kenya:": "๐Ÿ‡ฐโ€๐Ÿ‡ช", + ":key:": "๐Ÿ”‘", + ":keyboard:": "โŒจ", + ":keycap_ten:": "๐Ÿ”Ÿ", + ":kick_scooter:": "๐Ÿ›ด", + ":kimono:": "๐Ÿ‘˜", + ":kiribati:": "๐Ÿ‡ฐโ€๐Ÿ‡ฎ", + ":kiss:": "๐Ÿ’‹", + ":kissing:": "๐Ÿ˜—", + ":kissing_cat:": "๐Ÿ˜ฝ", + ":kissing_closed_eyes:": "๐Ÿ˜š", + ":kissing_heart:": "๐Ÿ˜˜", + ":kissing_smiling_eyes:": "๐Ÿ˜™", + ":kite:": "๐Ÿช", + ":kiwi_fruit:": "๐Ÿฅ", + ":kneeling_man:": "๐ŸงŽโ€โ™‚", + ":kneeling_person:": "๐ŸงŽ", + ":kneeling_woman:": "๐ŸงŽโ€โ™€", + ":knife:": "๐Ÿ”ช", + ":koala:": "๐Ÿจ", + ":koko:": "๐Ÿˆ", + ":kosovo:": "๐Ÿ‡ฝโ€๐Ÿ‡ฐ", + ":kr:": "๐Ÿ‡ฐโ€๐Ÿ‡ท", + ":kuwait:": "๐Ÿ‡ฐโ€๐Ÿ‡ผ", + ":kyrgyzstan:": "๐Ÿ‡ฐโ€๐Ÿ‡ฌ", + ":lab_coat:": "๐Ÿฅผ", + ":label:": "๐Ÿท", + ":lacrosse:": "๐Ÿฅ", + ":lantern:": "๐Ÿฎ", + ":laos:": "๐Ÿ‡ฑโ€๐Ÿ‡ฆ", + ":large_blue_circle:": "๐Ÿ”ต", + ":large_blue_diamond:": "๐Ÿ”ท", + ":large_orange_diamond:": "๐Ÿ”ถ", + ":last_quarter_moon:": "๐ŸŒ—", + ":last_quarter_moon_with_face:": "๐ŸŒœ", + ":latin_cross:": "โœ", + ":latvia:": "๐Ÿ‡ฑโ€๐Ÿ‡ป", + ":laughing:": "๐Ÿ˜†", + ":leafy_green:": "๐Ÿฅฌ", + ":leaves:": "๐Ÿƒ", + ":lebanon:": "๐Ÿ‡ฑโ€๐Ÿ‡ง", + ":ledger:": "๐Ÿ“’", + ":left_luggage:": "๐Ÿ›…", + ":left_right_arrow:": "โ†”", + ":left_speech_bubble:": "๐Ÿ—จ", + ":leftwards_arrow_with_hook:": "โ†ฉ", + ":leg:": "๐Ÿฆต", + ":lemon:": "๐Ÿ‹", + ":leo:": "โ™Œ", + ":leopard:": "๐Ÿ†", + ":lesotho:": "๐Ÿ‡ฑโ€๐Ÿ‡ธ", + ":level_slider:": "๐ŸŽš", + ":liberia:": "๐Ÿ‡ฑโ€๐Ÿ‡ท", + ":libra:": "โ™Ž", + ":libya:": "๐Ÿ‡ฑโ€๐Ÿ‡พ", + ":liechtenstein:": "๐Ÿ‡ฑโ€๐Ÿ‡ฎ", + ":light_rail:": "๐Ÿšˆ", + ":link:": "๐Ÿ”—", + ":lion:": "๐Ÿฆ", + ":lips:": "๐Ÿ‘„", + ":lipstick:": "๐Ÿ’„", + ":lithuania:": "๐Ÿ‡ฑโ€๐Ÿ‡น", + ":lizard:": "๐ŸฆŽ", + ":llama:": "๐Ÿฆ™", + ":lobster:": "๐Ÿฆž", + ":lock:": "๐Ÿ”’", + ":lock_with_ink_pen:": "๐Ÿ”", + ":lollipop:": "๐Ÿญ", + ":loop:": "โžฟ", + ":lotion_bottle:": "๐Ÿงด", + ":lotus_position:": "๐Ÿง˜", + ":lotus_position_man:": "๐Ÿง˜โ€โ™‚", + ":lotus_position_woman:": "๐Ÿง˜โ€โ™€", + ":loud_sound:": "๐Ÿ”Š", + ":loudspeaker:": "๐Ÿ“ข", + ":love_hotel:": "๐Ÿฉ", + ":love_letter:": "๐Ÿ’Œ", + ":love_you_gesture:": "๐ŸคŸ", + ":low_brightness:": "๐Ÿ”…", + ":luggage:": "๐Ÿงณ", + ":luxembourg:": "๐Ÿ‡ฑโ€๐Ÿ‡บ", + ":lying_face:": "๐Ÿคฅ", + ":m:": "โ“‚", + ":macau:": "๐Ÿ‡ฒโ€๐Ÿ‡ด", + ":macedonia:": "๐Ÿ‡ฒโ€๐Ÿ‡ฐ", + ":madagascar:": "๐Ÿ‡ฒโ€๐Ÿ‡ฌ", + ":mag:": "๐Ÿ”", + ":mag_right:": "๐Ÿ”Ž", + ":mage:": "๐Ÿง™", + ":mage_man:": "๐Ÿง™โ€โ™‚", + ":mage_woman:": "๐Ÿง™โ€โ™€", + ":magnet:": "๐Ÿงฒ", + ":mahjong:": "๐Ÿ€„", + ":mailbox:": "๐Ÿ“ซ", + ":mailbox_closed:": "๐Ÿ“ช", + ":mailbox_with_mail:": "๐Ÿ“ฌ", + ":mailbox_with_no_mail:": "๐Ÿ“ญ", + ":malawi:": "๐Ÿ‡ฒโ€๐Ÿ‡ผ", + ":malaysia:": "๐Ÿ‡ฒโ€๐Ÿ‡พ", + ":maldives:": "๐Ÿ‡ฒโ€๐Ÿ‡ป", + ":male_detective:": "๐Ÿ•ตโ€โ™‚", + ":male_sign:": "โ™‚", + ":mali:": "๐Ÿ‡ฒโ€๐Ÿ‡ฑ", + ":malta:": "๐Ÿ‡ฒโ€๐Ÿ‡น", + ":man:": "๐Ÿ‘จ", + ":man_artist:": "๐Ÿ‘จโ€๐ŸŽจ", + ":man_astronaut:": "๐Ÿ‘จโ€๐Ÿš€", + ":man_cartwheeling:": "๐Ÿคธโ€โ™‚", + ":man_cook:": "๐Ÿ‘จโ€๐Ÿณ", + ":man_dancing:": "๐Ÿ•บ", + ":man_facepalming:": "๐Ÿคฆโ€โ™‚", + ":man_factory_worker:": "๐Ÿ‘จโ€๐Ÿญ", + ":man_farmer:": "๐Ÿ‘จโ€๐ŸŒพ", + ":man_firefighter:": "๐Ÿ‘จโ€๐Ÿš’", + ":man_health_worker:": "๐Ÿ‘จโ€โš•", + ":man_in_manual_wheelchair:": "๐Ÿ‘จโ€๐Ÿฆฝ", + ":man_in_motorized_wheelchair:": "๐Ÿ‘จโ€๐Ÿฆผ", + ":man_in_tuxedo:": "๐Ÿคต", + ":man_judge:": "๐Ÿ‘จโ€โš–", + ":man_juggling:": "๐Ÿคนโ€โ™‚", + ":man_mechanic:": "๐Ÿ‘จโ€๐Ÿ”ง", + ":man_office_worker:": "๐Ÿ‘จโ€๐Ÿ’ผ", + ":man_pilot:": "๐Ÿ‘จโ€โœˆ", + ":man_playing_handball:": "๐Ÿคพโ€โ™‚", + ":man_playing_water_polo:": "๐Ÿคฝโ€โ™‚", + ":man_scientist:": "๐Ÿ‘จโ€๐Ÿ”ฌ", + ":man_shrugging:": "๐Ÿคทโ€โ™‚", + ":man_singer:": "๐Ÿ‘จโ€๐ŸŽค", + ":man_student:": "๐Ÿ‘จโ€๐ŸŽ“", + ":man_teacher:": "๐Ÿ‘จโ€๐Ÿซ", + ":man_technologist:": "๐Ÿ‘จโ€๐Ÿ’ป", + ":man_with_gua_pi_mao:": "๐Ÿ‘ฒ", + ":man_with_probing_cane:": "๐Ÿ‘จโ€๐Ÿฆฏ", + ":man_with_turban:": "๐Ÿ‘ณโ€โ™‚", + ":mandarin:": "๐ŸŠ", + ":mango:": "๐Ÿฅญ", + ":mans_shoe:": "๐Ÿ‘ž", + ":mantelpiece_clock:": "๐Ÿ•ฐ", + ":manual_wheelchair:": "๐Ÿฆฝ", + ":maple_leaf:": "๐Ÿ", + ":marshall_islands:": "๐Ÿ‡ฒโ€๐Ÿ‡ญ", + ":martial_arts_uniform:": "๐Ÿฅ‹", + ":martinique:": "๐Ÿ‡ฒโ€๐Ÿ‡ถ", + ":mask:": "๐Ÿ˜ท", + ":massage:": "๐Ÿ’†", + ":massage_man:": "๐Ÿ’†โ€โ™‚", + ":massage_woman:": "๐Ÿ’†โ€โ™€", + ":mate:": "๐Ÿง‰", + ":mauritania:": "๐Ÿ‡ฒโ€๐Ÿ‡ท", + ":mauritius:": "๐Ÿ‡ฒโ€๐Ÿ‡บ", + ":mayotte:": "๐Ÿ‡พโ€๐Ÿ‡น", + ":meat_on_bone:": "๐Ÿ–", + ":mechanic:": "๐Ÿง‘โ€๐Ÿ”ง", + ":mechanical_arm:": "๐Ÿฆพ", + ":mechanical_leg:": "๐Ÿฆฟ", + ":medal_military:": "๐ŸŽ–", + ":medal_sports:": "๐Ÿ…", + ":medical_symbol:": "โš•", + ":mega:": "๐Ÿ“ฃ", + ":melon:": "๐Ÿˆ", + ":memo:": "๐Ÿ“", + ":men_wrestling:": "๐Ÿคผโ€โ™‚", + ":menorah:": "๐Ÿ•Ž", + ":mens:": "๐Ÿšน", + ":mermaid:": "๐Ÿงœโ€โ™€", + ":merman:": "๐Ÿงœโ€โ™‚", + ":merperson:": "๐Ÿงœ", + ":metal:": "๐Ÿค˜", + ":metro:": "๐Ÿš‡", + ":mexico:": "๐Ÿ‡ฒโ€๐Ÿ‡ฝ", + ":microbe:": "๐Ÿฆ ", + ":micronesia:": "๐Ÿ‡ซโ€๐Ÿ‡ฒ", + ":microphone:": "๐ŸŽค", + ":microscope:": "๐Ÿ”ฌ", + ":middle_finger:": "๐Ÿ–•", + ":milk_glass:": "๐Ÿฅ›", + ":milky_way:": "๐ŸŒŒ", + ":minibus:": "๐Ÿš", + ":minidisc:": "๐Ÿ’ฝ", + ":mobile_phone_off:": "๐Ÿ“ด", + ":moldova:": "๐Ÿ‡ฒโ€๐Ÿ‡ฉ", + ":monaco:": "๐Ÿ‡ฒโ€๐Ÿ‡จ", + ":money_mouth_face:": "๐Ÿค‘", + ":money_with_wings:": "๐Ÿ’ธ", + ":moneybag:": "๐Ÿ’ฐ", + ":mongolia:": "๐Ÿ‡ฒโ€๐Ÿ‡ณ", + ":monkey:": "๐Ÿ’", + ":monkey_face:": "๐Ÿต", + ":monocle_face:": "๐Ÿง", + ":monorail:": "๐Ÿš", + ":montenegro:": "๐Ÿ‡ฒโ€๐Ÿ‡ช", + ":montserrat:": "๐Ÿ‡ฒโ€๐Ÿ‡ธ", + ":moon:": "๐ŸŒ”", + ":moon_cake:": "๐Ÿฅฎ", + ":morocco:": "๐Ÿ‡ฒโ€๐Ÿ‡ฆ", + ":mortar_board:": "๐ŸŽ“", + ":mosque:": "๐Ÿ•Œ", + ":mosquito:": "๐ŸฆŸ", + ":motor_boat:": "๐Ÿ›ฅ", + ":motor_scooter:": "๐Ÿ›ต", + ":motorcycle:": "๐Ÿ", + ":motorized_wheelchair:": "๐Ÿฆผ", + ":motorway:": "๐Ÿ›ฃ", + ":mount_fuji:": "๐Ÿ—ป", + ":mountain:": "โ›ฐ", + ":mountain_bicyclist:": "๐Ÿšต", + ":mountain_biking_man:": "๐Ÿšตโ€โ™‚", + ":mountain_biking_woman:": "๐Ÿšตโ€โ™€", + ":mountain_cableway:": "๐Ÿš ", + ":mountain_railway:": "๐Ÿšž", + ":mountain_snow:": "๐Ÿ”", + ":mouse:": "๐Ÿญ", + ":mouse2:": "๐Ÿ", + ":movie_camera:": "๐ŸŽฅ", + ":moyai:": "๐Ÿ—ฟ", + ":mozambique:": "๐Ÿ‡ฒโ€๐Ÿ‡ฟ", + ":mrs_claus:": "๐Ÿคถ", + ":muscle:": "๐Ÿ’ช", + ":mushroom:": "๐Ÿ„", + ":musical_keyboard:": "๐ŸŽน", + ":musical_note:": "๐ŸŽต", + ":musical_score:": "๐ŸŽผ", + ":mute:": "๐Ÿ”‡", + ":myanmar:": "๐Ÿ‡ฒโ€๐Ÿ‡ฒ", + ":nail_care:": "๐Ÿ’…", + ":name_badge:": "๐Ÿ“›", + ":namibia:": "๐Ÿ‡ณโ€๐Ÿ‡ฆ", + ":national_park:": "๐Ÿž", + ":nauru:": "๐Ÿ‡ณโ€๐Ÿ‡ท", + ":nauseated_face:": "๐Ÿคข", + ":nazar_amulet:": "๐Ÿงฟ", + ":necktie:": "๐Ÿ‘”", + ":negative_squared_cross_mark:": "โŽ", + ":nepal:": "๐Ÿ‡ณโ€๐Ÿ‡ต", + ":nerd_face:": "๐Ÿค“", + ":netherlands:": "๐Ÿ‡ณโ€๐Ÿ‡ฑ", + ":neutral_face:": "๐Ÿ˜", + ":new:": "๐Ÿ†•", + ":new_caledonia:": "๐Ÿ‡ณโ€๐Ÿ‡จ", + ":new_moon:": "๐ŸŒ‘", + ":new_moon_with_face:": "๐ŸŒš", + ":new_zealand:": "๐Ÿ‡ณโ€๐Ÿ‡ฟ", + ":newspaper:": "๐Ÿ“ฐ", + ":newspaper_roll:": "๐Ÿ—ž", + ":next_track_button:": "โญ", + ":ng:": "๐Ÿ†–", + ":ng_man:": "๐Ÿ™…โ€โ™‚", + ":ng_woman:": "๐Ÿ™…โ€โ™€", + ":nicaragua:": "๐Ÿ‡ณโ€๐Ÿ‡ฎ", + ":niger:": "๐Ÿ‡ณโ€๐Ÿ‡ช", + ":nigeria:": "๐Ÿ‡ณโ€๐Ÿ‡ฌ", + ":night_with_stars:": "๐ŸŒƒ", + ":nine:": "9โ€โƒฃ", + ":niue:": "๐Ÿ‡ณโ€๐Ÿ‡บ", + ":no_bell:": "๐Ÿ”•", + ":no_bicycles:": "๐Ÿšณ", + ":no_entry:": "โ›”", + ":no_entry_sign:": "๐Ÿšซ", + ":no_good:": "๐Ÿ™…", + ":no_good_man:": "๐Ÿ™…โ€โ™‚", + ":no_good_woman:": "๐Ÿ™…โ€โ™€", + ":no_mobile_phones:": "๐Ÿ“ต", + ":no_mouth:": "๐Ÿ˜ถ", + ":no_pedestrians:": "๐Ÿšท", + ":no_smoking:": "๐Ÿšญ", + ":non-potable_water:": "๐Ÿšฑ", + ":norfolk_island:": "๐Ÿ‡ณโ€๐Ÿ‡ซ", + ":north_korea:": "๐Ÿ‡ฐโ€๐Ÿ‡ต", + ":northern_mariana_islands:": "๐Ÿ‡ฒโ€๐Ÿ‡ต", + ":norway:": "๐Ÿ‡ณโ€๐Ÿ‡ด", + ":nose:": "๐Ÿ‘ƒ", + ":notebook:": "๐Ÿ““", + ":notebook_with_decorative_cover:": "๐Ÿ“”", + ":notes:": "๐ŸŽถ", + ":nut_and_bolt:": "๐Ÿ”ฉ", + ":o:": "โญ•", + ":o2:": "๐Ÿ…พ", + ":ocean:": "๐ŸŒŠ", + ":octopus:": "๐Ÿ™", + ":oden:": "๐Ÿข", + ":office:": "๐Ÿข", + ":office_worker:": "๐Ÿง‘โ€๐Ÿ’ผ", + ":oil_drum:": "๐Ÿ›ข", + ":ok:": "๐Ÿ†—", + ":ok_hand:": "๐Ÿ‘Œ", + ":ok_man:": "๐Ÿ™†โ€โ™‚", + ":ok_person:": "๐Ÿ™†", + ":ok_woman:": "๐Ÿ™†โ€โ™€", + ":old_key:": "๐Ÿ—", + ":older_adult:": "๐Ÿง“", + ":older_man:": "๐Ÿ‘ด", + ":older_woman:": "๐Ÿ‘ต", + ":om:": "๐Ÿ•‰", + ":oman:": "๐Ÿ‡ดโ€๐Ÿ‡ฒ", + ":on:": "๐Ÿ”›", + ":oncoming_automobile:": "๐Ÿš˜", + ":oncoming_bus:": "๐Ÿš", + ":oncoming_police_car:": "๐Ÿš”", + ":oncoming_taxi:": "๐Ÿš–", + ":one:": "1โ€โƒฃ", + ":one_piece_swimsuit:": "๐Ÿฉฑ", + ":onion:": "๐Ÿง…", + ":open_book:": "๐Ÿ“–", + ":open_file_folder:": "๐Ÿ“‚", + ":open_hands:": "๐Ÿ‘", + ":open_mouth:": "๐Ÿ˜ฎ", + ":open_umbrella:": "โ˜‚", + ":ophiuchus:": "โ›Ž", + ":orange:": "๐ŸŠ", + ":orange_book:": "๐Ÿ“™", + ":orange_circle:": "๐ŸŸ ", + ":orange_heart:": "๐Ÿงก", + ":orange_square:": "๐ŸŸง", + ":orangutan:": "๐Ÿฆง", + ":orthodox_cross:": "โ˜ฆ", + ":otter:": "๐Ÿฆฆ", + ":outbox_tray:": "๐Ÿ“ค", + ":owl:": "๐Ÿฆ‰", + ":ox:": "๐Ÿ‚", + ":oyster:": "๐Ÿฆช", + ":package:": "๐Ÿ“ฆ", + ":page_facing_up:": "๐Ÿ“„", + ":page_with_curl:": "๐Ÿ“ƒ", + ":pager:": "๐Ÿ“Ÿ", + ":paintbrush:": "๐Ÿ–Œ", + ":pakistan:": "๐Ÿ‡ตโ€๐Ÿ‡ฐ", + ":palau:": "๐Ÿ‡ตโ€๐Ÿ‡ผ", + ":palestinian_territories:": "๐Ÿ‡ตโ€๐Ÿ‡ธ", + ":palm_tree:": "๐ŸŒด", + ":palms_up_together:": "๐Ÿคฒ", + ":panama:": "๐Ÿ‡ตโ€๐Ÿ‡ฆ", + ":pancakes:": "๐Ÿฅž", + ":panda_face:": "๐Ÿผ", + ":paperclip:": "๐Ÿ“Ž", + ":paperclips:": "๐Ÿ–‡", + ":papua_new_guinea:": "๐Ÿ‡ตโ€๐Ÿ‡ฌ", + ":parachute:": "๐Ÿช‚", + ":paraguay:": "๐Ÿ‡ตโ€๐Ÿ‡พ", + ":parasol_on_ground:": "โ›ฑ", + ":parking:": "๐Ÿ…ฟ", + ":parrot:": "๐Ÿฆœ", + ":part_alternation_mark:": "ใ€ฝ", + ":partly_sunny:": "โ›…", + ":partying_face:": "๐Ÿฅณ", + ":passenger_ship:": "๐Ÿ›ณ", + ":passport_control:": "๐Ÿ›‚", + ":pause_button:": "โธ", + ":paw_prints:": "๐Ÿพ", + ":peace_symbol:": "โ˜ฎ", + ":peach:": "๐Ÿ‘", + ":peacock:": "๐Ÿฆš", + ":peanuts:": "๐Ÿฅœ", + ":pear:": "๐Ÿ", + ":pen:": "๐Ÿ–Š", + ":pencil:": "๐Ÿ“", + ":pencil2:": "โœ", + ":penguin:": "๐Ÿง", + ":pensive:": "๐Ÿ˜”", + ":people_holding_hands:": "๐Ÿง‘โ€๐Ÿคโ€๐Ÿง‘", + ":performing_arts:": "๐ŸŽญ", + ":persevere:": "๐Ÿ˜ฃ", + ":person_bald:": "๐Ÿง‘โ€๐Ÿฆฒ", + ":person_curly_hair:": "๐Ÿง‘โ€๐Ÿฆฑ", + ":person_fencing:": "๐Ÿคบ", + ":person_in_manual_wheelchair:": "๐Ÿง‘โ€๐Ÿฆฝ", + ":person_in_motorized_wheelchair:": "๐Ÿง‘โ€๐Ÿฆผ", + ":person_red_hair:": "๐Ÿง‘โ€๐Ÿฆฐ", + ":person_white_hair:": "๐Ÿง‘โ€๐Ÿฆณ", + ":person_with_probing_cane:": "๐Ÿง‘โ€๐Ÿฆฏ", + ":person_with_turban:": "๐Ÿ‘ณ", + ":peru:": "๐Ÿ‡ตโ€๐Ÿ‡ช", + ":petri_dish:": "๐Ÿงซ", + ":philippines:": "๐Ÿ‡ตโ€๐Ÿ‡ญ", + ":phone:": "โ˜Ž", + ":pick:": "โ›", + ":pie:": "๐Ÿฅง", + ":pig:": "๐Ÿท", + ":pig2:": "๐Ÿ–", + ":pig_nose:": "๐Ÿฝ", + ":pill:": "๐Ÿ’Š", + ":pilot:": "๐Ÿง‘โ€โœˆ", + ":pinching_hand:": "๐Ÿค", + ":pineapple:": "๐Ÿ", + ":ping_pong:": "๐Ÿ“", + ":pirate_flag:": "๐Ÿดโ€โ˜ ", + ":pisces:": "โ™“", + ":pitcairn_islands:": "๐Ÿ‡ตโ€๐Ÿ‡ณ", + ":pizza:": "๐Ÿ•", + ":place_of_worship:": "๐Ÿ›", + ":plate_with_cutlery:": "๐Ÿฝ", + ":play_or_pause_button:": "โฏ", + ":pleading_face:": "๐Ÿฅบ", + ":point_down:": "๐Ÿ‘‡", + ":point_left:": "๐Ÿ‘ˆ", + ":point_right:": "๐Ÿ‘‰", + ":point_up:": "โ˜", + ":point_up_2:": "๐Ÿ‘†", + ":poland:": "๐Ÿ‡ตโ€๐Ÿ‡ฑ", + ":police_car:": "๐Ÿš“", + ":police_officer:": "๐Ÿ‘ฎ", + ":policeman:": "๐Ÿ‘ฎโ€โ™‚", + ":policewoman:": "๐Ÿ‘ฎโ€โ™€", + ":poodle:": "๐Ÿฉ", + ":poop:": "๐Ÿ’ฉ", + ":popcorn:": "๐Ÿฟ", + ":portugal:": "๐Ÿ‡ตโ€๐Ÿ‡น", + ":post_office:": "๐Ÿฃ", + ":postal_horn:": "๐Ÿ“ฏ", + ":postbox:": "๐Ÿ“ฎ", + ":potable_water:": "๐Ÿšฐ", + ":potato:": "๐Ÿฅ”", + ":pouch:": "๐Ÿ‘", + ":poultry_leg:": "๐Ÿ—", + ":pound:": "๐Ÿ’ท", + ":pout:": "๐Ÿ˜ก", + ":pouting_cat:": "๐Ÿ˜พ", + ":pouting_face:": "๐Ÿ™Ž", + ":pouting_man:": "๐Ÿ™Žโ€โ™‚", + ":pouting_woman:": "๐Ÿ™Žโ€โ™€", + ":pray:": "๐Ÿ™", + ":prayer_beads:": "๐Ÿ“ฟ", + ":pregnant_woman:": "๐Ÿคฐ", + ":pretzel:": "๐Ÿฅจ", + ":previous_track_button:": "โฎ", + ":prince:": "๐Ÿคด", + ":princess:": "๐Ÿ‘ธ", + ":printer:": "๐Ÿ–จ", + ":probing_cane:": "๐Ÿฆฏ", + ":puerto_rico:": "๐Ÿ‡ตโ€๐Ÿ‡ท", + ":punch:": "๐Ÿ‘Š", + ":purple_circle:": "๐ŸŸฃ", + ":purple_heart:": "๐Ÿ’œ", + ":purple_square:": "๐ŸŸช", + ":purse:": "๐Ÿ‘›", + ":pushpin:": "๐Ÿ“Œ", + ":put_litter_in_its_place:": "๐Ÿšฎ", + ":qatar:": "๐Ÿ‡ถโ€๐Ÿ‡ฆ", + ":question:": "โ“", + ":rabbit:": "๐Ÿฐ", + ":rabbit2:": "๐Ÿ‡", + ":raccoon:": "๐Ÿฆ", + ":racehorse:": "๐ŸŽ", + ":racing_car:": "๐ŸŽ", + ":radio:": "๐Ÿ“ป", + ":radio_button:": "๐Ÿ”˜", + ":radioactive:": "โ˜ข", + ":rage:": "๐Ÿ˜ก", + ":railway_car:": "๐Ÿšƒ", + ":railway_track:": "๐Ÿ›ค", + ":rainbow:": "๐ŸŒˆ", + ":rainbow_flag:": "๐Ÿณโ€๐ŸŒˆ", + ":raised_back_of_hand:": "๐Ÿคš", + ":raised_eyebrow:": "๐Ÿคจ", + ":raised_hand:": "โœ‹", + ":raised_hand_with_fingers_splayed:": "๐Ÿ–", + ":raised_hands:": "๐Ÿ™Œ", + ":raising_hand:": "๐Ÿ™‹", + ":raising_hand_man:": "๐Ÿ™‹โ€โ™‚", + ":raising_hand_woman:": "๐Ÿ™‹โ€โ™€", + ":ram:": "๐Ÿ", + ":ramen:": "๐Ÿœ", + ":rat:": "๐Ÿ€", + ":razor:": "๐Ÿช’", + ":receipt:": "๐Ÿงพ", + ":record_button:": "โบ", + ":recycle:": "โ™ป", + ":red_car:": "๐Ÿš—", + ":red_circle:": "๐Ÿ”ด", + ":red_envelope:": "๐Ÿงง", + ":red_haired_man:": "๐Ÿ‘จโ€๐Ÿฆฐ", + ":red_haired_woman:": "๐Ÿ‘ฉโ€๐Ÿฆฐ", + ":red_square:": "๐ŸŸฅ", + ":registered:": "ยฎ", + ":relaxed:": "โ˜บ", + ":relieved:": "๐Ÿ˜Œ", + ":reminder_ribbon:": "๐ŸŽ—", + ":repeat:": "๐Ÿ”", + ":repeat_one:": "๐Ÿ”‚", + ":rescue_worker_helmet:": "โ›‘", + ":restroom:": "๐Ÿšป", + ":reunion:": "๐Ÿ‡ทโ€๐Ÿ‡ช", + ":revolving_hearts:": "๐Ÿ’ž", + ":rewind:": "โช", + ":rhinoceros:": "๐Ÿฆ", + ":ribbon:": "๐ŸŽ€", + ":rice:": "๐Ÿš", + ":rice_ball:": "๐Ÿ™", + ":rice_cracker:": "๐Ÿ˜", + ":rice_scene:": "๐ŸŽ‘", + ":right_anger_bubble:": "๐Ÿ—ฏ", + ":ring:": "๐Ÿ’", + ":ringed_planet:": "๐Ÿช", + ":robot:": "๐Ÿค–", + ":rocket:": "๐Ÿš€", + ":rofl:": "๐Ÿคฃ", + ":roll_eyes:": "๐Ÿ™„", + ":roll_of_paper:": "๐Ÿงป", + ":roller_coaster:": "๐ŸŽข", + ":romania:": "๐Ÿ‡ทโ€๐Ÿ‡ด", + ":rooster:": "๐Ÿ“", + ":rose:": "๐ŸŒน", + ":rosette:": "๐Ÿต", + ":rotating_light:": "๐Ÿšจ", + ":round_pushpin:": "๐Ÿ“", + ":rowboat:": "๐Ÿšฃ", + ":rowing_man:": "๐Ÿšฃโ€โ™‚", + ":rowing_woman:": "๐Ÿšฃโ€โ™€", + ":ru:": "๐Ÿ‡ทโ€๐Ÿ‡บ", + ":rugby_football:": "๐Ÿ‰", + ":runner:": "๐Ÿƒ", + ":running:": "๐Ÿƒ", + ":running_man:": "๐Ÿƒโ€โ™‚", + ":running_shirt_with_sash:": "๐ŸŽฝ", + ":running_woman:": "๐Ÿƒโ€โ™€", + ":rwanda:": "๐Ÿ‡ทโ€๐Ÿ‡ผ", + ":sa:": "๐Ÿˆ‚", + ":safety_pin:": "๐Ÿงท", + ":safety_vest:": "๐Ÿฆบ", + ":sagittarius:": "โ™", + ":sailboat:": "โ›ต", + ":sake:": "๐Ÿถ", + ":salt:": "๐Ÿง‚", + ":samoa:": "๐Ÿ‡ผโ€๐Ÿ‡ธ", + ":san_marino:": "๐Ÿ‡ธโ€๐Ÿ‡ฒ", + ":sandal:": "๐Ÿ‘ก", + ":sandwich:": "๐Ÿฅช", + ":santa:": "๐ŸŽ…", + ":sao_tome_principe:": "๐Ÿ‡ธโ€๐Ÿ‡น", + ":sari:": "๐Ÿฅป", + ":sassy_man:": "๐Ÿ’โ€โ™‚", + ":sassy_woman:": "๐Ÿ’โ€โ™€", + ":satellite:": "๐Ÿ“ก", + ":satisfied:": "๐Ÿ˜†", + ":saudi_arabia:": "๐Ÿ‡ธโ€๐Ÿ‡ฆ", + ":sauna_man:": "๐Ÿง–โ€โ™‚", + ":sauna_person:": "๐Ÿง–", + ":sauna_woman:": "๐Ÿง–โ€โ™€", + ":sauropod:": "๐Ÿฆ•", + ":saxophone:": "๐ŸŽท", + ":scarf:": "๐Ÿงฃ", + ":school:": "๐Ÿซ", + ":school_satchel:": "๐ŸŽ’", + ":scientist:": "๐Ÿง‘โ€๐Ÿ”ฌ", + ":scissors:": "โœ‚", + ":scorpion:": "๐Ÿฆ‚", + ":scorpius:": "โ™", + ":scotland:": "๐Ÿดโ€๓ งโ€๓ ขโ€๓ ณโ€๓ ฃโ€๓ ดโ€๓ ฟ", + ":scream:": "๐Ÿ˜ฑ", + ":scream_cat:": "๐Ÿ™€", + ":scroll:": "๐Ÿ“œ", + ":seat:": "๐Ÿ’บ", + ":secret:": "ใŠ™", + ":see_no_evil:": "๐Ÿ™ˆ", + ":seedling:": "๐ŸŒฑ", + ":selfie:": "๐Ÿคณ", + ":senegal:": "๐Ÿ‡ธโ€๐Ÿ‡ณ", + ":serbia:": "๐Ÿ‡ทโ€๐Ÿ‡ธ", + ":service_dog:": "๐Ÿ•โ€๐Ÿฆบ", + ":seven:": "7โ€โƒฃ", + ":seychelles:": "๐Ÿ‡ธโ€๐Ÿ‡จ", + ":shallow_pan_of_food:": "๐Ÿฅ˜", + ":shamrock:": "โ˜˜", + ":shark:": "๐Ÿฆˆ", + ":shaved_ice:": "๐Ÿง", + ":sheep:": "๐Ÿ‘", + ":shell:": "๐Ÿš", + ":shield:": "๐Ÿ›ก", + ":shinto_shrine:": "โ›ฉ", + ":ship:": "๐Ÿšข", + ":shirt:": "๐Ÿ‘•", + ":shit:": "๐Ÿ’ฉ", + ":shoe:": "๐Ÿ‘ž", + ":shopping:": "๐Ÿ›", + ":shopping_cart:": "๐Ÿ›’", + ":shorts:": "๐Ÿฉณ", + ":shower:": "๐Ÿšฟ", + ":shrimp:": "๐Ÿฆ", + ":shrug:": "๐Ÿคท", + ":shushing_face:": "๐Ÿคซ", + ":sierra_leone:": "๐Ÿ‡ธโ€๐Ÿ‡ฑ", + ":signal_strength:": "๐Ÿ“ถ", + ":singapore:": "๐Ÿ‡ธโ€๐Ÿ‡ฌ", + ":singer:": "๐Ÿง‘โ€๐ŸŽค", + ":sint_maarten:": "๐Ÿ‡ธโ€๐Ÿ‡ฝ", + ":six:": "6โ€โƒฃ", + ":six_pointed_star:": "๐Ÿ”ฏ", + ":skateboard:": "๐Ÿ›น", + ":ski:": "๐ŸŽฟ", + ":skier:": "โ›ท", + ":skull:": "๐Ÿ’€", + ":skull_and_crossbones:": "โ˜ ", + ":skunk:": "๐Ÿฆจ", + ":sled:": "๐Ÿ›ท", + ":sleeping:": "๐Ÿ˜ด", + ":sleeping_bed:": "๐Ÿ›Œ", + ":sleepy:": "๐Ÿ˜ช", + ":slightly_frowning_face:": "๐Ÿ™", + ":slightly_smiling_face:": "๐Ÿ™‚", + ":slot_machine:": "๐ŸŽฐ", + ":sloth:": "๐Ÿฆฅ", + ":slovakia:": "๐Ÿ‡ธโ€๐Ÿ‡ฐ", + ":slovenia:": "๐Ÿ‡ธโ€๐Ÿ‡ฎ", + ":small_airplane:": "๐Ÿ›ฉ", + ":small_blue_diamond:": "๐Ÿ”น", + ":small_orange_diamond:": "๐Ÿ”ธ", + ":small_red_triangle:": "๐Ÿ”บ", + ":small_red_triangle_down:": "๐Ÿ”ป", + ":smile:": "๐Ÿ˜„", + ":smile_cat:": "๐Ÿ˜ธ", + ":smiley:": "๐Ÿ˜ƒ", + ":smiley_cat:": "๐Ÿ˜บ", + ":smiling_face_with_three_hearts:": "๐Ÿฅฐ", + ":smiling_imp:": "๐Ÿ˜ˆ", + ":smirk:": "๐Ÿ˜", + ":smirk_cat:": "๐Ÿ˜ผ", + ":smoking:": "๐Ÿšฌ", + ":snail:": "๐ŸŒ", + ":snake:": "๐Ÿ", + ":sneezing_face:": "๐Ÿคง", + ":snowboarder:": "๐Ÿ‚", + ":snowflake:": "โ„", + ":snowman:": "โ›„", + ":snowman_with_snow:": "โ˜ƒ", + ":soap:": "๐Ÿงผ", + ":sob:": "๐Ÿ˜ญ", + ":soccer:": "โšฝ", + ":socks:": "๐Ÿงฆ", + ":softball:": "๐ŸฅŽ", + ":solomon_islands:": "๐Ÿ‡ธโ€๐Ÿ‡ง", + ":somalia:": "๐Ÿ‡ธโ€๐Ÿ‡ด", + ":soon:": "๐Ÿ”œ", + ":sos:": "๐Ÿ†˜", + ":sound:": "๐Ÿ”‰", + ":south_africa:": "๐Ÿ‡ฟโ€๐Ÿ‡ฆ", + ":south_georgia_south_sandwich_islands:": "๐Ÿ‡ฌโ€๐Ÿ‡ธ", + ":south_sudan:": "๐Ÿ‡ธโ€๐Ÿ‡ธ", + ":space_invader:": "๐Ÿ‘พ", + ":spades:": "โ™ ", + ":spaghetti:": "๐Ÿ", + ":sparkle:": "โ‡", + ":sparkler:": "๐ŸŽ‡", + ":sparkles:": "โœจ", + ":sparkling_heart:": "๐Ÿ’–", + ":speak_no_evil:": "๐Ÿ™Š", + ":speaker:": "๐Ÿ”ˆ", + ":speaking_head:": "๐Ÿ—ฃ", + ":speech_balloon:": "๐Ÿ’ฌ", + ":speedboat:": "๐Ÿšค", + ":spider:": "๐Ÿ•ท", + ":spider_web:": "๐Ÿ•ธ", + ":spiral_calendar:": "๐Ÿ—“", + ":spiral_notepad:": "๐Ÿ—’", + ":sponge:": "๐Ÿงฝ", + ":spoon:": "๐Ÿฅ„", + ":squid:": "๐Ÿฆ‘", + ":sri_lanka:": "๐Ÿ‡ฑโ€๐Ÿ‡ฐ", + ":st_barthelemy:": "๐Ÿ‡งโ€๐Ÿ‡ฑ", + ":st_helena:": "๐Ÿ‡ธโ€๐Ÿ‡ญ", + ":st_kitts_nevis:": "๐Ÿ‡ฐโ€๐Ÿ‡ณ", + ":st_lucia:": "๐Ÿ‡ฑโ€๐Ÿ‡จ", + ":st_martin:": "๐Ÿ‡ฒโ€๐Ÿ‡ซ", + ":st_pierre_miquelon:": "๐Ÿ‡ตโ€๐Ÿ‡ฒ", + ":st_vincent_grenadines:": "๐Ÿ‡ปโ€๐Ÿ‡จ", + ":stadium:": "๐ŸŸ", + ":standing_man:": "๐Ÿงโ€โ™‚", + ":standing_person:": "๐Ÿง", + ":standing_woman:": "๐Ÿงโ€โ™€", + ":star:": "โญ", + ":star2:": "๐ŸŒŸ", + ":star_and_crescent:": "โ˜ช", + ":star_of_david:": "โœก", + ":star_struck:": "๐Ÿคฉ", + ":stars:": "๐ŸŒ ", + ":station:": "๐Ÿš‰", + ":statue_of_liberty:": "๐Ÿ—ฝ", + ":steam_locomotive:": "๐Ÿš‚", + ":stethoscope:": "๐Ÿฉบ", + ":stew:": "๐Ÿฒ", + ":stop_button:": "โน", + ":stop_sign:": "๐Ÿ›‘", + ":stopwatch:": "โฑ", + ":straight_ruler:": "๐Ÿ“", + ":strawberry:": "๐Ÿ“", + ":stuck_out_tongue:": "๐Ÿ˜›", + ":stuck_out_tongue_closed_eyes:": "๐Ÿ˜", + ":stuck_out_tongue_winking_eye:": "๐Ÿ˜œ", + ":student:": "๐Ÿง‘โ€๐ŸŽ“", + ":studio_microphone:": "๐ŸŽ™", + ":stuffed_flatbread:": "๐Ÿฅ™", + ":sudan:": "๐Ÿ‡ธโ€๐Ÿ‡ฉ", + ":sun_behind_large_cloud:": "๐ŸŒฅ", + ":sun_behind_rain_cloud:": "๐ŸŒฆ", + ":sun_behind_small_cloud:": "๐ŸŒค", + ":sun_with_face:": "๐ŸŒž", + ":sunflower:": "๐ŸŒป", + ":sunglasses:": "๐Ÿ˜Ž", + ":sunny:": "โ˜€", + ":sunrise:": "๐ŸŒ…", + ":sunrise_over_mountains:": "๐ŸŒ„", + ":superhero:": "๐Ÿฆธ", + ":superhero_man:": "๐Ÿฆธโ€โ™‚", + ":superhero_woman:": "๐Ÿฆธโ€โ™€", + ":supervillain:": "๐Ÿฆน", + ":supervillain_man:": "๐Ÿฆนโ€โ™‚", + ":supervillain_woman:": "๐Ÿฆนโ€โ™€", + ":surfer:": "๐Ÿ„", + ":surfing_man:": "๐Ÿ„โ€โ™‚", + ":surfing_woman:": "๐Ÿ„โ€โ™€", + ":suriname:": "๐Ÿ‡ธโ€๐Ÿ‡ท", + ":sushi:": "๐Ÿฃ", + ":suspension_railway:": "๐ŸšŸ", + ":svalbard_jan_mayen:": "๐Ÿ‡ธโ€๐Ÿ‡ฏ", + ":swan:": "๐Ÿฆข", + ":swaziland:": "๐Ÿ‡ธโ€๐Ÿ‡ฟ", + ":sweat:": "๐Ÿ˜“", + ":sweat_drops:": "๐Ÿ’ฆ", + ":sweat_smile:": "๐Ÿ˜…", + ":sweden:": "๐Ÿ‡ธโ€๐Ÿ‡ช", + ":sweet_potato:": "๐Ÿ ", + ":swim_brief:": "๐Ÿฉฒ", + ":swimmer:": "๐ŸŠ", + ":swimming_man:": "๐ŸŠโ€โ™‚", + ":swimming_woman:": "๐ŸŠโ€โ™€", + ":switzerland:": "๐Ÿ‡จโ€๐Ÿ‡ญ", + ":symbols:": "๐Ÿ”ฃ", + ":synagogue:": "๐Ÿ•", + ":syria:": "๐Ÿ‡ธโ€๐Ÿ‡พ", + ":syringe:": "๐Ÿ’‰", + ":t-rex:": "๐Ÿฆ–", + ":taco:": "๐ŸŒฎ", + ":tada:": "๐ŸŽ‰", + ":taiwan:": "๐Ÿ‡นโ€๐Ÿ‡ผ", + ":tajikistan:": "๐Ÿ‡นโ€๐Ÿ‡ฏ", + ":takeout_box:": "๐Ÿฅก", + ":tanabata_tree:": "๐ŸŽ‹", + ":tangerine:": "๐ŸŠ", + ":tanzania:": "๐Ÿ‡นโ€๐Ÿ‡ฟ", + ":taurus:": "โ™‰", + ":taxi:": "๐Ÿš•", + ":tea:": "๐Ÿต", + ":teacher:": "๐Ÿง‘โ€๐Ÿซ", + ":technologist:": "๐Ÿง‘โ€๐Ÿ’ป", + ":teddy_bear:": "๐Ÿงธ", + ":telephone:": "โ˜Ž", + ":telephone_receiver:": "๐Ÿ“ž", + ":telescope:": "๐Ÿ”ญ", + ":tennis:": "๐ŸŽพ", + ":tent:": "โ›บ", + ":test_tube:": "๐Ÿงช", + ":thailand:": "๐Ÿ‡นโ€๐Ÿ‡ญ", + ":thermometer:": "๐ŸŒก", + ":thinking:": "๐Ÿค”", + ":thought_balloon:": "๐Ÿ’ญ", + ":thread:": "๐Ÿงต", + ":three:": "3โ€โƒฃ", + ":thumbsdown:": "๐Ÿ‘Ž", + ":thumbsup:": "๐Ÿ‘", + ":ticket:": "๐ŸŽซ", + ":tickets:": "๐ŸŽŸ", + ":tiger:": "๐Ÿฏ", + ":tiger2:": "๐Ÿ…", + ":timer_clock:": "โฒ", + ":timor_leste:": "๐Ÿ‡นโ€๐Ÿ‡ฑ", + ":tipping_hand_man:": "๐Ÿ’โ€โ™‚", + ":tipping_hand_person:": "๐Ÿ’", + ":tipping_hand_woman:": "๐Ÿ’โ€โ™€", + ":tired_face:": "๐Ÿ˜ซ", + ":tm:": "โ„ข", + ":togo:": "๐Ÿ‡นโ€๐Ÿ‡ฌ", + ":toilet:": "๐Ÿšฝ", + ":tokelau:": "๐Ÿ‡นโ€๐Ÿ‡ฐ", + ":tokyo_tower:": "๐Ÿ—ผ", + ":tomato:": "๐Ÿ…", + ":tonga:": "๐Ÿ‡นโ€๐Ÿ‡ด", + ":tongue:": "๐Ÿ‘…", + ":toolbox:": "๐Ÿงฐ", + ":tooth:": "๐Ÿฆท", + ":top:": "๐Ÿ”", + ":tophat:": "๐ŸŽฉ", + ":tornado:": "๐ŸŒช", + ":tr:": "๐Ÿ‡นโ€๐Ÿ‡ท", + ":trackball:": "๐Ÿ–ฒ", + ":tractor:": "๐Ÿšœ", + ":traffic_light:": "๐Ÿšฅ", + ":train:": "๐Ÿš‹", + ":train2:": "๐Ÿš†", + ":tram:": "๐ŸšŠ", + ":triangular_flag_on_post:": "๐Ÿšฉ", + ":triangular_ruler:": "๐Ÿ“", + ":trident:": "๐Ÿ”ฑ", + ":trinidad_tobago:": "๐Ÿ‡นโ€๐Ÿ‡น", + ":tristan_da_cunha:": "๐Ÿ‡นโ€๐Ÿ‡ฆ", + ":triumph:": "๐Ÿ˜ค", + ":trolleybus:": "๐ŸšŽ", + ":trophy:": "๐Ÿ†", + ":tropical_drink:": "๐Ÿน", + ":tropical_fish:": "๐Ÿ ", + ":truck:": "๐Ÿšš", + ":trumpet:": "๐ŸŽบ", + ":tshirt:": "๐Ÿ‘•", + ":tulip:": "๐ŸŒท", + ":tumbler_glass:": "๐Ÿฅƒ", + ":tunisia:": "๐Ÿ‡นโ€๐Ÿ‡ณ", + ":turkey:": "๐Ÿฆƒ", + ":turkmenistan:": "๐Ÿ‡นโ€๐Ÿ‡ฒ", + ":turks_caicos_islands:": "๐Ÿ‡นโ€๐Ÿ‡จ", + ":turtle:": "๐Ÿข", + ":tuvalu:": "๐Ÿ‡นโ€๐Ÿ‡ป", + ":tv:": "๐Ÿ“บ", + ":twisted_rightwards_arrows:": "๐Ÿ”€", + ":two:": "2โ€โƒฃ", + ":two_hearts:": "๐Ÿ’•", + ":two_men_holding_hands:": "๐Ÿ‘ฌ", + ":two_women_holding_hands:": "๐Ÿ‘ญ", + ":u5272:": "๐Ÿˆน", + ":u5408:": "๐Ÿˆด", + ":u55b6:": "๐Ÿˆบ", + ":u6307:": "๐Ÿˆฏ", + ":u6708:": "๐Ÿˆท", + ":u6709:": "๐Ÿˆถ", + ":u6e80:": "๐Ÿˆต", + ":u7121:": "๐Ÿˆš", + ":u7533:": "๐Ÿˆธ", + ":u7981:": "๐Ÿˆฒ", + ":u7a7a:": "๐Ÿˆณ", + ":uganda:": "๐Ÿ‡บโ€๐Ÿ‡ฌ", + ":uk:": "๐Ÿ‡ฌโ€๐Ÿ‡ง", + ":ukraine:": "๐Ÿ‡บโ€๐Ÿ‡ฆ", + ":umbrella:": "โ˜”", + ":unamused:": "๐Ÿ˜’", + ":underage:": "๐Ÿ”ž", + ":unicorn:": "๐Ÿฆ„", + ":united_arab_emirates:": "๐Ÿ‡ฆโ€๐Ÿ‡ช", + ":united_nations:": "๐Ÿ‡บโ€๐Ÿ‡ณ", + ":unlock:": "๐Ÿ”“", + ":up:": "๐Ÿ†™", + ":upside_down_face:": "๐Ÿ™ƒ", + ":uruguay:": "๐Ÿ‡บโ€๐Ÿ‡พ", + ":us:": "๐Ÿ‡บโ€๐Ÿ‡ธ", + ":us_outlying_islands:": "๐Ÿ‡บโ€๐Ÿ‡ฒ", + ":us_virgin_islands:": "๐Ÿ‡ปโ€๐Ÿ‡ฎ", + ":uzbekistan:": "๐Ÿ‡บโ€๐Ÿ‡ฟ", + ":v:": "โœŒ", + ":vampire:": "๐Ÿง›", + ":vampire_man:": "๐Ÿง›โ€โ™‚", + ":vampire_woman:": "๐Ÿง›โ€โ™€", + ":vanuatu:": "๐Ÿ‡ปโ€๐Ÿ‡บ", + ":vatican_city:": "๐Ÿ‡ปโ€๐Ÿ‡ฆ", + ":venezuela:": "๐Ÿ‡ปโ€๐Ÿ‡ช", + ":vertical_traffic_light:": "๐Ÿšฆ", + ":vhs:": "๐Ÿ“ผ", + ":vibration_mode:": "๐Ÿ“ณ", + ":video_camera:": "๐Ÿ“น", + ":video_game:": "๐ŸŽฎ", + ":vietnam:": "๐Ÿ‡ปโ€๐Ÿ‡ณ", + ":violin:": "๐ŸŽป", + ":virgo:": "โ™", + ":volcano:": "๐ŸŒ‹", + ":volleyball:": "๐Ÿ", + ":vomiting_face:": "๐Ÿคฎ", + ":vs:": "๐Ÿ†š", + ":vulcan_salute:": "๐Ÿ––", + ":waffle:": "๐Ÿง‡", + ":wales:": "๐Ÿดโ€๓ งโ€๓ ขโ€๓ ทโ€๓ ฌโ€๓ ณโ€๓ ฟ", + ":walking:": "๐Ÿšถ", + ":walking_man:": "๐Ÿšถโ€โ™‚", + ":walking_woman:": "๐Ÿšถโ€โ™€", + ":wallis_futuna:": "๐Ÿ‡ผโ€๐Ÿ‡ซ", + ":waning_crescent_moon:": "๐ŸŒ˜", + ":waning_gibbous_moon:": "๐ŸŒ–", + ":warning:": "โš ", + ":wastebasket:": "๐Ÿ—‘", + ":watch:": "โŒš", + ":water_buffalo:": "๐Ÿƒ", + ":water_polo:": "๐Ÿคฝ", + ":watermelon:": "๐Ÿ‰", + ":wave:": "๐Ÿ‘‹", + ":wavy_dash:": "ใ€ฐ", + ":waxing_crescent_moon:": "๐ŸŒ’", + ":waxing_gibbous_moon:": "๐ŸŒ”", + ":wc:": "๐Ÿšพ", + ":weary:": "๐Ÿ˜ฉ", + ":wedding:": "๐Ÿ’’", + ":weight_lifting:": "๐Ÿ‹", + ":weight_lifting_man:": "๐Ÿ‹โ€โ™‚", + ":weight_lifting_woman:": "๐Ÿ‹โ€โ™€", + ":western_sahara:": "๐Ÿ‡ชโ€๐Ÿ‡ญ", + ":whale:": "๐Ÿณ", + ":whale2:": "๐Ÿ‹", + ":wheel_of_dharma:": "โ˜ธ", + ":wheelchair:": "โ™ฟ", + ":white_check_mark:": "โœ…", + ":white_circle:": "โšช", + ":white_flag:": "๐Ÿณ", + ":white_flower:": "๐Ÿ’ฎ", + ":white_haired_man:": "๐Ÿ‘จโ€๐Ÿฆณ", + ":white_haired_woman:": "๐Ÿ‘ฉโ€๐Ÿฆณ", + ":white_heart:": "๐Ÿค", + ":white_large_square:": "โฌœ", + ":white_medium_small_square:": "โ—ฝ", + ":white_medium_square:": "โ—ป", + ":white_small_square:": "โ–ซ", + ":white_square_button:": "๐Ÿ”ณ", + ":wilted_flower:": "๐Ÿฅ€", + ":wind_chime:": "๐ŸŽ", + ":wind_face:": "๐ŸŒฌ", + ":wine_glass:": "๐Ÿท", + ":wink:": "๐Ÿ˜‰", + ":wolf:": "๐Ÿบ", + ":woman:": "๐Ÿ‘ฉ", + ":woman_artist:": "๐Ÿ‘ฉโ€๐ŸŽจ", + ":woman_astronaut:": "๐Ÿ‘ฉโ€๐Ÿš€", + ":woman_cartwheeling:": "๐Ÿคธโ€โ™€", + ":woman_cook:": "๐Ÿ‘ฉโ€๐Ÿณ", + ":woman_dancing:": "๐Ÿ’ƒ", + ":woman_facepalming:": "๐Ÿคฆโ€โ™€", + ":woman_factory_worker:": "๐Ÿ‘ฉโ€๐Ÿญ", + ":woman_farmer:": "๐Ÿ‘ฉโ€๐ŸŒพ", + ":woman_firefighter:": "๐Ÿ‘ฉโ€๐Ÿš’", + ":woman_health_worker:": "๐Ÿ‘ฉโ€โš•", + ":woman_in_manual_wheelchair:": "๐Ÿ‘ฉโ€๐Ÿฆฝ", + ":woman_in_motorized_wheelchair:": "๐Ÿ‘ฉโ€๐Ÿฆผ", + ":woman_judge:": "๐Ÿ‘ฉโ€โš–", + ":woman_juggling:": "๐Ÿคนโ€โ™€", + ":woman_mechanic:": "๐Ÿ‘ฉโ€๐Ÿ”ง", + ":woman_office_worker:": "๐Ÿ‘ฉโ€๐Ÿ’ผ", + ":woman_pilot:": "๐Ÿ‘ฉโ€โœˆ", + ":woman_playing_handball:": "๐Ÿคพโ€โ™€", + ":woman_playing_water_polo:": "๐Ÿคฝโ€โ™€", + ":woman_scientist:": "๐Ÿ‘ฉโ€๐Ÿ”ฌ", + ":woman_shrugging:": "๐Ÿคทโ€โ™€", + ":woman_singer:": "๐Ÿ‘ฉโ€๐ŸŽค", + ":woman_student:": "๐Ÿ‘ฉโ€๐ŸŽ“", + ":woman_teacher:": "๐Ÿ‘ฉโ€๐Ÿซ", + ":woman_technologist:": "๐Ÿ‘ฉโ€๐Ÿ’ป", + ":woman_with_headscarf:": "๐Ÿง•", + ":woman_with_probing_cane:": "๐Ÿ‘ฉโ€๐Ÿฆฏ", + ":woman_with_turban:": "๐Ÿ‘ณโ€โ™€", + ":womans_clothes:": "๐Ÿ‘š", + ":womans_hat:": "๐Ÿ‘’", + ":women_wrestling:": "๐Ÿคผโ€โ™€", + ":womens:": "๐Ÿšบ", + ":woozy_face:": "๐Ÿฅด", + ":world_map:": "๐Ÿ—บ", + ":worried:": "๐Ÿ˜Ÿ", + ":wrench:": "๐Ÿ”ง", + ":wrestling:": "๐Ÿคผ", + ":writing_hand:": "โœ", + ":x:": "โŒ", + ":yarn:": "๐Ÿงถ", + ":yawning_face:": "๐Ÿฅฑ", + ":yellow_circle:": "๐ŸŸก", + ":yellow_heart:": "๐Ÿ’›", + ":yellow_square:": "๐ŸŸจ", + ":yemen:": "๐Ÿ‡พโ€๐Ÿ‡ช", + ":yen:": "๐Ÿ’ด", + ":yin_yang:": "โ˜ฏ", + ":yo_yo:": "๐Ÿช€", + ":yum:": "๐Ÿ˜‹", + ":zambia:": "๐Ÿ‡ฟโ€๐Ÿ‡ฒ", + ":zany_face:": "๐Ÿคช", + ":zap:": "โšก", + ":zebra:": "๐Ÿฆ“", + ":zero:": "0โ€โƒฃ", + ":zimbabwe:": "๐Ÿ‡ฟโ€๐Ÿ‡ผ", + ":zipper_mouth_face:": "๐Ÿค", + ":zombie:": "๐ŸงŸ", + ":zombie_man:": "๐ŸงŸโ€โ™‚", + ":zombie_woman:": "๐ŸงŸโ€โ™€", + ":zzz:": "๐Ÿ’ค", + ":default:": "โ—", + "a": "a", + "b": "b", + "c": "c", + "d": "d", + "e": "e", + "f": "f", + "g": "g", + "h": "h", + "i": "i", + "j": "j", + "k": "k", + "l": "l", + "m": "m", + "n": "n", + "o": "o", + "p": "p", + "q": "q", + "r": "r", + "s": "s", + "t": "t", + "u": "u", + "v": "v", + "w": "w", + "x": "x", + "y": "y", + "z": "z", + "A": "A", + "B": "B", + "C": "C", + "D": "D", + "E": "E", + "F": "F", + "G": "G", + "H": "H", + "I": "I", + "J": "J", + "K": "K", + "L": "L", + "M": "M", + "N": "N", + "O": "O", + "P": "P", + "Q": "Q", + "R": "R", + "S": "S", + "T": "T", + "U": "U", + "V": "V", + "W": "W", + "X": "X", + "Y": "Y", + "Z": "Z", + "0": "0", + "1": "1", + "2": "2", + "3": "3", + "4": "4", + "5": "5", + "6": "6", + "7": "7", + "8": "8", + "9": "9", +} + + +if __name__ == "__main__": # pragma: no cover + import requests + import io + import re + import string + from pathlib import Path + from mitmproxy.tools.console.common import SYMBOL_MARK + + CHAR_MARKERS = list(string.ascii_letters) + list(string.digits) + EMOJI_SRC = ' ":{name}:": "{emoji_val}",' + CHAR_SRC = ' "{name}": "{emoji_val}",' + + out = io.StringIO() + + r = requests.get("https://api.github.com/emojis") + for name, url in r.json().items(): + codepoints = url.rpartition("/")[2].partition(".png")[0].split("-") + try: + emoji_val = "\u200d".join(chr(int(c, 16)) for c in codepoints) + except ValueError: + continue # some GitHub-specific emojis, e.g. "atom". + print(EMOJI_SRC.format(name=name, emoji_val=emoji_val), file=out) + + # add the default marker + print(EMOJI_SRC.format(name="default", emoji_val=SYMBOL_MARK), file=out) + + for c in CHAR_MARKERS: + print(CHAR_SRC.format(name=c, emoji_val=c), file=out) + + Path(__file__).write_text( + re.sub(r"(?<={\n)[\s\S]*(?=}\n)", lambda x: out.getvalue(), Path(__file__).read_text("utf8"), 1), + "utf8" + ) \ No newline at end of file diff --git a/mitmproxy/version.py b/mitmproxy/version.py index 18a12a595..726c7fcc7 100644 --- a/mitmproxy/version.py +++ b/mitmproxy/version.py @@ -7,7 +7,7 @@ MITMPROXY = "mitmproxy " + VERSION # Serialization format version. This is displayed nowhere, it just needs to be incremented by one # for each change in the file format. -FLOW_FORMAT_VERSION = 12 +FLOW_FORMAT_VERSION = 13 def get_dev_version() -> str: diff --git a/test/mitmproxy/addons/test_core.py b/test/mitmproxy/addons/test_core.py index 6844e5042..80bd0db18 100644 --- a/test/mitmproxy/addons/test_core.py +++ b/test/mitmproxy/addons/test_core.py @@ -33,9 +33,12 @@ def test_mark(): with taddons.context(loadcore=False): f = tflow.tflow() assert not f.marked - sa.mark([f], True) + sa.mark([f], ":default:") assert f.marked + with pytest.raises(exceptions.CommandError): + sa.mark([f], "invalid") + sa.mark_toggle([f]) assert not f.marked sa.mark_toggle([f]) diff --git a/test/mitmproxy/addons/test_view.py b/test/mitmproxy/addons/test_view.py index a7f664825..13429a6ab 100644 --- a/test/mitmproxy/addons/test_view.py +++ b/test/mitmproxy/addons/test_view.py @@ -8,6 +8,7 @@ from mitmproxy import exceptions from mitmproxy import io from mitmproxy.test import taddons from mitmproxy.tools.console import consoleaddons +from mitmproxy.tools.console.common import render_marker, SYMBOL_MARK def tft(*, method="get", start=0): @@ -614,3 +615,13 @@ def test_configure(): tctx.configure(v, console_focus_follow=True) assert v.focus_follow + + +@pytest.mark.parametrize("marker, expected", [ + [":default:", SYMBOL_MARK], + ["X", "X"], + [":grapes:", "\N{grapes}"], + [":not valid:", SYMBOL_MARK], [":weird", SYMBOL_MARK] +]) +def test_marker(marker, expected): + assert render_marker(marker) == expected \ No newline at end of file diff --git a/test/mitmproxy/data/dumpfile-10.mitm b/test/mitmproxy/data/dumpfile-10.mitm new file mode 100644 index 000000000..cbbf4daf2 --- /dev/null +++ b/test/mitmproxy/data/dumpfile-10.mitm @@ -0,0 +1 @@ +1383:7:version;2:10#4:mode;7:regular;8:response;0:~7:request;291:4:path;1:/,9:authority;0:,6:scheme;5:https,6:method;3:GET,4:port;3:443#4:host;11:example.com;13:timestamp_end;17:1621870806.728885^15:timestamp_start;17:1621870806.728884^8:trailers;0:~7:content;0:,7:headers;52:22:14:content-length,1:0,]22:4:Host,11:example.com,]]12:http_version;8:HTTP/1.1,}8:metadata;0:}6:marked;4:true!9:is_replay;0:~11:intercepted;5:false!4:type;4:http;11:server_conn;468:3:via;0:~4:via2;0:~11:cipher_list;0:]11:cipher_name;0:~11:alpn_offers;0:]16:certificate_list;0:]3:tls;5:false!5:error;0:~5:state;1:0#13:timestamp_end;0:~19:timestamp_tls_setup;0:~19:timestamp_tcp_setup;0:~15:timestamp_start;0:~11:tls_version;0:~21:alpn_proto_negotiated;0:~3:sni;11:example.com;15:tls_established;5:false!14:source_address;7:0:;1:0#]10:ip_address;21:11:example.com;3:443#]7:address;21:11:example.com;3:443#]2:id;36:14ddf3ed-32ad-4e46-a049-38e214ecaa7b;}11:client_conn;385:11:cipher_list;0:]11:alpn_offers;0:]16:certificate_list;0:]3:tls;5:false!5:error;0:~8:sockname;7:0:;1:0#]5:state;1:0#14:tls_extensions;0:~11:tls_version;0:~21:alpn_proto_negotiated;0:~11:cipher_name;0:~3:sni;0:~13:timestamp_end;0:~19:timestamp_tls_setup;0:~15:timestamp_start;0:~8:mitmcert;0:~15:tls_established;5:false!7:address;7:0:;1:0#]2:id;36:8b758ba3-70ce-49ac-873f-97a893864602;}5:error;0:~2:id;36:fac79186-100e-45ee-a9ab-f7369281cf50;} \ No newline at end of file diff --git a/test/mitmproxy/io/test_compat.py b/test/mitmproxy/io/test_compat.py index 904064a7b..da96c3888 100644 --- a/test/mitmproxy/io/test_compat.py +++ b/test/mitmproxy/io/test_compat.py @@ -9,6 +9,7 @@ from mitmproxy import exceptions ["dumpfile-018.mitm", "https://www.example.com/", 1], ["dumpfile-019.mitm", "https://webrv.rtb-seller.com/", 1], ["dumpfile-7-websocket.mitm", "https://echo.websocket.org/", 6], + ["dumpfile-10.mitm", "https://example.com/", 1] ]) def test_load(tdata, dumpfile, url, count): with open(tdata.path("mitmproxy/data/" + dumpfile), "rb") as f: diff --git a/test/mitmproxy/test_flow.py b/test/mitmproxy/test_flow.py index a09ba852f..c6c8d20d6 100644 --- a/test/mitmproxy/test_flow.py +++ b/test/mitmproxy/test_flow.py @@ -34,7 +34,7 @@ class TestSerialize: def test_roundtrip(self): sio = io.BytesIO() f = tflow.tflow() - f.marked = True + f.marked = ":default:" f.request.content = bytes(range(256)) w = mitmproxy.io.FlowWriter(sio) w.add(f) diff --git a/test/mitmproxy/test_flowfilter.py b/test/mitmproxy/test_flowfilter.py index 7c6a93526..03c2eff61 100644 --- a/test/mitmproxy/test_flowfilter.py +++ b/test/mitmproxy/test_flowfilter.py @@ -1,9 +1,7 @@ import io import pytest from unittest.mock import patch - from mitmproxy.test import tflow - from mitmproxy import flowfilter, http @@ -144,9 +142,16 @@ class TestMatchingHTTPFlow: def test_fmarked(self): q = self.req() assert not self.q("~marked", q) - q.marked = True + q.marked = ":default:" assert self.q("~marked", q) + def test_fmarker_char(self): + t = tflow.tflow() + t.marked = ":default:" + assert not self.q("~marker X", t) + t.marked = 'X' + assert self.q("~marker X", t) + def test_head(self): q = self.req() s = self.resp() diff --git a/test/mitmproxy/test_types.py b/test/mitmproxy/test_types.py index 2cd17d87f..1df108f17 100644 --- a/test/mitmproxy/test_types.py +++ b/test/mitmproxy/test_types.py @@ -124,6 +124,25 @@ def test_cutspec(): assert len(ret) == len(b.valid_prefixes) +def test_marker(): + with taddons.context() as tctx: + b = mitmproxy.types._MarkerType() + assert b.parse(tctx.master.commands, mitmproxy.types.Marker, ":red_circle:") == ":red_circle:" + assert b.parse(tctx.master.commands, mitmproxy.types.Marker, "true") == ":default:" + assert b.parse(tctx.master.commands, mitmproxy.types.Marker, "false") == "" + + with pytest.raises(mitmproxy.exceptions.TypeError): + b.parse(tctx.master.commands, mitmproxy.types.Marker, ":bogus:") + + assert b.is_valid(tctx.master.commands, mitmproxy.types.Marker, "true") is True + assert b.is_valid(tctx.master.commands, mitmproxy.types.Marker, "false") is True + assert b.is_valid(tctx.master.commands, mitmproxy.types.Marker, "bogus") is False + assert b.is_valid(tctx.master.commands, mitmproxy.types.Marker, "X") is True + assert b.is_valid(tctx.master.commands, mitmproxy.types.Marker, ":red_circle:") is True + ret = b.completion(tctx.master.commands, mitmproxy.types.Marker, ":smil") + assert len(ret) > 10 + + def test_arg(): with taddons.context() as tctx: b = mitmproxy.types._ArgType() diff --git a/test/mitmproxy/utils/test_emoji.py b/test/mitmproxy/utils/test_emoji.py new file mode 100644 index 000000000..a147ba885 --- /dev/null +++ b/test/mitmproxy/utils/test_emoji.py @@ -0,0 +1,6 @@ +from mitmproxy.utils import emoji +from mitmproxy.tools.console.common import SYMBOL_MARK + + +def test_emoji(): + assert emoji.emoji[":default:"] == SYMBOL_MARK