From d9ef60ccad55b037164cd61e8c64cdd5ff74b592 Mon Sep 17 00:00:00 2001 From: JW Date: Wed, 23 Aug 2023 20:55:40 +0200 Subject: [PATCH] Changes: - Implementation on all features in `clientSettings` - Code optimization - More detail exceptions - Downloading gifts --- .../jwdeveloper/tiktok/ClientSettings.java | 20 +- .../github/jwdeveloper/tiktok/Constants.java | 7 +- .../tiktok/events/TikTokEventBuilder.java | 85 ++++--- ...iveEvent.java => TikTokEventConsumer.java} | 2 +- .../messages/TikTokGiftMessageEvent.java | 41 ++-- .../messages/TikTokRankUpdateEvent.java | 20 +- .../TikTokLiveMessageException.java | 33 +++ .../TikTokLiveMessageParsingException.java | 23 -- .../TikTokLiveOfflineHostException.java | 8 + .../TikTokMessageMappingException.java | 15 ++ .../TikTokProtocolBufferException.java | 15 ++ .../tiktok/handler/TikTokMessageHandler.java | 10 + .../Resource/ClientFetchDataResponse.java | 7 - .../jwdeveloper/tiktok/live/GiftManager.java | 14 ++ .../jwdeveloper/tiktok/live/LiveClient.java | 1 + .../jwdeveloper/tiktok/models/GiftId.java | 4 +- .../jwdeveloper/tiktok/models/GiftStrike.java | 6 + .../tiktok/models/gifts/DefaultFormat.java | 19 +- .../tiktok/models/gifts/DisplayText.java | 11 +- .../tiktok/models/gifts/GiftLabelIcon.java | 19 +- .../tiktok/models/gifts/GiftPanelBanner.java | 11 +- .../tiktok/models/gifts/Image.java | 19 +- .../tiktok/models/gifts/LeftIcon.java | 19 +- .../tiktok/models/gifts/LockInfo.java | 5 +- .../{TikTokGift.java => TikTokGiftInfo.java} | 2 +- .../jwdeveloper/tiktok/TikTokGiftManager.java | 52 +++-- .../jwdeveloper/tiktok/TikTokLiveClient.java | 77 +++--- .../tiktok/TikTokLiveClientBuilder.java | 219 ++++++++++-------- .../jwdeveloper/tiktok}/TikTokRoomInfo.java | 4 +- .../tiktok/handlers/TikTokEventHandler.java | 34 ++- .../tiktok/handlers/TikTokMessageHandler.java | 93 +++++++- ... => TikTokMessageHandlerRegistration.java} | 52 ++--- .../handlers/WebResponseHandlerBase.java | 90 ------- .../tiktok/http/TikTokApiService.java | 12 +- .../websocket/TikTokWebSocketClient.java | 38 ++- .../websocket/TikTokWebSocketListener.java | 56 +++-- .../tiktok/WebResponseHandlerTests.java | 24 +- .../tiktok/ConfigurationExample.java | 24 +- .../io/github/jwdeveloper/tiktok/Main.java | 31 +-- .../jwdeveloper/tiktok/SimpleExample.java | 13 +- .../events_generator/EventsGenerator.java | 5 +- .../intefacee/EventsInterfaceGenerator.java | 10 +- .../tiktok/{ => utils}/FilesUtility.java | 2 +- .../jwdeveloper/tiktok/FilesUtility.class | Bin 2848 -> 0 bytes .../events_generator/EventsGenerator.class | Bin 4001 -> 4007 bytes .../intefacee/EventsInterfaceGenerator.class | Bin 6200 -> 6235 bytes 46 files changed, 684 insertions(+), 568 deletions(-) rename API/src/main/java/io/github/jwdeveloper/tiktok/events/{TikTokLiveEvent.java => TikTokEventConsumer.java} (72%) create mode 100644 API/src/main/java/io/github/jwdeveloper/tiktok/exceptions/TikTokLiveMessageException.java delete mode 100644 API/src/main/java/io/github/jwdeveloper/tiktok/exceptions/TikTokLiveMessageParsingException.java create mode 100644 API/src/main/java/io/github/jwdeveloper/tiktok/exceptions/TikTokLiveOfflineHostException.java create mode 100644 API/src/main/java/io/github/jwdeveloper/tiktok/exceptions/TikTokMessageMappingException.java create mode 100644 API/src/main/java/io/github/jwdeveloper/tiktok/exceptions/TikTokProtocolBufferException.java create mode 100644 API/src/main/java/io/github/jwdeveloper/tiktok/handler/TikTokMessageHandler.java delete mode 100644 API/src/main/java/io/github/jwdeveloper/tiktok/http/Resource/ClientFetchDataResponse.java create mode 100644 API/src/main/java/io/github/jwdeveloper/tiktok/live/GiftManager.java create mode 100644 API/src/main/java/io/github/jwdeveloper/tiktok/models/GiftStrike.java rename API/src/main/java/io/github/jwdeveloper/tiktok/models/gifts/{TikTokGift.java => TikTokGiftInfo.java} (98%) rename {API/src/main/java/io/github/jwdeveloper/tiktok/live => Client/src/main/java/io/github/jwdeveloper/tiktok}/TikTokRoomInfo.java (70%) rename Client/src/main/java/io/github/jwdeveloper/tiktok/handlers/{WebResponseHandler.java => TikTokMessageHandlerRegistration.java} (79%) delete mode 100644 Client/src/main/java/io/github/jwdeveloper/tiktok/handlers/WebResponseHandlerBase.java rename Tools/src/main/java/io/github/jwdeveloper/tiktok/{ => utils}/FilesUtility.java (95%) delete mode 100644 Tools/target/classes/io/github/jwdeveloper/tiktok/FilesUtility.class diff --git a/API/src/main/java/io/github/jwdeveloper/tiktok/ClientSettings.java b/API/src/main/java/io/github/jwdeveloper/tiktok/ClientSettings.java index d0fc367..c2a8c02 100644 --- a/API/src/main/java/io/github/jwdeveloper/tiktok/ClientSettings.java +++ b/API/src/main/java/io/github/jwdeveloper/tiktok/ClientSettings.java @@ -12,16 +12,7 @@ public class ClientSettings { /// /// Timeout for Connections /// - private Duration timeout; - /// - /// Polling-Interval for Socket-Connection - /// - /// Proxy for Connection - /// // public RotatingProxy Proxy; /// @@ -35,6 +26,11 @@ public class ClientSettings { /// private boolean retryOnConnectionFailure; + /// + /// Wait to connect again for selected amount of time + /// + private Duration retryConnectionTimeout; + /// /// Whether to handle Messages received from Room when Connecting /// @@ -59,12 +55,6 @@ public class ClientSettings { /// private boolean printMessageData; - /// - /// Whether to check Messages for Unparsed Data - /// - private boolean checkForUnparsedData; - - /// /// Tiktok user name /// 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 5f0cf8d..d959207 100644 --- a/API/src/main/java/io/github/jwdeveloper/tiktok/Constants.java +++ b/API/src/main/java/io/github/jwdeveloper/tiktok/Constants.java @@ -40,14 +40,13 @@ public class Constants { public static ClientSettings DefaultClientSettings() { var clientSettings = new ClientSettings(); clientSettings.setTimeout(Duration.ofSeconds(DEFAULT_TIMEOUT)); - clientSettings.setPollingInterval(Duration.ofSeconds(DEFAULT_POLLTIME)); clientSettings.setClientLanguage("en-US"); clientSettings.setHandleExistingMessagesOnConnect(true); clientSettings.setDownloadGiftInfo(true); - clientSettings.setRetryOnConnectionFailure(true); - clientSettings.setPrintToConsole(true); + clientSettings.setRetryOnConnectionFailure(false); + clientSettings.setRetryConnectionTimeout(Duration.ofSeconds(1)); + clientSettings.setPrintToConsole(false); clientSettings.setLogLevel(Level.ALL); - clientSettings.setCheckForUnparsedData(false); clientSettings.setPrintMessageData(false); clientSettings.setClientParameters(Constants.DefaultClientParams()); return clientSettings; diff --git a/API/src/main/java/io/github/jwdeveloper/tiktok/events/TikTokEventBuilder.java b/API/src/main/java/io/github/jwdeveloper/tiktok/events/TikTokEventBuilder.java index b25600c..11df854 100644 --- a/API/src/main/java/io/github/jwdeveloper/tiktok/events/TikTokEventBuilder.java +++ b/API/src/main/java/io/github/jwdeveloper/tiktok/events/TikTokEventBuilder.java @@ -1,95 +1,94 @@ package io.github.jwdeveloper.tiktok.events; import io.github.jwdeveloper.tiktok.events.messages.*; - import java.util.function.Consumer; public interface TikTokEventBuilder { - T onUnhandledSocial(Consumer event); + T onUnhandledSocial(TikTokEventConsumer event); - T onLinkMicFanTicket(Consumer event); + T onLinkMicFanTicket(TikTokEventConsumer event); - T onEnvelope(Consumer event); + T onEnvelope(TikTokEventConsumer event); - T onShopMessage(Consumer event); + T onShopMessage(TikTokEventConsumer event); - T onDetectMessage(Consumer event); + T onDetectMessage(TikTokEventConsumer event); - T onLinkLayerMessage(Consumer event); + T onLinkLayerMessage(TikTokEventConsumer event); - T onConnected(Consumer event); + T onConnected(TikTokEventConsumer event); - T onCaption(Consumer event); + T onCaption(TikTokEventConsumer event); - T onQuestion(Consumer event); + T onQuestion(TikTokEventConsumer event); - T onRoomPinMessage(Consumer event); + T onRoomPinMessage(TikTokEventConsumer event); - T onRoomMessage(Consumer event); + T onRoomMessage(TikTokEventConsumer event); - T onLivePaused(Consumer event); + T onLivePaused(TikTokEventConsumer event); - T onLike(Consumer event); + T onLike(TikTokEventConsumer event); - T onLinkMessage(Consumer event); + T onLinkMessage(TikTokEventConsumer event); - T onBarrageMessage(Consumer event); + T onBarrageMessage(TikTokEventConsumer event); - T onGiftMessage(Consumer event); + T onGiftMessage(TikTokEventConsumer event); - T onLinkMicArmies(Consumer event); + T onLinkMicArmies(TikTokEventConsumer event); - T onEmote(Consumer event); + T onEmote(TikTokEventConsumer event); - T onUnauthorizedMember(Consumer event); + T onUnauthorizedMember(TikTokEventConsumer event); - T onInRoomBanner(Consumer event); + T onInRoomBanner(TikTokEventConsumer event); - T onLinkMicMethod(Consumer event); + T onLinkMicMethod(TikTokEventConsumer event); - T onSubscribe(Consumer event); + T onSubscribe(TikTokEventConsumer event); - T onPollMessage(Consumer event); + T onPollMessage(TikTokEventConsumer event); - T onFollow(Consumer event); + T onFollow(TikTokEventConsumer event); - T onRoomViewerData(Consumer event); + T onRoomViewerData(TikTokEventConsumer event); - T onGoalUpdate(Consumer event); + T onGoalUpdate(TikTokEventConsumer event); - T onComment(Consumer event); + T onComment(TikTokEventConsumer event); - T onRankUpdate(Consumer event); + T onRankUpdate(TikTokEventConsumer event); - T onIMDelete(Consumer event); + T onIMDelete(TikTokEventConsumer event); - T onLiveEnded(Consumer event); + T onLiveEnded(TikTokEventConsumer event); - T onError(Consumer event); + T onError(TikTokEventConsumer event); - T onUnhandled(Consumer event); + T onUnhandled(TikTokEventConsumer event); - T onJoin(Consumer event); + T onJoin(TikTokEventConsumer event); - T onRankText(Consumer event); + T onRankText(TikTokEventConsumer event); - T onShare(Consumer event); + T onShare(TikTokEventConsumer event); - T onUnhandledMember(Consumer event); + T onUnhandledMember(TikTokEventConsumer event); - T onSubNotify(Consumer event); + T onSubNotify(TikTokEventConsumer event); - T onLinkMicBattle(Consumer event); + T onLinkMicBattle(TikTokEventConsumer event); - T onDisconnected(Consumer event); + T onDisconnected(TikTokEventConsumer event); - T onGiftBroadcast(Consumer event); + T onGiftBroadcast(TikTokEventConsumer event); - T onUnhandledControl(Consumer event); + T onUnhandledControl(TikTokEventConsumer event); - T onEvent(Consumer event); + T onEvent(TikTokEventConsumer event); } diff --git a/API/src/main/java/io/github/jwdeveloper/tiktok/events/TikTokLiveEvent.java b/API/src/main/java/io/github/jwdeveloper/tiktok/events/TikTokEventConsumer.java similarity index 72% rename from API/src/main/java/io/github/jwdeveloper/tiktok/events/TikTokLiveEvent.java rename to API/src/main/java/io/github/jwdeveloper/tiktok/events/TikTokEventConsumer.java index 57ecd9a..1156f4a 100644 --- a/API/src/main/java/io/github/jwdeveloper/tiktok/events/TikTokLiveEvent.java +++ b/API/src/main/java/io/github/jwdeveloper/tiktok/events/TikTokEventConsumer.java @@ -2,7 +2,7 @@ package io.github.jwdeveloper.tiktok.events; import io.github.jwdeveloper.tiktok.live.LiveClient; -public interface TikTokLiveEvent +public interface TikTokEventConsumer { void onEvent(LiveClient liveClient, T event); } diff --git a/API/src/main/java/io/github/jwdeveloper/tiktok/events/messages/TikTokGiftMessageEvent.java b/API/src/main/java/io/github/jwdeveloper/tiktok/events/messages/TikTokGiftMessageEvent.java index 5beec96..c07c862 100644 --- a/API/src/main/java/io/github/jwdeveloper/tiktok/events/messages/TikTokGiftMessageEvent.java +++ b/API/src/main/java/io/github/jwdeveloper/tiktok/events/messages/TikTokGiftMessageEvent.java @@ -3,38 +3,39 @@ package io.github.jwdeveloper.tiktok.events.messages; import io.github.jwdeveloper.tiktok.annotations.Nullable; import io.github.jwdeveloper.tiktok.events.TikTokEvent; import io.github.jwdeveloper.tiktok.events.objects.Gift; +import io.github.jwdeveloper.tiktok.events.objects.TikTokGift; import io.github.jwdeveloper.tiktok.events.objects.User; import io.github.jwdeveloper.tiktok.messages.WebcastGiftMessage; import lombok.Getter; @Getter public class TikTokGiftMessageEvent extends TikTokEvent { - private final Gift gift; - @Nullable - private User sender; + private final Gift gift; - private final String purchaseId; + @Nullable + private User sender; - private final String receipt; + private final String purchaseId; - private final Integer amount; + private final String receipt; - private final Boolean streakFinished; + private final Integer amount; - private final Integer streakIndex; + private final Boolean streakFinished; - public TikTokGiftMessageEvent(WebcastGiftMessage msg) { - super(msg.getHeader());; - gift = new Gift(msg.getGiftDetails()); - if(msg.hasSender()) - { - sender = new User(msg.getSender()); + private final Integer streakIndex; + + public TikTokGiftMessageEvent(WebcastGiftMessage msg) { + super(msg.getHeader()); + gift = new Gift(msg.getGiftDetails()); + if (msg.hasSender()) { + sender = new User(msg.getSender()); + } + purchaseId = msg.getLogId(); + receipt = msg.getReceiptJson(); + amount = msg.getAmount(); + streakFinished = msg.getRepeatEnd(); + streakIndex = msg.getRepeatCount(); } - purchaseId = msg.getLogId(); - receipt = msg.getReceiptJson(); - amount = msg.getAmount(); - streakFinished = msg.getRepeatEnd(); - streakIndex = msg.getRepeatCount(); - } } diff --git a/API/src/main/java/io/github/jwdeveloper/tiktok/events/messages/TikTokRankUpdateEvent.java b/API/src/main/java/io/github/jwdeveloper/tiktok/events/messages/TikTokRankUpdateEvent.java index 752e25c..36d54bc 100644 --- a/API/src/main/java/io/github/jwdeveloper/tiktok/events/messages/TikTokRankUpdateEvent.java +++ b/API/src/main/java/io/github/jwdeveloper/tiktok/events/messages/TikTokRankUpdateEvent.java @@ -20,10 +20,15 @@ public class TikTokRankUpdateEvent extends TikTokEvent { var rankData = msg.getData().getRankings(); eventType = rankData.getType(); label = rankData.getLabel(); - rank = rankData.getDetails(0).getLabel(); + if(rankData.getDetailsList().isEmpty()) + { + rank = ""; + } + else + { + rank = rankData.getDetails(0).getLabel(); + } color = rankData.getColor().getColor(); - - } public TikTokRankUpdateEvent(WebcastRankUpdateMessage msg) { @@ -31,7 +36,14 @@ public class TikTokRankUpdateEvent extends TikTokEvent { var rankData = msg.getData().getRankData(); eventType = rankData.getType(); label = rankData.getLabel(); - rank = rankData.getDetails(0).getLabel(); + if(rankData.getDetailsList().isEmpty()) + { + rank = ""; + } + else + { + rank = rankData.getDetails(0).getLabel(); + } color = rankData.getColor().getColor(); } diff --git a/API/src/main/java/io/github/jwdeveloper/tiktok/exceptions/TikTokLiveMessageException.java b/API/src/main/java/io/github/jwdeveloper/tiktok/exceptions/TikTokLiveMessageException.java new file mode 100644 index 0000000..18f5736 --- /dev/null +++ b/API/src/main/java/io/github/jwdeveloper/tiktok/exceptions/TikTokLiveMessageException.java @@ -0,0 +1,33 @@ +package io.github.jwdeveloper.tiktok.exceptions; + +import io.github.jwdeveloper.tiktok.messages.WebcastResponse; +import lombok.Getter; + +import java.util.Base64; + +public class TikTokLiveMessageException extends TikTokLiveException { + + @Getter + private final WebcastResponse.Message webcastMessage; + @Getter + private final WebcastResponse webcastResponse; + + + public TikTokLiveMessageException(WebcastResponse.Message message, + WebcastResponse webcastResponse, + Throwable cause) { + super("Error while handling Message: " + message.getType() + ": \n", cause); + this.webcastMessage = message; + this.webcastResponse = webcastResponse; + } + + public void messageToBase64() + { + var decoded = Base64.getEncoder().encodeToString(webcastMessage.getBinary().toByteArray()); + } + + public void webcastResponseToBase64() + { + var decoded = Base64.getEncoder().encodeToString(webcastResponse.toByteArray()); + } +} diff --git a/API/src/main/java/io/github/jwdeveloper/tiktok/exceptions/TikTokLiveMessageParsingException.java b/API/src/main/java/io/github/jwdeveloper/tiktok/exceptions/TikTokLiveMessageParsingException.java deleted file mode 100644 index 1a1c7a9..0000000 --- a/API/src/main/java/io/github/jwdeveloper/tiktok/exceptions/TikTokLiveMessageParsingException.java +++ /dev/null @@ -1,23 +0,0 @@ -package io.github.jwdeveloper.tiktok.exceptions; - -public class TikTokLiveMessageParsingException extends TikTokLiveException -{ - public TikTokLiveMessageParsingException() { - } - - public TikTokLiveMessageParsingException(String message) { - super(message); - } - - public TikTokLiveMessageParsingException(String message, Throwable cause) { - super(message, cause); - } - - public TikTokLiveMessageParsingException(Throwable cause) { - super(cause); - } - - public TikTokLiveMessageParsingException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { - super(message, cause, enableSuppression, writableStackTrace); - } -} diff --git a/API/src/main/java/io/github/jwdeveloper/tiktok/exceptions/TikTokLiveOfflineHostException.java b/API/src/main/java/io/github/jwdeveloper/tiktok/exceptions/TikTokLiveOfflineHostException.java new file mode 100644 index 0000000..b5090d4 --- /dev/null +++ b/API/src/main/java/io/github/jwdeveloper/tiktok/exceptions/TikTokLiveOfflineHostException.java @@ -0,0 +1,8 @@ +package io.github.jwdeveloper.tiktok.exceptions; + +public class TikTokLiveOfflineHostException extends TikTokLiveException +{ + public TikTokLiveOfflineHostException(String message) { + super(message); + } +} diff --git a/API/src/main/java/io/github/jwdeveloper/tiktok/exceptions/TikTokMessageMappingException.java b/API/src/main/java/io/github/jwdeveloper/tiktok/exceptions/TikTokMessageMappingException.java new file mode 100644 index 0000000..c63c40d --- /dev/null +++ b/API/src/main/java/io/github/jwdeveloper/tiktok/exceptions/TikTokMessageMappingException.java @@ -0,0 +1,15 @@ +package io.github.jwdeveloper.tiktok.exceptions; + + +public class TikTokMessageMappingException extends TikTokLiveException +{ + public TikTokMessageMappingException(Class inputClazz, Class outputClass, Throwable throwable) + { + super("Unable to handle mapping from class: " + inputClazz.getSimpleName() + " to class " + outputClass.getSimpleName(),throwable); + } + + public TikTokMessageMappingException(Class inputClazz, Class outputClass, String message) + { + super("Unable to handle mapping from class: " + inputClazz.getSimpleName() + " to class " + outputClass.getSimpleName()+": "+message); + } +} diff --git a/API/src/main/java/io/github/jwdeveloper/tiktok/exceptions/TikTokProtocolBufferException.java b/API/src/main/java/io/github/jwdeveloper/tiktok/exceptions/TikTokProtocolBufferException.java new file mode 100644 index 0000000..7b5e721 --- /dev/null +++ b/API/src/main/java/io/github/jwdeveloper/tiktok/exceptions/TikTokProtocolBufferException.java @@ -0,0 +1,15 @@ +package io.github.jwdeveloper.tiktok.exceptions; + +import lombok.Getter; + +public class TikTokProtocolBufferException extends TikTokLiveException +{ + @Getter + private final byte[] bytes; + + public TikTokProtocolBufferException(String message, byte[] bytes, Throwable cause) + { + super(message, cause); + this.bytes = bytes; + } +} 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 new file mode 100644 index 0000000..d102f3b --- /dev/null +++ b/API/src/main/java/io/github/jwdeveloper/tiktok/handler/TikTokMessageHandler.java @@ -0,0 +1,10 @@ +package io.github.jwdeveloper.tiktok.handler; + + +import io.github.jwdeveloper.tiktok.events.TikTokEvent; +import io.github.jwdeveloper.tiktok.messages.WebcastResponse; + +public interface TikTokMessageHandler +{ + TikTokEvent handle(WebcastResponse.Message message) throws Exception; +} diff --git a/API/src/main/java/io/github/jwdeveloper/tiktok/http/Resource/ClientFetchDataResponse.java b/API/src/main/java/io/github/jwdeveloper/tiktok/http/Resource/ClientFetchDataResponse.java deleted file mode 100644 index bfe2e6a..0000000 --- a/API/src/main/java/io/github/jwdeveloper/tiktok/http/Resource/ClientFetchDataResponse.java +++ /dev/null @@ -1,7 +0,0 @@ -package io.github.jwdeveloper.tiktok.http.Resource; - -import lombok.Data; - -@Data -public class ClientFetchDataResponse { -} 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 new file mode 100644 index 0000000..1e20618 --- /dev/null +++ b/API/src/main/java/io/github/jwdeveloper/tiktok/live/GiftManager.java @@ -0,0 +1,14 @@ +package io.github.jwdeveloper.tiktok.live; + +import io.github.jwdeveloper.tiktok.events.objects.TikTokGift; +import io.github.jwdeveloper.tiktok.models.GiftId; +import io.github.jwdeveloper.tiktok.models.gifts.TikTokGiftInfo; + +import java.util.Map; + +public interface GiftManager +{ + Map getGiftsInfo(); + + Map getActiveGifts(); +} diff --git a/API/src/main/java/io/github/jwdeveloper/tiktok/live/LiveClient.java b/API/src/main/java/io/github/jwdeveloper/tiktok/live/LiveClient.java index cdc7f5c..43fb9d9 100644 --- a/API/src/main/java/io/github/jwdeveloper/tiktok/live/LiveClient.java +++ b/API/src/main/java/io/github/jwdeveloper/tiktok/live/LiveClient.java @@ -6,5 +6,6 @@ public interface LiveClient { void disconnect(); + GiftManager getGiftManager(); LiveRoomInfo getRoomInfo(); } diff --git a/API/src/main/java/io/github/jwdeveloper/tiktok/models/GiftId.java b/API/src/main/java/io/github/jwdeveloper/tiktok/models/GiftId.java index 382ccf9..bce712d 100644 --- a/API/src/main/java/io/github/jwdeveloper/tiktok/models/GiftId.java +++ b/API/src/main/java/io/github/jwdeveloper/tiktok/models/GiftId.java @@ -7,7 +7,7 @@ import lombok.Data; @AllArgsConstructor public class GiftId { - public long Gift; + private long giftId; - public String UserName; + private String userName; } diff --git a/API/src/main/java/io/github/jwdeveloper/tiktok/models/GiftStrike.java b/API/src/main/java/io/github/jwdeveloper/tiktok/models/GiftStrike.java new file mode 100644 index 0000000..4f984f3 --- /dev/null +++ b/API/src/main/java/io/github/jwdeveloper/tiktok/models/GiftStrike.java @@ -0,0 +1,6 @@ +package io.github.jwdeveloper.tiktok.models; + +public enum GiftStrike +{ + BEGIN, UPDATE, ENDED +} diff --git a/API/src/main/java/io/github/jwdeveloper/tiktok/models/gifts/DefaultFormat.java b/API/src/main/java/io/github/jwdeveloper/tiktok/models/gifts/DefaultFormat.java index 0501399..6383180 100644 --- a/API/src/main/java/io/github/jwdeveloper/tiktok/models/gifts/DefaultFormat.java +++ b/API/src/main/java/io/github/jwdeveloper/tiktok/models/gifts/DefaultFormat.java @@ -3,14 +3,13 @@ package io.github.jwdeveloper.tiktok.models.gifts; import lombok.Data; @Data -public class DefaultFormat -{ - private boolean bold ; - private String color ; - private int font_size ; - private boolean italic ; - private int italic_angle ; - private boolean use_highlight_color ; - private boolean use_remote_color ; - private int weight ; +public class DefaultFormat { + private boolean bold; + private String color; + private int font_size; + private boolean italic; + private int italic_angle; + private boolean use_highlight_color; + private boolean use_remote_color; + private int weight; } \ No newline at end of file diff --git a/API/src/main/java/io/github/jwdeveloper/tiktok/models/gifts/DisplayText.java b/API/src/main/java/io/github/jwdeveloper/tiktok/models/gifts/DisplayText.java index d218682..aea8dec 100644 --- a/API/src/main/java/io/github/jwdeveloper/tiktok/models/gifts/DisplayText.java +++ b/API/src/main/java/io/github/jwdeveloper/tiktok/models/gifts/DisplayText.java @@ -5,10 +5,9 @@ import lombok.Data; import java.util.List; @Data -public class DisplayText -{ - private DefaultFormat default_format ; - private String default_pattern ; - private String key ; - private List pieces ; +public class DisplayText { + private DefaultFormat default_format; + private String default_pattern; + private String key; + private List pieces; } \ No newline at end of file diff --git a/API/src/main/java/io/github/jwdeveloper/tiktok/models/gifts/GiftLabelIcon.java b/API/src/main/java/io/github/jwdeveloper/tiktok/models/gifts/GiftLabelIcon.java index 2cb947e..35cb25b 100644 --- a/API/src/main/java/io/github/jwdeveloper/tiktok/models/gifts/GiftLabelIcon.java +++ b/API/src/main/java/io/github/jwdeveloper/tiktok/models/gifts/GiftLabelIcon.java @@ -5,14 +5,13 @@ import lombok.Data; import java.util.List; @Data -public class GiftLabelIcon -{ - private String avg_color ; - private int height ; - private int image_type ; - private boolean is_animated ; - private String open_web_url ; - private String uri ; - private List url_list ; - private int width ; +public class GiftLabelIcon { + private String avg_color; + private int height; + private int image_type; + private boolean is_animated; + private String open_web_url; + private String uri; + private List url_list; + private int width; } \ No newline at end of file diff --git a/API/src/main/java/io/github/jwdeveloper/tiktok/models/gifts/GiftPanelBanner.java b/API/src/main/java/io/github/jwdeveloper/tiktok/models/gifts/GiftPanelBanner.java index 31edfd6..ac01b21 100644 --- a/API/src/main/java/io/github/jwdeveloper/tiktok/models/gifts/GiftPanelBanner.java +++ b/API/src/main/java/io/github/jwdeveloper/tiktok/models/gifts/GiftPanelBanner.java @@ -6,10 +6,9 @@ import java.util.List; @Data -public class GiftPanelBanner -{ - private List bg_color_values ; - private DisplayText display_text ; - private LeftIcon left_icon ; - private String schema_url ; +public class GiftPanelBanner { + private List bg_color_values; + private DisplayText display_text; + private LeftIcon left_icon; + private String schema_url; } \ No newline at end of file diff --git a/API/src/main/java/io/github/jwdeveloper/tiktok/models/gifts/Image.java b/API/src/main/java/io/github/jwdeveloper/tiktok/models/gifts/Image.java index c088d27..b600ec1 100644 --- a/API/src/main/java/io/github/jwdeveloper/tiktok/models/gifts/Image.java +++ b/API/src/main/java/io/github/jwdeveloper/tiktok/models/gifts/Image.java @@ -5,14 +5,13 @@ import lombok.Data; import java.util.List; @Data -public class Image -{ - private String avg_color ; - private int height ; - private int image_type ; - private boolean is_animated ; - private String open_web_url ; - private String uri ; - private List url_list ; - private int width ; +public class Image { + private String avg_color; + private int height; + private int image_type; + private boolean is_animated; + private String open_web_url; + private String uri; + private List url_list; + private int width; } diff --git a/API/src/main/java/io/github/jwdeveloper/tiktok/models/gifts/LeftIcon.java b/API/src/main/java/io/github/jwdeveloper/tiktok/models/gifts/LeftIcon.java index 635292b..4744a9b 100644 --- a/API/src/main/java/io/github/jwdeveloper/tiktok/models/gifts/LeftIcon.java +++ b/API/src/main/java/io/github/jwdeveloper/tiktok/models/gifts/LeftIcon.java @@ -5,16 +5,15 @@ import lombok.Data; import java.util.List; @Data -public class LeftIcon -{ - private String avg_color ; - private int height ; - private int image_type ; - private boolean is_animated ; - private String open_web_url ; - private String uri ; - private List url_list ; - private int width ; +public class LeftIcon { + private String avg_color; + private int height; + private int image_type; + private boolean is_animated; + private String open_web_url; + private String uri; + private List url_list; + private int width; } diff --git a/API/src/main/java/io/github/jwdeveloper/tiktok/models/gifts/LockInfo.java b/API/src/main/java/io/github/jwdeveloper/tiktok/models/gifts/LockInfo.java index c0a64f8..5f55557 100644 --- a/API/src/main/java/io/github/jwdeveloper/tiktok/models/gifts/LockInfo.java +++ b/API/src/main/java/io/github/jwdeveloper/tiktok/models/gifts/LockInfo.java @@ -1,6 +1,9 @@ package io.github.jwdeveloper.tiktok.models.gifts; +import lombok.Data; + +@Data public class LockInfo { - public int lock_type; + private int lock_type; } diff --git a/API/src/main/java/io/github/jwdeveloper/tiktok/models/gifts/TikTokGift.java b/API/src/main/java/io/github/jwdeveloper/tiktok/models/gifts/TikTokGiftInfo.java similarity index 98% rename from API/src/main/java/io/github/jwdeveloper/tiktok/models/gifts/TikTokGift.java rename to API/src/main/java/io/github/jwdeveloper/tiktok/models/gifts/TikTokGiftInfo.java index c8af9b4..9ab55c6 100644 --- a/API/src/main/java/io/github/jwdeveloper/tiktok/models/gifts/TikTokGift.java +++ b/API/src/main/java/io/github/jwdeveloper/tiktok/models/gifts/TikTokGiftInfo.java @@ -5,7 +5,7 @@ import lombok.Data; import java.util.List; @Data -public class TikTokGift +public class TikTokGiftInfo { private int action_type; private int app_id; diff --git a/Client/src/main/java/io/github/jwdeveloper/tiktok/TikTokGiftManager.java b/Client/src/main/java/io/github/jwdeveloper/tiktok/TikTokGiftManager.java index b7d7fd3..c3d8d60 100644 --- a/Client/src/main/java/io/github/jwdeveloper/tiktok/TikTokGiftManager.java +++ b/Client/src/main/java/io/github/jwdeveloper/tiktok/TikTokGiftManager.java @@ -1,45 +1,47 @@ package io.github.jwdeveloper.tiktok; import io.github.jwdeveloper.tiktok.events.objects.TikTokGift; -import io.github.jwdeveloper.tiktok.http.TikTokApiService; +import io.github.jwdeveloper.tiktok.live.GiftManager; +import io.github.jwdeveloper.tiktok.messages.WebcastGiftMessage; import io.github.jwdeveloper.tiktok.models.GiftId; - +import io.github.jwdeveloper.tiktok.models.gifts.TikTokGiftInfo; import lombok.Getter; import java.util.HashMap; -import java.util.List; import java.util.Map; -import java.util.logging.Logger; -public class TikTokGiftManager { - private Logger logger; - private ClientSettings clientSettings; - private TikTokApiService apiService; - private Map gifts; +public class TikTokGiftManager implements GiftManager { @Getter - private Map activeGifts; + private final Map giftsInfo; + @Getter + private final Map activeGifts; - public TikTokGiftManager(Logger logger, TikTokApiService apiService, ClientSettings clientSettings) { - this.logger = logger; - this.clientSettings = clientSettings; - this.apiService = apiService; - this.gifts = new HashMap<>(); + public TikTokGiftManager() { + giftsInfo = new HashMap<>(); activeGifts = new HashMap<>(); } - public void loadGifts() { - if (!clientSettings.isDownloadGiftInfo()) { - return; + public TikTokGift updateActiveGift(WebcastGiftMessage giftMessage) { + var giftId = new GiftId(giftMessage.getGiftId(), giftMessage.getSender().getUniqueId()); + if (activeGifts.containsKey(giftId)) { + var gift = activeGifts.get(giftId); + gift.setAmount(giftMessage.getAmount()); + } else { + var newGift = new TikTokGift(giftMessage); + activeGifts.put(giftId, newGift); } - logger.info("Fetching gifts"); - //TODO gifts =apiService.fetchAvailableGifts(); + + var gift = activeGifts.get(giftId); + + if (giftMessage.getRepeatEnd()) { + gift.setStreakFinished(true); + activeGifts.remove(giftId); + } + return gift; } - public List getGifts() - { - return gifts.values().stream().toList(); + public void loadGifsInfo(Map gifts) { + this.giftsInfo.putAll(gifts); } - - } diff --git a/Client/src/main/java/io/github/jwdeveloper/tiktok/TikTokLiveClient.java b/Client/src/main/java/io/github/jwdeveloper/tiktok/TikTokLiveClient.java index e8aaf00..90717b3 100644 --- a/Client/src/main/java/io/github/jwdeveloper/tiktok/TikTokLiveClient.java +++ b/Client/src/main/java/io/github/jwdeveloper/tiktok/TikTokLiveClient.java @@ -1,53 +1,70 @@ package io.github.jwdeveloper.tiktok; +import io.github.jwdeveloper.tiktok.events.messages.TikTokDisconnectedEvent; +import io.github.jwdeveloper.tiktok.events.messages.TikTokErrorEvent; import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveException; +import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveOfflineHostException; import io.github.jwdeveloper.tiktok.handlers.TikTokEventHandler; import io.github.jwdeveloper.tiktok.http.TikTokApiService; import io.github.jwdeveloper.tiktok.live.ConnectionState; +import io.github.jwdeveloper.tiktok.live.GiftManager; import io.github.jwdeveloper.tiktok.live.LiveClient; import io.github.jwdeveloper.tiktok.live.LiveRoomInfo; -import io.github.jwdeveloper.tiktok.live.TikTokRoomInfo; import io.github.jwdeveloper.tiktok.websocket.TikTokWebSocketClient; import java.util.logging.Logger; public class TikTokLiveClient implements LiveClient { - private final TikTokRoomInfo meta; - private final TikTokGiftManager giftManager; + private final TikTokRoomInfo liveRoomInfo; + private final TikTokGiftManager tikTokGiftManager; private final TikTokApiService apiClient; private final TikTokWebSocketClient webSocketClient; private final TikTokEventHandler tikTokEventHandler; + private final ClientSettings clientSettings; private final Logger logger; - public TikTokLiveClient(TikTokRoomInfo tikTokLiveMeta, TikTokApiService tikTokApiService, TikTokWebSocketClient webSocketClient, TikTokGiftManager tikTokGiftManager, TikTokEventHandler tikTokEventHandler, + ClientSettings clientSettings, Logger logger) { - this.meta = tikTokLiveMeta; - this.giftManager = tikTokGiftManager; + this.liveRoomInfo = tikTokLiveMeta; + this.tikTokGiftManager = tikTokGiftManager; this.apiClient = tikTokApiService; this.webSocketClient = webSocketClient; - this.logger = logger; this.tikTokEventHandler = tikTokEventHandler; + this.clientSettings = clientSettings; + this.logger = logger; } - - public void connect() { try { tryConnect(); - } catch (Exception e) { - e.printStackTrace(); + } + catch (TikTokLiveException e) + { setState(ConnectionState.DISCONNECTED); + tikTokEventHandler.publish(this, new TikTokErrorEvent(e)); + tikTokEventHandler.publish(this, new TikTokDisconnectedEvent()); + + if(e instanceof TikTokLiveOfflineHostException && clientSettings.isRetryOnConnectionFailure()) + { + try { + Thread.sleep(clientSettings.getRetryConnectionTimeout().toMillis()); + } + catch (Exception ignored){} + logger.info("Reconnecting"); + this.connect(); + } + throw e; } } public void disconnect() { - if (!meta.hasConnectionState(ConnectionState.CONNECTED)) { + if (!liveRoomInfo.hasConnectionState(ConnectionState.CONNECTED)) { return; } webSocketClient.stop(); @@ -55,40 +72,48 @@ public class TikTokLiveClient implements LiveClient { } + public void tryConnect() { - if (meta.hasConnectionState(ConnectionState.CONNECTED)) + if (liveRoomInfo.hasConnectionState(ConnectionState.CONNECTED)) throw new TikTokLiveException("Already connected"); - if (meta.hasConnectionState(ConnectionState.CONNECTING)) + if (liveRoomInfo.hasConnectionState(ConnectionState.CONNECTING)) throw new TikTokLiveException("Already connecting"); logger.info("Connecting"); setState(ConnectionState.CONNECTING); - var roomId = apiClient.fetchRoomId(meta.getUserName()); - meta.setRoomId(roomId); - var roomData =apiClient.fetchRoomInfo(); - if (roomData.getStatus() == 0 || roomData.getStatus() == 4) - { - throw new TikTokLiveException("LiveStream for HostID could not be found. Is the Host online?"); + var roomId = apiClient.fetchRoomId(liveRoomInfo.getUserName()); + liveRoomInfo.setRoomId(roomId); + var roomData = apiClient.fetchRoomInfo(); + if (roomData.getStatus() == 0 || roomData.getStatus() == 4) { + throw new TikTokLiveOfflineHostException("LiveStream for HostID could not be found. Is the Host online?"); } - // giftManager.loadGifts(); + if (clientSettings.isDownloadGiftInfo()) + { + logger.info("Fetch Gift info"); + var gifts = apiClient.fetchAvailableGifts(); + tikTokGiftManager.loadGifsInfo(gifts); + } var clientData = apiClient.fetchClientData(); - webSocketClient.start(clientData); + webSocketClient.start(clientData, this); setState(ConnectionState.CONNECTED); } - - public LiveRoomInfo getRoomInfo() { - return meta; + return liveRoomInfo; + } + + @Override + public GiftManager getGiftManager() { + return tikTokGiftManager; } private void setState(ConnectionState connectionState) { logger.info("TikTokLive client state: " + connectionState.name()); - meta.setConnectionState(connectionState); + liveRoomInfo.setConnectionState(connectionState); } 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 58895c7..3ae8f37 100644 --- a/Client/src/main/java/io/github/jwdeveloper/tiktok/TikTokLiveClientBuilder.java +++ b/Client/src/main/java/io/github/jwdeveloper/tiktok/TikTokLiveClientBuilder.java @@ -2,19 +2,21 @@ package io.github.jwdeveloper.tiktok; import io.github.jwdeveloper.tiktok.events.TikTokEvent; import io.github.jwdeveloper.tiktok.events.TikTokEventBuilder; -import io.github.jwdeveloper.tiktok.handlers.TikTokEventHandler; +import io.github.jwdeveloper.tiktok.events.TikTokEventConsumer; import io.github.jwdeveloper.tiktok.events.messages.*; -import io.github.jwdeveloper.tiktok.handlers.WebResponseHandler; +import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveException; +import io.github.jwdeveloper.tiktok.handlers.TikTokEventHandler; +import io.github.jwdeveloper.tiktok.handlers.TikTokMessageHandlerRegistration; import io.github.jwdeveloper.tiktok.http.TikTokApiService; import io.github.jwdeveloper.tiktok.http.TikTokCookieJar; import io.github.jwdeveloper.tiktok.http.TikTokHttpApiClient; import io.github.jwdeveloper.tiktok.http.TikTokHttpRequestFactory; import io.github.jwdeveloper.tiktok.live.LiveClient; -import io.github.jwdeveloper.tiktok.live.TikTokRoomInfo; import io.github.jwdeveloper.tiktok.websocket.TikTokWebSocketClient; import java.time.Duration; import java.util.function.Consumer; +import java.util.logging.Level; import java.util.logging.Logger; public class TikTokLiveClientBuilder implements TikTokEventBuilder { @@ -40,18 +42,13 @@ public class TikTokLiveClientBuilder implements TikTokEventBuilder event) { - tikTokEventHandler.subscribe(TikTokUnhandledSocialEvent.class,event); + + public TikTokLiveClientBuilder onUnhandledSocial( + TikTokEventConsumer event) { + tikTokEventHandler.subscribe(TikTokUnhandledSocialEvent.class, event); return this; } - public TikTokLiveClientBuilder onLinkMicFanTicket(Consumer event) { - tikTokEventHandler.subscribe(TikTokLinkMicFanTicketEvent.class,event); + public TikTokLiveClientBuilder onLinkMicFanTicket( + TikTokEventConsumer event) { + tikTokEventHandler.subscribe(TikTokLinkMicFanTicketEvent.class, event); return this; } - public TikTokLiveClientBuilder onEnvelope(Consumer event) { - tikTokEventHandler.subscribe(TikTokEnvelopeEvent.class,event); + public TikTokLiveClientBuilder onEnvelope(TikTokEventConsumer event) { + tikTokEventHandler.subscribe(TikTokEnvelopeEvent.class, event); return this; } - public TikTokLiveClientBuilder onShopMessage(Consumer event) { - tikTokEventHandler.subscribe(TikTokShopMessageEvent.class,event); + public TikTokLiveClientBuilder onShopMessage(TikTokEventConsumer event) { + tikTokEventHandler.subscribe(TikTokShopMessageEvent.class, event); return this; } - public TikTokLiveClientBuilder onDetectMessage(Consumer event) { - tikTokEventHandler.subscribe(TikTokDetectMessageEvent.class,event); + public TikTokLiveClientBuilder onDetectMessage( + TikTokEventConsumer event) { + tikTokEventHandler.subscribe(TikTokDetectMessageEvent.class, event); return this; } - public TikTokLiveClientBuilder onLinkLayerMessage(Consumer event) { - tikTokEventHandler.subscribe(TikTokLinkLayerMessageEvent.class,event); + public TikTokLiveClientBuilder onLinkLayerMessage( + TikTokEventConsumer event) { + tikTokEventHandler.subscribe(TikTokLinkLayerMessageEvent.class, event); return this; } - public TikTokLiveClientBuilder onConnected(Consumer event) { - tikTokEventHandler.subscribe(TikTokConnectedEvent.class,event); + public TikTokLiveClientBuilder onConnected(TikTokEventConsumer event) { + tikTokEventHandler.subscribe(TikTokConnectedEvent.class, event); return this; } - public TikTokLiveClientBuilder onCaption(Consumer event) { - tikTokEventHandler.subscribe(TikTokCaptionEvent.class,event); + public TikTokLiveClientBuilder onCaption(TikTokEventConsumer event) { + tikTokEventHandler.subscribe(TikTokCaptionEvent.class, event); return this; } - public TikTokLiveClientBuilder onQuestion(Consumer event) { - tikTokEventHandler.subscribe(TikTokQuestionEvent.class,event); + public TikTokLiveClientBuilder onQuestion(TikTokEventConsumer event) { + tikTokEventHandler.subscribe(TikTokQuestionEvent.class, event); return this; } - public TikTokLiveClientBuilder onRoomPinMessage(Consumer event) { - tikTokEventHandler.subscribe(TikTokRoomPinMessageEvent.class,event); + public TikTokLiveClientBuilder onRoomPinMessage( + TikTokEventConsumer event) { + tikTokEventHandler.subscribe(TikTokRoomPinMessageEvent.class, event); return this; } - public TikTokLiveClientBuilder onRoomMessage(Consumer event) { - tikTokEventHandler.subscribe(TikTokRoomMessageEvent.class,event); + public TikTokLiveClientBuilder onRoomMessage(TikTokEventConsumer event) { + tikTokEventHandler.subscribe(TikTokRoomMessageEvent.class, event); return this; } - public TikTokLiveClientBuilder onLivePaused(Consumer event) { - tikTokEventHandler.subscribe(TikTokLivePausedEvent.class,event); + public TikTokLiveClientBuilder onLivePaused(TikTokEventConsumer event) { + tikTokEventHandler.subscribe(TikTokLivePausedEvent.class, event); return this; } - public TikTokLiveClientBuilder onLike(Consumer event) { - tikTokEventHandler.subscribe(TikTokLikeEvent.class,event); + public TikTokLiveClientBuilder onLike(TikTokEventConsumer event) { + tikTokEventHandler.subscribe(TikTokLikeEvent.class, event); return this; } - public TikTokLiveClientBuilder onLinkMessage(Consumer event) { - tikTokEventHandler.subscribe(TikTokLinkMessageEvent.class,event); + public TikTokLiveClientBuilder onLinkMessage(TikTokEventConsumer event) { + tikTokEventHandler.subscribe(TikTokLinkMessageEvent.class, event); return this; } - public TikTokLiveClientBuilder onBarrageMessage(Consumer event) { - tikTokEventHandler.subscribe(TikTokBarrageMessageEvent.class,event); + public TikTokLiveClientBuilder onBarrageMessage( + TikTokEventConsumer event) { + tikTokEventHandler.subscribe(TikTokBarrageMessageEvent.class, event); return this; } - public TikTokLiveClientBuilder onGiftMessage(Consumer event) { - tikTokEventHandler.subscribe(TikTokGiftMessageEvent.class,event); + public TikTokLiveClientBuilder onGiftMessage(TikTokEventConsumer event) { + tikTokEventHandler.subscribe(TikTokGiftMessageEvent.class, event); return this; } - public TikTokLiveClientBuilder onLinkMicArmies(Consumer event) { - tikTokEventHandler.subscribe(TikTokLinkMicArmiesEvent.class,event); + public TikTokLiveClientBuilder onLinkMicArmies( + TikTokEventConsumer event) { + tikTokEventHandler.subscribe(TikTokLinkMicArmiesEvent.class, event); return this; } - public TikTokLiveClientBuilder onEmote(Consumer event) { - tikTokEventHandler.subscribe(TikTokEmoteEvent.class,event); + public TikTokLiveClientBuilder onEmote(TikTokEventConsumer event) { + tikTokEventHandler.subscribe(TikTokEmoteEvent.class, event); return this; } public TikTokLiveClientBuilder onUnauthorizedMember( - Consumer event) { - tikTokEventHandler.subscribe(TikTokUnauthorizedMemberEvent.class,event); + TikTokEventConsumer event) { + tikTokEventHandler.subscribe(TikTokUnauthorizedMemberEvent.class, event); return this; } - public TikTokLiveClientBuilder onInRoomBanner(Consumer event) { - tikTokEventHandler.subscribe(TikTokInRoomBannerEvent.class,event); + public TikTokLiveClientBuilder onInRoomBanner( + TikTokEventConsumer event) { + tikTokEventHandler.subscribe(TikTokInRoomBannerEvent.class, event); return this; } - public TikTokLiveClientBuilder onLinkMicMethod(Consumer event) { - tikTokEventHandler.subscribe(TikTokLinkMicMethodEvent.class,event); + public TikTokLiveClientBuilder onLinkMicMethod( + TikTokEventConsumer event) { + tikTokEventHandler.subscribe(TikTokLinkMicMethodEvent.class, event); return this; } - public TikTokLiveClientBuilder onSubscribe(Consumer event) { - tikTokEventHandler.subscribe(TikTokSubscribeEvent.class,event); + public TikTokLiveClientBuilder onSubscribe(TikTokEventConsumer event) { + tikTokEventHandler.subscribe(TikTokSubscribeEvent.class, event); return this; } - public TikTokLiveClientBuilder onPollMessage(Consumer event) { - tikTokEventHandler.subscribe(TikTokPollMessageEvent.class,event); + public TikTokLiveClientBuilder onPollMessage(TikTokEventConsumer event) { + tikTokEventHandler.subscribe(TikTokPollMessageEvent.class, event); return this; } - public TikTokLiveClientBuilder onFollow(Consumer event) { - tikTokEventHandler.subscribe(TikTokFollowEvent.class,event); + public TikTokLiveClientBuilder onFollow(TikTokEventConsumer event) { + tikTokEventHandler.subscribe(TikTokFollowEvent.class, event); return this; } - public TikTokLiveClientBuilder onRoomViewerData(Consumer event) { - tikTokEventHandler.subscribe(TikTokRoomViewerDataEvent.class,event); + public TikTokLiveClientBuilder onRoomViewerData( + TikTokEventConsumer event) { + tikTokEventHandler.subscribe(TikTokRoomViewerDataEvent.class, event); return this; } - public TikTokLiveClientBuilder onGoalUpdate(Consumer event) { - tikTokEventHandler.subscribe(TikTokGoalUpdateEvent.class,event); + public TikTokLiveClientBuilder onGoalUpdate(TikTokEventConsumer event) { + tikTokEventHandler.subscribe(TikTokGoalUpdateEvent.class, event); return this; } - public TikTokLiveClientBuilder onComment(Consumer event) { - tikTokEventHandler.subscribe(TikTokCommentEvent.class,event); + public TikTokLiveClientBuilder onComment(TikTokEventConsumer event) { + tikTokEventHandler.subscribe(TikTokCommentEvent.class, event); return this; } - public TikTokLiveClientBuilder onRankUpdate(Consumer event) { - tikTokEventHandler.subscribe(TikTokRankUpdateEvent.class,event); + public TikTokLiveClientBuilder onRankUpdate(TikTokEventConsumer event) { + tikTokEventHandler.subscribe(TikTokRankUpdateEvent.class, event); return this; } - public TikTokLiveClientBuilder onIMDelete(Consumer event) { - tikTokEventHandler.subscribe(TikTokIMDeleteEvent.class,event); + public TikTokLiveClientBuilder onIMDelete(TikTokEventConsumer event) { + tikTokEventHandler.subscribe(TikTokIMDeleteEvent.class, event); return this; } - public TikTokLiveClientBuilder onLiveEnded(Consumer event) { - tikTokEventHandler.subscribe(TikTokLiveEndedEvent.class,event); + public TikTokLiveClientBuilder onLiveEnded(TikTokEventConsumer event) { + tikTokEventHandler.subscribe(TikTokLiveEndedEvent.class, event); return this; } - public TikTokLiveClientBuilder onError(Consumer event) { - tikTokEventHandler.subscribe(TikTokErrorEvent.class,event); + public TikTokLiveClientBuilder onError(TikTokEventConsumer event) { + tikTokEventHandler.subscribe(TikTokErrorEvent.class, event); return this; } - public TikTokLiveClientBuilder onUnhandled(Consumer event) { - tikTokEventHandler.subscribe(TikTokUnhandledEvent.class,event); + public TikTokLiveClientBuilder onUnhandled(TikTokEventConsumer event) { + tikTokEventHandler.subscribe(TikTokUnhandledEvent.class, event); return this; } - public TikTokLiveClientBuilder onJoin(Consumer event) { - tikTokEventHandler.subscribe(TikTokJoinEvent.class,event); + public TikTokLiveClientBuilder onJoin(TikTokEventConsumer event) { + tikTokEventHandler.subscribe(TikTokJoinEvent.class, event); return this; } - public TikTokLiveClientBuilder onRankText(Consumer event) { - tikTokEventHandler.subscribe(TikTokRankTextEvent.class,event); + public TikTokLiveClientBuilder onRankText(TikTokEventConsumer event) { + tikTokEventHandler.subscribe(TikTokRankTextEvent.class, event); return this; } - public TikTokLiveClientBuilder onShare(Consumer event) { - tikTokEventHandler.subscribe(TikTokShareEvent.class,event); + public TikTokLiveClientBuilder onShare(TikTokEventConsumer event) { + tikTokEventHandler.subscribe(TikTokShareEvent.class, event); return this; } - public TikTokLiveClientBuilder onUnhandledMember(Consumer event) { - tikTokEventHandler.subscribe(TikTokUnhandledMemberEvent.class,event); + public TikTokLiveClientBuilder onUnhandledMember( + TikTokEventConsumer event) { + tikTokEventHandler.subscribe(TikTokUnhandledMemberEvent.class, event); return this; } - public TikTokLiveClientBuilder onSubNotify(Consumer event) { - tikTokEventHandler.subscribe(TikTokSubNotifyEvent.class,event); + public TikTokLiveClientBuilder onSubNotify(TikTokEventConsumer event) { + tikTokEventHandler.subscribe(TikTokSubNotifyEvent.class, event); return this; } - public TikTokLiveClientBuilder onLinkMicBattle(Consumer event) { - tikTokEventHandler.subscribe(TikTokLinkMicBattleEvent.class,event); + public TikTokLiveClientBuilder onLinkMicBattle( + TikTokEventConsumer event) { + tikTokEventHandler.subscribe(TikTokLinkMicBattleEvent.class, event); return this; } - public TikTokLiveClientBuilder onDisconnected(Consumer event) { - tikTokEventHandler.subscribe(TikTokDisconnectedEvent.class,event); + public TikTokLiveClientBuilder onDisconnected( + TikTokEventConsumer event) { + tikTokEventHandler.subscribe(TikTokDisconnectedEvent.class, event); return this; } - public TikTokLiveClientBuilder onGiftBroadcast(Consumer event) { - tikTokEventHandler.subscribe(TikTokGiftBroadcastEvent.class,event); + public TikTokLiveClientBuilder onGiftBroadcast( + TikTokEventConsumer event) { + tikTokEventHandler.subscribe(TikTokGiftBroadcastEvent.class, event); return this; } - public TikTokLiveClientBuilder onUnhandledControl(Consumer event) { - tikTokEventHandler.subscribe(TikTokUnhandledControlEvent.class,event); + public TikTokLiveClientBuilder onUnhandledControl( + TikTokEventConsumer event) { + tikTokEventHandler.subscribe(TikTokUnhandledControlEvent.class, event); return this; } - public TikTokLiveClientBuilder onEvent(Consumer event) { - tikTokEventHandler.subscribe(TikTokEvent.class,event); + public TikTokLiveClientBuilder onEvent(TikTokEventConsumer event) { + tikTokEventHandler.subscribe(TikTokEvent.class, event); return this; } } @@ -306,3 +324,6 @@ public class TikTokLiveClientBuilder implements TikTokEventBuilder events; +public class TikTokEventHandler { + private final Map events; - public TikTokEventHandler() - { + public TikTokEventHandler() { events = new HashMap<>(); } - public void publish(TikTokEvent tikTokEvent) - { - if(events.containsKey(TikTokEvent.class.getSimpleName())) - { + public void publish(TikTokLiveClient tikTokLiveClient, TikTokEvent tikTokEvent) { + if (events.containsKey(TikTokEvent.class.getSimpleName())) { var handler = events.get(TikTokEvent.class.getSimpleName()); - handler.accept(tikTokEvent); + handler.onEvent(tikTokLiveClient, tikTokEvent); } var name = tikTokEvent.getClass().getSimpleName(); - if(!events.containsKey(name)) - { + if (!events.containsKey(name)) { return; } var handler = events.get(name); - handler.accept(tikTokEvent); + handler.onEvent(tikTokLiveClient, tikTokEvent); } - public void subscribe(Class clazz, Consumer event) - { - events.put(clazz.getSimpleName(),event); + public void subscribe(Class clazz, TikTokEventConsumer event) { + events.put(clazz.getSimpleName(), event); } - - + public void unsubscribe(Class clazz) { + events.remove(clazz); + } } 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 b8b2714..75d932b 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 @@ -1,12 +1,97 @@ package io.github.jwdeveloper.tiktok.handlers; +import com.google.protobuf.ByteString; +import io.github.jwdeveloper.tiktok.ClientSettings; +import io.github.jwdeveloper.tiktok.TikTokLiveClient; import io.github.jwdeveloper.tiktok.events.TikTokEvent; +import io.github.jwdeveloper.tiktok.events.messages.TikTokErrorEvent; +import io.github.jwdeveloper.tiktok.events.messages.TikTokUnhandledEvent; +import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveMessageException; +import io.github.jwdeveloper.tiktok.exceptions.TikTokMessageMappingException; import io.github.jwdeveloper.tiktok.messages.WebcastResponse; -public interface TikTokMessageHandler -{ - Class getHandleClazz(); +import java.util.Arrays; +import java.util.Base64; +import java.util.HashMap; +import java.util.Map; +import java.util.function.Function; +import java.util.logging.Logger; - TikTokEvent handle(WebcastResponse.Message message) throws Exception; + +public abstract class TikTokMessageHandler { + + private final Map handlers; + private final TikTokEventHandler tikTokEventHandler; + private final ClientSettings clientSettings; + protected final Logger logger; + + public TikTokMessageHandler(TikTokEventHandler tikTokEventHandler,ClientSettings clientSettings, Logger logger) { + handlers = new HashMap<>(); + this.tikTokEventHandler = tikTokEventHandler; + this.clientSettings = clientSettings; + this.logger = logger; + init(); + } + + public abstract void init(); + + public void register(Class clazz, Function func) { + handlers.put(clazz.getSimpleName(), func::apply); + } + + public void register(Class input, Class output) { + register(input, (e) -> mapMessageToEvent(input, output, e)); + } + + public void handle(TikTokLiveClient client, WebcastResponse webcastResponse) { + for (var message : webcastResponse.getMessagesList()) { + try + { + if(clientSettings.isPrintMessageData()) + { + var type= message.getType(); + var base64 = Base64.getEncoder().encodeToString(message.getBinary().toByteArray()); + logger.info(type+": \n "+base64); + } + handleSingleMessage(client, message); + } catch (Exception e) { + var exception = new TikTokLiveMessageException(message, webcastResponse, e); + tikTokEventHandler.publish(client, new TikTokErrorEvent(exception)); + } + } + } + + private void handleSingleMessage(TikTokLiveClient client, WebcastResponse.Message message) throws Exception { + if (!handlers.containsKey(message.getType())) { + tikTokEventHandler.publish(client, new TikTokUnhandledEvent(message)); + return; + } + var handler = handlers.get(message.getType()); + var tiktokEvent = handler.handle(message); + tikTokEventHandler.publish(client, tiktokEvent); + } + + protected TikTokEvent mapMessageToEvent(Class inputClazz, Class outputClass, WebcastResponse.Message message) { + try { + var parseMethod = inputClazz.getDeclaredMethod("parseFrom", ByteString.class); + var deserialized = parseMethod.invoke(null, message.getBinary()); + + 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); + } + } } diff --git a/Client/src/main/java/io/github/jwdeveloper/tiktok/handlers/WebResponseHandler.java b/Client/src/main/java/io/github/jwdeveloper/tiktok/handlers/TikTokMessageHandlerRegistration.java similarity index 79% rename from Client/src/main/java/io/github/jwdeveloper/tiktok/handlers/WebResponseHandler.java rename to Client/src/main/java/io/github/jwdeveloper/tiktok/handlers/TikTokMessageHandlerRegistration.java index 2d7dbdf..384277c 100644 --- a/Client/src/main/java/io/github/jwdeveloper/tiktok/handlers/WebResponseHandler.java +++ b/Client/src/main/java/io/github/jwdeveloper/tiktok/handlers/TikTokMessageHandlerRegistration.java @@ -1,6 +1,8 @@ package io.github.jwdeveloper.tiktok.handlers; +import io.github.jwdeveloper.tiktok.ClientSettings; import io.github.jwdeveloper.tiktok.TikTokGiftManager; +import io.github.jwdeveloper.tiktok.TikTokRoomInfo; import io.github.jwdeveloper.tiktok.events.TikTokEvent; import io.github.jwdeveloper.tiktok.events.messages.*; import io.github.jwdeveloper.tiktok.events.objects.TikTokGift; @@ -9,15 +11,22 @@ import io.github.jwdeveloper.tiktok.models.GiftId; import io.github.jwdeveloper.tiktok.models.SocialTypes; import lombok.SneakyThrows; +import java.util.logging.Logger; import java.util.regex.Matcher; import java.util.regex.Pattern; -public class WebResponseHandler extends WebResponseHandlerBase { +public class TikTokMessageHandlerRegistration extends TikTokMessageHandler { private final TikTokGiftManager giftManager; + private final TikTokRoomInfo roomInfo; - public WebResponseHandler(TikTokEventHandler tikTokEventHandler, TikTokGiftManager giftManager) { - super(tikTokEventHandler); + public TikTokMessageHandlerRegistration(TikTokEventHandler tikTokEventHandler, + ClientSettings clientSettings, + Logger logger, + TikTokGiftManager giftManager, + TikTokRoomInfo roomInfo) { + super(tikTokEventHandler, clientSettings, logger); this.giftManager = giftManager; + this.roomInfo = roomInfo; } @Override @@ -30,7 +39,7 @@ public class WebResponseHandler extends WebResponseHandlerBase { //Room status events register(WebcastLiveIntroMessage.class, TikTokRoomMessageEvent.class); - register(WebcastRoomUserSeqMessage.class, TikTokRoomViewerDataEvent.class); //TODO update viewer count ViewerCount = userSeqMessage.ViewerCount; + register(WebcastRoomUserSeqMessage.class, this::handleRoomUserSeqMessage); register(RoomMessage.class, TikTokRoomMessageEvent.class); register(WebcastRoomMessage.class, TikTokRoomMessageEvent.class); register(WebcastCaptionMessage.class, TikTokCaptionEvent.class); @@ -74,9 +83,9 @@ public class WebResponseHandler extends WebResponseHandlerBase { } + @SneakyThrows - private TikTokEvent handleWebcastControlMessage(WebcastResponse.Message msg) - { + private TikTokEvent handleWebcastControlMessage(WebcastResponse.Message msg) { var message = WebcastControlMessage.parseFrom(msg.getBinary()); return switch (message.getAction()) { case STREAM_PAUSED -> new TikTokLivePausedEvent(); @@ -88,29 +97,7 @@ public class WebResponseHandler extends WebResponseHandlerBase { @SneakyThrows private TikTokEvent handleGift(WebcastResponse.Message msg) { var giftMessage = WebcastGiftMessage.parseFrom(msg.getBinary()); - var giftId = new GiftId(giftMessage.getGiftId(), giftMessage.getSender().getUniqueId()); - - var activeGifts = giftManager.getActiveGifts(); - if (activeGifts.containsKey(giftId)) { - // Debug.Log($"Updating Gift[{giftId.Gift}]Amount[{message.Amount}]"); - var gift = activeGifts.get(giftId); - gift.setAmount(giftMessage.getAmount()); - } else { - TikTokGift newGift = new TikTokGift(giftMessage); - activeGifts.put(giftId, newGift); - // Debug.Log($"New Gift[{giftId.Gift}]Amount[{message.Amount}]"); - // RunEvent(OnGift, newGift); - } - if (giftMessage.getRepeatEnd()) { - //if (ShouldLog(LogLevel.Verbose)) - // Debug.Log($"GiftStreak Ended: [{giftId.Gift}] Amount[{message.Amount}]") - var gift = activeGifts.get(giftId); - gift.setStreakFinished(true); - activeGifts.remove(gift); - } - - // Debug.Log($"Handling GiftMessage"); - + giftManager.updateActiveGift(giftMessage); return new TikTokGiftMessageEvent(giftMessage); } @@ -146,4 +133,11 @@ public class WebResponseHandler extends WebResponseHandlerBase { default -> new TikTokUnhandledMemberEvent(message); }; } + + private TikTokEvent handleRoomUserSeqMessage(WebcastResponse.Message msg) + { + var event = (TikTokRoomViewerDataEvent)mapMessageToEvent(WebcastRoomUserSeqMessage.class, TikTokRoomViewerDataEvent.class, msg); + roomInfo.setViewersCount(event.getViewerCount()); + return event; + } } diff --git a/Client/src/main/java/io/github/jwdeveloper/tiktok/handlers/WebResponseHandlerBase.java b/Client/src/main/java/io/github/jwdeveloper/tiktok/handlers/WebResponseHandlerBase.java deleted file mode 100644 index 36183eb..0000000 --- a/Client/src/main/java/io/github/jwdeveloper/tiktok/handlers/WebResponseHandlerBase.java +++ /dev/null @@ -1,90 +0,0 @@ -package io.github.jwdeveloper.tiktok.handlers; - - -import com.google.protobuf.ByteString; -import io.github.jwdeveloper.tiktok.events.TikTokEvent; -import io.github.jwdeveloper.tiktok.events.messages.TikTokErrorEvent; -import io.github.jwdeveloper.tiktok.events.messages.TikTokUnhandledEvent; -import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveException; -import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveMessageParsingException; -import io.github.jwdeveloper.tiktok.messages.WebcastResponse; - -import java.util.Arrays; -import java.util.Base64; -import java.util.HashMap; -import java.util.Map; -import java.util.function.Function; - - -public abstract class WebResponseHandlerBase { - - private final Map handlers; - private final TikTokEventHandler tikTokEventHandler; - - public WebResponseHandlerBase(TikTokEventHandler tikTokEventHandler) { - handlers = new HashMap<>(); - this.tikTokEventHandler = tikTokEventHandler; - init(); - } - - public abstract void init(); - - public void register(Class input, Class output) { - register(input, (e) -> - { - try { - var parseMethod = input.getDeclaredMethod("parseFrom", ByteString.class); - var deserialized = parseMethod.invoke(null, e.getBinary()); - - var constructors = Arrays.stream(output.getConstructors()).filter(ea -> Arrays.stream(ea.getParameterTypes()).toList().contains(input)).findFirst(); - - var tiktokEvent = constructors.get().newInstance(deserialized); - return (TikTokEvent)tiktokEvent; - } catch (Exception ex) - { - throw new TikTokLiveMessageParsingException("Unable to handle parsing from class: " + input.getSimpleName() + " to class " + output.getSimpleName(), ex); - } - }); - } - - public void register(Class clazz, Function func) { - var haandler = new TikTokMessageHandler() { - @Override - public Class getHandleClazz() { - return clazz; - } - - @Override - public TikTokEvent handle(WebcastResponse.Message message) throws Exception { - return func.apply(message); - } - }; - - handlers.put(haandler.getHandleClazz().getSimpleName(), haandler); - } - - public void handle(WebcastResponse webcastResponse) { - for (var message : webcastResponse.getMessagesList()) { - try { - handleSingleMessage(message); - } catch (Exception e) - { - - var decoded = Base64.getEncoder().encodeToString(message.getBinary().toByteArray()); - - var exception = new TikTokLiveException("Error whilst Handling Message"+message.getType()+": \n"+decoded, e); - tikTokEventHandler.publish(new TikTokErrorEvent(exception)); - } - } - } - - public void handleSingleMessage(WebcastResponse.Message message) throws Exception { - if (!handlers.containsKey(message.getType())) { - tikTokEventHandler.publish(new TikTokUnhandledEvent(message)); - return; - } - var handler = handlers.get(message.getType()); - var tiktokEvent = handler.handle(message); - tikTokEventHandler.publish(tiktokEvent); - } -} diff --git a/Client/src/main/java/io/github/jwdeveloper/tiktok/http/TikTokApiService.java b/Client/src/main/java/io/github/jwdeveloper/tiktok/http/TikTokApiService.java index 9783599..dc278d2 100644 --- a/Client/src/main/java/io/github/jwdeveloper/tiktok/http/TikTokApiService.java +++ b/Client/src/main/java/io/github/jwdeveloper/tiktok/http/TikTokApiService.java @@ -2,10 +2,10 @@ package io.github.jwdeveloper.tiktok.http; import com.google.gson.Gson; import io.github.jwdeveloper.tiktok.ClientSettings; -import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveException; +import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveOfflineHostException; import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveRequestException; import io.github.jwdeveloper.tiktok.live.LiveRoomMeta; -import io.github.jwdeveloper.tiktok.models.gifts.TikTokGift; +import io.github.jwdeveloper.tiktok.models.gifts.TikTokGiftInfo; import io.github.jwdeveloper.tiktok.messages.WebcastResponse; import java.util.HashMap; @@ -50,7 +50,7 @@ public class TikTokApiService { } if (id.isEmpty()) { - throw new TikTokLiveException("Unable to fetch room ID"); + throw new TikTokLiveOfflineHostException("Unable to fetch room ID, live host could be offline or name is misspelled"); } clientSettings.getClientParameters().put("room_id", id); @@ -99,7 +99,7 @@ public class TikTokApiService { } } - public Map fetchAvailableGifts() { + public Map fetchAvailableGifts() { try { var response = apiClient.GetJObjectFromWebcastAPI("gift/list/", clientSettings.getClientParameters()); if(!response.has("data")) @@ -112,11 +112,11 @@ public class TikTokApiService { return new HashMap<>(); } var giftsJsonList = dataJson.get("gifts").getAsJsonArray(); - var gifts = new HashMap(); + var gifts = new HashMap(); var gson = new Gson(); for(var jsonGift : giftsJsonList) { - var gift = gson.fromJson(jsonGift, TikTokGift.class); + var gift = gson.fromJson(jsonGift, TikTokGiftInfo.class); logger.info("Found Available Gift "+ gift.getName()+ " with ID "+gift.getId()); gifts.put(gift.getId(),gift); } diff --git a/Client/src/main/java/io/github/jwdeveloper/tiktok/websocket/TikTokWebSocketClient.java b/Client/src/main/java/io/github/jwdeveloper/tiktok/websocket/TikTokWebSocketClient.java index 9142113..e064b66 100644 --- a/Client/src/main/java/io/github/jwdeveloper/tiktok/websocket/TikTokWebSocketClient.java +++ b/Client/src/main/java/io/github/jwdeveloper/tiktok/websocket/TikTokWebSocketClient.java @@ -3,9 +3,10 @@ package io.github.jwdeveloper.tiktok.websocket; import io.github.jwdeveloper.tiktok.ClientSettings; import io.github.jwdeveloper.tiktok.Constants; +import io.github.jwdeveloper.tiktok.TikTokLiveClient; import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveException; import io.github.jwdeveloper.tiktok.handlers.TikTokEventHandler; -import io.github.jwdeveloper.tiktok.handlers.WebResponseHandler; +import io.github.jwdeveloper.tiktok.handlers.TikTokMessageHandlerRegistration; import io.github.jwdeveloper.tiktok.http.HttpUtils; import io.github.jwdeveloper.tiktok.http.TikTokCookieJar; import io.github.jwdeveloper.tiktok.http.TikTokHttpRequestFactory; @@ -23,18 +24,18 @@ public class TikTokWebSocketClient { private final ClientSettings clientSettings; private final TikTokCookieJar tikTokCookieJar; private final TikTokHttpRequestFactory factory; - private final WebResponseHandler webResponseHandler; + private final TikTokMessageHandlerRegistration webResponseHandler; private final TikTokEventHandler tikTokEventHandler; private WebSocket webSocket; - private boolean isConnected; + private TikTokLiveClient tikTokLiveClient; public TikTokWebSocketClient(Logger logger, TikTokCookieJar tikTokCookieJar, TikTokHttpRequestFactory factory, ClientSettings clientSettings, - WebResponseHandler webResponseHandler, + TikTokMessageHandlerRegistration webResponseHandler, TikTokEventHandler tikTokEventHandler) { this.logger = logger; this.tikTokCookieJar = tikTokCookieJar; @@ -45,21 +46,22 @@ public class TikTokWebSocketClient { isConnected = false; } - public void start(WebcastResponse webcastResponse) - { - if(isConnected) - { + public void start(WebcastResponse webcastResponse, TikTokLiveClient tikTokLiveClient) { + this.tikTokLiveClient = tikTokLiveClient; + if (isConnected) { stop(); } if (webcastResponse.getSocketUrl().isEmpty() || webcastResponse.getSocketParamsList().isEmpty()) { throw new TikTokLiveException("Could not find Room"); } try { - var url =getWebSocketUrl(webcastResponse); - webSocket =startWebSocket(url); - if (clientSettings.isHandleExistingMessagesOnConnect()) { - // HandleWebcastMessages(webcastResponse); + var url = getWebSocketUrl(webcastResponse); + if (clientSettings.isHandleExistingMessagesOnConnect()) + { + logger.info("Handling existing messages"); + webResponseHandler.handle(tikTokLiveClient, webcastResponse); } + webSocket = startWebSocket(url); } catch (Exception e) { throw new TikTokLiveException("Failed to connect to the websocket", e); } @@ -82,23 +84,17 @@ public class TikTokWebSocketClient { private WebSocket startWebSocket(String url) throws Exception { var cookie = tikTokCookieJar.parseCookies(); - // System.out.println("WssIP: " + url); - // System.out.println("Cookie: " + cookie); - var map = new HashMap(); map.put("Cookie", cookie); - - return factory.openSocket() + return factory.openSocket() .subprotocols("echo-protocol") .connectTimeout(Duration.ofSeconds(15)) .header("Cookie", cookie) - .buildAsync(URI.create(url), new TikTokWebSocketListener(webResponseHandler, tikTokEventHandler)).get(); + .buildAsync(URI.create(url), new TikTokWebSocketListener(webResponseHandler, tikTokEventHandler, tikTokLiveClient)).get(); } - public void stop() { - if(isConnected && webSocket != null) - { + if (isConnected && webSocket != null) { webSocket.sendClose(WebSocket.NORMAL_CLOSURE, "ok"); } } 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 1c5cc06..c4db861 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 @@ -1,12 +1,14 @@ package io.github.jwdeveloper.tiktok.websocket; +import com.google.protobuf.ByteString; +import io.github.jwdeveloper.tiktok.TikTokLiveClient; import io.github.jwdeveloper.tiktok.events.messages.TikTokConnectedEvent; import io.github.jwdeveloper.tiktok.events.messages.TikTokDisconnectedEvent; import io.github.jwdeveloper.tiktok.events.messages.TikTokErrorEvent; -import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveMessageParsingException; +import io.github.jwdeveloper.tiktok.exceptions.TikTokProtocolBufferException; import io.github.jwdeveloper.tiktok.handlers.TikTokEventHandler; -import io.github.jwdeveloper.tiktok.handlers.WebResponseHandler; +import io.github.jwdeveloper.tiktok.handlers.TikTokMessageHandlerRegistration; import io.github.jwdeveloper.tiktok.messages.WebcastResponse; import io.github.jwdeveloper.tiktok.messages.WebcastWebsocketAck; import io.github.jwdeveloper.tiktok.messages.WebcastWebsocketMessage; @@ -14,18 +16,23 @@ import io.github.jwdeveloper.tiktok.messages.WebcastWebsocketMessage; import java.io.ByteArrayOutputStream; import java.net.http.WebSocket; import java.nio.ByteBuffer; +import java.util.Optional; import java.util.concurrent.CompletionStage; public class TikTokWebSocketListener implements java.net.http.WebSocket.Listener { private final ByteArrayOutputStream accumulatedData = new ByteArrayOutputStream(); - private final WebResponseHandler webResponseHandler; + private final TikTokMessageHandlerRegistration webResponseHandler; private final TikTokEventHandler tikTokEventHandler; + private final TikTokLiveClient tikTokLiveClient; - public TikTokWebSocketListener(WebResponseHandler webResponseHandler, TikTokEventHandler tikTokEventHandler) { + public TikTokWebSocketListener(TikTokMessageHandlerRegistration webResponseHandler, + TikTokEventHandler tikTokEventHandler, + TikTokLiveClient tikTokLiveClient) { this.webResponseHandler = webResponseHandler; this.tikTokEventHandler = tikTokEventHandler; + this.tikTokLiveClient = tikTokLiveClient; } @Override @@ -39,7 +46,7 @@ public class TikTokWebSocketListener implements java.net.http.WebSocket.Listener accumulatedData.reset(); } } catch (Exception e) { - tikTokEventHandler.publish(new TikTokErrorEvent(e)); + tikTokEventHandler.publish(tikTokLiveClient, new TikTokErrorEvent(e)); } webSocket.request(1); return null; @@ -47,38 +54,51 @@ public class TikTokWebSocketListener implements java.net.http.WebSocket.Listener @Override public void onOpen(java.net.http.WebSocket webSocket) { - tikTokEventHandler.publish(new TikTokConnectedEvent()); + tikTokEventHandler.publish(tikTokLiveClient,new TikTokConnectedEvent()); webSocket.request(1); } @Override public void onError(java.net.http.WebSocket webSocket, Throwable error) { - tikTokEventHandler.publish(new TikTokErrorEvent(error)); + tikTokEventHandler.publish(tikTokLiveClient,new TikTokErrorEvent(error)); webSocket.request(1); } @Override public CompletionStage onClose(java.net.http.WebSocket webSocket, int statusCode, String reason) { - tikTokEventHandler.publish(new TikTokDisconnectedEvent()); + tikTokEventHandler.publish(tikTokLiveClient,new TikTokDisconnectedEvent()); return java.net.http.WebSocket.Listener.super.onClose(webSocket, statusCode, reason); } private void handleBinary(WebSocket webSocket, byte[] buffer) { - try { + var websocketMessageOptional = getWebcastWebsocketMessage(buffer); + if (websocketMessageOptional.isEmpty()) { + return; + } + var websocketMessage = websocketMessageOptional.get(); + sendAckId(webSocket, websocketMessage.getId()); + var webResponse = getWebResponseMessage(websocketMessage.getBinary()); + webResponseHandler.handle(tikTokLiveClient, webResponse); + } + + private Optional getWebcastWebsocketMessage(byte[] buffer) { + try { var websocketMessage = WebcastWebsocketMessage.parseFrom(buffer); if (websocketMessage.getBinary().isEmpty()) { - return; - } - sendAckId(webSocket, websocketMessage.getId()); - try { - var response = WebcastResponse.parseFrom(websocketMessage.getBinary()); - webResponseHandler.handle(response); - } catch (Exception e) { - throw new TikTokLiveMessageParsingException("Unable to read WebcastResponse", e); + return Optional.empty(); } + return Optional.of(websocketMessage); } catch (Exception e) { - throw new TikTokLiveMessageParsingException("Unable to read WebcastWebsocketMessage", e); + throw new TikTokProtocolBufferException("Unable to parse WebcastWebsocketMessage", buffer, e); + } + } + + private WebcastResponse getWebResponseMessage(ByteString buffer) { + try { + return WebcastResponse.parseFrom(buffer); + } catch (Exception e) { + throw new TikTokProtocolBufferException("Unable to parse WebcastResponse", buffer.toByteArray(), e); } } diff --git a/Client/src/test/java/io/github/jwdeveloper/tiktok/WebResponseHandlerTests.java b/Client/src/test/java/io/github/jwdeveloper/tiktok/WebResponseHandlerTests.java index d6fcfe4..04a0a65 100644 --- a/Client/src/test/java/io/github/jwdeveloper/tiktok/WebResponseHandlerTests.java +++ b/Client/src/test/java/io/github/jwdeveloper/tiktok/WebResponseHandlerTests.java @@ -1,31 +1,25 @@ package io.github.jwdeveloper.tiktok; -import com.google.protobuf.InvalidProtocolBufferException; import io.github.jwdeveloper.tiktok.common.TikTokBaseTest; -import io.github.jwdeveloper.tiktok.events.messages.*; import io.github.jwdeveloper.tiktok.handlers.TikTokEventHandler; -import io.github.jwdeveloper.tiktok.handlers.WebResponseHandler; -import io.github.jwdeveloper.tiktok.messages.WebcastResponse; -import io.github.jwdeveloper.tiktok.messages.WebcastSocialMessage; -import io.github.jwdeveloper.tiktok.models.SocialTypes; +import io.github.jwdeveloper.tiktok.handlers.TikTokMessageHandlerRegistration; import org.junit.Before; -import org.junit.Test; -import java.util.regex.Matcher; -import java.util.regex.Pattern; +import java.util.logging.Logger; import static org.mockito.Mockito.mock; -public class WebResponseHandlerTests extends TikTokBaseTest -{ - public static WebResponseHandler sut; +public class WebResponseHandlerTests extends TikTokBaseTest { + public static TikTokMessageHandlerRegistration sut; @Before - public void before() - { + public void before() { var mockEventHandler = mock(TikTokEventHandler.class); var mockGiftManager = mock(TikTokGiftManager.class); - sut = new WebResponseHandler(mockEventHandler, mockGiftManager); + var mockRoomInfo = mock(TikTokRoomInfo.class); + var mockClientSettings = mock(ClientSettings.class); + var mockLogger = mock(Logger.class); + sut = new TikTokMessageHandlerRegistration(mockEventHandler,mockClientSettings,mockLogger, mockGiftManager, mockRoomInfo); } diff --git a/TestApplication/src/main/java/io/github/jwdeveloper/tiktok/ConfigurationExample.java b/TestApplication/src/main/java/io/github/jwdeveloper/tiktok/ConfigurationExample.java index 6d21f0d..9003c6e 100644 --- a/TestApplication/src/main/java/io/github/jwdeveloper/tiktok/ConfigurationExample.java +++ b/TestApplication/src/main/java/io/github/jwdeveloper/tiktok/ConfigurationExample.java @@ -4,24 +4,22 @@ import java.io.IOException; import java.time.Duration; import java.util.logging.Level; -public class ConfigurationExample -{ +public class ConfigurationExample { public static void main(String[] args) throws IOException { TikTokLive.newClient(Main.TEST_TIKTOK_USER) .configure(clientSettings -> { - clientSettings.setHostName(Main.TEST_TIKTOK_USER); //tiktok user - clientSettings.setClientLanguage("en"); //language - clientSettings.setTimeout(Duration.ofSeconds(2)); //connection timeout - clientSettings.setLogLevel(Level.ALL); //log level - clientSettings.setDownloadGiftInfo(true); //TODO - clientSettings.setCheckForUnparsedData(true); //TODO - clientSettings.setPollingInterval(Duration.ofSeconds(1)); //TODO - clientSettings.setPrintMessageData(true); //TODO - clientSettings.setPrintToConsole(true); //TODO - clientSettings.setHandleExistingMessagesOnConnect(true); //TODO - clientSettings.setRetryOnConnectionFailure(true); //TODO + clientSettings.setHostName(Main.TEST_TIKTOK_USER); // TikTok user name + clientSettings.setClientLanguage("en"); // Language + clientSettings.setTimeout(Duration.ofSeconds(2)); // Connection timeout + clientSettings.setLogLevel(Level.ALL); // Log level + clientSettings.setDownloadGiftInfo(true); // Downloading meta information about gifts. You can access it by client.getGiftManager().getGiftsInfo(); + clientSettings.setPrintMessageData(true); // Printing TikTok Protocol buffer messages in Base64 format + clientSettings.setPrintToConsole(true); // Printing all logs to console even if log level is Level.OFF + clientSettings.setHandleExistingMessagesOnConnect(true); // Invokes all TikTok events that had occurred before connection + clientSettings.setRetryOnConnectionFailure(true); // Reconnecting if TikTok user is offline + clientSettings.setRetryConnectionTimeout(Duration.ofSeconds(1)); // Timeout before next reconnection }) .buildAndRun(); System.in.read(); diff --git a/TestApplication/src/main/java/io/github/jwdeveloper/tiktok/Main.java b/TestApplication/src/main/java/io/github/jwdeveloper/tiktok/Main.java index 5e2bfb2..e552c55 100644 --- a/TestApplication/src/main/java/io/github/jwdeveloper/tiktok/Main.java +++ b/TestApplication/src/main/java/io/github/jwdeveloper/tiktok/Main.java @@ -1,12 +1,13 @@ package io.github.jwdeveloper.tiktok; import io.github.jwdeveloper.tiktok.events.messages.*; +import io.github.jwdeveloper.tiktok.live.LiveClient; import java.io.IOException; public class Main { - public static String TEST_TIKTOK_USER = "mr_cios"; + public static String TEST_TIKTOK_USER = "vadimpyrography"; public static void main(String[] args) throws IOException { var client = TikTokLive.newClient(TEST_TIKTOK_USER) @@ -21,59 +22,59 @@ public class Main { .onLike(Main::onLike) .onGiftMessage(Main::onGiftMessage) .onEmote(Main::onEmote) - .onError(tikTokErrorEvent -> + .onError((_client, error) -> { - // tikTokErrorEvent.getException().printStackTrace(); + error.getException().printStackTrace(); }) .buildAndRun(); - var viewers = client.getRoomInfo().getViewersCount(); System.in.read(); } - private static void onConnected(TikTokConnectedEvent e) { + private static void onConnected(LiveClient tikTokLive, TikTokConnectedEvent e) { print("Connected"); } - private static void onDisconnected(TikTokDisconnectedEvent e) { + private static void onDisconnected(LiveClient tikTokLive, TikTokDisconnectedEvent e) { print("Disconnected"); } - private static void onViewerData(TikTokRoomViewerDataEvent e) { + private static void onViewerData(LiveClient tikTokLive, TikTokRoomViewerDataEvent e) { print("Viewer count is:", e.getViewerCount()); } - private static void onJoin(TikTokJoinEvent e) { + private static void onJoin(LiveClient tikTokLive, TikTokJoinEvent e) { print(e.getUser().getUniqueId(), "joined!"); } - private static void onComment(TikTokCommentEvent e) { + private static void onComment(LiveClient tikTokLive, TikTokCommentEvent e) { print(e.getUser().getUniqueId(), e.getText()); } - private static void onFollow(TikTokFollowEvent e) { + private static void onFollow(LiveClient tikTokLive, TikTokFollowEvent e) { print(e.getNewFollower().getUniqueId(), "followed!"); } - private static void onShare(TikTokShareEvent e) { + private static void onShare(LiveClient tikTokLive, TikTokShareEvent e) { print(e.getUser().getUniqueId(), "shared!"); } - private static void onSubscribe(TikTokSubscribeEvent e) { + private static void onSubscribe(LiveClient tikTokLive, TikTokSubscribeEvent e) { print(e.getNewSubscriber().getUniqueId(), "subscribed!"); } - private static void onLike(TikTokLikeEvent e) { + private static void onLike(LiveClient tikTokLive, TikTokLikeEvent e) { print(e.getSender().getUniqueId(), "liked!"); } - private static void onGiftMessage(TikTokGiftMessageEvent e) { + private static void onGiftMessage(LiveClient tikTokLive, TikTokGiftMessageEvent e) + { print(e.getSender().getUniqueId(), "sent", e.getAmount(), "x", e.getGift().getName()); } - private static void onEmote(TikTokEmoteEvent e) { + private static void onEmote(LiveClient tikTokLive, TikTokEmoteEvent e) { print(e.getUser().getUniqueId(), "sent", e.getEmoteId()); } diff --git a/TestApplication/src/main/java/io/github/jwdeveloper/tiktok/SimpleExample.java b/TestApplication/src/main/java/io/github/jwdeveloper/tiktok/SimpleExample.java index ee13b08..bbf56a9 100644 --- a/TestApplication/src/main/java/io/github/jwdeveloper/tiktok/SimpleExample.java +++ b/TestApplication/src/main/java/io/github/jwdeveloper/tiktok/SimpleExample.java @@ -6,21 +6,24 @@ public class SimpleExample { public static void main(String[] args) throws IOException { TikTokLive.newClient(Main.TEST_TIKTOK_USER) - .onConnected(event -> + .onConnected((client, event) -> { System.out.println("Connected"); }) - .onJoin(event -> + .onJoin((client, event) -> { System.out.println("User joined -> " + event.getUser().getNickName()); }) - .onComment(event -> + .onComment((client, event) -> { System.out.println(event.getUser().getUniqueId() + ": " + event.getText()); }) - .onError(event -> + .onEvent((client, event) -> + { + System.out.println("Viewers count: "+client.getRoomInfo().getViewersCount()); + }) + .onError((client, event) -> { - System.out.println("OTO tajeminica wiary"); event.getException().printStackTrace(); }) .buildAndRun(); diff --git a/Tools/src/main/java/io/github/jwdeveloper/tiktok/events_generator/EventsGenerator.java b/Tools/src/main/java/io/github/jwdeveloper/tiktok/events_generator/EventsGenerator.java index d37fee2..986b663 100644 --- a/Tools/src/main/java/io/github/jwdeveloper/tiktok/events_generator/EventsGenerator.java +++ b/Tools/src/main/java/io/github/jwdeveloper/tiktok/events_generator/EventsGenerator.java @@ -1,12 +1,9 @@ package io.github.jwdeveloper.tiktok.events_generator; -import io.github.jwdeveloper.tiktok.FilesUtility; +import io.github.jwdeveloper.tiktok.utils.FilesUtility; import java.io.File; import java.io.IOException; -import java.nio.file.Files; -import java.util.ArrayList; -import java.util.List; public class EventsGenerator { diff --git a/Tools/src/main/java/io/github/jwdeveloper/tiktok/intefacee/EventsInterfaceGenerator.java b/Tools/src/main/java/io/github/jwdeveloper/tiktok/intefacee/EventsInterfaceGenerator.java index e541d6d..f0c713a 100644 --- a/Tools/src/main/java/io/github/jwdeveloper/tiktok/intefacee/EventsInterfaceGenerator.java +++ b/Tools/src/main/java/io/github/jwdeveloper/tiktok/intefacee/EventsInterfaceGenerator.java @@ -20,16 +20,16 @@ public class EventsInterfaceGenerator { // System.out.println(clazz.getName()); } - //var result = generateInterface("io.github.jwdeveloper.tiktok.events", classes);System.out.println(result); + // var result = generateInterface("io.github.jwdeveloper.tiktok.events", classes);System.out.println(result); - var result = getBuilderImplementation("x",classes); System.out.println(result); + var result = getBuilderImplementation("x",classes); System.out.println(result); } public String generateInterface(String packageName, Set> eventsClasses) { - TypeSpec.Builder classBuilder = TypeSpec.interfaceBuilder("TikTokEvents"); + TypeSpec.Builder classBuilder = TypeSpec.interfaceBuilder("TikTokEventBuilder"); classBuilder.addModifiers(Modifier.PUBLIC); classBuilder.addTypeVariable(TypeVariableName.get("T")); @@ -46,7 +46,7 @@ public class EventsInterfaceGenerator { MethodSpec.Builder constructorBuilder = MethodSpec.methodBuilder("on" + methodName); - var name = "Consumer<" + clazzName + ">"; + var name = "TikTokEventConsumer<" + clazzName + ">"; constructorBuilder.addModifiers(Modifier.ABSTRACT, Modifier.PUBLIC); constructorBuilder.addParameter(ClassName.bestGuess(name), "event"); constructorBuilder.returns(TypeVariableName.get("T")); @@ -91,7 +91,7 @@ public class EventsInterfaceGenerator { MethodSpec.Builder constructorBuilder = MethodSpec.methodBuilder( methodName); - var name = "Consumer<" + clazzName + ">"; + var name = "TikTokEventConsumer<" + clazzName + ">"; constructorBuilder.addModifiers( Modifier.PUBLIC); constructorBuilder.addParameter(ClassName.bestGuess(name), "event"); constructorBuilder.addStatement("tikTokEventHandler.subscribe("+clazzName+".class,event)"); diff --git a/Tools/src/main/java/io/github/jwdeveloper/tiktok/FilesUtility.java b/Tools/src/main/java/io/github/jwdeveloper/tiktok/utils/FilesUtility.java similarity index 95% rename from Tools/src/main/java/io/github/jwdeveloper/tiktok/FilesUtility.java rename to Tools/src/main/java/io/github/jwdeveloper/tiktok/utils/FilesUtility.java index 0b61e5e..f4e169c 100644 --- a/Tools/src/main/java/io/github/jwdeveloper/tiktok/FilesUtility.java +++ b/Tools/src/main/java/io/github/jwdeveloper/tiktok/utils/FilesUtility.java @@ -1,4 +1,4 @@ -package io.github.jwdeveloper.tiktok; +package io.github.jwdeveloper.tiktok.utils; import java.io.IOException; import java.nio.charset.StandardCharsets; diff --git a/Tools/target/classes/io/github/jwdeveloper/tiktok/FilesUtility.class b/Tools/target/classes/io/github/jwdeveloper/tiktok/FilesUtility.class deleted file mode 100644 index 7fbc771b1a8a62454a213d76c965a20664697200..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2848 zcma)8TU!%H7=8x=OTx+_9-%6Vs04!Rp|)zMZNXzrzzSlOwsuJdSO~l6W&_f5`%`-3 zO)qLM6z$V`*NZ;=P1<*6L)aMfF?pVyoo~MH{Z8-9?7uIb{S9Cgza-FvW&<%3Eoc?! zTC!Jdt7y9m*5urh%m)IkqmJtY7X_LJQ!@tI>XfDe-*FcbNTA(-X<`RD1a@i=*YT`* zrzowPcCc8c`GO=`W-ziNok8T;OGOlF7OVl}yJpVB)B1 zW=p>4m8F5>o3+w?onG|4HG8fo6F7#Hi6ION?63=ksYjx%`Iz*!UT;eCO_HMZmzZNDr7 zw#0S|wqFaj!sEokWonm6bW^Pb)eJ zB(q-LF3#A#qvlm%ELe2dhvDp7d#E;0I~5p+GO>DKM7N1%J=;?XPnn)D)y7>&RKXZ` zhwJs+e#WK1b&_zP+&>YCw zC0#rNUooJ1aw?w&<^(#lT;~}c2JtCp!L@^m&nz#zMbTaxL|fTjm8$vz$G5?0EKq7j zz{q=UAYE3lZJwqoOo8sAy)sv@2e=(|HwRAgl-!n~se8O29;o%ilvnZdRsY@EtjfF- zDr4S0W1biAaI{M~87z8*a%U?_349ITK-olqia@_Ej&7pku6oPT%IZjHVb9z7!1KxD z_Lb=Dzi6seqtL-Mo<`*VK-Tk?E2T_h{t-!?;WVibRe$@%(B+$LtD7L22Sy15eS@#7CdNMEW1Z(@$|kVB~i-*%eM6qWwZ_q$lY9uf;93(YeIoBNX&Cl_25^QF~+ff zvy8d)@Ez^mC<;Z-@Cm zQp^1S(N)IH$_MjQ8LPJizJ+*;%stF>51L*QB+O1FsKbtRB@|z)@t&csqC{N9dwBy_ rf8!*|o9+m2;#ej)=)9=4R^W0}CH5#=#RGhc?82A{Bfd-f`C^48%HsQ|&0IpCN+yDRo delta 127 zcmZ23zfgX{2}aGyfh@8c-+bg|}n42v1G7`8EJGwfy1VK~5`w^^Q# fjZxHyftkUWfs?_MfsetAL6X57sL^V&6@M-O!WS1o diff --git a/Tools/target/classes/io/github/jwdeveloper/tiktok/intefacee/EventsInterfaceGenerator.class b/Tools/target/classes/io/github/jwdeveloper/tiktok/intefacee/EventsInterfaceGenerator.class index 46a980590eb1dc4560255e69b35e0a77b1b68998..f9993eaef9332f61409de4b474bda856df17e389 100644 GIT binary patch delta 876 zcmZXSOK1~O6o&sh(`Kg0Q0U}Q(}mayT?8b-xUy}O)`D()(1J*J#elJzXddc95#1@c zx{A1P<4WAr7)@ifHLX=^HJTV7)mSw?;`?oVEs7_TNeIZmxo6Hf^WXnFOv06O8K>rk zM*+0sPt>?sG^@S7f!@GC_YSW=+!^t0+2{?%_K8exl5v_rsp^J|=)xHVF@Dh0WQZ#m zLV}+%dDUSCQ_vfZ1pN!bn|vV&7kRVNW*Aj)7?)!G%F&wo*G9a-TM6$JMDU(V4HK;& z8N`5}$@t7*tGcEu;15N%dV}rEBjYPCG^}E?+@(6$FW#pv^CZc;6O109)-ePYr9{9O zMT1sUFiyEr8o*^t&>O=QT&0-g(`r8(<89`Jdy7*`P)l*0K2^-FVUp(RiS# zx`CSzu@ZGi;TCFeTh}l3($vdPr2)bmS|vyl8YMLU#XJ(a12>5z$-yjLWu&pJx;%l- z)r}I&@$+rtwhoo~?M# z;t_R=Ysn%ie#Gi*$*Pg*Zm|ahrocCvANd(4{z}gL-g4 z2lZov4!RR-bx=3`KxNQ;1vFm)%~wEkI%v8An)?sbZPDaPpv6y1pz%g$PZ?Ci3k~@t sUeRfx%@qj#gBCw&@e96Dr-e4ThW?T7uwy@VY3E6t(9R$DiQlmQ0||fI$^ZZW delta 826 zcmY+CTWkzr6vzMH&f3fDXzc8TO{1g;@zTcjN!k+CAR$PbNF$NBY+`Ng*3J$hF5yKy zc={yb)sr`BS*vtgtBTTXb=}swEp@HBUmhgl%B<18 z$FELtn=n~w4M$pIk>;JDXhKOI7MNq6h$fto(1~RX(&qM!in2rvw{Ho>Wmu39aR}!m zoJWdhT_InZ!4(fB)Od7eVry8jql=-AyQfU&ZBnJ}vV>#kPVSM8TPt3Pc#Su9yp^Eh z9iQRus~lqxVo~P6ICW`?MHO{>C|=JR9r(nZ@(SxWhB^G8TqVw48H+{K4m*DE{qiD~ z;ThRKw}&unU}Poq>Q;*<;R>?k8Lpy_Y=-}qH?bbR!82=>rm7Ms#4qzb90y?dK;|gI90&)M!^gjt+--+E-Kkj3gF3r=|SF@bQjhbph5Z- zCO}IjXvqXEnV>}jbl3zf68`_7L9gDf462ouK?_rBS|&gRlyu}5cuC$%H#bV~?{)h@ gw;%DDGSzgGtLgQ>AVB~2Zrz{4N!@?Ncl<=)FCSsi#sB~S