From 2e0851f7f7963fbdef5fa9d2b82d1edf6b246580 Mon Sep 17 00:00:00 2001 From: Max Baumann Date: Sun, 25 Aug 2024 18:14:27 +0200 Subject: [PATCH] final fixes --- mod/app/src/main/java/bttv/Tokenizer.java | 122 ++++++++++++++++++ .../java/tv/twitch/chat/ChatMessageInfo.java | 6 + .../chat/library/model/ChatMessageInfo.java | 1 - ...ry.SubNoticeChatMessageFactory.smali.patch | 4 +- ....library.model.ChatMessageInfo.smali.patch | 2 +- 5 files changed, 130 insertions(+), 5 deletions(-) create mode 100644 mod/twitch/src/main/java/tv/twitch/chat/ChatMessageInfo.java diff --git a/mod/app/src/main/java/bttv/Tokenizer.java b/mod/app/src/main/java/bttv/Tokenizer.java index b6c39c5f..3706a44e 100644 --- a/mod/app/src/main/java/bttv/Tokenizer.java +++ b/mod/app/src/main/java/bttv/Tokenizer.java @@ -20,6 +20,11 @@ import tv.twitch.android.shared.chat.pub.model.messages.MessageToken.EmoticonToken; import tv.twitch.android.shared.chat.pub.messages.ui.ChatMessageInterface; import tv.twitch.android.shared.chat.ChatMessageDelegate; +import tv.twitch.chat.AutoModFlags; +import tv.twitch.chat.ChatEmoticonToken; +import tv.twitch.chat.ChatMessageToken; +import tv.twitch.chat.ChatMessageTokenType; +import tv.twitch.chat.ChatTextToken; import tv.twitch.chat.library.model.ChatMessageInfo; public class Tokenizer { @@ -102,6 +107,95 @@ public static void retokenizeLiveChatMessage(ChatMessageInterface chatMessageInt } } + /** @noinspection unused */ + public static void retokenizeLiveChatMessage(tv.twitch.chat.ChatMessageInfo info) { + try { + Context ctx = Data.ctx; + int channel = Data.currentBroadcasterId; + + ArrayList newTokens = new ArrayList<>(info.tokens.length + 10); + + boolean shouldHighlight = false; + boolean shouldBlock = false; + + for (tv.twitch.chat.ChatMessageToken token : info.tokens) { + Log.d("LBTTV", "retokenizeLiveChatMessage: " + token); + if (!isTextTokenOld(token)) { + if (isEmoteTokenOld(token) && !newTokens.isEmpty()) { + tv.twitch.chat.ChatMessageToken prevToken = newTokens.get(newTokens.size() - 1); + if (prevToken != null && !endsWithSpaceOld(prevToken)) { + ChatTextToken spaceToken = new ChatTextToken(); + spaceToken.text = " "; + spaceToken.autoModFlags = new AutoModFlags(); + newTokens.add(spaceToken); + } + } + newTokens.add(token); + continue; + } + + ChatTextToken textToken = (ChatTextToken) token; + String text = textToken.text; + + if (text.equals(" ")) { + // " ".split(" ") will produce an empty array + // this is why we need to handle this edge-case + newTokens.add(textToken); + continue; + } + String[] tokens = text.split(" "); + + StringBuilder currentText = new StringBuilder(); + for (String word : tokens) { + if (Blacklist.shouldBlock(word)) { + shouldBlock = true; + } + if (Highlight.shouldHighlight(word)) { + shouldHighlight = true; + } + Emote emote = Emotes.getEmote(ctx, word, channel); + if (emote == null) { + currentText.append(word).append(" "); + continue; + } + // emote found + String before = currentText.toString(); + if (!before.isEmpty()) { + ChatTextToken everythingBeforeEmote = new ChatTextToken(); + everythingBeforeEmote.text = before; + everythingBeforeEmote.autoModFlags = textToken.autoModFlags; + newTokens.add(everythingBeforeEmote); + } + ChatEmoticonToken emoteToken = new ChatEmoticonToken(); + emoteToken.emoticonText = word; + emoteToken.emoticonId = "BTTV-" + emote.id; + newTokens.add(emoteToken); + + // prepare next TextToken + currentText.setLength(0); + currentText.append(' '); + } + String before = currentText.toString(); + if (!before.trim().isEmpty()) { + ChatTextToken everything = new ChatTextToken(); + everything.text = before; + everything.autoModFlags = textToken.autoModFlags; + newTokens.add(everything); + } + } + + info.tokens = newTokens.toArray(new ChatMessageToken[0]); + + if (shouldBlock) { + info.messageType = "bttv-blocked-message"; + } else if (shouldHighlight) { + info.messageType = "bttv-highlighted-message"; + } + } catch (Throwable throwable) { + Log.e("LBTTV", "retokenizeLiveChatMessage: " + throwable.getMessage()); + } + } + public static void retokenizeLiveChatMessage(ChatMessageInfo info) { Context ctx = Data.ctx; int channel = Data.currentBroadcasterId; @@ -196,6 +290,19 @@ private static boolean endsWithSpace(@NotNull tv.twitch.chat.library.model.Messa return lastChar == ' '; } + private static boolean endsWithSpaceOld(@NotNull tv.twitch.chat.ChatMessageToken token) { + if (token.type.getValue() != ChatMessageTokenType.Text.getValue()) { + return false; + } + ChatTextToken textToken = (ChatTextToken) token; + String text = textToken.text; + if (text.isEmpty()) { + return false; + } + char lastChar = text.charAt(text.length() - 1); + return lastChar == ' '; + } + private static boolean isTextToken(tv.twitch.chat.library.model.MessageToken token) { if (token == null) { return false; @@ -203,10 +310,25 @@ private static boolean isTextToken(tv.twitch.chat.library.model.MessageToken tok return token instanceof tv.twitch.chat.library.model.MessageToken.TextToken; } + private static boolean isTextTokenOld(tv.twitch.chat.ChatMessageToken token) { + if (token == null) { + return false; + } + return token.type.getValue() == ChatMessageTokenType.Text.getValue(); + } + + private static boolean isEmoteToken(tv.twitch.chat.library.model.MessageToken token) { if (token == null) { return false; } return token instanceof tv.twitch.chat.library.model.MessageToken.EmoteToken; } + + private static boolean isEmoteTokenOld(tv.twitch.chat.ChatMessageToken token) { + if (token == null) { + return false; + } + return token.type.getValue() == ChatMessageTokenType.Emoticon.getValue(); + } } diff --git a/mod/twitch/src/main/java/tv/twitch/chat/ChatMessageInfo.java b/mod/twitch/src/main/java/tv/twitch/chat/ChatMessageInfo.java new file mode 100644 index 00000000..d7d572c9 --- /dev/null +++ b/mod/twitch/src/main/java/tv/twitch/chat/ChatMessageInfo.java @@ -0,0 +1,6 @@ +package tv.twitch.chat; + +public class ChatMessageInfo { + public tv.twitch.chat.ChatMessageToken[] tokens; + public String messageType; +} diff --git a/mod/twitch/src/main/java/tv/twitch/chat/library/model/ChatMessageInfo.java b/mod/twitch/src/main/java/tv/twitch/chat/library/model/ChatMessageInfo.java index 6b09ba26..660ee9a3 100644 --- a/mod/twitch/src/main/java/tv/twitch/chat/library/model/ChatMessageInfo.java +++ b/mod/twitch/src/main/java/tv/twitch/chat/library/model/ChatMessageInfo.java @@ -5,7 +5,6 @@ package tv.twitch.chat.library.model; import java.util.List; -import java.util.Map; public class ChatMessageInfo { public List tokens; diff --git a/patches/emotes/tv.twitch.android.shared.chat.messagefactory.SubNoticeChatMessageFactory.smali.patch b/patches/emotes/tv.twitch.android.shared.chat.messagefactory.SubNoticeChatMessageFactory.smali.patch index 1b1d5f22..5226aaac 100644 --- a/patches/emotes/tv.twitch.android.shared.chat.messagefactory.SubNoticeChatMessageFactory.smali.patch +++ b/patches/emotes/tv.twitch.android.shared.chat.messagefactory.SubNoticeChatMessageFactory.smali.patch @@ -1,14 +1,12 @@ diff --git a/smali_classes6/tv/twitch/android/shared/chat/messagefactory/SubNoticeChatMessageFactory.smali b/smali_classes6/tv/twitch/android/shared/chat/messagefactory/SubNoticeChatMessageFactory.smali --- a/smali_classes6/tv/twitch/android/shared/chat/messagefactory/SubNoticeChatMessageFactory.smali +++ b/smali_classes6/tv/twitch/android/shared/chat/messagefactory/SubNoticeChatMessageFactory.smali -@@ -318,6 +318,13 @@ +@@ -318,6 +318,11 @@ .line 62 iget-object v4, v1, Ltv/twitch/chat/ChatSubscriptionNotice;->userMessage:Ltv/twitch/chat/ChatMessageInfo; + # BTTV + # Add bttv emotes -+ # expects: -+ # v4: tv.twitch.chat.ChatMessageInfo + invoke-static {v4}, Lbttv/Tokenizer;->retokenizeLiveChatMessage(Ltv/twitch/chat/ChatMessageInfo;)V + # /BTTV + diff --git a/patches/tv.twitch.chat.library.model.ChatMessageInfo.smali.patch b/patches/tv.twitch.chat.library.model.ChatMessageInfo.smali.patch index c9f2666b..be5b7820 100644 --- a/patches/tv.twitch.chat.library.model.ChatMessageInfo.smali.patch +++ b/patches/tv.twitch.chat.library.model.ChatMessageInfo.smali.patch @@ -13,7 +13,7 @@ diff --git a/smali_classes8/tv/twitch/chat/library/model/ChatMessageInfo.smali b .field private final timestamp:Ljava/lang/Long; -.field private final tokens:Ljava/util/List; -+.field public final tokens:Ljava/util/List; ++.field public tokens:Ljava/util/List; .annotation system Ldalvik/annotation/Signature; value = { "Ljava/util/List<",