@@ -32,6 +32,11 @@ public Description getCommentText() throws ParsingException {
3232 return new Description (text , Description .PLAIN_TEXT );
3333 }
3434
35+ /**
36+ * Extracts text from a live chat message, handling both regular text and emojis.
37+ * YouTube live chat messages use {@code runs} array where each element has either
38+ * {@code text} or {@code emoji}.
39+ */
3540 @ Nonnull
3641 private static String extractChatMessageText (final JsonObject message ) {
3742 if (message == null || message .isEmpty ()) {
@@ -51,20 +56,65 @@ private static String extractChatMessageText(final JsonObject message) {
5156 for (int i = 0 ; i < runs .size (); i ++) {
5257 final JsonObject run = runs .getObject (i );
5358 if (run .has ("text" )) {
54- textBuilder .append (run .getString ("text" , "" ));
59+ final String text = run .getString ("text" , "" );
60+ textBuilder .append (text );
5561 } else if (run .has ("emoji" )) {
5662 final JsonObject emoji = run .getObject ("emoji" );
57- if (emoji .has ("emojiId" )) {
58- textBuilder .append (emoji .getString ("emojiId" , "" ));
59- } else {
60- textBuilder .append ("[emoji]" );
63+ final String emojiText = extractEmojiText (emoji );
64+ if (emojiText != null ) {
65+ textBuilder .append (emojiText );
6166 }
6267 }
6368 }
6469
6570 return textBuilder .toString ();
6671 }
6772
73+ /**
74+ * Extracts a textual representation of a YouTube live chat emoji.
75+ * For standard emojis, {@code emojiId} contains the Unicode character.
76+ * For custom emojis, uses the first shortcut (e.g. {@code :wave:}) if available.
77+ */
78+ @ Nonnull
79+ private static String extractEmojiText (final JsonObject emoji ) {
80+ if (emoji == null || emoji .isEmpty ()) {
81+ return "" ;
82+ }
83+
84+ // For standard emojis, emojiId is the Unicode character itself.
85+ // For custom emojis it is an ID, but still better than nothing.
86+ if (emoji .has ("emojiId" )) {
87+ final String emojiId = emoji .getString ("emojiId" , "" );
88+ if (!emojiId .isEmpty ()) {
89+ return emojiId ;
90+ }
91+ }
92+
93+ // Try to get shortcuts like ":wave:", ":heart:", ":face-blue-smiling:"
94+ if (emoji .has ("shortcuts" )) {
95+ final JsonArray shortcuts = emoji .getArray ("shortcuts" );
96+ for (int i = 0 ; i < shortcuts .size (); i ++) {
97+ final String shortcut = shortcuts .getString (i , "" );
98+ if (!shortcut .isEmpty ()) {
99+ return shortcut ;
100+ }
101+ }
102+ }
103+
104+ // Fallback: try searchTerms
105+ if (emoji .has ("searchTerms" )) {
106+ final JsonArray searchTerms = emoji .getArray ("searchTerms" );
107+ for (int i = 0 ; i < searchTerms .size (); i ++) {
108+ final String term = searchTerms .getString (i , "" );
109+ if (!term .isEmpty ()) {
110+ return ":" + term + ":" ;
111+ }
112+ }
113+ }
114+
115+ return "[emoji]" ;
116+ }
117+
68118 @ Override
69119 public String getCommentId () throws ParsingException {
70120 return chatMessage .getString ("id" , "" );
0 commit comments