From 2d6111ef4d8e87bed508ad2aa14b574f38a44a0a Mon Sep 17 00:00:00 2001 From: JW Date: Thu, 12 Oct 2023 03:41:36 +0200 Subject: [PATCH] Breaking changes: 'Gift': changed from class to enum, so now you can handle incoming gifts in switch `Events` - new: onGiftComboFinished - Removed: onGiftBrodcast - Rename: onGiftMessage -> onGift onRoomPinMessage -> onRoomPin onRoomMessage -> onRoom onLinkMessage -> onLink onBarrageMessage -> onBarrage onPollMessage -> onPoll onShopMessage -> onShop onDetectMessage -> onDetect `GiftManager` added: registerGift findById findByName getGifts removed: getActiveGifts --- API/pom.xml | 19 ++++ .../github/jwdeveloper/tiktok/Constants.java | 1 + .../data/events/common/TikTokEmptyEvent.java | 10 ++ .../data/events/common/TikTokEvent.java | 4 +- .../events/gift/TikTokGiftComboEvent.java | 26 ++++- .../data/events/gift/TikTokGiftEvent.java | 14 ++- .../TikTokWebsocketMessageEvent.java | 11 ++ .../jwdeveloper/tiktok/data/models/Text.java | 7 +- .../tiktok/data/models/{ => gifts}/Gift.java | 3 +- .../data/models/gifts/GiftSendType.java | 18 ++++ .../tiktok/data/models/users/User.java | 3 - .../tiktok/handler/TikTokMessageHandler.java | 4 +- .../jwdeveloper/tiktok/live/GiftManager.java | 2 +- .../jwdeveloper/tiktok/live/TrackedUser.java | 2 +- .../tiktok/live/builder/EventsBuilder.java | 1 - .../jwdeveloper/tiktok/utils/Stopwatch.java | 20 ++++ Client/pom.xml | 2 +- .../tiktok/TikTokLiveClientBuilder.java | 10 +- .../tiktok/gifts/TikTokGiftManager.java | 2 +- .../tiktok/handlers/TikTokMessageHandler.java | 64 ++++-------- .../TikTokMessageHandlerRegistration.java | 55 +++------- .../events/TikTokGiftEventHandler.java | 86 +++++++++++++++ .../tiktok/http/TikTokHttpClient.java | 10 +- .../mappers/TikTokGenericEventMapper.java | 85 +++++++++++++++ .../websocket/TikTokWebSocketListener.java | 2 +- .../websocket/TikTokWebSocketPingingTask.java | 3 +- .../tiktok/gifts/TikTokGiftManagerTest.java | 2 +- Examples/pom.xml | 2 +- .../jwdeveloper/tiktok/SimpleExample$1.class | Bin 855 -> 879 bytes .../tiktok/tools/collector/RunCollector.java | 49 +++++++-- .../collector/client/MessageCollector.java | 2 +- .../collector/client/TikTokClientFactory.java | 15 ++- .../TikTokMessagessCollectorBuilder.java | 2 +- .../tiktok/tools/tester/RunJsonTester.java | 10 +- .../tiktok/tools/collector/RunCollector.class | Bin 1118 -> 5206 bytes .../jwdeveloper/tiktok/webviewer/Main.java | 1 + .../tiktok/webviewer/TikTokManager.java | 52 ++++++++-- .../webviewer/handlers/TikTokHandler.java | 21 +++- .../src/main/resources/public/index.html | 48 +++++++-- .../jwdeveloper/tiktok/CodeExample.java | 98 ++++++++++++++++++ .../tiktok/EventsInfoGenerator.java | 2 +- .../src/main/resources/template.md | 39 +++++-- .../tiktok/mockClient/TikTokMockBuilder.java | 8 +- .../mockClient/mocks/WebsocketClientMock.java | 7 +- .../tiktok/mockClient/TikTokMockBuilder.class | Bin 6456 -> 6756 bytes .../mocks/WebsocketClientMock$MsgStruct.class | Bin 2120 -> 2120 bytes .../mocks/WebsocketClientMock.class | Bin 5864 -> 6518 bytes pom.xml | 15 +-- 48 files changed, 657 insertions(+), 180 deletions(-) create mode 100644 API/src/main/java/io/github/jwdeveloper/tiktok/data/events/common/TikTokEmptyEvent.java rename API/src/main/java/io/github/jwdeveloper/tiktok/data/models/{ => gifts}/Gift.java (99%) create mode 100644 API/src/main/java/io/github/jwdeveloper/tiktok/data/models/gifts/GiftSendType.java create mode 100644 API/src/main/java/io/github/jwdeveloper/tiktok/utils/Stopwatch.java create mode 100644 Client/src/main/java/io/github/jwdeveloper/tiktok/handlers/events/TikTokGiftEventHandler.java create mode 100644 Client/src/main/java/io/github/jwdeveloper/tiktok/mappers/TikTokGenericEventMapper.java create mode 100644 Tools-ReadmeGenerator/src/main/java/io/github/jwdeveloper/tiktok/CodeExample.java diff --git a/API/pom.xml b/API/pom.xml index 18fd420..97f494f 100644 --- a/API/pom.xml +++ b/API/pom.xml @@ -58,6 +58,25 @@ + + org.apache.maven.plugins + maven-javadoc-plugin + 3.3.0 + + + attach-javadocs + package + + jar + + + -html,-syntax,-accessibility,-missing + false + true + + + + \ No newline at end of file diff --git a/API/src/main/java/io/github/jwdeveloper/tiktok/Constants.java b/API/src/main/java/io/github/jwdeveloper/tiktok/Constants.java index a2dcf50..a2236fd 100644 --- a/API/src/main/java/io/github/jwdeveloper/tiktok/Constants.java +++ b/API/src/main/java/io/github/jwdeveloper/tiktok/Constants.java @@ -116,6 +116,7 @@ public class Constants { public static Map DefaultRequestHeaders() { var headers = new HashMap(); + headers.put("authority","www.tiktok.com"); headers.put("Connection", "keep-alive"); headers.put("Cache-Control", "max-age=0"); headers.put("Accept", "text/html,application/json,application/protobuf"); diff --git a/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/common/TikTokEmptyEvent.java b/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/common/TikTokEmptyEvent.java new file mode 100644 index 0000000..bb51d4e --- /dev/null +++ b/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/common/TikTokEmptyEvent.java @@ -0,0 +1,10 @@ +package io.github.jwdeveloper.tiktok.data.events.common; + + +/** + * + */ +public class TikTokEmptyEvent extends TikTokEvent +{ + +} diff --git a/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/common/TikTokEvent.java b/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/common/TikTokEvent.java index 3e36636..1c01ec5 100644 --- a/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/common/TikTokEvent.java +++ b/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/common/TikTokEvent.java @@ -26,8 +26,8 @@ package io.github.jwdeveloper.tiktok.data.events.common; import io.github.jwdeveloper.tiktok.utils.JsonUtil; import lombok.Getter; -/* - Base class for all events +/** + * Base class for all events */ @Getter public abstract class TikTokEvent { diff --git a/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/gift/TikTokGiftComboEvent.java b/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/gift/TikTokGiftComboEvent.java index 439cd26..2363fbe 100644 --- a/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/gift/TikTokGiftComboEvent.java +++ b/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/gift/TikTokGiftComboEvent.java @@ -24,16 +24,32 @@ package io.github.jwdeveloper.tiktok.data.events.gift; import io.github.jwdeveloper.tiktok.annotations.EventMeta; import io.github.jwdeveloper.tiktok.annotations.EventType; -import io.github.jwdeveloper.tiktok.data.models.Gift; - +import io.github.jwdeveloper.tiktok.data.models.gifts.Gift; +import io.github.jwdeveloper.tiktok.data.models.gifts.GiftSendType; import io.github.jwdeveloper.tiktok.messages.webcast.WebcastGiftMessage; import lombok.Getter; + +/** + * Triggered every time gift is sent + * + * @see GiftSendType it has 3 states + * + * Example when user sends gift with combo + * Combo: 1 -> comboState = GiftSendType.Begin + * Combo: 4 -> comboState = GiftSendType.Active + * Combo: 8 -> comboState = GiftSendType.Active + * Combo: 12 -> comboState = GiftSendType.Finsihed + * + * Remember if comboState is Finsihed both TikTokGiftComboEvent and TikTokGiftEvent event gets triggered + */ @EventMeta(eventType = EventType.Message) @Getter -public class TikTokGiftComboEvent extends TikTokGiftEvent -{ - public TikTokGiftComboEvent(Gift gift, WebcastGiftMessage msg) { +public class TikTokGiftComboEvent extends TikTokGiftEvent { + private final GiftSendType comboState; + + public TikTokGiftComboEvent(Gift gift, WebcastGiftMessage msg, GiftSendType comboState) { super(gift, msg); + this.comboState = comboState; } } diff --git a/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/gift/TikTokGiftEvent.java b/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/gift/TikTokGiftEvent.java index a95f8f7..d3a2ff8 100644 --- a/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/gift/TikTokGiftEvent.java +++ b/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/gift/TikTokGiftEvent.java @@ -26,14 +26,17 @@ package io.github.jwdeveloper.tiktok.data.events.gift; import io.github.jwdeveloper.tiktok.annotations.EventMeta; import io.github.jwdeveloper.tiktok.annotations.EventType; import io.github.jwdeveloper.tiktok.data.events.common.TikTokHeaderEvent; -import io.github.jwdeveloper.tiktok.data.models.Gift; +import io.github.jwdeveloper.tiktok.data.models.gifts.Gift; +import io.github.jwdeveloper.tiktok.data.models.gifts.GiftSendType; import io.github.jwdeveloper.tiktok.data.models.users.User; import io.github.jwdeveloper.tiktok.messages.webcast.WebcastGiftMessage; import lombok.Getter; /* - * Triggered every time a gift arrives. + * Triggered when user sends gifts that has + * no combo (most of expensive gifts) + * or if combo has finished */ @EventMeta(eventType = EventType.Message) @Getter @@ -41,15 +44,10 @@ public class TikTokGiftEvent extends TikTokHeaderEvent { private final Gift gift; private final User user; private final int combo; - private final boolean comboFinished; - private final int comboIndex; - public TikTokGiftEvent(Gift gift, WebcastGiftMessage msg) { super(msg.getCommon()); this.gift = gift; - user = User.map(msg.getUser(),msg.getUserIdentity()); + user = User.map(msg.getUser(), msg.getUserIdentity()); combo = msg.getComboCount(); - comboFinished = msg.getRepeatEnd() > 0; - comboIndex = msg.getRepeatCount(); } } diff --git a/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/websocket/TikTokWebsocketMessageEvent.java b/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/websocket/TikTokWebsocketMessageEvent.java index 814450d..2576996 100644 --- a/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/websocket/TikTokWebsocketMessageEvent.java +++ b/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/websocket/TikTokWebsocketMessageEvent.java @@ -28,6 +28,9 @@ import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent; import io.github.jwdeveloper.tiktok.messages.webcast.WebcastResponse; import lombok.AllArgsConstructor; import lombok.Getter; +import lombok.Value; + +import java.time.Duration; /** @@ -41,4 +44,12 @@ public class TikTokWebsocketMessageEvent extends TikTokEvent private TikTokEvent event; private WebcastResponse.Message message; + + private MetaData metaData; + + @Value + public static class MetaData + { + Duration handlingTime; + } } diff --git a/API/src/main/java/io/github/jwdeveloper/tiktok/data/models/Text.java b/API/src/main/java/io/github/jwdeveloper/tiktok/data/models/Text.java index 68af552..bb467e7 100644 --- a/API/src/main/java/io/github/jwdeveloper/tiktok/data/models/Text.java +++ b/API/src/main/java/io/github/jwdeveloper/tiktok/data/models/Text.java @@ -69,9 +69,14 @@ public class Text { var format = matcher.replaceAll("%s"); var output = new ArrayList(); - for (var piece : textPieces) { + for (var piece : textPieces) + { output.add(piece.getText()); } + if(matcher.groupCount() != output.size()) + { + return format; + } return String.format(format, output.toArray()); } diff --git a/API/src/main/java/io/github/jwdeveloper/tiktok/data/models/Gift.java b/API/src/main/java/io/github/jwdeveloper/tiktok/data/models/gifts/Gift.java similarity index 99% rename from API/src/main/java/io/github/jwdeveloper/tiktok/data/models/Gift.java rename to API/src/main/java/io/github/jwdeveloper/tiktok/data/models/gifts/Gift.java index 20529e5..de88661 100644 --- a/API/src/main/java/io/github/jwdeveloper/tiktok/data/models/Gift.java +++ b/API/src/main/java/io/github/jwdeveloper/tiktok/data/models/gifts/Gift.java @@ -21,8 +21,9 @@ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ // This enum is generated -package io.github.jwdeveloper.tiktok.data.models; +package io.github.jwdeveloper.tiktok.data.models.gifts; +import io.github.jwdeveloper.tiktok.data.models.Picture; import lombok.Getter; @Getter diff --git a/API/src/main/java/io/github/jwdeveloper/tiktok/data/models/gifts/GiftSendType.java b/API/src/main/java/io/github/jwdeveloper/tiktok/data/models/gifts/GiftSendType.java new file mode 100644 index 0000000..3a1b6c7 --- /dev/null +++ b/API/src/main/java/io/github/jwdeveloper/tiktok/data/models/gifts/GiftSendType.java @@ -0,0 +1,18 @@ +package io.github.jwdeveloper.tiktok.data.models.gifts; + +public enum GiftSendType +{ + Finished, + Begin, + Active; + + + public static GiftSendType fromNumber(long number) + { + return switch ((int) number) { + case 0 -> GiftSendType.Finished; + case 1, 2, 4 -> GiftSendType.Active; + default -> GiftSendType.Finished; + }; + } +} diff --git a/API/src/main/java/io/github/jwdeveloper/tiktok/data/models/users/User.java b/API/src/main/java/io/github/jwdeveloper/tiktok/data/models/users/User.java index d84815a..28ea7b7 100644 --- a/API/src/main/java/io/github/jwdeveloper/tiktok/data/models/users/User.java +++ b/API/src/main/java/io/github/jwdeveloper/tiktok/data/models/users/User.java @@ -46,9 +46,6 @@ public class User { @Getter(AccessLevel.NONE) private Set attributes; - @Setter - private boolean tracked; - public List getAttributes() { return attributes.stream().toList(); } diff --git a/API/src/main/java/io/github/jwdeveloper/tiktok/handler/TikTokMessageHandler.java b/API/src/main/java/io/github/jwdeveloper/tiktok/handler/TikTokMessageHandler.java index 0f58193..a5f1cb2 100644 --- a/API/src/main/java/io/github/jwdeveloper/tiktok/handler/TikTokMessageHandler.java +++ b/API/src/main/java/io/github/jwdeveloper/tiktok/handler/TikTokMessageHandler.java @@ -25,8 +25,10 @@ package io.github.jwdeveloper.tiktok.handler; import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent; +import java.util.List; + public interface TikTokMessageHandler { - TikTokEvent handle(byte[] messagePayload) throws Exception; + List handle(byte[] messagePayload) throws Exception; } diff --git a/API/src/main/java/io/github/jwdeveloper/tiktok/live/GiftManager.java b/API/src/main/java/io/github/jwdeveloper/tiktok/live/GiftManager.java index 3c32abc..628bf86 100644 --- a/API/src/main/java/io/github/jwdeveloper/tiktok/live/GiftManager.java +++ b/API/src/main/java/io/github/jwdeveloper/tiktok/live/GiftManager.java @@ -22,7 +22,7 @@ */ package io.github.jwdeveloper.tiktok.live; -import io.github.jwdeveloper.tiktok.data.models.Gift; +import io.github.jwdeveloper.tiktok.data.models.gifts.Gift; import io.github.jwdeveloper.tiktok.data.models.Picture; import java.util.List; diff --git a/API/src/main/java/io/github/jwdeveloper/tiktok/live/TrackedUser.java b/API/src/main/java/io/github/jwdeveloper/tiktok/live/TrackedUser.java index ea5d444..6cd9341 100644 --- a/API/src/main/java/io/github/jwdeveloper/tiktok/live/TrackedUser.java +++ b/API/src/main/java/io/github/jwdeveloper/tiktok/live/TrackedUser.java @@ -23,7 +23,7 @@ package io.github.jwdeveloper.tiktok.live; import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent; -import io.github.jwdeveloper.tiktok.data.models.Gift; +import io.github.jwdeveloper.tiktok.data.models.gifts.Gift; import io.github.jwdeveloper.tiktok.data.models.users.User; import java.util.List; diff --git a/API/src/main/java/io/github/jwdeveloper/tiktok/live/builder/EventsBuilder.java b/API/src/main/java/io/github/jwdeveloper/tiktok/live/builder/EventsBuilder.java index 65859d1..988f9cf 100644 --- a/API/src/main/java/io/github/jwdeveloper/tiktok/live/builder/EventsBuilder.java +++ b/API/src/main/java/io/github/jwdeveloper/tiktok/live/builder/EventsBuilder.java @@ -52,7 +52,6 @@ public interface EventsBuilder { T onWebsocketUnhandledMessage(EventConsumer event); T onGiftCombo(EventConsumer event); - T onGift(EventConsumer event); T onQuestion(EventConsumer event); diff --git a/API/src/main/java/io/github/jwdeveloper/tiktok/utils/Stopwatch.java b/API/src/main/java/io/github/jwdeveloper/tiktok/utils/Stopwatch.java new file mode 100644 index 0000000..22e2e48 --- /dev/null +++ b/API/src/main/java/io/github/jwdeveloper/tiktok/utils/Stopwatch.java @@ -0,0 +1,20 @@ +package io.github.jwdeveloper.tiktok.utils; + +public class Stopwatch { + private long startTime; + private long stopTime; + + public void start() { + startTime = System.nanoTime(); + } + + public long stop() { + stopTime = System.nanoTime(); + return getElapsedTime(); + } + + public long getElapsedTime() { + return stopTime - startTime; + } + +} \ No newline at end of file diff --git a/Client/pom.xml b/Client/pom.xml index d5bfae8..4009d70 100644 --- a/Client/pom.xml +++ b/Client/pom.xml @@ -80,7 +80,7 @@ *:* - **/tiktokSchema.proto/** + **/*.proto diff --git a/Client/src/main/java/io/github/jwdeveloper/tiktok/TikTokLiveClientBuilder.java b/Client/src/main/java/io/github/jwdeveloper/tiktok/TikTokLiveClientBuilder.java index 618bd24..6d70eea 100644 --- a/Client/src/main/java/io/github/jwdeveloper/tiktok/TikTokLiveClientBuilder.java +++ b/Client/src/main/java/io/github/jwdeveloper/tiktok/TikTokLiveClientBuilder.java @@ -41,6 +41,7 @@ import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveException; import io.github.jwdeveloper.tiktok.gifts.TikTokGiftManager; import io.github.jwdeveloper.tiktok.handlers.TikTokEventObserver; import io.github.jwdeveloper.tiktok.handlers.TikTokMessageHandlerRegistration; +import io.github.jwdeveloper.tiktok.handlers.events.TikTokGiftEventHandler; import io.github.jwdeveloper.tiktok.http.TikTokApiService; import io.github.jwdeveloper.tiktok.http.TikTokCookieJar; import io.github.jwdeveloper.tiktok.http.TikTokHttpClient; @@ -50,6 +51,7 @@ import io.github.jwdeveloper.tiktok.listener.TikTokListenersManager; import io.github.jwdeveloper.tiktok.live.LiveClient; import io.github.jwdeveloper.tiktok.live.builder.EventConsumer; import io.github.jwdeveloper.tiktok.live.builder.LiveClientBuilder; +import io.github.jwdeveloper.tiktok.mappers.TikTokGenericEventMapper; import io.github.jwdeveloper.tiktok.utils.ConsoleColors; import io.github.jwdeveloper.tiktok.websocket.TikTokWebSocketClient; @@ -147,10 +149,14 @@ public class TikTokLiveClientBuilder implements LiveClientBuilder { var apiClient = new TikTokHttpClient(cookieJar, requestFactory); var apiService = new TikTokApiService(apiClient, logger, clientSettings); var giftManager = new TikTokGiftManager(); + var eventMapper = new TikTokGenericEventMapper(); + var giftHandler = new TikTokGiftEventHandler(giftManager); var webResponseHandler = new TikTokMessageHandlerRegistration(tikTokEventHandler, - giftManager, - tiktokRoomInfo); + tiktokRoomInfo, + eventMapper, + giftHandler + ); var webSocketClient = new TikTokWebSocketClient(logger, cookieJar, diff --git a/Client/src/main/java/io/github/jwdeveloper/tiktok/gifts/TikTokGiftManager.java b/Client/src/main/java/io/github/jwdeveloper/tiktok/gifts/TikTokGiftManager.java index 41616be..e97b58e 100644 --- a/Client/src/main/java/io/github/jwdeveloper/tiktok/gifts/TikTokGiftManager.java +++ b/Client/src/main/java/io/github/jwdeveloper/tiktok/gifts/TikTokGiftManager.java @@ -22,7 +22,7 @@ */ package io.github.jwdeveloper.tiktok.gifts; -import io.github.jwdeveloper.tiktok.data.models.Gift; +import io.github.jwdeveloper.tiktok.data.models.gifts.Gift; import io.github.jwdeveloper.tiktok.data.models.Picture; import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveException; import io.github.jwdeveloper.tiktok.live.GiftManager; diff --git a/Client/src/main/java/io/github/jwdeveloper/tiktok/handlers/TikTokMessageHandler.java b/Client/src/main/java/io/github/jwdeveloper/tiktok/handlers/TikTokMessageHandler.java index 2259f26..e65fe4a 100644 --- a/Client/src/main/java/io/github/jwdeveloper/tiktok/handlers/TikTokMessageHandler.java +++ b/Client/src/main/java/io/github/jwdeveloper/tiktok/handlers/TikTokMessageHandler.java @@ -23,18 +23,20 @@ package io.github.jwdeveloper.tiktok.handlers; -import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent; import io.github.jwdeveloper.tiktok.data.events.TikTokErrorEvent; +import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent; import io.github.jwdeveloper.tiktok.data.events.websocket.TikTokWebsocketMessageEvent; import io.github.jwdeveloper.tiktok.data.events.websocket.TikTokWebsocketResponseEvent; import io.github.jwdeveloper.tiktok.data.events.websocket.TikTokWebsocketUnhandledMessageEvent; import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveMessageException; -import io.github.jwdeveloper.tiktok.exceptions.TikTokMessageMappingException; import io.github.jwdeveloper.tiktok.live.LiveClient; +import io.github.jwdeveloper.tiktok.mappers.TikTokGenericEventMapper; import io.github.jwdeveloper.tiktok.messages.webcast.WebcastResponse; +import io.github.jwdeveloper.tiktok.utils.Stopwatch; -import java.util.Arrays; +import java.time.Duration; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.function.Function; @@ -43,21 +45,24 @@ public abstract class TikTokMessageHandler { private final Map handlers; private final TikTokEventObserver tikTokEventHandler; + protected final TikTokGenericEventMapper mapper; - public TikTokMessageHandler(TikTokEventObserver tikTokEventHandler) { + public TikTokMessageHandler(TikTokEventObserver tikTokEventHandler, TikTokGenericEventMapper mapper) { handlers = new HashMap<>(); this.tikTokEventHandler = tikTokEventHandler; - init(); + this.mapper = mapper; } - public abstract void init(); - public void registerMapping(Class clazz, Function func) { + handlers.put(clazz.getSimpleName(), messagePayload -> List.of(func.apply(messagePayload))); + } + + public void registerMappings(Class clazz, Function> func) { handlers.put(clazz.getSimpleName(), func::apply); } public void registerMapping(Class input, Class output) { - registerMapping(input, (e) -> mapMessageToEvent(input, output, e)); + registerMapping(input, (e) -> mapper.mapToEvent(input, output, e)); } public void handle(LiveClient client, WebcastResponse webcastResponse) { @@ -71,18 +76,6 @@ public abstract class TikTokMessageHandler { } } } - public void handleSingleMessage(LiveClient client, String type, byte[] bytes) throws Exception { - - if (!handlers.containsKey(type)) { - tikTokEventHandler.publish(client, new TikTokWebsocketUnhandledMessageEvent(WebcastResponse.Message.newBuilder().setMethod(type).build())); - return; - } - var handler = handlers.get(type); - var tiktokEvent = handler.handle(bytes); - tikTokEventHandler.publish(client, new TikTokWebsocketMessageEvent(tiktokEvent, WebcastResponse.Message.newBuilder().build())); - tikTokEventHandler.publish(client, tiktokEvent); - } - public void handleSingleMessage(LiveClient client, WebcastResponse.Message message) throws Exception { var messageClassName = message.getMethod(); @@ -91,29 +84,16 @@ public abstract class TikTokMessageHandler { return; } var handler = handlers.get(messageClassName); - var tiktokEvent = handler.handle(message.getPayload().toByteArray()); - tikTokEventHandler.publish(client, new TikTokWebsocketMessageEvent(tiktokEvent, message)); - tikTokEventHandler.publish(client, tiktokEvent); - } + var stopwatch = new Stopwatch(); + stopwatch.start(); + var events = handler.handle(message.getPayload().toByteArray()); + var handlingTimeInMs = stopwatch.stop(); + var metadata = new TikTokWebsocketMessageEvent.MetaData(Duration.ofNanos(handlingTimeInMs)); - protected TikTokEvent mapMessageToEvent(Class inputClazz, Class outputClass, byte[] payload) { - try { - var parseMethod = inputClazz.getDeclaredMethod("parseFrom", byte[].class); - var deserialized = parseMethod.invoke(null,payload); - var constructors = Arrays.stream(outputClass.getConstructors()) - .filter(ea -> Arrays.stream(ea.getParameterTypes()) - .toList() - .contains(inputClazz)) - .findFirst(); - - if (constructors.isEmpty()) { - throw new TikTokMessageMappingException(inputClazz, outputClass, "Unable to find constructor with input class type"); - } - - var tiktokEvent = constructors.get().newInstance(deserialized); - return (TikTokEvent) tiktokEvent; - } catch (Exception ex) { - throw new TikTokMessageMappingException(inputClazz, outputClass, ex); + for (var event : events) { + tikTokEventHandler.publish(client, new TikTokWebsocketMessageEvent(event, message, metadata)); + tikTokEventHandler.publish(client, event); } } + } diff --git a/Client/src/main/java/io/github/jwdeveloper/tiktok/handlers/TikTokMessageHandlerRegistration.java b/Client/src/main/java/io/github/jwdeveloper/tiktok/handlers/TikTokMessageHandlerRegistration.java index 720c79d..d4298b5 100644 --- a/Client/src/main/java/io/github/jwdeveloper/tiktok/handlers/TikTokMessageHandlerRegistration.java +++ b/Client/src/main/java/io/github/jwdeveloper/tiktok/handlers/TikTokMessageHandlerRegistration.java @@ -23,11 +23,8 @@ package io.github.jwdeveloper.tiktok.handlers; import io.github.jwdeveloper.tiktok.TikTokRoomInfo; -import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent; import io.github.jwdeveloper.tiktok.data.events.*; -import io.github.jwdeveloper.tiktok.data.events.TikTokBarrageEvent; -import io.github.jwdeveloper.tiktok.data.events.gift.TikTokGiftComboEvent; -import io.github.jwdeveloper.tiktok.data.events.gift.TikTokGiftEvent; +import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent; import io.github.jwdeveloper.tiktok.data.events.poll.TikTokPollEndEvent; import io.github.jwdeveloper.tiktok.data.events.poll.TikTokPollEvent; import io.github.jwdeveloper.tiktok.data.events.poll.TikTokPollStartEvent; @@ -39,10 +36,9 @@ import io.github.jwdeveloper.tiktok.data.events.social.TikTokFollowEvent; import io.github.jwdeveloper.tiktok.data.events.social.TikTokJoinEvent; import io.github.jwdeveloper.tiktok.data.events.social.TikTokLikeEvent; import io.github.jwdeveloper.tiktok.data.events.social.TikTokShareEvent; -import io.github.jwdeveloper.tiktok.data.models.Gift; -import io.github.jwdeveloper.tiktok.data.models.Picture; import io.github.jwdeveloper.tiktok.data.models.Text; -import io.github.jwdeveloper.tiktok.gifts.TikTokGiftManager; +import io.github.jwdeveloper.tiktok.handlers.events.TikTokGiftEventHandler; +import io.github.jwdeveloper.tiktok.mappers.TikTokGenericEventMapper; import io.github.jwdeveloper.tiktok.messages.webcast.*; import io.github.jwdeveloper.tiktok.models.SocialTypes; import lombok.SneakyThrows; @@ -50,19 +46,21 @@ import lombok.SneakyThrows; import java.util.regex.Pattern; public class TikTokMessageHandlerRegistration extends TikTokMessageHandler { - private final TikTokGiftManager giftManager; + private final TikTokRoomInfo roomInfo; + private final TikTokGiftEventHandler giftHandler; private final Pattern socialMediaPattern = Pattern.compile("pm_mt_guidance_viewer_([0-9]+)_share"); public TikTokMessageHandlerRegistration(TikTokEventObserver tikTokEventHandler, - TikTokGiftManager giftManager, - TikTokRoomInfo roomInfo) { - super(tikTokEventHandler); - this.giftManager = giftManager; + TikTokRoomInfo roomInfo, + TikTokGenericEventMapper genericTikTokEventMapper, + TikTokGiftEventHandler tikTokGiftEventHandler) { + super(tikTokEventHandler, genericTikTokEventMapper); + this.giftHandler = tikTokGiftEventHandler; this.roomInfo = roomInfo; + init(); } - @Override public void init() { //ConnectionEvents events @@ -80,7 +78,7 @@ public class TikTokMessageHandlerRegistration extends TikTokMessageHandler { //User Interactions events registerMapping(WebcastChatMessage.class, TikTokCommentEvent.class); registerMapping(WebcastLikeMessage.class, this::handleLike); - registerMapping(WebcastGiftMessage.class, this::handleGift); + registerMappings(WebcastGiftMessage.class, giftHandler::handleGift); registerMapping(WebcastSocialMessage.class, this::handleSocialMedia); registerMapping(WebcastMemberMessage.class, this::handleMemberMessage); @@ -124,29 +122,6 @@ public class TikTokMessageHandlerRegistration extends TikTokMessageHandler { }; } - @SneakyThrows - private TikTokEvent handleGift(byte[] msg) { - var giftMessage = WebcastGiftMessage.parseFrom(msg); - - - var gift = giftManager.findById((int) giftMessage.getGiftId()); - if (gift == Gift.UNDEFINED) { - gift = giftManager.findByName(giftMessage.getGift().getName()); - } - if (gift == Gift.UNDEFINED) { - gift = giftManager.registerGift( - (int) giftMessage.getGift().getId(), - giftMessage.getGift().getName(), - giftMessage.getGift().getDiamondCount(), - Picture.map(giftMessage.getGift().getImage())); - } - - if (giftMessage.getRepeatEnd() > 0) { - return new TikTokGiftComboEvent(gift, giftMessage); - } - - return new TikTokGiftEvent(gift, giftMessage); - } @SneakyThrows private TikTokEvent handleSocialMedia(byte[] msg) { @@ -181,13 +156,13 @@ public class TikTokMessageHandlerRegistration extends TikTokMessageHandler { } private TikTokEvent handleRoomUserSeqMessage(byte[] msg) { - var event = (TikTokRoomUserInfoEvent) mapMessageToEvent(WebcastRoomUserSeqMessage.class, TikTokRoomUserInfoEvent.class, msg); + var event = (TikTokRoomUserInfoEvent) mapper.mapToEvent(WebcastRoomUserSeqMessage.class, TikTokRoomUserInfoEvent.class, msg); roomInfo.setViewersCount(event.getTotalUsers()); return event; } private TikTokEvent handleLike(byte[] msg) { - var event = (TikTokLikeEvent) mapMessageToEvent(WebcastLikeMessage.class, TikTokLikeEvent.class, msg); + var event = (TikTokLikeEvent) mapper.mapToEvent(WebcastLikeMessage.class, TikTokLikeEvent.class, msg); roomInfo.setLikesCount(event.getTotalLikes()); return event; } @@ -200,7 +175,7 @@ public class TikTokMessageHandlerRegistration extends TikTokMessageHandler { return new TikTokRoomPinEvent(pinMessage, chatEvent); } - //TODO check + //TODO Probably not working @SneakyThrows private TikTokEvent handlePollEvent(byte[] msg) { var poolMessage = WebcastPollMessage.parseFrom(msg); diff --git a/Client/src/main/java/io/github/jwdeveloper/tiktok/handlers/events/TikTokGiftEventHandler.java b/Client/src/main/java/io/github/jwdeveloper/tiktok/handlers/events/TikTokGiftEventHandler.java new file mode 100644 index 0000000..29d1238 --- /dev/null +++ b/Client/src/main/java/io/github/jwdeveloper/tiktok/handlers/events/TikTokGiftEventHandler.java @@ -0,0 +1,86 @@ +package io.github.jwdeveloper.tiktok.handlers.events; + +import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent; +import io.github.jwdeveloper.tiktok.data.events.gift.TikTokGiftComboEvent; +import io.github.jwdeveloper.tiktok.data.events.gift.TikTokGiftEvent; +import io.github.jwdeveloper.tiktok.data.models.Picture; +import io.github.jwdeveloper.tiktok.data.models.gifts.Gift; +import io.github.jwdeveloper.tiktok.data.models.gifts.GiftSendType; +import io.github.jwdeveloper.tiktok.live.GiftManager; +import io.github.jwdeveloper.tiktok.messages.webcast.WebcastGiftMessage; +import lombok.SneakyThrows; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class TikTokGiftEventHandler { + private final GiftManager giftManager; + private final Map giftsMessages; + + public TikTokGiftEventHandler(GiftManager giftManager) { + this.giftManager = giftManager; + giftsMessages = new HashMap<>(); + } + + @SneakyThrows + public List handleGift(byte[] msg) { + var currentMessage = WebcastGiftMessage.parseFrom(msg); + var userId = currentMessage.getUser().getId(); + var currentType = GiftSendType.fromNumber(currentMessage.getSendType()); + var containsPreviousMessage = giftsMessages.containsKey(userId); + + if (!containsPreviousMessage) { + if (currentType == GiftSendType.Finished) { + return List.of(getGiftEvent(currentMessage)); + } else { + giftsMessages.put(userId, currentMessage); + return List.of(getGiftComboEvent(currentMessage, GiftSendType.Begin)); + } + } + + var previousMessage = giftsMessages.get(userId); + var previousType = GiftSendType.fromNumber(previousMessage.getSendType()); + if (currentType == GiftSendType.Active && + previousType == GiftSendType.Active) { + giftsMessages.put(userId, currentMessage); + return List.of(getGiftComboEvent(currentMessage, GiftSendType.Active)); + } + + + if (currentType == GiftSendType.Finished && + previousType == GiftSendType.Active) { + giftsMessages.clear(); + return List.of( + getGiftComboEvent(currentMessage, GiftSendType.Finished), + getGiftEvent(currentMessage)); + } + + return List.of(); + } + + private TikTokGiftEvent getGiftEvent(WebcastGiftMessage message) { + var gift = getGiftObject(message); + return new TikTokGiftEvent(gift, message); + } + + private TikTokGiftEvent getGiftComboEvent(WebcastGiftMessage message, GiftSendType state) { + var gift = getGiftObject(message); + return new TikTokGiftComboEvent(gift, message, state); + } + + private Gift getGiftObject(WebcastGiftMessage giftMessage) { + var gift = giftManager.findById((int) giftMessage.getGiftId()); + if (gift == Gift.UNDEFINED) { + gift = giftManager.findByName(giftMessage.getGift().getName()); + } + if (gift == Gift.UNDEFINED) { + gift = giftManager.registerGift( + (int) giftMessage.getGift().getId(), + giftMessage.getGift().getName(), + giftMessage.getGift().getDiamondCount(), + Picture.map(giftMessage.getGift().getImage())); + } + return gift; + } +} diff --git a/Client/src/main/java/io/github/jwdeveloper/tiktok/http/TikTokHttpClient.java b/Client/src/main/java/io/github/jwdeveloper/tiktok/http/TikTokHttpClient.java index 49a86a7..83e17fe 100644 --- a/Client/src/main/java/io/github/jwdeveloper/tiktok/http/TikTokHttpClient.java +++ b/Client/src/main/java/io/github/jwdeveloper/tiktok/http/TikTokHttpClient.java @@ -133,12 +133,12 @@ public class TikTokHttpClient { private String getSignedUrl(String url, Map parameters) { var fullUrl = HttpUtils.parseParameters(url,parameters); - var singHeaders = new TreeMap(); - singHeaders.put("client", "ttlive-java"); - singHeaders.put("uuc", 1); - singHeaders.put("url", fullUrl); + var signParams = new TreeMap(); + signParams.put("client", "ttlive-java"); + signParams.put("uuc", 1); + signParams.put("url", fullUrl); - var request = requestFactory.setQueries(singHeaders); + var request = requestFactory.setQueries(signParams); var content = request.get(Constants.TIKTOK_SIGN_API); diff --git a/Client/src/main/java/io/github/jwdeveloper/tiktok/mappers/TikTokGenericEventMapper.java b/Client/src/main/java/io/github/jwdeveloper/tiktok/mappers/TikTokGenericEventMapper.java new file mode 100644 index 0000000..b517637 --- /dev/null +++ b/Client/src/main/java/io/github/jwdeveloper/tiktok/mappers/TikTokGenericEventMapper.java @@ -0,0 +1,85 @@ +package io.github.jwdeveloper.tiktok.mappers; + +import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent; +import io.github.jwdeveloper.tiktok.exceptions.TikTokMessageMappingException; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + +/** + * Goal of this class is to map ProtocolBuffer objects to TikTok Event in generic way + * + * First parameter is ProtocolBuffer class type + * Second parameters is TikTokEvent class type + * Third parameters is bytes payload + * + * mapToEvent(WebcastGiftMessage.class, TikTokGiftEvent.class, payload) + * + * How does it work? + * 1. Finds method `parseFrom(byte[] bytes)` inside ProtocolBuffer class + * 2. put payload to the method methods and create new instance of ProtcolBuffer object + * 3. Finds in TikTokEvent constructor that takes ProtocolBuffer type as parameter + * 4. create new Instance in TikTokEvents using object from step 2 and constructor from step 3 + * + * methodCache and constructorCache are used to boost performance + */ +public class TikTokGenericEventMapper { + + private record TypePair(Class a, Class b) { + } + + private final Map, Method> methodCache; + private final Map> constructorCache; + + public TikTokGenericEventMapper() { + this.methodCache = new HashMap<>(); + this.constructorCache = new HashMap<>(); + } + + public TikTokEvent mapToEvent(Class inputClazz, Class outputClass, byte[] payload) { + try { + var method = getParsingMethod(inputClazz); + var deserializedMessage = method.invoke(null, payload); + var constructor = getParsingConstructor(inputClazz, outputClass); + + var tiktokEvent = constructor.newInstance(deserializedMessage); + return (TikTokEvent) tiktokEvent; + } catch (Exception ex) { + throw new TikTokMessageMappingException(inputClazz, outputClass, ex); + } + } + + private Method getParsingMethod(Class input) throws NoSuchMethodException { + if (methodCache.containsKey(input)) { + return methodCache.get(input); + } + var method = input.getDeclaredMethod("parseFrom", byte[].class); + methodCache.put(input, method); + return method; + } + + private Constructor getParsingConstructor(Class input, Class output) { + var pair = new TypePair(input, output); + if (constructorCache.containsKey(pair)) { + return constructorCache.get(pair); + } + + var optional = Arrays.stream(output.getConstructors()) + .filter(ea -> Arrays.stream(ea.getParameterTypes()) + .toList() + .contains(input)) + .findFirst(); + + if (optional.isEmpty()) { + throw new TikTokMessageMappingException(input, output, "Unable to find constructor with input class type"); + } + + constructorCache.put(pair, optional.get()); + return optional.get(); + } + + +} diff --git a/Client/src/main/java/io/github/jwdeveloper/tiktok/websocket/TikTokWebSocketListener.java b/Client/src/main/java/io/github/jwdeveloper/tiktok/websocket/TikTokWebSocketListener.java index 2678d1e..ecd87aa 100644 --- a/Client/src/main/java/io/github/jwdeveloper/tiktok/websocket/TikTokWebSocketListener.java +++ b/Client/src/main/java/io/github/jwdeveloper/tiktok/websocket/TikTokWebSocketListener.java @@ -125,7 +125,7 @@ public class TikTokWebSocketListener extends WebSocketClient { } return Optional.of(websocketMessage); } catch (Exception e) { - throw new TikTokProtocolBufferException("Unable to parse WebcastWebsocketMessage", buffer, e); + throw new TikTokProtocolBufferException("Unable to parse WebcastPushFrame", buffer, e); } } diff --git a/Client/src/main/java/io/github/jwdeveloper/tiktok/websocket/TikTokWebSocketPingingTask.java b/Client/src/main/java/io/github/jwdeveloper/tiktok/websocket/TikTokWebSocketPingingTask.java index 1a413a3..1b48ea8 100644 --- a/Client/src/main/java/io/github/jwdeveloper/tiktok/websocket/TikTokWebSocketPingingTask.java +++ b/Client/src/main/java/io/github/jwdeveloper/tiktok/websocket/TikTokWebSocketPingingTask.java @@ -28,7 +28,6 @@ import java.util.Random; public class TikTokWebSocketPingingTask { private Thread thread; - private boolean isRunning = false; private final int MIN_TIMEOUT = 5; private final int MAX_TIMEOUT = 100; @@ -37,7 +36,7 @@ public class TikTokWebSocketPingingTask public void run(WebSocket webSocket) { stop(); - var thread = new Thread(() -> + thread = new Thread(() -> { pingTask(webSocket); }); diff --git a/Client/src/test/java/io/github/jwdeveloper/tiktok/gifts/TikTokGiftManagerTest.java b/Client/src/test/java/io/github/jwdeveloper/tiktok/gifts/TikTokGiftManagerTest.java index 85c6eb3..5f6aeed 100644 --- a/Client/src/test/java/io/github/jwdeveloper/tiktok/gifts/TikTokGiftManagerTest.java +++ b/Client/src/test/java/io/github/jwdeveloper/tiktok/gifts/TikTokGiftManagerTest.java @@ -22,7 +22,7 @@ */ package io.github.jwdeveloper.tiktok.gifts; -import io.github.jwdeveloper.tiktok.data.models.Gift; +import io.github.jwdeveloper.tiktok.data.models.gifts.Gift; import io.github.jwdeveloper.tiktok.data.models.Picture; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; diff --git a/Examples/pom.xml b/Examples/pom.xml index cec5ec0..e340b30 100644 --- a/Examples/pom.xml +++ b/Examples/pom.xml @@ -46,7 +46,7 @@ 4.0.0 - TestApplication + Examples io.github.jwdeveloper.tiktok diff --git a/Examples/target/classes/io/github/jwdeveloper/tiktok/SimpleExample$1.class b/Examples/target/classes/io/github/jwdeveloper/tiktok/SimpleExample$1.class index 01865c98811fbe24825734054a6300591670f63b..6c17f4a98807f653e3f4066014981f3aa88b4b6c 100644 GIT binary patch delta 123 zcmcc4_MUBmB%|?UdnQ@6l*E!m{oMSN)SP1d^vtx9VtscY$;iM~mY7qTTFl5`p`jV= o15zr0u5@CZE2G`SBPJ{$eG|XQF_~glx7n8Q93!LsWFBU30I~=u4gdfE delta 73 zcmaFQcAag4B%|)cg|ZW?ctqSY(@Gc_*vb-fN>hs&8H_YEqkSM!6MLK)Ehb(tnasr~ U!=w)t+#Jq$hLKTwvI?^|0AWKGssI20 diff --git a/Tools-EventsCollector/src/main/java/io/github/jwdeveloper/tiktok/tools/collector/RunCollector.java b/Tools-EventsCollector/src/main/java/io/github/jwdeveloper/tiktok/tools/collector/RunCollector.java index 3d37013..72c5730 100644 --- a/Tools-EventsCollector/src/main/java/io/github/jwdeveloper/tiktok/tools/collector/RunCollector.java +++ b/Tools-EventsCollector/src/main/java/io/github/jwdeveloper/tiktok/tools/collector/RunCollector.java @@ -22,8 +22,10 @@ */ package io.github.jwdeveloper.tiktok.tools.collector; +import io.github.jwdeveloper.tiktok.messages.webcast.WebcastGiftMessage; import io.github.jwdeveloper.tiktok.tools.collector.client.TikTokMessageCollectorClient; +import java.io.IOException; import java.sql.SQLException; public class RunCollector { @@ -33,15 +35,48 @@ public class RunCollector { //WebcastLinkMicBattleItemCard does streamer win battle? - public static void main(String[] args) throws SQLException { + public static void main(String[] args) throws SQLException, IOException { - TikTokMessageCollectorClient.create("messageCollector") - .addUser("bangbetmenygy") - .addUser("mr_cios") - .addUser("sleepstreamxxx") - .addUser("psychotropnazywo") - .addUser("accordionistka") + TikTokMessageCollectorClient.create("giftsCollector") + .addUser("cbcgod") + // .addUser("mr_cios") + // .addUser("cbcgod") + // .addUser("psychotropnazywo") + // .addUser("accordionistka") + .addEventFilter(WebcastGiftMessage.class) + .addOnBuilder(liveClientBuilder -> + { + liveClientBuilder.onGift((liveClient, event) -> + { + + }); + + liveClientBuilder.onGiftCombo((liveClient, event) -> + { + + }); + + liveClientBuilder.onGift((liveClient, event) -> + { + var sb = new StringBuilder(); + sb.append("GIFT User: " + event.getUser().getDisplayName()+" "); + sb.append("Name: " + event.getGift().name() + " "); + sb.append("Combo: " + event.getCombo() + " "); + System.out.println(sb.toString()); + }); + liveClientBuilder.onGiftCombo((liveClient, event) -> + { + var sb = new StringBuilder(); + sb.append("COMBO User: " + event.getUser().getDisplayName()+" "); + sb.append("Name: " + event.getGift().name() + " "); + sb.append("Combo: " + event.getCombo() + " "); + sb.append("Type: " + event.getComboState().name()); + System.out.println(sb.toString()); + }); + }) .buildAndRun(); + + System.in.read(); } diff --git a/Tools-EventsCollector/src/main/java/io/github/jwdeveloper/tiktok/tools/collector/client/MessageCollector.java b/Tools-EventsCollector/src/main/java/io/github/jwdeveloper/tiktok/tools/collector/client/MessageCollector.java index b80c064..a5915c7 100644 --- a/Tools-EventsCollector/src/main/java/io/github/jwdeveloper/tiktok/tools/collector/client/MessageCollector.java +++ b/Tools-EventsCollector/src/main/java/io/github/jwdeveloper/tiktok/tools/collector/client/MessageCollector.java @@ -62,7 +62,7 @@ public class MessageCollector { var queue = messages.get(name); if (queue.size() > limit) { - queue.poll(); + queue.remove(); } queue.add(new MessageData(base64, host, LocalDateTime.now().toString())); diff --git a/Tools-EventsCollector/src/main/java/io/github/jwdeveloper/tiktok/tools/collector/client/TikTokClientFactory.java b/Tools-EventsCollector/src/main/java/io/github/jwdeveloper/tiktok/tools/collector/client/TikTokClientFactory.java index 58afd77..5cfb59a 100644 --- a/Tools-EventsCollector/src/main/java/io/github/jwdeveloper/tiktok/tools/collector/client/TikTokClientFactory.java +++ b/Tools-EventsCollector/src/main/java/io/github/jwdeveloper/tiktok/tools/collector/client/TikTokClientFactory.java @@ -34,6 +34,7 @@ import io.github.jwdeveloper.tiktok.tools.collector.tables.TikTokMessageModel; import io.github.jwdeveloper.tiktok.tools.collector.tables.TikTokResponseModel; import java.util.Base64; +import java.util.List; import java.util.concurrent.CompletableFuture; import java.util.function.Consumer; @@ -46,8 +47,9 @@ public class TikTokClientFactory { this.tikTokDatabase = tikTokDatabase; } - public CompletableFuture runClientAsync(String tiktokUser, Consumer onBuilder) { + public CompletableFuture runClientAsync(String tiktokUser, List> filters, Consumer onBuilder) { var builder = TikTokLive.newClient(tiktokUser); + var msgFilter = filters.stream().map(Class::getSimpleName).toList(); onBuilder.accept(builder); return builder.onConnected((liveClient, event) -> { @@ -62,7 +64,12 @@ public class TikTokClientFactory { responseModel.setHostName(liveClient.getRoomInfo().getHostName()); tikTokDatabase.insertResponse(responseModel); liveClient.getLogger().info("Response"); - for (var message : event.getResponse().getMessagesList()) { + for (var message : event.getResponse().getMessagesList()) + { + if(msgFilter.size() > 0 && !msgFilter.contains(message.getMethod())) + { + continue; + } messageCollector.addMessage(liveClient.getLogger(), liveClient.getRoomInfo().getHostName(), message); } }) @@ -71,7 +78,7 @@ public class TikTokClientFactory { var eventName = event.getEvent().getClass().getSimpleName(); /* - if (filter.size() != 0 && !filter.contains(event.getEvent().getClass())) { + if (msgFilter.size() != 0 && !msgFilter.contains(event.getEvent().getClass())) { return; }*/ @@ -83,7 +90,7 @@ public class TikTokClientFactory { model.setMessage(messageBinary); // tikTokDatabase.insertMessage(model); - liveClient.getLogger().info("EVENT: [" + tiktokUser + "] " + eventName); + // liveClient.getLogger().info("EVENT: [" + tiktokUser + "] " + eventName); }) .onError((liveClient, event) -> { diff --git a/Tools-EventsCollector/src/main/java/io/github/jwdeveloper/tiktok/tools/collector/client/TikTokMessagessCollectorBuilder.java b/Tools-EventsCollector/src/main/java/io/github/jwdeveloper/tiktok/tools/collector/client/TikTokMessagessCollectorBuilder.java index 5cf9189..e3738ee 100644 --- a/Tools-EventsCollector/src/main/java/io/github/jwdeveloper/tiktok/tools/collector/client/TikTokMessagessCollectorBuilder.java +++ b/Tools-EventsCollector/src/main/java/io/github/jwdeveloper/tiktok/tools/collector/client/TikTokMessagessCollectorBuilder.java @@ -82,7 +82,7 @@ public class TikTokMessagessCollectorBuilder { db.init(); var factory = new TikTokClientFactory(messageCollector, db); for (var user : users) { - var client = factory.runClientAsync(user, onBuilder); + var client = factory.runClientAsync(user,filters, onBuilder); client.thenAccept(liveClient -> { tiktokclients.add(liveClient); diff --git a/Tools-EventsCollector/src/main/java/io/github/jwdeveloper/tiktok/tools/tester/RunJsonTester.java b/Tools-EventsCollector/src/main/java/io/github/jwdeveloper/tiktok/tools/tester/RunJsonTester.java index 4ffa762..0bb898e 100644 --- a/Tools-EventsCollector/src/main/java/io/github/jwdeveloper/tiktok/tools/tester/RunJsonTester.java +++ b/Tools-EventsCollector/src/main/java/io/github/jwdeveloper/tiktok/tools/tester/RunJsonTester.java @@ -47,7 +47,15 @@ public class RunJsonTester { sb.append(MessageUtil.getContent(event.getData())); - liveClient.getLogger().info(sb.toString()); + // liveClient.getLogger().info(sb.toString()); + }). + onGift((liveClient, event) -> + { + liveClient.getLogger().info("Gift event: "+event.toJson()); + }) + .onGiftCombo((liveClient, event) -> + { + liveClient.getLogger().info("GiftCombo event"+event.toJson()); }) .onError((liveClient, event) -> { diff --git a/Tools-EventsCollector/target/classes/io/github/jwdeveloper/tiktok/tools/collector/RunCollector.class b/Tools-EventsCollector/target/classes/io/github/jwdeveloper/tiktok/tools/collector/RunCollector.class index 8d8152ea478f89a0ea13cf716f9a1ea2e4af7385..784b75945a23bd38f3c05ef887a0635ffaf7763c 100644 GIT binary patch literal 5206 zcmcgw340sW6+O>(JhCznM+pgmHZjCdJA_OOF%U#H%W-0m;}Ds+6uOM0u{_aeMrcM3 z?oJoz0xh(qrKLMv=}Ouv)U+avH-6#Y z3(o_%4gZRx1Dy)GRIEd{K<^oSPS-5mE@+e4Ge*u6=)TRgP4A#U=fL3U7-9mK7R(vX zO*xju1x_W7IMyprRa}Bg1x}idRxrKUYF0aQHgC)smQyw=nr9Y0r>J?3W4T&xaj%xM zOvCoHDYH1`6ekSV)eA;la>}11gj~hYJww18NH+jxyozZTl7s30S)to7W~6Fbd83ky zp;zk7<_bK7W^MR1|C#INVl6DR7gkoi(yK-SxET;CYN; z30){5Z&Psvu4K3<`RE+IJZ4&+Q4yGpdNF0`uDeD~Ops$QRk0mA=u179Gs@)Cj)B1- zh*i(Dw3(`%^GwIqQjYCbOZ2>iewB)=u~R@L^hrC6iGUXZzrfD5VS>bSjf!jWGJ*A3 zNsl9T{#4Z#I8IC22I>N2Z>D*&2ZPw9;5rq%as84c%*?x~-jRKqe1X;R9po>fMehQB#ATX@rCfrQYIkwLXf#gcISmvCe`Q|g3 z{Y~|Vt;c@csvxPdpd6s6wmw-RCrzP2lGkJ0?bwpX0uux6ox4QPQa~ZWB4sR@V4WM5 zKo6@pB2lgn^rW0p)=8if!wGa@Siw<&t<5zi1Q*9BI^#HwaRs-lxC3c{k+#O>bx+p} znR_m4;>=>5lLq>VL+2|6!;`r$aPvxG@FkXnw~1@MV4zjr+d>Z`H~TyPGbeG zjnQFxzapFM)1MNpLeN3NkZe1Q*gxfhj$BhB-Yj9%XCjDY?y3Q3A96 zlErNq&p!hXT?|DUs4{fz)O^{Xg=J~seJdqulxeME5{O|+)-6v(6>}^tPL)a9C{ZVQ zI5$evDDGD=FFhLboWRI9UWeB!c!P>J;!Tmd71_vumZca=7Qf|4aXO9%WH!D<;K0h1 zUp^829891`2I~RbE1MYw4+-pVE3vt@^F*lMTgZSEQ&eC>+O&-m)l$}|OzByRBZ;(= z)2-8b#gzSUu*;h@nKQ}u1+SgPBvqDlc}Q#-xM!I=5_7dnuN0_c(=yWn@uT<4)0qdc ztKj|gwx6l)eU_HFGhLrk@OUIpTIL}*pz-nT8@uuWjkDvXL?5Lo9kSzxsN#?`^$<-*Mh zY-?f7Vu5Y)+6@Bb|CiVN-1HrG=)X2KkkMqsP*Z;|Qy}A1D>;LgWTxrHXgcqa$-ryb zh~s#!SJBH8hBxcv-3{INQXF5#R}_3z#nH=6Urf zMSCws3tPA;P;gwg^OoWEryZwQEhk$76dhTz(XaE7<*T0zRJIo!J+DH^Dc!O%re`F3 zajvOU2cMCQA-(m@I3C2eRD2L0>XpCG3fOB#rJPeL@w+1UvRot*K`clR&#Cwvp6bO@ z9C%(1d{4z^@nkQaidX+MoW3?EO^5NBp^;$MFlipx~GC{C-iOza`+o=@wjy z#uh{V#M%crygEe7`=ak#sZbAC48P{ZFEu$aGTA3@lDGDWz8HSXb6Q>jgWm52di;w^ z(ETHiWyvu1V)!!?>Dc(#RDCl)+Qx0$sQBNN22Yc}30%|Sq~!>%;2#3p+b`uUF~|m7 z#i(@f`w~$2LBoGuuzd%68lQsCb-T_(Jj0g`ypye*26o_GY}H@^-i?RZ>%k*<4_C>} z2A^`>&V=$TdJ-FI*qGQ-!{rNj2~a~{4gJ&SFi^vu>4xa-L;wu19i-?z*h~ytF@Y;F z$*_q8#sX#=yxPI9tPO8`uIz9p%k&4BK!FyLijJ z1>^j=ooepzG4=&G@KJn>c!&re$0vv~MjJkfPoaajnU^8%$3xtyDDF4=xZm0U_O@o+ zZ?EHC4(1h%4RC-e4-)1f!aPivM=-)4NuK~>stz$lh@bHxChHJcOG1dl+#z||!o~f* zur0x4U6=^$rIoBtD~Z^5K@k#9CqD1%{sO+p=PCY|?rDxagKsdP^6flH^_}qTyZCE>A=eK|G+dttilpE)YzvA!sC${|uo(L8m delta 411 zcmYk1&rZTX5XQenp`}5D9uP%9L=lmH8e?MOP2&SdjPYbj-C(utlC~iA;xmvwfsfz? zjRzkysi^f15K+4<(%*^la{th{}{yaG7D&RE%%Qx zv$*Z|{GiFKQyB{klI2|JhHzypG9+D-^S;Vc zQqy(eTpGeQT<=CxprV+-3QED=%y~>gnPES8VELdONd=wwJ8K0+C40}Hbi}~X`LSVg zhV;q6J`|?Obx%0WYi+2ZgjGc73m`H?5hJcq)uPNOM{7@DkJI)#F>C{QREUXR0X9&j zDvnLm$Rr##re?sftV+*_tMe12)l7(Nh@}wAgb4~~f8MK*X|@81924Z3CdUkU=CFkV a>a=L%-@9eHt&_e%F-w~?DcW?7VEYFlg-VS8 diff --git a/Tools-EventsWebViewer/src/main/java/io/github/jwdeveloper/tiktok/webviewer/Main.java b/Tools-EventsWebViewer/src/main/java/io/github/jwdeveloper/tiktok/webviewer/Main.java index af59fb3..9600f2e 100644 --- a/Tools-EventsWebViewer/src/main/java/io/github/jwdeveloper/tiktok/webviewer/Main.java +++ b/Tools-EventsWebViewer/src/main/java/io/github/jwdeveloper/tiktok/webviewer/Main.java @@ -45,6 +45,7 @@ public class Main { app.get("/tiktok/connect", handler::connect); app.get("/tiktok/disconnect", handler::disconnect); app.get("/tiktok/events", handler::events); + app.get("/tiktok/events/pages", handler::eventPages); app.get("/tiktok/events/message", handler::eventMessage); } } diff --git a/Tools-EventsWebViewer/src/main/java/io/github/jwdeveloper/tiktok/webviewer/TikTokManager.java b/Tools-EventsWebViewer/src/main/java/io/github/jwdeveloper/tiktok/webviewer/TikTokManager.java index 6f1c99b..f6e423b 100644 --- a/Tools-EventsWebViewer/src/main/java/io/github/jwdeveloper/tiktok/webviewer/TikTokManager.java +++ b/Tools-EventsWebViewer/src/main/java/io/github/jwdeveloper/tiktok/webviewer/TikTokManager.java @@ -23,7 +23,6 @@ package io.github.jwdeveloper.tiktok.webviewer; import com.google.protobuf.InvalidProtocolBufferException; -import io.github.jwdeveloper.tiktok.messages.webcast.WebcastResponse; import io.github.jwdeveloper.tiktok.tools.collector.client.MessageCollector; import io.github.jwdeveloper.tiktok.tools.collector.client.TikTokMessageCollectorClient; import io.github.jwdeveloper.tiktok.tools.collector.client.TikTokMessagessCollectorBuilder; @@ -34,6 +33,7 @@ import java.sql.SQLException; import java.util.Base64; import java.util.List; import java.util.Random; +import java.util.concurrent.atomic.AtomicInteger; public class TikTokManager { TikTokMessagessCollectorBuilder client; @@ -45,7 +45,17 @@ public class TikTokManager { public void connect(String name) throws SQLException { disconnect(); - client = TikTokMessageCollectorClient.create(msgCollector, "web").addUser(name); + client = TikTokMessageCollectorClient.create(msgCollector, "web") + .addOnBuilder(liveClientBuilder -> + { + + + liveClientBuilder.onGift((liveClient, event) -> + { + + }); + }) + .addUser(name); client.buildAndRun(); } @@ -58,19 +68,49 @@ public class TikTokManager { } - public MessageDto getMessage(String event) throws InvalidProtocolBufferException { + public MessageDto getMessage(String event, String index) throws InvalidProtocolBufferException { var eventData = msgCollector.getMessages().get(event); var messages = eventData.stream().toList(); var random = new Random(); - var index = random.nextInt(messages.size()-1); - var msg = messages.get(index); + + var msgIndex = 0; + if (index != null && !index.isEmpty()) { + msgIndex = Integer.parseInt(index); + msgIndex = Math.min(msgIndex, messages.size() - 1); + msgIndex = Math.max(msgIndex, 0); + } + + + var msg = messages.get(msgIndex); var bytes = Base64.getDecoder().decode(msg.getEventData()); - var content = MessageUtil.getContent(event,bytes); + var content = MessageUtil.getContent(event, bytes); return new MessageDto(content, msg.getEventData(), event); } + + public PagesDto getPages(String event) throws InvalidProtocolBufferException { + var eventData = msgCollector.getMessages().get(event); + var messages = eventData.stream().toList(); + + var counter = new AtomicInteger(-1); + var pages = messages.stream().map(e -> + { + return "http://localhost:8001/tiktok/events/message?eventName=" + event + "&page=" + counter.incrementAndGet(); + }).toList(); + + return new PagesDto(event, messages.size(), pages); + } + + @Value + public class PagesDto { + String eventName; + int pages; + List links; + } + + @Value public class MessageDto { String content; diff --git a/Tools-EventsWebViewer/src/main/java/io/github/jwdeveloper/tiktok/webviewer/handlers/TikTokHandler.java b/Tools-EventsWebViewer/src/main/java/io/github/jwdeveloper/tiktok/webviewer/handlers/TikTokHandler.java index da21628..c36ea63 100644 --- a/Tools-EventsWebViewer/src/main/java/io/github/jwdeveloper/tiktok/webviewer/handlers/TikTokHandler.java +++ b/Tools-EventsWebViewer/src/main/java/io/github/jwdeveloper/tiktok/webviewer/handlers/TikTokHandler.java @@ -23,6 +23,7 @@ package io.github.jwdeveloper.tiktok.webviewer.handlers; import com.google.gson.Gson; +import com.google.gson.GsonBuilder; import com.google.protobuf.InvalidProtocolBufferException; import io.github.jwdeveloper.tiktok.webviewer.TikTokManager; import io.javalin.http.Context; @@ -55,7 +56,7 @@ public class TikTokHandler { public void events(Context context) throws SQLException { var events = tikTokManager.getEventsNames(); - var gson = new Gson(); + var gson = getGson(); var result = gson.toJson(events); context.result(result); context.status(200); @@ -63,8 +64,22 @@ public class TikTokHandler { public void eventMessage(Context context) throws InvalidProtocolBufferException { String name = context.queryParam("eventName"); - var result = tikTokManager.getMessage(name); - var gson = new Gson(); + String page = context.queryParam("page"); + + var result = tikTokManager.getMessage(name, page); + var gson = getGson(); context.result(gson.toJson(result)); } + + public void eventPages(Context context) throws InvalidProtocolBufferException { + String name = context.queryParam("eventName"); + var result = tikTokManager.getPages(name); + var gson = getGson(); + context.result(gson.toJson(result)); + } + + + public Gson getGson() { + return new GsonBuilder().disableHtmlEscaping().setPrettyPrinting().create(); + } } diff --git a/Tools-EventsWebViewer/src/main/resources/public/index.html b/Tools-EventsWebViewer/src/main/resources/public/index.html index b43cfe3..e7e5d51 100644 --- a/Tools-EventsWebViewer/src/main/resources/public/index.html +++ b/Tools-EventsWebViewer/src/main/resources/public/index.html @@ -103,6 +103,10 @@ language: 'json', theme: 'vs-dark' }); + editor.onDidChangeModelContent(function () { + console.log("hello") + }); + }); @@ -130,11 +134,8 @@
@@ -156,10 +157,9 @@