Emoji Mode is a brand new feature that allows the server to automatically match and send corresponding emoji identifiers based on conversation content. Clients can display custom emoji animations, images, or other visual effects based on these identifiers.
EMOJI (Type Value = 9)false, true, dimi, dimi2, jfbAdd the emoji_mode parameter in the TCP authentication message:
##START[AUTH][task_id][seq]your_jwt_token##emoji_mode:true##END
Or in HTTP API (if you are using HTTP interface):
{
"emoji_mode": "true"
}
| Parameter Value | Description | Prompt Match | Answer Match | Matching Algorithm | Prompt with playSound |
|---|---|---|---|---|---|
false or not passed | Disable emoji function | ❌ | ❌ | - | - |
true | Answer-only matching | ❌ | ✅ | Sentiment Analysis | - |
dimi | Match both question and answer | ✅ | ✅ | Keyword Matching | ✅ playSound:1 |
dimi2 | Match both question and answer | ✅ | ✅ | Keyword Matching | ❌ |
jfb | Match both question and answer (5 emotion categories) | ✅ | ✅ | JFB Sentiment Analysis (angry/sad/hesitant/anxious/excited) | ❌ |
false if this parameter is not passedtrue/false and "true"/"false" are supportedMessageType.EMOJI = 9
##START + Header + JSON_Data + ##END
| Field | Length | Description |
|---|---|---|
| msg_type | 1 byte | Message Type = 9 |
| task_id | 8 bytes | Task ID (UTF-8 encoded) |
| seq | 4 bytes | Sequence Number (fixed as "0000") |
{
"emoji": "emoji_key"
}
Assuming task_id = abc12345, the matched emoji is happy:
##START[0x09][abc12345][0000]{"emoji":"happy"}##END
Binary representation:
0x23 0x23 0x53 0x54 0x41 0x52 0x54 // ##START (7 bytes)
0x09 // msg_type = 9 (1 byte)
0x61 0x62 0x63 0x31 0x32 0x33 0x34 0x35 // task_id = "abc12345" (8 bytes)
0x30 0x30 0x30 0x30 // seq = "0000" (4 bytes)
{"emoji":"happy"} // JSON data (variable length)
0x23 0x23 0x45 0x4E 0x44 // ##END (5 bytes)
Based on sentiment analysis algorithm, returns the following 20 emotion identifiers:
| Emoji Key | Description | Trigger Examples |
|---|---|---|
happy | Happy | "Great!" / "Awesome" |
laughing | Laughing | "HAHAHA" / "So funny" |
sad | Sad | "Feeling down" / "Disappointed" |
angry | Angry | "So mad" / "Hate it" |
crying | Crying | "Wanna cry" / "Sobbing" |
loving | Loving | "Love you" / "Like it" |
surprised | Surprised | "Oh my" / "Wow" |
shocked | Shocked | "Can't believe" / "Scared" |
thinking | Thinking | "?" / "Let me think" |
embarrassed | Embarrassed | "Sorry" / "Shy" |
winking | Winking | "You know what I mean" / "Naughty" |
cool | Cool | "Impressive" / "Awesome" |
relaxed | Relaxed | "Comfortable" / "Pleasant" |
delicious | Delicious | "Yummy" / "Tasty" |
kissy | Kiss | "Mua" / "Love kiss" |
confident | Confident | "Of course" / "Definitely" |
sleepy | Sleepy | "Good night" / "So tired" |
silly | Silly | "Silly goose" / "Dopey" |
confused | Confused | "Don't understand" / "Puzzled" |
funny | Funny | "Humorous" / "Hilarious" |
Based on keyword matching, supports a large number of scenario-based emojis, for example:
| Emoji Key | Keyword Examples |
|---|---|
hu_die | "go for a walk", "spring walk" |
sheng_bing | "sore throat", "喉咙痛" |
xia_yu | "after the rain", "下雨" |
bi_xin | "比心", "heart gesture" |
kai_hua | "peach blossoms", "开花" |
| ... | ... |
💡 Tip: Dimi mode supports mixed Chinese/English matching, prioritizing longer keywords.
Data file: emoji_service/JFB_emoji_mode.json, 5 categories total, no emoji sent if no match (returns None):
| Emoji Key | Description | Trigger Examples |
|---|---|---|
angry | Angry | "So mad" / "Hate it" |
sad | Sad | "Sad" / "Wanna cry" |
hesitant | Hesitant | "Don't know what to do" / "?" / "..." |
anxious | Anxious | "Worried" / "Nervous" |
excited | Excited | "Great!" / "Awesome" |
💡 Tip: JFB mode punctuation rules —
?alone →hesitant;...→hesitant;!+ positive content →excited;!+ negative content →angry.
import struct
import json
START_MARK = b'##START'
END_MARK = b'##END'
def parse_emoji_message(data):
"""Parse EMOJI message"""
if data.startswith(START_MARK) and data.endswith(END_MARK):
# Remove markers
frame = data[len(START_MARK):-len(END_MARK)]
# Parse header
msg_type = frame[0]
task_id = frame[1:9].decode('utf-8')
seq = frame[9:13].decode('utf-8')
# Check if it's an EMOJI message
if msg_type == 9:
# Parse JSON data
json_data = frame[13:].decode('utf-8')
emoji_info = json.loads(json_data)
return {
'type': 'emoji',
'task_id': task_id,
'emoji_key': emoji_info['emoji']
}
return None
# Usage Example
data = b'##START\x09abc123450000{"emoji":"happy"}##END'
result = parse_emoji_message(data)
print(result)
# Output: {'type': 'emoji', 'task_id': 'abc12345', 'emoji_key': 'happy'}
using System;
using System.Text;
using Newtonsoft.Json.Linq;
public class EmojiMessage
{
public string Type { get; set; }
public string TaskId { get; set; }
public string EmojiKey { get; set; }
}
public class MessageParser
{
private static readonly byte[] START_MARK = Encoding.UTF8.GetBytes("##START");
private static readonly byte[] END_MARK = Encoding.UTF8.GetBytes("##END");
public static EmojiMessage ParseEmojiMessage(byte[] data)
{
// Check start and end markers
if (!StartsWith(data, START_MARK) || !EndsWith(data, END_MARK))
return null;
// Extract frame data
int frameStart = START_MARK.Length;
int frameEnd = data.Length - END_MARK.Length;
// Parse message type
byte msgType = data[frameStart];
if (msgType != 9)
return null; // Not an EMOJI message
// Parse task_id (8 bytes)
string taskId = Encoding.UTF8.GetString(data, frameStart + 1, 8);
// Parse JSON data
int jsonStart = frameStart + 13; // 1 + 8 + 4
int jsonLength = frameEnd - jsonStart;
string jsonData = Encoding.UTF8.GetString(data, jsonStart, jsonLength);
// Parse JSON
JObject json = JObject.Parse(jsonData);
return new EmojiMessage
{
Type = "emoji",
TaskId = taskId,
EmojiKey = json["emoji"].ToString()
};
}
private static bool StartsWith(byte[] data, byte[] prefix)
{
if (data.Length < prefix.Length) return false;
for (int i = 0; i < prefix.Length; i++)
if (data[i] != prefix[i]) return false;
return true;
}
private static bool EndsWith(byte[] data, byte[] suffix)
{
if (data.Length < suffix.Length) return false;
int offset = data.Length - suffix.Length;
for (int i = 0; i < suffix.Length; i++)
if (data[offset + i] != suffix[i]) return false;
return true;
}
}
public class EmojiDisplay : MonoBehaviour
{
[SerializeField] private Dictionary<string, AnimationClip> emojiAnimations;
[SerializeField] private Animator characterAnimator;
public void ShowEmoji(string emojiKey)
{
if (emojiAnimations.ContainsKey(emojiKey))
{
// Play corresponding expression animation
characterAnimator.Play(emojiKey);
// Or show emoji icon
ShowEmojiIcon(emojiKey);
}
else
{
Debug.LogWarning($"Emoji not found: {emojiKey}");
}
}
private void ShowEmojiIcon(string emojiKey)
{
// Display expression bubble above character
// Implement your own display logic here
}
}
import socket
import threading
class TCPClient:
def __init__(self, host, port):
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sock.connect((host, port))
self.buffer = b""
def receive_loop(self):
"""Message receive loop"""
while True:
data = self.sock.recv(1024)
if not data:
break
self.buffer += data
# Process complete messages in buffer
while b'##END' in self.buffer:
frame, self.buffer = self.buffer.split(b'##END', 1)
if b'##START' in frame:
frame = frame[frame.index(b'##START'):]
frame += b'##END' # Add back the delimiter
# Parse message
self.handle_message(frame)
def handle_message(self, frame):
"""Handle single message"""
if len(frame) < 20:
return
msg_type = frame[7] # Skip ##START
if msg_type == 4: # TEXT
# Handle text message
self.handle_text(frame)
elif msg_type == 2: # AUDIO_FRAME
# Handle audio message
self.handle_audio(frame)
elif msg_type == 9: # EMOJI
# Handle emoji message
emoji_msg = parse_emoji_message(frame)
if emoji_msg:
print(f"Received emoji: {emoji_msg['emoji_key']}")
self.show_emoji(emoji_msg['emoji_key'])
def show_emoji(self, emoji_key):
"""Show emoji (implement by yourself)"""
pass
Client Server
| |
|----(1) Send AUTH------------------------------>|
| emoji_mode: true |
| |
|<---(2) Send AUTH Success-------------------------|
| |
|----(3) Send User Input-------------------------->|
| "Hello!" |
| |
|<---(4) TEXT: "Hello!"----------------------------|
|<---(5) EMOJI: "happy"---------------------------| ← Answer-only matching
|<---(6) TEXT: "Nice to meet you"-----------------|
|<---(7) EMOJI: "happy"---------------------------|
|<---(8) END_FRAME--------------------------------|
Client Server
| |
|----(1) Send AUTH------------------------------>|
| emoji_mode: dimi |
| |
|<---(2) Send AUTH Success-------------------------|
| |
|----(3) Send User Input-------------------------->|
| "It's raining today" |
| |
|<---(4) EMOJI: "xia_yu"---------------------------| ← Matches question
|<---(5) TEXT: "Remember to bring an umbrella"---|
|<---(6) EMOJI: "care"---------------------------| ← Matches answer
|<---(7) END_FRAME--------------------------------|
{
"emotion_keywords": {
"happy": [
"开心", "高兴", "快乐", "愉快", "幸福", "满意", "棒", "好", "不错",
"完美", "棒极了", "太好了", "好呀", "好的",
"happy", "joy", "great", "good", "nice", "awesome", "fantastic", "wonderful"
],
"laughing": [
"哈哈", "哈哈哈", "呵呵", "嘿嘿", "嘻嘻", "笑死", "太好笑了", "笑死我了",
"lol", "lmao", "haha", "hahaha", "hehe", "rofl", "funny", "laugh"
],
"funny": [
"搞笑", "滑稽", "逗", "幽默", "笑点", "段子", "笑话", "太逗了",
"hilarious", "joke", "comedy"
],
"sad": [
"伤心", "难过", "悲哀", "悲伤", "忧郁", "郁闷", "沮丧", "失望",
"想哭", "难受", "不开心", "唉", "呜呜",
"sad", "upset", "unhappy", "depressed", "sorrow", "gloomy"
],
"angry": [
"生气", "愤怒", "气死", "讨厌", "烦人", "可恶", "烦死了", "恼火",
"暴躁", "火大", "气炸了",
"angry", "mad", "annoyed", "furious", "pissed", "hate"
],
"crying": [
"哭泣", "泪流", "大哭", "伤心欲绝", "泪目", "流泪", "哭死", "哭晕",
"想哭", "泪崩",
"cry", "crying", "tears", "sob", "weep"
],
"loving": [
"爱你", "喜欢", "爱", "亲爱的", "宝贝", "么么哒", "抱抱", "想你",
"思念", "最爱", "亲亲", "喜欢你",
"love", "like", "adore", "darling", "sweetie", "honey", "miss you", "heart"
],
"embarrassed": [
"尴尬", "不好意思", "害羞", "脸红", "难为情", "社死", "丢脸", "出丑",
"embarrassed", "awkward", "shy", "blush"
],
"surprised": [
"惊讶", "吃惊", "天啊", "哇塞", "哇", "居然", "竟然", "没想到", "出乎意料",
"surprise", "wow", "omg", "oh my god", "amazing", "unbelievable"
],
"shocked": [
"震惊", "吓到", "惊呆了", "不敢相信", "震撼", "吓死", "恐怖", "害怕", "吓人",
"shocked", "shocking", "scared", "frightened", "terrified", "horror"
],
"thinking": [
"思考", "考虑", "想一下", "琢磨", "沉思", "冥想", "想", "思考中", "在想",
"think", "thinking", "consider", "ponder", "meditate"
],
"winking": [
"调皮", "眨眼", "你懂的", "坏笑", "邪恶", "奸笑", "使眼色",
"wink", "teasing", "naughty", "mischievous"
],
"cool": [
"酷", "帅", "厉害", "棒极了", "真棒", "牛逼", "强", "优秀", "杰出", "出色",
"cool", "awesome", "amazing", "great", "impressive", "perfect"
],
"relaxed": [
"放松", "舒服", "惬意", "悠闲", "轻松", "舒适", "安逸", "自在",
"relax", "relaxed", "comfortable", "cozy", "chill", "peaceful"
],
"delicious": [
"好吃", "美味", "香", "馋", "可口", "香甜", "大餐", "大快朵颐", "流口水", "垂涎",
"delicious", "yummy", "tasty", "yum", "appetizing", "mouthwatering"
],
"kissy": [
"亲亲", "么么", "吻", "mua", "muah", "亲一下", "飞吻",
"kiss", "xoxo", "hug", "smooch"
],
"confident": [
"自信", "肯定", "确定", "毫无疑问", "当然", "必须的", "确信", "坚信",
"confident", "sure", "certain", "definitely", "positive"
],
"sleepy": [
"困", "睡觉", "晚安", "想睡", "好累", "疲惫", "疲倦", "困了", "想休息", "睡意",
"sleep", "sleepy", "tired", "exhausted", "bedtime", "good night"
],
"silly": [
"傻", "笨", "呆", "憨", "蠢", "二", "憨憨", "傻乎乎", "呆萌",
"silly", "stupid", "dumb", "foolish", "goofy", "ridiculous"
],
"confused": [
"疑惑", "不明白", "不懂", "困惑", "疑问", "为什么", "怎么回事", "啥意思", "不清楚",
"confused", "puzzled", "doubt", "question", "what", "why", "how"
]
},
"special_phrases": [
{
"phrases": [
"你真", "你好", "您真", "你真棒", "你好厉害", "你太强了", "你真好", "你真聪明",
"you are", "you're", "you look", "you seem", "so smart", "so kind"
],
"emotion": "loving"
},
{
"phrases": [
"我真", "我最", "我太棒了", "我厉害", "我聪明", "我优秀",
"i am", "i'm", "i feel", "so good", "so happy"
],
"emotion": "cool"
},
{
"phrases": [
"睡觉", "晚安", "睡了", "好梦", "休息了", "去睡了",
"sleep", "good night", "bedtime", "go to bed"
],
"emotion": "sleepy"
}
],
"punctuation_rules": {
"question_only": "thinking",
"ellipsis": "thinking",
"exclamation_positive": {
"match_emotions": ["happy", "laughing", "cool"],
"result": "laughing"
},
"exclamation_negative": {
"match_emotions": ["angry", "sad", "crying"],
"result": "angry"
},
"exclamation_default": "surprised"
},
"priority_order": [
"laughing", "crying", "angry", "surprised", "shocked",
"loving", "happy", "funny", "cool",
"sad", "embarrassed", "confused",
"thinking", "winking", "relaxed",
"delicious", "kissy", "confident", "sleepy", "silly"
],
"default_emotion": "happy",
"long_text_threshold": 20,
"long_text_repeat_weight": 0.5
}
{
"emotion_keywords": {
"happy": [
"开心", "高兴", "快乐", "愉快", "幸福", "满意", "棒", "好", "不错",
"完美", "棒极了", "太好了", "好呀", "好的",
"happy", "joy", "great", "good", "nice", "awesome", "fantastic", "wonderful"
],
"laughing": [
"哈哈", "哈哈哈", "呵呵", "嘿嘿", "嘻嘻", "笑死", "太好笑了", "笑死我了",
"lol", "lmao", "haha", "hahaha", "hehe", "rofl", "funny", "laugh"
],
"funny": [
"搞笑", "滑稽", "逗", "幽默", "笑点", "段子", "笑话", "太逗了",
"hilarious", "joke", "comedy"
],
"sad": [
"伤心", "难过", "悲哀", "悲伤", "忧郁", "郁闷", "沮丧", "失望",
"想哭", "难受", "不开心", "唉", "呜呜",
"sad", "upset", "unhappy", "depressed", "sorrow", "gloomy"
],
"angry": [
"生气", "愤怒", "气死", "讨厌", "烦人", "可恶", "烦死了", "恼火",
"暴躁", "火大", "气炸了",
"angry", "mad", "annoyed", "furious", "pissed", "hate"
],
"crying": [
"哭泣", "泪流", "大哭", "伤心欲绝", "泪目", "流泪", "哭死", "哭晕",
"想哭", "泪崩",
"cry", "crying", "tears", "sob", "weep"
],
"loving": [
"爱你", "喜欢", "爱", "亲爱的", "宝贝", "么么哒", "抱抱", "想你",
"思念", "最爱", "亲亲", "喜欢你",
"love", "like", "adore", "darling", "sweetie", "honey", "miss you", "heart"
],
"embarrassed": [
"尴尬", "不好意思", "害羞", "脸红", "难为情", "社死", "丢脸", "出丑",
"embarrassed", "awkward", "shy", "blush"
],
"surprised": [
"惊讶", "吃惊", "天啊", "哇塞", "哇", "居然", "竟然", "没想到", "出乎意料",
"surprise", "wow", "omg", "oh my god", "amazing", "unbelievable"
],
"shocked": [
"震惊", "吓到", "惊呆了", "不敢相信", "震撼", "吓死", "恐怖", "害怕", "吓人",
"shocked", "shocking", "scared", "frightened", "terrified", "horror"
],
"thinking": [
"思考", "考虑", "想一下", "琢磨", "沉思", "冥想", "想", "思考中", "在想",
"think", "thinking", "consider", "ponder", "meditate"
],
"winking": [
"调皮", "眨眼", "你懂的", "坏笑", "邪恶", "奸笑", "使眼色",
"wink", "teasing", "naughty", "mischievous"
],
"cool": [
"酷", "帅", "厉害", "棒极了", "真棒", "牛逼", "强", "优秀", "杰出", "出色",
"cool", "awesome", "amazing", "great", "impressive", "perfect"
],
"relaxed": [
"放松", "舒服", "惬意", "悠闲", "轻松", "舒适", "安逸", "自在",
"relax", "relaxed", "comfortable", "cozy", "chill", "peaceful"
],
"delicious": [
"好吃", "美味", "香", "馋", "可口", "香甜", "大餐", "大快朵颐", "流口水", "垂涎",
"delicious", "yummy", "tasty", "yum", "appetizing", "mouthwatering"
],
"kissy": [
"亲亲", "么么", "吻", "mua", "muah", "亲一下", "飞吻",
"kiss", "xoxo", "hug", "smooch"
],
"confident": [
"自信", "肯定", "确定", "毫无疑问", "当然", "必须的", "确信", "坚信",
"confident", "sure", "certain", "definitely", "positive"
],
"sleepy": [
"困", "睡觉", "晚安", "想睡", "好累", "疲惫", "疲倦", "困了", "想休息", "睡意",
"sleep", "sleepy", "tired", "exhausted", "bedtime", "good night"
],
"silly": [
"傻", "笨", "呆", "憨", "蠢", "二", "憨憨", "傻乎乎", "呆萌",
"silly", "stupid", "dumb", "foolish", "goofy", "ridiculous"
],
"confused": [
"疑惑", "不明白", "不懂", "困惑", "疑问", "为什么", "怎么回事", "啥意思", "不清楚",
"confused", "puzzled", "doubt", "question", "what", "why", "how"
]
},
"special_phrases": [
{
"phrases": [
"你真", "你好", "您真", "你真棒", "你好厉害", "你太强了", "你真好", "你真聪明",
"you are", "you're", "you look", "you seem", "so smart", "so kind"
],
"emotion": "loving"
},
{
"phrases": [
"我真", "我最", "我太棒了", "我厉害", "我聪明", "我优秀",
"i am", "i'm", "i feel", "so good", "so happy"
],
"emotion": "cool"
},
{
"phrases": [
"睡觉", "晚安", "睡了", "好梦", "休息了", "去睡了",
"sleep", "good night", "bedtime", "go to bed"
],
"emotion": "sleepy"
}
],
"punctuation_rules": {
"question_only": "thinking",
"ellipsis": "thinking",
"exclamation_positive": {
"match_emotions": ["happy", "laughing", "cool"],
"result": "laughing"
},
"exclamation_negative": {
"match_emotions": ["angry", "sad", "crying"],
"result": "angry"
},
"exclamation_default": "surprised"
},
"priority_order": [
"laughing", "crying", "angry", "surprised", "shocked",
"loving", "happy", "funny", "cool",
"sad", "embarrassed", "confused",
"thinking", "winking", "relaxed",
"delicious", "kissy", "confident", "sleepy", "silly"
],
"default_emotion": "happy",
"long_text_threshold": 20,
"long_text_repeat_weight": 0.5
}
try:
emoji_msg = parse_emoji_message(frame)
if emoji_msg:
show_emoji(emoji_msg['emoji_key'])
except Exception as e:
logging.warning(f"Failed to parse emoji message: {e}")
# Ignore error and continue processing other messages
# Test cases
test_cases = [
("false", "Hello", 0), # Expect 0 emojis
("true", "HAHAHA, so funny!", 1), # Expect 1 emoji
("dimi", "Today is 666", 2), # Expect 2 emojis (question+answer)
]
for emoji_mode, input_text, expected_emoji_count in test_cases:
# Send AUTH (set emoji_mode)
# Send input
# Count received EMOJI messages
# Verify if it matches expectation
A: Check the following:
emoji_mode parameter was passed during authentication and is not falseA:
A:
playSound:1)playSoundplaySoundA: Client maintains an emoji_key → animation/image mapping table:
{
"happy": "happy_animation.anim",
"laughing": "laugh_animation.anim",
"xia_yu": "rain_icon.png"
}
A:
happy, xia_yu, tai_hao_xiaoFor questions, please contact the technical support team or refer to the complete protocol documentation.