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 fa72993..90ccc12 100644 --- a/API/src/main/java/io/github/jwdeveloper/tiktok/ClientSettings.java +++ b/API/src/main/java/io/github/jwdeveloper/tiktok/ClientSettings.java @@ -3,6 +3,8 @@ package io.github.jwdeveloper.tiktok; import lombok.Data; import java.time.Duration; +import java.util.HashMap; +import java.util.Map; import java.util.logging.Level; @Data @@ -11,12 +13,12 @@ public class ClientSettings { /// Timeout for Connections /// - private Duration Timeout; + private Duration timeout; /// /// Polling-Interval for Socket-Connection /// /// Proxy for Connection /// @@ -26,46 +28,49 @@ public class ClientSettings { /// ISO-Language for Client /// - private String ClientLanguage; + private String clientLanguage; /// /// Size for Buffer for Socket-Connection /// - private int SocketBufferSize; + private int socketBufferSize; /// /// Whether to Retry if Connection Fails /// - private boolean RetryOnConnectionFailure; - + private boolean retryOnConnectionFailure; /// /// Whether to handle Messages received from Room when Connecting /// - private boolean HandleExistingMessagesOnConnect; + private boolean handleExistingMessagesOnConnect; /// /// Whether to download List of Gifts for Room when Connecting /// - private boolean DownloadGiftInfo; + private boolean downloadGiftInfo; /// /// Whether to print Logs to Console /// - private boolean PrintToConsole; + private boolean printToConsole; /// /// LoggingLevel for Logs /// - private Level LogLevel; + private Level logLevel; /// /// Whether to print Base64-Data for Messages to Console /// - private boolean PrintMessageData; + private boolean printMessageData; /// /// Whether to check Messages for Unparsed Data /// - private boolean CheckForUnparsedData; + private boolean checkForUnparsedData; + + private String hostName; + + private Map clientParameters; } 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 350c13b..7694057 100644 --- a/API/src/main/java/io/github/jwdeveloper/tiktok/Constants.java +++ b/API/src/main/java/io/github/jwdeveloper/tiktok/Constants.java @@ -39,7 +39,6 @@ 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"); @@ -51,6 +50,7 @@ public class Constants { 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/objects/Badge.java b/API/src/main/java/io/github/jwdeveloper/tiktok/events/objects/Badge.java index 3cbd35d..f80bb2d 100644 --- a/API/src/main/java/io/github/jwdeveloper/tiktok/events/objects/Badge.java +++ b/API/src/main/java/io/github/jwdeveloper/tiktok/events/objects/Badge.java @@ -7,14 +7,14 @@ import java.util.List; @Getter public class Badge { - private final ComboBadge comboBadges; + private ComboBadge comboBadges; private final List textBadges; private final List imageBadges; public Badge(io.github.jwdeveloper.tiktok.messages.Badge badge) { textBadges = badge.getTextBadgesList().stream().map(b -> new TextBadge(b.getType(), b.getName())).toList(); imageBadges = badge.getImageBadgesList().stream().map(b -> new ImageBadge(b.getDisplayType(), new Picture(b.getImage()))).toList(); - comboBadges = new ComboBadge(new Picture(badge.getComplexBadge().getImageUrl()), badge.getComplexBadge().getData()); + comboBadges = new ComboBadge(new Picture("badge.getComplexBadge().getImageUrl()"), badge.getComplexBadge().getData()); } diff --git a/API/src/main/java/io/github/jwdeveloper/tiktok/exceptions/TikTokLiveRequestException.java b/API/src/main/java/io/github/jwdeveloper/tiktok/exceptions/TikTokLiveRequestException.java new file mode 100644 index 0000000..e9debf4 --- /dev/null +++ b/API/src/main/java/io/github/jwdeveloper/tiktok/exceptions/TikTokLiveRequestException.java @@ -0,0 +1,23 @@ +package io.github.jwdeveloper.tiktok.exceptions; + +public class TikTokLiveRequestException extends TikTokLiveException +{ + public TikTokLiveRequestException() { + } + + public TikTokLiveRequestException(String message) { + super(message); + } + + public TikTokLiveRequestException(String message, Throwable cause) { + super(message, cause); + } + + public TikTokLiveRequestException(Throwable cause) { + super(cause); + } + + public TikTokLiveRequestException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { + super(message, cause, enableSuppression, writableStackTrace); + } +} diff --git a/API/src/main/proto/tiktokSchema.proto b/API/src/main/proto/tiktokSchema.proto index 6a89818..96a7510 100644 --- a/API/src/main/proto/tiktokSchema.proto +++ b/API/src/main/proto/tiktokSchema.proto @@ -186,7 +186,7 @@ message Badge { message BadgeComplex { uint32 data1 = 1; - string imageUrl = 2; + //string imageUrl = 2; Protocol message had invalid UTF-8 string data = 4; DataContainer detail1 = 5; string data2 = 6; @@ -377,7 +377,7 @@ message RankTextMessage { // Links to Image-Files on the TikTok CDN message Picture { repeated string urls = 1; // Usually has 3 different urls with different sizes/extensions - string prefix = 2; // uri + // string prefix = 2; // uri not working uint32 data1 = 3; uint32 data2 = 4; string color = 5; @@ -681,7 +681,7 @@ message WebcastGiftMessage { uint32 data11 = 34; message GiftData1 { - string data1 = 1; + // string data1 = 1; not working uint32 data2 = 2; uint32 data3 = 3; } 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 53e8b09..e8aaf00 100644 --- a/Client/src/main/java/io/github/jwdeveloper/tiktok/TikTokLiveClient.java +++ b/Client/src/main/java/io/github/jwdeveloper/tiktok/TikTokLiveClient.java @@ -7,7 +7,7 @@ import io.github.jwdeveloper.tiktok.live.ConnectionState; 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 io.github.jwdeveloper.tiktok.websocket.TikTokWebSocketClient; import java.util.logging.Logger; @@ -15,14 +15,14 @@ public class TikTokLiveClient implements LiveClient { private final TikTokRoomInfo meta; private final TikTokGiftManager giftManager; private final TikTokApiService apiClient; - private final TikTokWebsocketClient webSocketClient; + private final TikTokWebSocketClient webSocketClient; private final TikTokEventHandler tikTokEventHandler; private final Logger logger; public TikTokLiveClient(TikTokRoomInfo tikTokLiveMeta, TikTokApiService tikTokApiService, - TikTokWebsocketClient webSocketClient, + TikTokWebSocketClient webSocketClient, TikTokGiftManager tikTokGiftManager, TikTokEventHandler tikTokEventHandler, Logger logger) { @@ -57,9 +57,9 @@ public class TikTokLiveClient implements LiveClient { public void tryConnect() { if (meta.hasConnectionState(ConnectionState.CONNECTED)) - throw new RuntimeException("Already connected"); + throw new TikTokLiveException("Already connected"); if (meta.hasConnectionState(ConnectionState.CONNECTING)) - throw new RuntimeException("Already connecting"); + throw new TikTokLiveException("Already connecting"); logger.info("Connecting"); setState(ConnectionState.CONNECTING); 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 8ac82cd..394fbec 100644 --- a/Client/src/main/java/io/github/jwdeveloper/tiktok/TikTokLiveClientBuilder.java +++ b/Client/src/main/java/io/github/jwdeveloper/tiktok/TikTokLiveClientBuilder.java @@ -11,51 +11,29 @@ 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 io.github.jwdeveloper.tiktok.websocket.TikTokWebSocketClient; import java.time.Duration; -import java.util.Map; import java.util.function.Consumer; import java.util.logging.Logger; public class TikTokLiveClientBuilder implements TikTokEventBuilder { - private String userName; private final ClientSettings clientSettings; - private Map clientParameters; private final Logger logger; private final TikTokEventHandler tikTokEventHandler; public TikTokLiveClientBuilder(String userName) { this.tikTokEventHandler = new TikTokEventHandler(); - this.userName = userName; this.clientSettings = Constants.DefaultClientSettings(); - this.clientParameters = Constants.DefaultClientParams(); + this.clientSettings.setHostName(userName); this.logger = Logger.getLogger(TikTokLive.class.getName()); } - - - - public TikTokLiveClientBuilder clientSettings(Consumer consumer) { + public TikTokLiveClientBuilder configure(Consumer consumer) { consumer.accept(clientSettings); return this; } - public TikTokLiveClientBuilder hostUserName(String userName) { - this.userName = userName; - return this; - } - - public TikTokLiveClientBuilder clientParameters(Map clientParameters) { - this.clientParameters = clientParameters; - return this; - } - - public TikTokLiveClientBuilder addClientParameters(String key, Object value) { - this.clientParameters.put(key, value); - return this; - } - private void validate() { if (clientSettings.getTimeout() == null) { @@ -75,16 +53,13 @@ public class TikTokLiveClientBuilder implements TikTokEventBuilder "+id); return id; } @@ -60,7 +62,7 @@ public class TikTokApiService { public LiveRoomMeta fetchRoomInfo() { logger.info("Fetch RoomInfo"); try { - var response = apiClient.GetJObjectFromWebcastAPI("room/info/", clientParams); + var response = apiClient.GetJObjectFromWebcastAPI("room/info/", clientSettings.getClientParameters()); if (!response.has("data")) { return new LiveRoomMeta(); } @@ -78,7 +80,7 @@ public class TikTokApiService { logger.info("RoomInfo status -> "+info.getStatus()); return info; } catch (Exception e) { - throw new TikTokLiveException("Failed to fetch room info from WebCast, see stacktrace for more info.", e); + throw new TikTokLiveRequestException("Failed to fetch room info from WebCast, see stacktrace for more info.", e); } } @@ -86,20 +88,20 @@ public class TikTokApiService { { logger.info("Fetch ClientData"); try { - var response = apiClient.GetDeserializedMessage("im/fetch/", clientParams); - clientParams.put("cursor",response.getCursor()); - clientParams.put("internal_ext", response.getAckIds()); + var response = apiClient.GetDeserializedMessage("im/fetch/", clientSettings.getClientParameters()); + clientSettings.getClientParameters().put("cursor",response.getCursor()); + clientSettings.getClientParameters().put("internal_ext", response.getAckIds()); return response; } catch (Exception e) { - throw new TikTokLiveException("Failed to fetch client data", e); + throw new TikTokLiveRequestException("Failed to fetch client data", e); } } public Map fetchAvailableGifts() { try { - var response = apiClient.GetJObjectFromWebcastAPI("gift/list/", clientParams); + var response = apiClient.GetJObjectFromWebcastAPI("gift/list/", clientSettings.getClientParameters()); if(!response.has("data")) { return new HashMap<>(); @@ -120,7 +122,7 @@ public class TikTokApiService { } return gifts; } catch (Exception e) { - throw new TikTokLiveException("Failed to fetch giftTokens from WebCast, see stacktrace for more info.", e); + throw new TikTokLiveRequestException("Failed to fetch giftTokens from WebCast, see stacktrace for more info.", e); } } } diff --git a/Client/src/main/java/io/github/jwdeveloper/tiktok/http/TikTokHttpApiClient.java b/Client/src/main/java/io/github/jwdeveloper/tiktok/http/TikTokHttpApiClient.java index df8cf05..7ff955f 100644 --- a/Client/src/main/java/io/github/jwdeveloper/tiktok/http/TikTokHttpApiClient.java +++ b/Client/src/main/java/io/github/jwdeveloper/tiktok/http/TikTokHttpApiClient.java @@ -4,7 +4,7 @@ import com.google.gson.JsonObject; import com.google.gson.JsonParser; import io.github.jwdeveloper.tiktok.ClientSettings; import io.github.jwdeveloper.tiktok.Constants; -import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveException; +import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveRequestException; import io.github.jwdeveloper.tiktok.messages.WebcastResponse; import java.net.URI; @@ -16,27 +16,23 @@ import java.util.Map; import java.util.TreeMap; public class TikTokHttpApiClient { - private final ClientSettings clientSettings; private final TikTokHttpRequestFactory requestFactory; private final TikTokCookieJar tikTokCookieJar; - - public TikTokHttpApiClient(TikTokCookieJar tikTokCookieJar, ClientSettings clientSettings, TikTokHttpRequestFactory requestFactory) { - this.clientSettings = clientSettings; + public TikTokHttpApiClient(TikTokCookieJar tikTokCookieJar, TikTokHttpRequestFactory requestFactory) { this.requestFactory = requestFactory; this.tikTokCookieJar = tikTokCookieJar; } - public String GetLivestreamPage(String userName) { var url = Constants.TIKTOK_URL_WEB + "@" + userName + "/live/"; - var get = getRequest(url, null, false); + var get = getRequest(url, null); return get; } public JsonObject GetJObjectFromWebcastAPI(String path, Map parameters) { - var get = getRequest(Constants.TIKTOK_URL_WEBCAST + path, parameters, false); + var get = getRequest(Constants.TIKTOK_URL_WEBCAST + path, parameters); var json = JsonParser.parseString(get); var jsonObject = json.getAsJsonObject(); return jsonObject; @@ -49,12 +45,11 @@ public class TikTokHttpApiClient { } catch (Exception e) { - throw new TikTokLiveException("Unable to deserialize message: "+path,e); + throw new TikTokLiveRequestException("Unable to deserialize message: "+path,e); } } - - private String getRequest(String url, Map parameters, boolean signURL) { + private String getRequest(String url, Map parameters) { if (parameters == null) { parameters = new HashMap<>(); } @@ -86,7 +81,7 @@ public class TikTokHttpApiClient { } catch (Exception e) { - throw new TikTokLiveException("unabel to send signature"); + throw new TikTokLiveRequestException("Unable to send signature"); } } @@ -112,7 +107,7 @@ public class TikTokHttpApiClient { requestFactory.setAgent(userAgent); return signedUrl; } catch (Exception e) { - throw new TikTokLiveException("Insufficent values have been supplied for signing. Likely due to an update. Post an issue on GitHub.", e); + throw new TikTokLiveRequestException("Insufficient values have been supplied for signing. Likely due to an update. Post an issue on GitHub.", e); } } diff --git a/Client/src/main/java/io/github/jwdeveloper/tiktok/http/TikTokHttpRequestFactory.java b/Client/src/main/java/io/github/jwdeveloper/tiktok/http/TikTokHttpRequestFactory.java index a9440b8..822690b 100644 --- a/Client/src/main/java/io/github/jwdeveloper/tiktok/http/TikTokHttpRequestFactory.java +++ b/Client/src/main/java/io/github/jwdeveloper/tiktok/http/TikTokHttpRequestFactory.java @@ -2,10 +2,10 @@ package io.github.jwdeveloper.tiktok.http; import io.github.jwdeveloper.tiktok.Constants; +import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveRequestException; import lombok.SneakyThrows; import java.net.CookieManager; -import java.net.ProxySelector; import java.net.URI; import java.net.URLEncoder; import java.net.http.HttpClient; @@ -18,24 +18,16 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -public class TikTokHttpRequestFactory implements TikTokHttpRequest -{ - private CookieManager cookieManager; - private HttpClient client; - - private Duration timeout; - - private ProxySelector webProxy; +public class TikTokHttpRequestFactory implements TikTokHttpRequest { + private final CookieManager cookieManager; + private final Map defaultHeaders; + private final TikTokCookieJar tikTokCookieJar; + private final HttpClient client; private String query; - private Boolean sent; - private Map defaultHeaders; - - private TikTokCookieJar tikTokCookieJar; public TikTokHttpRequestFactory(TikTokCookieJar tikTokCookieJar) { - - cookieManager = new CookieManager(); this.tikTokCookieJar = tikTokCookieJar; + this.cookieManager = new CookieManager(); defaultHeaders = Constants.DefaultRequestHeaders(); client = HttpClient.newBuilder() .cookieHandler(cookieManager) @@ -43,8 +35,7 @@ public class TikTokHttpRequestFactory implements TikTokHttpRequest .build(); } - public WebSocket.Builder openSocket() - { + public WebSocket.Builder openSocket() { return client.newWebSocketBuilder(); } @@ -52,26 +43,21 @@ public class TikTokHttpRequestFactory implements TikTokHttpRequest public String Get(String url) { var uri = URI.create(url); var request = HttpRequest.newBuilder().GET(); - for(var header : defaultHeaders.entrySet()) - { - //request.setHeader(header.getKey(),header.getValue()); - } if (query != null) { var baseUri = uri.toString(); var requestUri = URI.create(baseUri + "?" + query); request.uri(requestUri); } - return GetContent(request.build()); + return GetContent(request.build()); } @SneakyThrows public String Post(String url, HttpRequest.BodyPublisher data) { var uri = URI.create(url); var request = HttpRequest.newBuilder().POST(data); - for(var header : defaultHeaders.entrySet()) - { - request.setHeader(header.getKey(),header.getValue()); + for (var header : defaultHeaders.entrySet()) { + request.setHeader(header.getKey(), header.getValue()); } if (query != null) { var baseUri = uri.toString(); @@ -81,14 +67,12 @@ public class TikTokHttpRequestFactory implements TikTokHttpRequest return GetContent(request.build()); } - public TikTokHttpRequest setHeader(String key, String value) - { - defaultHeaders.put(key,value); + public TikTokHttpRequest setHeader(String key, String value) { + defaultHeaders.put(key, value); return this; } - public TikTokHttpRequest setAgent( String value) - { + public TikTokHttpRequest setAgent(String value) { defaultHeaders.put("User-Agent", value); return this; } @@ -111,26 +95,18 @@ public class TikTokHttpRequestFactory implements TikTokHttpRequest } - - - private String GetContent(HttpRequest request) throws Exception { var response = client.send(request, HttpResponse.BodyHandlers.ofString()); - sent = true; - if (response.statusCode() == 404) - { - throw new RuntimeException("Request responded with 404 NOT_FOUND"); + if (response.statusCode() == 404) { + throw new TikTokLiveRequestException("Request responded with 404 NOT_FOUND"); } - if(response.statusCode() != 200) - { - throw new RuntimeException("Request was unsuccessful "+response.statusCode()); + if (response.statusCode() != 200) { + throw new TikTokLiveRequestException("Request was unsuccessful " + response.statusCode()); } - var cookies = response.headers().allValues("Set-Cookie"); - for(var cookie : cookies) - { + for (var cookie : cookies) { var split = cookie.split(";")[0].split("="); var uri = request.uri(); @@ -139,9 +115,9 @@ public class TikTokHttpRequestFactory implements TikTokHttpRequest var value = split[1]; tikTokCookieJar.set(key, value); - var map = new HashMap>(); - map.put(key,List.of(value)); - cookieManager.put(uri,map); + var map = new HashMap>(); + map.put(key, List.of(value)); + cookieManager.put(uri, map); } return response.body(); 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 similarity index 91% rename from Client/src/main/java/io/github/jwdeveloper/tiktok/websocket/TikTokWebsocketClient.java rename to Client/src/main/java/io/github/jwdeveloper/tiktok/websocket/TikTokWebSocketClient.java index 9d47c87..9142113 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 @@ -13,16 +13,13 @@ import io.github.jwdeveloper.tiktok.messages.WebcastResponse; import java.net.URI; import java.net.http.WebSocket; -import java.nio.ByteBuffer; import java.time.Duration; import java.util.HashMap; -import java.util.Map; import java.util.TreeMap; import java.util.logging.Logger; -public class TikTokWebsocketClient { +public class TikTokWebSocketClient { private final Logger logger; - private final Map clientParams; private final ClientSettings clientSettings; private final TikTokCookieJar tikTokCookieJar; private final TikTokHttpRequestFactory factory; @@ -33,15 +30,13 @@ public class TikTokWebsocketClient { private boolean isConnected; - public TikTokWebsocketClient(Logger logger, + public TikTokWebSocketClient(Logger logger, TikTokCookieJar tikTokCookieJar, - Map clientParams, TikTokHttpRequestFactory factory, ClientSettings clientSettings, WebResponseHandler webResponseHandler, TikTokEventHandler tikTokEventHandler) { this.logger = logger; - this.clientParams = clientParams; this.tikTokCookieJar = tikTokCookieJar; this.clientSettings = clientSettings; this.factory = factory; @@ -78,7 +73,7 @@ public class TikTokWebsocketClient { var headers = Constants.DefaultRequestHeaders(); - var clone = new TreeMap<>(clientParams); + var clone = new TreeMap<>(clientSettings.getClientParameters()); clone.putAll(headers); clone.put(name, value); var url = webcastResponse.getSocketUrl(); diff --git a/Client/src/test/java/io/github/jwdeveloper/tiktok/ParseMessagesTests.java b/Client/src/test/java/io/github/jwdeveloper/tiktok/ParseMessagesTests.java new file mode 100644 index 0000000..93985d2 --- /dev/null +++ b/Client/src/test/java/io/github/jwdeveloper/tiktok/ParseMessagesTests.java @@ -0,0 +1,41 @@ +package io.github.jwdeveloper.tiktok; + +import com.google.protobuf.InvalidProtocolBufferException; +import io.github.jwdeveloper.tiktok.messages.WebcastChatMessage; +import io.github.jwdeveloper.tiktok.messages.WebcastGiftMessage; +import io.github.jwdeveloper.tiktok.messages.WebcastLikeMessage; +import io.github.jwdeveloper.tiktok.messages.WebcastWebsocketMessage; +import org.junit.Test; + +public class ParseMessagesTests extends TikTokBaseTest +{ + + + // @Test + public void ShouldParseWebcastWebsocketMessage() throws InvalidProtocolBufferException { + var bytes = getFileBytesUtf("WebcastWebsocketMessage.bin"); + var message = WebcastWebsocketMessage.parseFrom(bytes); + System.out.println("id: " + message.getId()); + System.out.println("type: " + message.getType()); + System.out.println("binary: " + message.getBinary().size()); + } + + @Test + public void ShouldParseLikeMessage() throws InvalidProtocolBufferException { + var bytes = getFileBytesUtf("LikeMessage.bin"); + var message = WebcastLikeMessage.parseFrom(bytes); + } + + @Test + public void ShouldParseGiftMessage() throws InvalidProtocolBufferException { + var bytes = getFileBytesUtf("MessageWebcastGiftMessage.bin"); + var message = WebcastGiftMessage.parseFrom(bytes); + } + @Test + public void ShouldParseMessageWebcastChatMessage() throws InvalidProtocolBufferException { + var bytes = getFileBytesUtf("MessageWebcastChatMessage.bin"); + var message = WebcastChatMessage.parseFrom(bytes); + } + + +} diff --git a/Client/src/test/java/io/github/jwdeveloper/tiktok/TikTokBaseTest.java b/Client/src/test/java/io/github/jwdeveloper/tiktok/TikTokBaseTest.java new file mode 100644 index 0000000..b9b76d3 --- /dev/null +++ b/Client/src/test/java/io/github/jwdeveloper/tiktok/TikTokBaseTest.java @@ -0,0 +1,34 @@ +package io.github.jwdeveloper.tiktok; + +import com.google.protobuf.InvalidProtocolBufferException; +import io.github.jwdeveloper.tiktok.messages.WebcastWebsocketMessage; + +import java.io.IOException; +import java.util.Base64; + +public class TikTokBaseTest +{ + public byte[] getFileBytes(String path) + { + try { + var stream = getClass().getClassLoader().getResourceAsStream(path); + var bytes= stream.readAllBytes(); + stream.close(); + return bytes; + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + public byte[] getFileBytesUtf(String path) + { + try { + var stream = getClass().getClassLoader().getResourceAsStream(path); + var bytes= stream.readAllBytes(); + stream.close(); + return Base64.getDecoder().decode(bytes); + } catch (IOException e) { + throw new RuntimeException(e); + } + } +} diff --git a/Client/src/test/resources/LikeMessage.bin b/Client/src/test/resources/LikeMessage.bin new file mode 100644 index 0000000..69ebc71 --- /dev/null +++ b/Client/src/test/resources/LikeMessage.bin @@ -0,0 +1 @@ +GKUBUAGSAYQPChVsaXZlX3Jvb21fZW50ZXJfdG9hc3QSD3swOnVzZXJ9IGpvaW5lZBoOCgkjYjhmZmZmZmYgkAMiyQ4ICxIMIJADCgcjOENFN0ZGqgG1DgqyDroBAPICTE1TNHdMakFCQUFBQURuX3JCNDhyQlJlZUhVOVdTYllOTm5sQU15YWVSQTJJd05JaWprRm5aQU9WUGdKZW5DNmFZNXV6RnU4cEYyVGoaB/Cfl6PvuI+yAQQIdhA9ggIAsgIHdHR4Lnp5boIE5QgQFBgIIAFS6QJzc2xvY2FsOi8vd2ViY2FzdF9seW54dmlld19wb3B1cD91c2Vfc3Bhcms9MSZ1cmw9aHR0cHMlM0ElMkYlMkZsZjE2LWdlY2tvLXNvdXJjZS50aWt0b2tjZG4uY29tJTJGb2JqJTJGYnl0ZS1ndXJkLXNvdXJjZS1zZyUyRnRpa3RvayUyRmZlJTJGbGl2ZSUyRnRpa3Rva19saXZlX3JldmVudWVfdXNlcl9sZXZlbF9tYWluJTJGc3JjJTJGcGFnZXMlMkZwcml2aWxlZ2UlMkZwYW5lbCUyRnRlbXBsYXRlLmpzJmhpZGVfc3RhdHVzX2Jhcj0wJmhpZGVfbmF2X2Jhcj0xJmNvbnRhaW5lcl9iZ19jb2xvcj0wMDAwMDAwMCZoZWlnaHQ9OTAlMjUmYmRobV9iaWQ9dGlrdG9rX2xpdmVfcmV2ZW51ZV91c2VyX2xldmVsX21haW4mdXNlX2ZvcmVzdD0xWAFiTgoBMhITNzEzODM4MTE3Njc4NzU1NjEzMhoBMCIubW9ja19maXhfd2lkdGhfdHJhbnNwYXJlbnRfNzEzODM4MTE3Njc4NzU1NjEzMioBOLoBmwV4DoABD6IBBggBEAMYIBLVBApcaHR0cHM6Ly9wMTYtd2ViY2FzdC50aWt0b2tjZG4uY29tL3dlYmNhc3QtdmEvZ3JhZGVfYmFkZ2VfaWNvbl9saXRlX2x2NV92MS5wbmd+dHBsdi1vYmouaW1hZ2UKXGh0dHBzOi8vcDE5LXdlYmNhc3QudGlrdG9rY2RuLmNvbS93ZWJjYXN0LXZhL2dyYWRlX2JhZGdlX2ljb25fbGl0ZV9sdjVfdjEucG5nfnRwbHYtb2JqLmltYWdlEit3ZWJjYXN0LXZhL2dyYWRlX2JhZGdlX2ljb25fbGl0ZV9sdjVfdjEucG5nOukCc3Nsb2NhbDovL3dlYmNhc3RfbHlueHZpZXdfcG9wdXA/dXNlX3NwYXJrPTEmdXJsPWh0dHBzJTNBJTJGJTJGbGYxNi1nZWNrby1zb3VyY2UudGlrdG9rY2RuLmNvbSUyRm9iaiUyRmJ5dGUtZ3VyZC1zb3VyY2Utc2clMkZ0aWt0b2slMkZmZSUyRmxpdmUlMkZ0aWt0b2tfbGl2ZV9yZXZlbnVlX3VzZXJfbGV2ZWxfbWFpbiUyRnNyYyUyRnBhZ2VzJTJGcHJpdmlsZWdlJTJGcGFuZWwlMkZ0ZW1wbGF0ZS5qcyZoaWRlX3N0YXR1c19iYXI9MCZoaWRlX25hdl9iYXI9MSZjb250YWluZXJfYmdfY29sb3I9MDAwMDAwMDAmaGVpZ2h0PTkwJTI1JmJkaG1fYmlkPXRpa3Rva19saXZlX3JldmVudWVfdXNlcl9sZXZlbF9tYWluJnVzZV9mb3Jlc3Q9MSIBOCoGCAEQAxggWg0KABIJIzk5NUY5MEVGYg0KABIJIzk5NUY5MEVGCAQyADoGGgISACIACAQIhYDcgoac26tcSs0ECrQBaHR0cHM6Ly9wMTYtc2lnbi12YS50aWt0b2tjZG4uY29tL3Rvcy1tYWxpdmEtYXZ0LTAwNjgvODZhN2JlYjk3MmY3YTQwYjIwYzVlZTI4MDY4NjU1MjN+dHBsdi10aWt0b2stc2hyaW5rOjcyOjcyLndlYnA/eC1leHBpcmVzPTE2OTI4OTY0MDAmeC1zaWduYXR1cmU9RUFIam1Ua1N1UVVKV1VBMzBkVGZDMUFMOVVvJTNECqgBaHR0cHM6Ly9wMTYtc2lnbi12YS50aWt0b2tjZG4uY29tL3Rvcy1tYWxpdmEtYXZ0LTAwNjgvODZhN2JlYjk3MmY3YTQwYjIwYzVlZTI4MDY4NjU1MjN+YzVfMTAweDEwMC53ZWJwP3gtZXhwaXJlcz0xNjkyODk2NDAwJngtc2lnbmF0dXJlPWFQTlF2ZmwlMkZvMUtxd2tvSjhJY1BWSHRGVUtZJTNECqoBaHR0cHM6Ly9wMTYtc2lnbi12YS50aWt0b2tjZG4uY29tL3Rvcy1tYWxpdmEtYXZ0LTAwNjgvODZhN2JlYjk3MmY3YTQwYjIwYzVlZTI4MDY4NjU1MjN+YzVfMTAweDEwMC5qcGVnP3gtZXhwaXJlcz0xNjkyODk2NDAwJngtc2lnbmF0dXJlPWYlMkZCVWY3QnU5U21GMm1uMm8xaWEzNDNhJTJGTFklM0QSPDEwMHgxMDAvdG9zLW1hbGl2YS1hdnQtMDA2OC84NmE3YmViOTcyZjdhNDBiMjBjNWVlMjgwNjg2NTUyM5oBB3Vua25vd26iAQVjbGljawrHDzABQoQPChVsaXZlX3Jvb21fZW50ZXJfdG9hc3QSD3swOnVzZXJ9IGpvaW5lZBoOCgkjYjhmZmZmZmYgkAMiyQ4ICxIMCgcjOENFN0ZGIJADqgG1DgqyDoICALICB3R0eC56eW6CBOUIEBQYCCABUukCc3Nsb2NhbDovL3dlYmNhc3RfbHlueHZpZXdfcG9wdXA/dXNlX3NwYXJrPTEmdXJsPWh0dHBzJTNBJTJGJTJGbGYxNi1nZWNrby1zb3VyY2UudGlrdG9rY2RuLmNvbSUyRm9iaiUyRmJ5dGUtZ3VyZC1zb3VyY2Utc2clMkZ0aWt0b2slMkZmZSUyRmxpdmUlMkZ0aWt0b2tfbGl2ZV9yZXZlbnVlX3VzZXJfbGV2ZWxfbWFpbiUyRnNyYyUyRnBhZ2VzJTJGcHJpdmlsZWdlJTJGcGFuZWwlMkZ0ZW1wbGF0ZS5qcyZoaWRlX3N0YXR1c19iYXI9MCZoaWRlX25hdl9iYXI9MSZjb250YWluZXJfYmdfY29sb3I9MDAwMDAwMDAmaGVpZ2h0PTkwJTI1JmJkaG1fYmlkPXRpa3Rva19saXZlX3JldmVudWVfdXNlcl9sZXZlbF9tYWluJnVzZV9mb3Jlc3Q9MVgBYk4iLm1vY2tfZml4X3dpZHRoX3RyYW5zcGFyZW50XzcxMzgzODExNzY3ODc1NTYxMzIqATgKATISEzcxMzgzODExNzY3ODc1NTYxMzIaATC6AZsFEtUEClxodHRwczovL3AxNi13ZWJjYXN0LnRpa3Rva2Nkbi5jb20vd2ViY2FzdC12YS9ncmFkZV9iYWRnZV9pY29uX2xpdGVfbHY1X3YxLnBuZ350cGx2LW9iai5pbWFnZQpcaHR0cHM6Ly9wMTktd2ViY2FzdC50aWt0b2tjZG4uY29tL3dlYmNhc3QtdmEvZ3JhZGVfYmFkZ2VfaWNvbl9saXRlX2x2NV92MS5wbmd+dHBsdi1vYmouaW1hZ2USK3dlYmNhc3QtdmEvZ3JhZGVfYmFkZ2VfaWNvbl9saXRlX2x2NV92MS5wbmc66QJzc2xvY2FsOi8vd2ViY2FzdF9seW54dmlld19wb3B1cD91c2Vfc3Bhcms9MSZ1cmw9aHR0cHMlM0ElMkYlMkZsZjE2LWdlY2tvLXNvdXJjZS50aWt0b2tjZG4uY29tJTJGb2JqJTJGYnl0ZS1ndXJkLXNvdXJjZS1zZyUyRnRpa3RvayUyRmZlJTJGbGl2ZSUyRnRpa3Rva19saXZlX3JldmVudWVfdXNlcl9sZXZlbF9tYWluJTJGc3JjJTJGcGFnZXMlMkZwcml2aWxlZ2UlMkZwYW5lbCUyRnRlbXBsYXRlLmpzJmhpZGVfc3RhdHVzX2Jhcj0wJmhpZGVfbmF2X2Jhcj0xJmNvbnRhaW5lcl9iZ19jb2xvcj0wMDAwMDAwMCZoZWlnaHQ9OTAlMjUmYmRobV9iaWQ9dGlrdG9rX2xpdmVfcmV2ZW51ZV91c2VyX2xldmVsX21haW4mdXNlX2ZvcmVzdD0xOgYaAhIAIgBiDQoAEgkjOTk1RjkwRUYIBCIBOCoGGCAIARADMgBaDRIJIzk5NUY5MEVGCgB4DoABD6IBBggBEAMYIAgESs0EEjwxMDB4MTAwL3Rvcy1tYWxpdmEtYXZ0LTAwNjgvODZhN2JlYjk3MmY3YTQwYjIwYzVlZTI4MDY4NjU1MjMKtAFodHRwczovL3AxNi1zaWduLXZhLnRpa3Rva2Nkbi5jb20vdG9zLW1hbGl2YS1hdnQtMDA2OC84NmE3YmViOTcyZjdhNDBiMjBjNWVlMjgwNjg2NTUyM350cGx2LXRpa3Rvay1zaHJpbms6NzI6NzIud2VicD94LWV4cGlyZXM9MTY5Mjg5NjQwMCZ4LXNpZ25hdHVyZT1FQUhqbVRrU3VRVUpXVUEzMGRUZkMxQUw5VW8lM0QKqAFodHRwczovL3AxNi1zaWduLXZhLnRpa3Rva2Nkbi5jb20vdG9zLW1hbGl2YS1hdnQtMDA2OC84NmE3YmViOTcyZjdhNDBiMjBjNWVlMjgwNjg2NTUyM35jNV8xMDB4MTAwLndlYnA/eC1leHBpcmVzPTE2OTI4OTY0MDAmeC1zaWduYXR1cmU9YVBOUXZmbCUyRm8xS3F3a29KOEljUFZIdEZVS1klM0QKqgFodHRwczovL3AxNi1zaWduLXZhLnRpa3Rva2Nkbi5jb20vdG9zLW1hbGl2YS1hdnQtMDA2OC84NmE3YmViOTcyZjdhNDBiMjBjNWVlMjgwNjg2NTUyM35jNV8xMDB4MTAwLmpwZWc/eC1leHBpcmVzPTE2OTI4OTY0MDAmeC1zaWduYXR1cmU9ZiUyRkJVZjdCdTlTbUYybW4ybzFpYTM0M2ElMkZMWSUzRBoH8J+Xo++4j7IBBAh2ED26AQDyAkxNUzR3TGpBQkFBQUFEbl9yQjQ4ckJSZWVIVTlXU2JZTk5ubEFNeWFlUkEySXdOSWlqa0ZuWkFPVlBnSmVuQzZhWTV1ekZ1OHBGMlRqCIWA3IKGnNurXEgBsAEDuAEBwAEBChRXZWJjYXN0TWVtYmVyTWVzc2FnZRCrlqKYuK+78mQYoJaG5sHJrvJkILTa/vGhMVABErIOSs0ECrQBaHR0cHM6Ly9wMTYtc2lnbi12YS50aWt0b2tjZG4uY29tL3Rvcy1tYWxpdmEtYXZ0LTAwNjgvODZhN2JlYjk3MmY3YTQwYjIwYzVlZTI4MDY4NjU1MjN+dHBsdi10aWt0b2stc2hyaW5rOjcyOjcyLndlYnA/eC1leHBpcmVzPTE2OTI4OTY0MDAmeC1zaWduYXR1cmU9RUFIam1Ua1N1UVVKV1VBMzBkVGZDMUFMOVVvJTNECqgBaHR0cHM6Ly9wMTYtc2lnbi12YS50aWt0b2tjZG4uY29tL3Rvcy1tYWxpdmEtYXZ0LTAwNjgvODZhN2JlYjk3MmY3YTQwYjIwYzVlZTI4MDY4NjU1MjN+YzVfMTAweDEwMC53ZWJwP3gtZXhwaXJlcz0xNjkyODk2NDAwJngtc2lnbmF0dXJlPWFQTlF2ZmwlMkZvMUtxd2tvSjhJY1BWSHRGVUtZJTNECqoBaHR0cHM6Ly9wMTYtc2lnbi12YS50aWt0b2tjZG4uY29tL3Rvcy1tYWxpdmEtYXZ0LTAwNjgvODZhN2JlYjk3MmY3YTQwYjIwYzVlZTI4MDY4NjU1MjN+YzVfMTAweDEwMC5qcGVnP3gtZXhwaXJlcz0xNjkyODk2NDAwJngtc2lnbmF0dXJlPWYlMkZCVWY3QnU5U21GMm1uMm8xaWEzNDNhJTJGTFklM0QSPDEwMHgxMDAvdG9zLW1hbGl2YS1hdnQtMDA2OC84NmE3YmViOTcyZjdhNDBiMjBjNWVlMjgwNjg2NTUyM7IBBAh2ED2CAgCyAgd0dHguenluGgfwn5ej77iPugEA8gJMTVM0d0xqQUJBQUFBRG5fckI0OHJCUmVlSFU5V1NiWU5ObmxBTXlhZVJBMkl3TklpamtGblpBT1ZQZ0plbkM2YVk1dXpGdThwRjJUaoIE5QhiTgoBMhITNzEzODM4MTE3Njc4NzU1NjEzMhoBMCIubW9ja19maXhfd2lkdGhfdHJhbnNwYXJlbnRfNzEzODM4MTE3Njc4NzU1NjEzMioBOLoBmwUiATgyAFoNCgASCSM5OTVGOTBFRoABD6IBBggBEAMYIAgEEtUEClxodHRwczovL3AxNi13ZWJjYXN0LnRpa3Rva2Nkbi5jb20vd2ViY2FzdC12YS9ncmFkZV9iYWRnZV9pY29uX2xpdGVfbHY1X3YxLnBuZ350cGx2LW9iai5pbWFnZQpcaHR0cHM6Ly9wMTktd2ViY2FzdC50aWt0b2tjZG4uY29tL3dlYmNhc3QtdmEvZ3JhZGVfYmFkZ2VfaWNvbl9saXRlX2x2NV92MS5wbmd+dHBsdi1vYmouaW1hZ2USK3dlYmNhc3QtdmEvZ3JhZGVfYmFkZ2VfaWNvbl9saXRlX2x2NV92MS5wbmc66QJzc2xvY2FsOi8vd2ViY2FzdF9seW54dmlld19wb3B1cD91c2Vfc3Bhcms9MSZ1cmw9aHR0cHMlM0ElMkYlMkZsZjE2LWdlY2tvLXNvdXJjZS50aWt0b2tjZG4uY29tJTJGb2JqJTJGYnl0ZS1ndXJkLXNvdXJjZS1zZyUyRnRpa3RvayUyRmZlJTJGbGl2ZSUyRnRpa3Rva19saXZlX3JldmVudWVfdXNlcl9sZXZlbF9tYWluJTJGc3JjJTJGcGFnZXMlMkZwcml2aWxlZ2UlMkZwYW5lbCUyRnRlbXBsYXRlLmpzJmhpZGVfc3RhdHVzX2Jhcj0wJmhpZGVfbmF2X2Jhcj0xJmNvbnRhaW5lcl9iZ19jb2xvcj0wMDAwMDAwMCZoZWlnaHQ9OTAlMjUmYmRobV9iaWQ9dGlrdG9rX2xpdmVfcmV2ZW51ZV91c2VyX2xldmVsX21haW4mdXNlX2ZvcmVzdD0xKgYYIAgBEAM6BhoCEgAiAGINCgASCSM5OTVGOTBFRngOCAQQFBgIIAFS6QJzc2xvY2FsOi8vd2ViY2FzdF9seW54dmlld19wb3B1cD91c2Vfc3Bhcms9MSZ1cmw9aHR0cHMlM0ElMkYlMkZsZjE2LWdlY2tvLXNvdXJjZS50aWt0b2tjZG4uY29tJTJGb2JqJTJGYnl0ZS1ndXJkLXNvdXJjZS1zZyUyRnRpa3RvayUyRmZlJTJGbGl2ZSUyRnRpa3Rva19saXZlX3JldmVudWVfdXNlcl9sZXZlbF9tYWluJTJGc3JjJTJGcGFnZXMlMkZwcml2aWxlZ2UlMkZwYW5lbCUyRnRlbXBsYXRlLmpzJmhpZGVfc3RhdHVzX2Jhcj0wJmhpZGVfbmF2X2Jhcj0xJmNvbnRhaW5lcl9iZ19jb2xvcj0wMDAwMDAwMCZoZWlnaHQ9OTAlMjUmYmRobV9iaWQ9dGlrdG9rX2xpdmVfcmV2ZW51ZV91c2VyX2xldmVsX21haW4mdXNlX2ZvcmVzdD0xWAEIhYDcgoac26tc \ No newline at end of file diff --git a/Client/src/test/resources/MessageWebcastChatMessage.bin b/Client/src/test/resources/MessageWebcastChatMessage.bin new file mode 100644 index 0000000..56ca920 --- /dev/null +++ b/Client/src/test/resources/MessageWebcastChatMessage.bin @@ -0,0 +1 @@ +kgEGEAEYASABmgEUCg51c2VyX3R5cGVfcnVsZRDgpxKaAR4KEWNvbW11bml0eS1mbGFnZ2VkEP///////////wGaARoKDmNvbW1lbnRhdG9yX2lkEIaIw5TSz92DYJoBEgoHZGVmYXVsdBDw+ICX6fCAA5oBEAoLZGVmYXVsdF9hcHAQkE6aAREKBnJhbmtWMxDjk7aZ6fCAA5oBGgoPdHRwX3J1bGVfcmVyYW5rENit45vp8IADmgEaEKj/ptWcvtCuAQoOdGltZXN0YW1wX2Rlc2OaATUKKnRpa2Nhc3RfY29tbXVuaXR5X2NvbW1lbnRfMTg4NjZfdjdfcjY1NTA2ORDb6LqZ6fCAA5oBOhCk6pOe6fCAAwovdGlrY2FzdF9jb21tdW5pdHlfY29tbWVudF8xODg2Nl92N19yNjU1MDY5X2Rlc2OaARoKD2lkY19ydWxlX3JlcmFuaxDY4eyu6fCAA5oBFhDY4eyu6fCAAwoLdjEzX3I3MTIwODiaARYKC3YxM19yNzEyMzU1ENjh7K7p8IADmgEWCgt2MTNfcjcxMjM1NhDY4eyu6fCAA5oBFgoLdjEyX3I3MDIwNzUQ2OHsrunwgAOaARoKD2lkY19ydWxlX3JlcmFuaxDY4eyu6fCAA5oBFgoLdjE0X3I3MjIxOTMQ2OHsrunwgAOaARYQ2OHsrunwgAMKC3YxNF9yNzIyMjAwmgEbChB2MTRfcjcyMjIwM191Z18xENjh7K7p8IADmgEbChB2MTRfcjcyMjIwM191Z18yENjh7K7p8IADmgEbChB2MTRfcjcyMjIwM191Z18zENjh7K7p8IADmgEbChB2MTRfcjcyMjIwM191Z180ENjh7K7p8IADmgEbChB2MTRfcjcyMjIwM191Z181ENjh7K7p8IADmgEbENjh7K7p8IADChB2MTRfcjcyMjIwM191Z182mgEbChB2MTRfcjcyMjIwNF91Z18xENjh7K7p8IADmgEbChB2MTRfcjcyMjIwNF91Z18yENjh7K7p8IADmgEbChB2MTRfcjcyMjIwNF91Z18zENjh7K7p8IADmgEbChB2MTRfcjcyMjIwNF91Z180ENjh7K7p8IADmgEbChB2MTRfcjcyMjIwNF91Z181ENjh7K7p8IADmgEbChB2MTRfcjcyMjIwNF91Z182ENjh7K7p8IADClAKEldlYmNhc3RDaGF0TWVzc2FnZSCEs+vyoTEwAbABBbgBAsABAhCglqOM8Ym98mQYoZabqPPRuvJkSAJQAnoIdXNlYXN0MmHIAc+t6/KhMRLSFAiGiMOU0s/dg2AaCWFsbWFuZG8yOboBAKoB7wEgEDAeClxodHRwczovL3AxNi13ZWJjYXN0LnRpa3Rva2Nkbi5jb20vd2ViY2FzdC12YS85NDM3Zjc0N2NmMTY3NTZhNzYxYjUzYTQ1Y2JiYmM2ZH50cGx2LW9iai5pbWFnZQpcaHR0cHM6Ly9wMTktd2ViY2FzdC50aWt0b2tjZG4uY29tL3dlYmNhc3QtdmEvOTQzN2Y3NDdjZjE2NzU2YTc2MWI1M2E0NWNiYmJjNmR+dHBsdi1vYmouaW1hZ2USK3dlYmNhc3QtdmEvOTQzN2Y3NDdjZjE2NzU2YTc2MWI1M2E0NWNiYmJjNmQYELICCWFsbWFuZG8yOUrpAwqbAWh0dHBzOi8vcDc3LXNpZ24tc2cudGlrdG9rY2RuLmNvbS90aWt0b2stb2JqLzE2ODkzNjI5MTc1NDcwMTB+dHBsdi10aWt0b2stc2hyaW5rOjcyOjcyLndlYnA/eC1leHBpcmVzPTE2OTI4OTY0MDAmeC1zaWduYXR1cmU9VFh2dGUzanlOb0dGWWRuUnh0QmViQjJSSTJvJTNECpABaHR0cHM6Ly9wNzctc2lnbi1zZy50aWt0b2tjZG4uY29tL2F3ZW1lLzEwMHgxMDAvdGlrdG9rLW9iai8xNjg5MzYyOTE3NTQ3MDEwLndlYnA/eC1leHBpcmVzPTE2OTI4OTY0MDAmeC1zaWduYXR1cmU9YTQzOEZ0VENKVjFYQVNSaGdCZnZDMUF3NUVBJTNECpABaHR0cHM6Ly9wNzctc2lnbi1zZy50aWt0b2tjZG4uY29tL2F3ZW1lLzEwMHgxMDAvdGlrdG9rLW9iai8xNjg5MzYyOTE3NTQ3MDEwLmpwZWc/eC1leHBpcmVzPTE2OTI4OTY0MDAmeC1zaWduYXR1cmU9cDFGdWE1RnVtb3pDYWY2emFQdDRjMlJKUHVJJTNEEiMxMDB4MTAwL3Rpa3Rvay1vYmovMTY4OTM2MjkxNzU0NzAxMLIBCAjVAxCUBRgCggIA8gJMTVM0d0xqQUJBQUFBTnVQSGNfRmlta1ZOaEtfV0RfdENWYldqZTVtTFBfN1ktUmlOdmFiaWltTU1DbGFzOTJIcVNHM3JFRGMxU1hTZoIEvgIIARAeGAQgAWI8KgEwCgEyEhM3MTE5ODA5MDk4NjYwNjk0Nzg5GgEwIhxtb2NrX3N1Yl83MTE5ODA5MDk4NjYwNjk0Nzg5ogH0AQgBEu8BClxodHRwczovL3AxNi13ZWJjYXN0LnRpa3Rva2Nkbi5jb20vd2ViY2FzdC12YS85NDM3Zjc0N2NmMTY3NTZhNzYxYjUzYTQ1Y2JiYmM2ZH50cGx2LW9iai5pbWFnZQpcaHR0cHM6Ly9wMTktd2ViY2FzdC50aWt0b2tjZG4uY29tL3dlYmNhc3QtdmEvOTQzN2Y3NDdjZjE2NzU2YTc2MWI1M2E0NWNiYmJjNmR+dHBsdi1vYmouaW1hZ2USK3dlYmNhc3QtdmEvOTQzN2Y3NDdjZjE2NzU2YTc2MWI1M2E0NWNiYmJjNmQYECAQMB6CBOoIYk8KATISEzcxMzgzODE3NDcyOTI1NTkxNDAaATAiLm1vY2tfZml4X3dpZHRoX3RyYW5zcGFyZW50XzcxMzgzODE3NDcyOTI1NTkxNDAqAjE2ugGfBToGGgISACIAWg0SCSNCMzQ3N0VGRgoAYg0SCSNCMzQ3N0VGRgoAeA4IBBLYBApdaHR0cHM6Ly9wMTYtd2ViY2FzdC50aWt0b2tjZG4uY29tL3dlYmNhc3QtdmEvZ3JhZGVfYmFkZ2VfaWNvbl9saXRlX2x2MTVfdjIucG5nfnRwbHYtb2JqLmltYWdlCl1odHRwczovL3AxOS13ZWJjYXN0LnRpa3Rva2Nkbi5jb20vd2ViY2FzdC12YS9ncmFkZV9iYWRnZV9pY29uX2xpdGVfbHYxNV92Mi5wbmd+dHBsdi1vYmouaW1hZ2USLHdlYmNhc3QtdmEvZ3JhZGVfYmFkZ2VfaWNvbl9saXRlX2x2MTVfdjIucG5nOukCc3Nsb2NhbDovL3dlYmNhc3RfbHlueHZpZXdfcG9wdXA/dXNlX3NwYXJrPTEmdXJsPWh0dHBzJTNBJTJGJTJGbGYxNi1nZWNrby1zb3VyY2UudGlrdG9rY2RuLmNvbSUyRm9iaiUyRmJ5dGUtZ3VyZC1zb3VyY2Utc2clMkZ0aWt0b2slMkZmZSUyRmxpdmUlMkZ0aWt0b2tfbGl2ZV9yZXZlbnVlX3VzZXJfbGV2ZWxfbWFpbiUyRnNyYyUyRnBhZ2VzJTJGcHJpdmlsZWdlJTJGcGFuZWwlMkZ0ZW1wbGF0ZS5qcyZoaWRlX3N0YXR1c19iYXI9MCZoaWRlX25hdl9iYXI9MSZjb250YWluZXJfYmdfY29sb3I9MDAwMDAwMDAmaGVpZ2h0PTkwJTI1JmJkaG1fYmlkPXRpa3Rva19saXZlX3JldmVudWVfdXNlcl9sZXZlbF9tYWluJnVzZV9mb3Jlc3Q9MSICMTYqBggBEAEYIIABDzIAogEGCAEQARggCAQQFBgIIAFS6QJzc2xvY2FsOi8vd2ViY2FzdF9seW54dmlld19wb3B1cD91c2Vfc3Bhcms9MSZ1cmw9aHR0cHMlM0ElMkYlMkZsZjE2LWdlY2tvLXNvdXJjZS50aWt0b2tjZG4uY29tJTJGb2JqJTJGYnl0ZS1ndXJkLXNvdXJjZS1zZyUyRnRpa3RvayUyRmZlJTJGbGl2ZSUyRnRpa3Rva19saXZlX3JldmVudWVfdXNlcl9sZXZlbF9tYWluJTJGc3JjJTJGcGFnZXMlMkZwcml2aWxlZ2UlMkZwYW5lbCUyRnRlbXBsYXRlLmpzJmhpZGVfc3RhdHVzX2Jhcj0wJmhpZGVfbmF2X2Jhcj0xJmNvbnRhaW5lcl9iZ19jb2xvcj0wMDAwMDAwMCZoZWlnaHQ9OTAlMjUmYmRobV9iaWQ9dGlrdG9rX2xpdmVfcmV2ZW51ZV91c2VyX2xldmVsX21haW4mdXNlX2ZvcmVzdD0xWAGCBL4CWAFiPAoBMhITNzExOTgwOTA5ODY2MDY5NDc4ORoBMCIcbW9ja19zdWJfNzExOTgwOTA5ODY2MDY5NDc4OSoBMLoB8gF4DoABDqIBCAgBKARAAUgBCAQSvwEKTmh0dHBzOi8vcDE2LXdlYmNhc3QudGlrdG9rY2RuLmNvbS93ZWJjYXN0LXZhL3N1YnNfYmFkZ2VfTHYxLnBuZ350cGx2LW9iai5pbWFnZQpOaHR0cHM6Ly9wMTktd2ViY2FzdC50aWt0b2tjZG4uY29tL3dlYmNhc3QtdmEvc3Vic19iYWRnZV9MdjEucG5nfnRwbHYtb2JqLmltYWdlEh13ZWJjYXN0LXZhL3N1YnNfYmFkZ2VfTHYxLnBuZyIDVklQKggIASgEQAFIAVoNEgkjOTlGRkJGMTUKAAgEEB4YBCABapEDEo4DChM3MjAyNTQ2ODY4NjEyNjgwNDUzEvYCCosBaHR0cHM6Ly9wMTYtd2ViY2FzdC50aWt0b2tjZG4uY29tL3dlYmNhc3QtdmEvc3ViX2FiMTMxYWMxZWRiNjA3NjgxNjUwOWQyMjlkOWM0MDY4MTFkZTJlMmY2NTAxNDA3ZjA3ZWE1NmM1ZGQ0ZmI4OGN+dHBsdi1meWp1eHV4YWc4LXdlYnAud2VicAqLAWh0dHBzOi8vcDE5LXdlYmNhc3QudGlrdG9rY2RuLmNvbS93ZWJjYXN0LXZhL3N1Yl9hYjEzMWFjMWVkYjYwNzY4MTY1MDlkMjI5ZDljNDA2ODExZGUyZTJmNjUwMTQwN2YwN2VhNTZjNWRkNGZiODhjfnRwbHYtZnlqdXh1eGFnOC13ZWJwLndlYnAST3dlYmNhc3QtdmEvc3ViX2FiMTMxYWMxZWRiNjA3NjgxNjUwOWQyMjlkOWM0MDY4MTFkZTJlMmY2NTAxNDA3ZjA3ZWE1NmM1ZGQ0ZmI4OGMqByNDQ0IxQTNqkwMIARKOAwoTNzIwMjU0Njg2ODYxMjY4MDQ1MxL2AioHI0U2RkFEQwqLAWh0dHBzOi8vcDE2LXdlYmNhc3QudGlrdG9rY2RuLmNvbS93ZWJjYXN0LXZhL3N1Yl9hYjEzMWFjMWVkYjYwNzY4MTY1MDlkMjI5ZDljNDA2ODExZGUyZTJmNjUwMTQwN2YwN2VhNTZjNWRkNGZiODhjfnRwbHYtZnlqdXh1eGFnOC13ZWJwLndlYnAKiwFodHRwczovL3AxOS13ZWJjYXN0LnRpa3Rva2Nkbi5jb20vd2ViY2FzdC12YS9zdWJfYWIxMzFhYzFlZGI2MDc2ODE2NTA5ZDIyOWQ5YzQwNjgxMWRlMmUyZjY1MDE0MDdmMDdlYTU2YzVkZDRmYjg4Y350cGx2LWZ5anV4dXhhZzgtd2VicC53ZWJwEk93ZWJjYXN0LXZhL3N1Yl9hYjEzMWFjMWVkYjYwNzY4MTY1MDlkMjI5ZDljNDA2ODExZGUyZTJmNjUwMTQwN2YwN2VhNTZjNWRkNGZiODhjapMDCAISjgMKEzcyMDI1NDY4Njg2MTI2ODA0NTMS9gIKiwFodHRwczovL3AxNi13ZWJjYXN0LnRpa3Rva2Nkbi5jb20vd2ViY2FzdC12YS9zdWJfYWIxMzFhYzFlZGI2MDc2ODE2NTA5ZDIyOWQ5YzQwNjgxMWRlMmUyZjY1MDE0MDdmMDdlYTU2YzVkZDRmYjg4Y350cGx2LWZ5anV4dXhhZzgtd2VicC53ZWJwCosBaHR0cHM6Ly9wMTktd2ViY2FzdC50aWt0b2tjZG4uY29tL3dlYmNhc3QtdmEvc3ViX2FiMTMxYWMxZWRiNjA3NjgxNjUwOWQyMjlkOWM0MDY4MTFkZTJlMmY2NTAxNDA3ZjA3ZWE1NmM1ZGQ0ZmI4OGN+dHBsdi1meWp1eHV4YWc4LXdlYnAud2VicBJPd2ViY2FzdC12YS9zdWJfYWIxMzFhYzFlZGI2MDc2ODE2NTA5ZDIyOWQ5YzQwNjgxMWRlMmUyZjY1MDE0MDdmMDdlYTU2YzVkZDRmYjg4YyoHI0UwQkNCQ2qTAwgDEo4DChM3MjAyNTQ2ODY4NjEyNjgwNDUzEvYCCosBaHR0cHM6Ly9wMTYtd2ViY2FzdC50aWt0b2tjZG4uY29tL3dlYmNhc3QtdmEvc3ViX2FiMTMxYWMxZWRiNjA3NjgxNjUwOWQyMjlkOWM0MDY4MTFkZTJlMmY2NTAxNDA3ZjA3ZWE1NmM1ZGQ0ZmI4OGN+dHBsdi1meWp1eHV4YWc4LXdlYnAud2VicAqLAWh0dHBzOi8vcDE5LXdlYmNhc3QudGlrdG9rY2RuLmNvbS93ZWJjYXN0LXZhL3N1Yl9hYjEzMWFjMWVkYjYwNzY4MTY1MDlkMjI5ZDljNDA2ODExZGUyZTJmNjUwMTQwN2YwN2VhNTZjNWRkNGZiODhjfnRwbHYtZnlqdXh1eGFnOC13ZWJwLndlYnAST3dlYmNhc3QtdmEvc3ViX2FiMTMxYWMxZWRiNjA3NjgxNjUwOWQyMjlkOWM0MDY4MTFkZTJlMmY2NTAxNDA3ZjA3ZWE1NmM1ZGQ0ZmI4OGMqByM1MjQwMzdqkwMSjgMKEzcyMDI1NDY4Njg2MTI2ODA0NTMS9gIKiwFodHRwczovL3AxNi13ZWJjYXN0LnRpa3Rva2Nkbi5jb20vd2ViY2FzdC12YS9zdWJfYWIxMzFhYzFlZGI2MDc2ODE2NTA5ZDIyOWQ5YzQwNjgxMWRlMmUyZjY1MDE0MDdmMDdlYTU2YzVkZDRmYjg4Y350cGx2LWZ5anV4dXhhZzgtd2VicC53ZWJwCosBaHR0cHM6Ly9wMTktd2ViY2FzdC50aWt0b2tjZG4uY29tL3dlYmNhc3QtdmEvc3ViX2FiMTMxYWMxZWRiNjA3NjgxNjUwOWQyMjlkOWM0MDY4MTFkZTJlMmY2NTAxNDA3ZjA3ZWE1NmM1ZGQ0ZmI4OGN+dHBsdi1meWp1eHV4YWc4LXdlYnAud2VicBJPd2ViY2FzdC12YS9zdWJfYWIxMzFhYzFlZGI2MDc2ODE2NTA5ZDIyOWQ5YzQwNjgxMWRlMmUyZjY1MDE0MDdmMDdlYTU2YzVkZDRmYjg4YyoHIzdDN0NBMwgEapMDCAUSjgMKEzcyMDI1NDY4Njg2MTI2ODA0NTMS9gIKiwFodHRwczovL3AxNi13ZWJjYXN0LnRpa3Rva2Nkbi5jb20vd2ViY2FzdC12YS9zdWJfYWIxMzFhYzFlZGI2MDc2ODE2NTA5ZDIyOWQ5YzQwNjgxMWRlMmUyZjY1MDE0MDdmMDdlYTU2YzVkZDRmYjg4Y350cGx2LWZ5anV4dXhhZzgtd2VicC53ZWJwCosBaHR0cHM6Ly9wMTktd2ViY2FzdC50aWt0b2tjZG4uY29tL3dlYmNhc3QtdmEvc3ViX2FiMTMxYWMxZWRiNjA3NjgxNjUwOWQyMjlkOWM0MDY4MTFkZTJlMmY2NTAxNDA3ZjA3ZWE1NmM1ZGQ0ZmI4OGN+dHBsdi1meWp1eHV4YWc4LXdlYnAud2VicBJPd2ViY2FzdC12YS9zdWJfYWIxMzFhYzFlZGI2MDc2ODE2NTA5ZDIyOWQ5YzQwNjgxMWRlMmUyZjY1MDE0MDdmMDdlYTU2YzVkZDRmYjg4YyoHI0NFQ0VFQmqTAwgGEo4DChM3MjAyNTQ2ODY4NjEyNjgwNDUzEvYCCosBaHR0cHM6Ly9wMTYtd2ViY2FzdC50aWt0b2tjZG4uY29tL3dlYmNhc3QtdmEvc3ViX2FiMTMxYWMxZWRiNjA3NjgxNjUwOWQyMjlkOWM0MDY4MTFkZTJlMmY2NTAxNDA3ZjA3ZWE1NmM1ZGQ0ZmI4OGN+dHBsdi1meWp1eHV4YWc4LXdlYnAud2VicAqLAWh0dHBzOi8vcDE5LXdlYmNhc3QudGlrdG9rY2RuLmNvbS93ZWJjYXN0LXZhL3N1Yl9hYjEzMWFjMWVkYjYwNzY4MTY1MDlkMjI5ZDljNDA2ODExZGUyZTJmNjUwMTQwN2YwN2VhNTZjNWRkNGZiODhjfnRwbHYtZnlqdXh1eGFnOC13ZWJwLndlYnAST3dlYmNhc3QtdmEvc3ViX2FiMTMxYWMxZWRiNjA3NjgxNjUwOWQyMjlkOWM0MDY4MTFkZTJlMmY2NTAxNDA3ZjA3ZWE1NmM1ZGQ0ZmI4OGMqByNBMzdDOTZqkwMIBxKOAwoTNzIwMjU0Njg2ODYxMjY4MDQ1MxL2AhJPd2ViY2FzdC12YS9zdWJfYWIxMzFhYzFlZGI2MDc2ODE2NTA5ZDIyOWQ5YzQwNjgxMWRlMmUyZjY1MDE0MDdmMDdlYTU2YzVkZDRmYjg4YyoHI0ZBRkFGQQqLAWh0dHBzOi8vcDE2LXdlYmNhc3QudGlrdG9rY2RuLmNvbS93ZWJjYXN0LXZhL3N1Yl9hYjEzMWFjMWVkYjYwNzY4MTY1MDlkMjI5ZDljNDA2ODExZGUyZTJmNjUwMTQwN2YwN2VhNTZjNWRkNGZiODhjfnRwbHYtZnlqdXh1eGFnOC13ZWJwLndlYnAKiwFodHRwczovL3AxOS13ZWJjYXN0LnRpa3Rva2Nkbi5jb20vd2ViY2FzdC12YS9zdWJfYWIxMzFhYzFlZGI2MDc2ODE2NTA5ZDIyOWQ5YzQwNjgxMWRlMmUyZjY1MDE0MDdmMDdlYTU2YzVkZDRmYjg4Y350cGx2LWZ5anV4dXhhZzgtd2VicC53ZWJwapMDCAgSjgMKEzcyMDI1NDY4Njg2MTI2ODA0NTMS9gIKiwFodHRwczovL3AxNi13ZWJjYXN0LnRpa3Rva2Nkbi5jb20vd2ViY2FzdC12YS9zdWJfYWIxMzFhYzFlZGI2MDc2ODE2NTA5ZDIyOWQ5YzQwNjgxMWRlMmUyZjY1MDE0MDdmMDdlYTU2YzVkZDRmYjg4Y350cGx2LWZ5anV4dXhhZzgtd2VicC53ZWJwCosBaHR0cHM6Ly9wMTktd2ViY2FzdC50aWt0b2tjZG4uY29tL3dlYmNhc3QtdmEvc3ViX2FiMTMxYWMxZWRiNjA3NjgxNjUwOWQyMjlkOWM0MDY4MTFkZTJlMmY2NTAxNDA3ZjA3ZWE1NmM1ZGQ0ZmI4OGN+dHBsdi1meWp1eHV4YWc4LXdlYnAud2VicBJPd2ViY2FzdC12YS9zdWJfYWIxMzFhYzFlZGI2MDc2ODE2NTA5ZDIyOWQ5YzQwNjgxMWRlMmUyZjY1MDE0MDdmMDdlYTU2YzVkZDRmYjg4YyoHI0ZGRUJGOGqTAwgJEo4DChM3MjAyNTQ2ODY4NjEyNjgwNDUzEvYCCosBaHR0cHM6Ly9wMTYtd2ViY2FzdC50aWt0b2tjZG4uY29tL3dlYmNhc3QtdmEvc3ViX2FiMTMxYWMxZWRiNjA3NjgxNjUwOWQyMjlkOWM0MDY4MTFkZTJlMmY2NTAxNDA3ZjA3ZWE1NmM1ZGQ0ZmI4OGN+dHBsdi1meWp1eHV4YWc4LXdlYnAud2VicAqLAWh0dHBzOi8vcDE5LXdlYmNhc3QudGlrdG9rY2RuLmNvbS93ZWJjYXN0LXZhL3N1Yl9hYjEzMWFjMWVkYjYwNzY4MTY1MDlkMjI5ZDljNDA2ODExZGUyZTJmNjUwMTQwN2YwN2VhNTZjNWRkNGZiODhjfnRwbHYtZnlqdXh1eGFnOC13ZWJwLndlYnAST3dlYmNhc3QtdmEvc3ViX2FiMTMxYWMxZWRiNjA3NjgxNjUwOWQyMjlkOWM0MDY4MTFkZTJlMmY2NTAxNDA3ZjA3ZWE1NmM1ZGQ0ZmI4OGMqByM4OUEzN0NqkwMIChKOAwoTNzIwMjU0Njg2ODYxMjY4MDQ1MxL2AgqLAWh0dHBzOi8vcDE2LXdlYmNhc3QudGlrdG9rY2RuLmNvbS93ZWJjYXN0LXZhL3N1Yl9hYjEzMWFjMWVkYjYwNzY4MTY1MDlkMjI5ZDljNDA2ODExZGUyZTJmNjUwMTQwN2YwN2VhNTZjNWRkNGZiODhjfnRwbHYtZnlqdXh1eGFnOC13ZWJwLndlYnAKiwFodHRwczovL3AxOS13ZWJjYXN0LnRpa3Rva2Nkbi5jb20vd2ViY2FzdC12YS9zdWJfYWIxMzFhYzFlZGI2MDc2ODE2NTA5ZDIyOWQ5YzQwNjgxMWRlMmUyZjY1MDE0MDdmMDdlYTU2YzVkZDRmYjg4Y350cGx2LWZ5anV4dXhhZzgtd2VicC53ZWJwEk93ZWJjYXN0LXZhL3N1Yl9hYjEzMWFjMWVkYjYwNzY4MTY1MDlkMjI5ZDljNDA2ODExZGUyZTJmNjUwMTQwN2YwN2VhNTZjNWRkNGZiODhjKgcjMzczNzUyapMDEo4DChM3MjAyNTQ2ODY4NjEyNjgwNDUzEvYCEk93ZWJjYXN0LXZhL3N1Yl9hYjEzMWFjMWVkYjYwNzY4MTY1MDlkMjI5ZDljNDA2ODExZGUyZTJmNjUwMTQwN2YwN2VhNTZjNWRkNGZiODhjKgcjNjY2NjY2CosBaHR0cHM6Ly9wMTYtd2ViY2FzdC50aWt0b2tjZG4uY29tL3dlYmNhc3QtdmEvc3ViX2FiMTMxYWMxZWRiNjA3NjgxNjUwOWQyMjlkOWM0MDY4MTFkZTJlMmY2NTAxNDA3ZjA3ZWE1NmM1ZGQ0ZmI4OGN+dHBsdi1meWp1eHV4YWc4LXdlYnAud2VicAqLAWh0dHBzOi8vcDE5LXdlYmNhc3QudGlrdG9rY2RuLmNvbS93ZWJjYXN0LXZhL3N1Yl9hYjEzMWFjMWVkYjYwNzY4MTY1MDlkMjI5ZDljNDA2ODExZGUyZTJmNjUwMTQwN2YwN2VhNTZjNWRkNGZiODhjfnRwbHYtZnlqdXh1eGFnOC13ZWJwLndlYnAIC2qTAxKOAwoTNzIwMjU0Njg2ODYxMjY4MDQ1MxL2AhJPd2ViY2FzdC12YS9zdWJfYWIxMzFhYzFlZGI2MDc2ODE2NTA5ZDIyOWQ5YzQwNjgxMWRlMmUyZjY1MDE0MDdmMDdlYTU2YzVkZDRmYjg4YyoHI0VCQ0VFMQqLAWh0dHBzOi8vcDE2LXdlYmNhc3QudGlrdG9rY2RuLmNvbS93ZWJjYXN0LXZhL3N1Yl9hYjEzMWFjMWVkYjYwNzY4MTY1MDlkMjI5ZDljNDA2ODExZGUyZTJmNjUwMTQwN2YwN2VhNTZjNWRkNGZiODhjfnRwbHYtZnlqdXh1eGFnOC13ZWJwLndlYnAKiwFodHRwczovL3AxOS13ZWJjYXN0LnRpa3Rva2Nkbi5jb20vd2ViY2FzdC12YS9zdWJfYWIxMzFhYzFlZGI2MDc2ODE2NTA5ZDIyOWQ5YzQwNjgxMWRlMmUyZjY1MDE0MDdmMDdlYTU2YzVkZDRmYjg4Y350cGx2LWZ5anV4dXhhZzgtd2VicC53ZWJwCAxqkwMIDRKOAwoTNzIwMjU0Njg2ODYxMjY4MDQ1MxL2AgqLAWh0dHBzOi8vcDE2LXdlYmNhc3QudGlrdG9rY2RuLmNvbS93ZWJjYXN0LXZhL3N1Yl9hYjEzMWFjMWVkYjYwNzY4MTY1MDlkMjI5ZDljNDA2ODExZGUyZTJmNjUwMTQwN2YwN2VhNTZjNWRkNGZiODhjfnRwbHYtZnlqdXh1eGFnOC13ZWJwLndlYnAKiwFodHRwczovL3AxOS13ZWJjYXN0LnRpa3Rva2Nkbi5jb20vd2ViY2FzdC12YS9zdWJfYWIxMzFhYzFlZGI2MDc2ODE2NTA5ZDIyOWQ5YzQwNjgxMWRlMmUyZjY1MDE0MDdmMDdlYTU2YzVkZDRmYjg4Y350cGx2LWZ5anV4dXhhZzgtd2VicC53ZWJwEk93ZWJjYXN0LXZhL3N1Yl9hYjEzMWFjMWVkYjYwNzY4MTY1MDlkMjI5ZDljNDA2ODExZGUyZTJmNjUwMTQwN2YwN2VhNTZjNWRkNGZiODhjKgcjQjFDQ0EzapMDEo4DChM3MjAyNTQ2ODY4NjEyNjgwNDUzEvYCCosBaHR0cHM6Ly9wMTYtd2ViY2FzdC50aWt0b2tjZG4uY29tL3dlYmNhc3QtdmEvc3ViX2FiMTMxYWMxZWRiNjA3NjgxNjUwOWQyMjlkOWM0MDY4MTFkZTJlMmY2NTAxNDA3ZjA3ZWE1NmM1ZGQ0ZmI4OGN+dHBsdi1meWp1eHV4YWc4LXdlYnAud2VicAqLAWh0dHBzOi8vcDE5LXdlYmNhc3QudGlrdG9rY2RuLmNvbS93ZWJjYXN0LXZhL3N1Yl9hYjEzMWFjMWVkYjYwNzY4MTY1MDlkMjI5ZDljNDA2ODExZGUyZTJmNjUwMTQwN2YwN2VhNTZjNWRkNGZiODhjfnRwbHYtZnlqdXh1eGFnOC13ZWJwLndlYnAST3dlYmNhc3QtdmEvc3ViX2FiMTMxYWMxZWRiNjA3NjgxNjUwOWQyMjlkOWM0MDY4MTFkZTJlMmY2NTAxNDA3ZjA3ZWE1NmM1ZGQ0ZmI4OGMqByNGMEYwRjAIDmqTAwgPEo4DChM3MjAyNTQ2ODY4NjEyNjgwNDUzEvYCCosBaHR0cHM6Ly9wMTYtd2ViY2FzdC50aWt0b2tjZG4uY29tL3dlYmNhc3QtdmEvc3ViX2FiMTMxYWMxZWRiNjA3NjgxNjUwOWQyMjlkOWM0MDY4MTFkZTJlMmY2NTAxNDA3ZjA3ZWE1NmM1ZGQ0ZmI4OGN+dHBsdi1meWp1eHV4YWc4LXdlYnAud2VicAqLAWh0dHBzOi8vcDE5LXdlYmNhc3QudGlrdG9rY2RuLmNvbS93ZWJjYXN0LXZhL3N1Yl9hYjEzMWFjMWVkYjYwNzY4MTY1MDlkMjI5ZDljNDA2ODExZGUyZTJmNjUwMTQwN2YwN2VhNTZjNWRkNGZiODhjfnRwbHYtZnlqdXh1eGFnOC13ZWJwLndlYnAST3dlYmNhc3QtdmEvc3ViX2FiMTMxYWMxZWRiNjA3NjgxNjUwOWQyMjlkOWM0MDY4MTFkZTJlMmY2NTAxNDA3ZjA3ZWE1NmM1ZGQ0ZmI4OGMqByNDRUNFRUJqkwMIEBKOAwoTNzIwMjU0Njg2ODYxMjY4MDQ1MxL2AgqLAWh0dHBzOi8vcDE2LXdlYmNhc3QudGlrdG9rY2RuLmNvbS93ZWJjYXN0LXZhL3N1Yl9hYjEzMWFjMWVkYjYwNzY4MTY1MDlkMjI5ZDljNDA2ODExZGUyZTJmNjUwMTQwN2YwN2VhNTZjNWRkNGZiODhjfnRwbHYtZnlqdXh1eGFnOC13ZWJwLndlYnAKiwFodHRwczovL3AxOS13ZWJjYXN0LnRpa3Rva2Nkbi5jb20vd2ViY2FzdC12YS9zdWJfYWIxMzFhYzFlZGI2MDc2ODE2NTA5ZDIyOWQ5YzQwNjgxMWRlMmUyZjY1MDE0MDdmMDdlYTU2YzVkZDRmYjg4Y350cGx2LWZ5anV4dXhhZzgtd2VicC53ZWJwEk93ZWJjYXN0LXZhL3N1Yl9hYjEzMWFjMWVkYjYwNzY4MTY1MDlkMjI5ZDljNDA2ODExZGUyZTJmNjUwMTQwN2YwN2VhNTZjNWRkNGZiODhjKgcjRENGNEZBapMDEo4DChM3MjAyNTQ2ODY4NjEyNjgwNDUzEvYCCosBaHR0cHM6Ly9wMTYtd2ViY2FzdC50aWt0b2tjZG4uY29tL3dlYmNhc3QtdmEvc3ViX2FiMTMxYWMxZWRiNjA3NjgxNjUwOWQyMjlkOWM0MDY4MTFkZTJlMmY2NTAxNDA3ZjA3ZWE1NmM1ZGQ0ZmI4OGN+dHBsdi1meWp1eHV4YWc4LXdlYnAud2VicAqLAWh0dHBzOi8vcDE5LXdlYmNhc3QudGlrdG9rY2RuLmNvbS93ZWJjYXN0LXZhL3N1Yl9hYjEzMWFjMWVkYjYwNzY4MTY1MDlkMjI5ZDljNDA2ODExZGUyZTJmNjUwMTQwN2YwN2VhNTZjNWRkNGZiODhjfnRwbHYtZnlqdXh1eGFnOC13ZWJwLndlYnAST3dlYmNhc3QtdmEvc3ViX2FiMTMxYWMxZWRiNjA3NjgxNjUwOWQyMjlkOWM0MDY4MTFkZTJlMmY2NTAxNDA3ZjA3ZWE1NmM1ZGQ0ZmI4OGMqByNFNkZBREMIEWqTAwgSEo4DChM3MjAyNTQ2ODY4NjEyNjgwNDUzEvYCCosBaHR0cHM6Ly9wMTYtd2ViY2FzdC50aWt0b2tjZG4uY29tL3dlYmNhc3QtdmEvc3ViX2FiMTMxYWMxZWRiNjA3NjgxNjUwOWQyMjlkOWM0MDY4MTFkZTJlMmY2NTAxNDA3ZjA3ZWE1NmM1ZGQ0ZmI4OGN+dHBsdi1meWp1eHV4YWc4LXdlYnAud2VicAqLAWh0dHBzOi8vcDE5LXdlYmNhc3QudGlrdG9rY2RuLmNvbS93ZWJjYXN0LXZhL3N1Yl9hYjEzMWFjMWVkYjYwNzY4MTY1MDlkMjI5ZDljNDA2ODExZGUyZTJmNjUwMTQwN2YwN2VhNTZjNWRkNGZiODhjfnRwbHYtZnlqdXh1eGFnOC13ZWJwLndlYnAST3dlYmNhc3QtdmEvc3ViX2FiMTMxYWMxZWRiNjA3NjgxNjUwOWQyMjlkOWM0MDY4MTFkZTJlMmY2NTAxNDA3ZjA3ZWE1NmM1ZGQ0ZmI4OGMqByNFMEJDQkM= \ No newline at end of file diff --git a/Client/src/test/resources/MessageWebcastGiftMessage.bin b/Client/src/test/resources/MessageWebcastGiftMessage.bin new file mode 100644 index 0000000..a6283ba --- /dev/null +++ b/Client/src/test/resources/MessageWebcastGiftMessage.bin @@ -0,0 +1 @@ +erUECoQCCmVodHRwczovL3AxNi13ZWJjYXN0LnRpa3Rva2Nkbi5jb20vaW1nL21hbGl2YS93ZWJjYXN0LXZhL2ViYTNhOWJiODVjMzNlMDE3ZjM2NDhlYWY4OGQ3MTg5fnRwbHYtb2JqLnBuZwplaHR0cHM6Ly9wMTktd2ViY2FzdC50aWt0b2tjZG4uY29tL2ltZy9tYWxpdmEvd2ViY2FzdC12YS9lYmEzYTliYjg1YzMzZTAxN2YzNjQ4ZWFmODhkNzE4OX50cGx2LW9iai5wbmcSK3dlYmNhc3QtdmEvZWJhM2E5YmI4NWMzM2UwMTdmMzY0OGVhZjg4ZDcxODkqByM3QzlCQTMg6Ac4AWABggEEUm9zZaoBhAIKZWh0dHBzOi8vcDE2LXdlYmNhc3QudGlrdG9rY2RuLmNvbS9pbWcvbWFsaXZhL3dlYmNhc3QtdmEvZWJhM2E5YmI4NWMzM2UwMTdmMzY0OGVhZjg4ZDcxODl+dHBsdi1vYmoucG5nCmVodHRwczovL3AxOS13ZWJjYXN0LnRpa3Rva2Nkbi5jb20vaW1nL21hbGl2YS93ZWJjYXN0LXZhL2ViYTNhOWJiODVjMzNlMDE3ZjM2NDhlYWY4OGQ3MTg5fnRwbHYtb2JqLnBuZxIrd2ViY2FzdC12YS9lYmEzYTliYjg1YzMzZTAxN2YzNjQ4ZWFmODhkNzE4OSoHI0EzQTNDQ9IGAQASCVNlbnQgUm9zZSiXLFABWAFoAYICAggBEJcsKAEwAVikjMbyoTFoAXIdEAEYAwoX////////////Af///////////wEylgGIAQEKwxEguIzG8qExMAFCxhAing8ICxIOCgkjZmY4Y2U3ZmYgkAOqAYgPCoMPsgIJbWFsb3dhbmFf8gJMTVM0d0xqQUJBQUFBTkR5S3pmZGNWTE9qVC1WdHQzQThaYmladnBiSmtCNmo5NjJQNU1MM3BDS2Z0Qkt4Wl9HS0xSc0lQSVZZdmFpTwiFiKqu0tmcwF4aIvCfp5rigI3imYDvuI9NYWxvd2FuYfCfp5zigI3imYDvuI9KgwUKyAFodHRwczovL3AxNi1zaWduLXVzZWFzdDJhLnRpa3Rva2Nkbi5jb20vdG9zLXVzZWFzdDJhLWF2dC0wMDY4LWV1dHRwLzZmNzg5YWQ4OGU5NmRjZThjMTljOWZkZGE1MTE0ZTk4fnRwbHYtdGlrdG9rLXNocmluazo3Mjo3Mi53ZWJwP3gtZXhwaXJlcz0xNjkyODk2NDAwJngtc2lnbmF0dXJlPXQzNG5PYlloRXJ3cFNaczIlMkZYMCUyRnE1TCUyRkwyWSUzRAq2AWh0dHBzOi8vcDE2LXNpZ24tdXNlYXN0MmEudGlrdG9rY2RuLmNvbS90b3MtdXNlYXN0MmEtYXZ0LTAwNjgtZXV0dHAvNmY3ODlhZDg4ZTk2ZGNlOGMxOWM5ZmRkYTUxMTRlOTh+YzVfMTAweDEwMC53ZWJwP3gtZXhwaXJlcz0xNjkyODk2NDAwJngtc2lnbmF0dXJlPTFFNzNWb3g0WjIxeiUyRmNnY29DSjg5U3VzSWZvJTNECrYBaHR0cHM6Ly9wMTYtc2lnbi11c2Vhc3QyYS50aWt0b2tjZG4uY29tL3Rvcy11c2Vhc3QyYS1hdnQtMDA2OC1ldXR0cC82Zjc4OWFkODhlOTZkY2U4YzE5YzlmZGRhNTExNGU5OH5jNV8xMDB4MTAwLmpwZWc/eC1leHBpcmVzPTE2OTI4OTY0MDAmeC1zaWduYXR1cmU9RyUyQk9hT2c5ZURGNFd0dkpUSVVndmxueHNZSmslM0QSRDEwMHgxMDAvdG9zLXVzZWFzdDJhLWF2dC0wMDY4LWV1dHRwLzZmNzg5YWQ4OGU5NmRjZThjMTljOWZkZGE1MTE0ZTk4ggThCCABUukCc3Nsb2NhbDovL3dlYmNhc3RfbHlueHZpZXdfcG9wdXA/dXNlX3NwYXJrPTEmdXJsPWh0dHBzJTNBJTJGJTJGbGYxNi1nZWNrby1zb3VyY2UudGlrdG9rY2RuLmNvbSUyRm9iaiUyRmJ5dGUtZ3VyZC1zb3VyY2Utc2clMkZ0aWt0b2slMkZmZSUyRmxpdmUlMkZ0aWt0b2tfbGl2ZV9yZXZlbnVlX3VzZXJfbGV2ZWxfbWFpbiUyRnNyYyUyRnBhZ2VzJTJGcHJpdmlsZWdlJTJGcGFuZWwlMkZ0ZW1wbGF0ZS5qcyZoaWRlX3N0YXR1c19iYXI9MCZoaWRlX25hdl9iYXI9MSZjb250YWluZXJfYmdfY29sb3I9MDAwMDAwMDAmaGVpZ2h0PTkwJTI1JmJkaG1fYmlkPXRpa3Rva19saXZlX3JldmVudWVfdXNlcl9sZXZlbF9tYWluJnVzZV9mb3Jlc3Q9MVgBYk8KATISEzcxMzgzODE3NDcyOTI1NzU1MjQaATAiLm1vY2tfZml4X3dpZHRoX3RyYW5zcGFyZW50XzcxMzgzODE3NDcyOTI1NzU1MjQqAjE3ugGWBSoGCAEQAhggMgA6BiIAGgISAFoNCgASCSNCMzQ3N0VGRmINCgASCSNCMzQ3N0VGRngOgAEPCAQiAjE3EtgEOukCc3Nsb2NhbDovL3dlYmNhc3RfbHlueHZpZXdfcG9wdXA/dXNlX3NwYXJrPTEmdXJsPWh0dHBzJTNBJTJGJTJGbGYxNi1nZWNrby1zb3VyY2UudGlrdG9rY2RuLmNvbSUyRm9iaiUyRmJ5dGUtZ3VyZC1zb3VyY2Utc2clMkZ0aWt0b2slMkZmZSUyRmxpdmUlMkZ0aWt0b2tfbGl2ZV9yZXZlbnVlX3VzZXJfbGV2ZWxfbWFpbiUyRnNyYyUyRnBhZ2VzJTJGcHJpdmlsZWdlJTJGcGFuZWwlMkZ0ZW1wbGF0ZS5qcyZoaWRlX3N0YXR1c19iYXI9MCZoaWRlX25hdl9iYXI9MSZjb250YWluZXJfYmdfY29sb3I9MDAwMDAwMDAmaGVpZ2h0PTkwJTI1JmJkaG1fYmlkPXRpa3Rva19saXZlX3JldmVudWVfdXNlcl9sZXZlbF9tYWluJnVzZV9mb3Jlc3Q9MQpdaHR0cHM6Ly9wMTYtd2ViY2FzdC50aWt0b2tjZG4uY29tL3dlYmNhc3QtdmEvZ3JhZGVfYmFkZ2VfaWNvbl9saXRlX2x2MTVfdjIucG5nfnRwbHYtb2JqLmltYWdlCl1odHRwczovL3AxOS13ZWJjYXN0LnRpa3Rva2Nkbi5jb20vd2ViY2FzdC12YS9ncmFkZV9iYWRnZV9pY29uX2xpdGVfbHYxNV92Mi5wbmd+dHBsdi1vYmouaW1hZ2USLHdlYmNhc3QtdmEvZ3JhZGVfYmFkZ2VfaWNvbl9saXRlX2x2MTVfdjIucG5nCAQQFBgIsgEGCLYHEM16ugEAggIAEAEiNwgMsgEyIP///////////wEIlywSIgoabGl2ZV9naWZ0X2NvcHl3cml0aW5nXzU2NTUSBFJvc2UiFggBEg4KCSNmZmZhY2UxNSCQA1oCeDEKH3dlYmNhc3RfYXdlbWVfZ2lmdF9zZW5kX21lc3NhZ2USIXswOnVzZXJ9IHNlbnQgezE6Z2lmdH0gezI6c3RyaW5nfRoOCgkjZmZmYWNlMTUgkANIAVACsAEFEKGWwcyLubzyZBihlpuo89G68mS4AQHAAQIKEldlYmNhc3RHaWZ0TWVzc2FnZTo68J+nmuKAjeKZgO+4j01hbG93YW5h8J+nnOKAjeKZgO+4jzogZ2lmdGVkIHRoZSBob3N0IDEgUm9zZTqZD7oBALICCW1hbG93YW5hX/ICTE1TNHdMakFCQUFBQU5EeUt6ZmRjVkxPalQtVnR0M0E4WmJpWnZwYkprQjZqOTYyUDVNTDNwQ0tmdEJLeFpfR0tMUnNJUElWWXZhaU+iQBM2ODA5NTY4ODYyMDEyMDgxMTU3GiLwn6ea4oCN4pmA77iPTWFsb3dhbmHwn6ec4oCN4pmA77iPsgEGCLYHEM16ggIAggThCGJPCgEyEhM3MTM4MzgxNzQ3MjkyNTc1NTI0GgEwIi5tb2NrX2ZpeF93aWR0aF90cmFuc3BhcmVudF83MTM4MzgxNzQ3MjkyNTc1NTI0KgIxN7oBlgUIBCICMTcqBggBEAIYIDIAOgYiABoCEgCAAQ8S2AQKXWh0dHBzOi8vcDE2LXdlYmNhc3QudGlrdG9rY2RuLmNvbS93ZWJjYXN0LXZhL2dyYWRlX2JhZGdlX2ljb25fbGl0ZV9sdjE1X3YyLnBuZ350cGx2LW9iai5pbWFnZQpdaHR0cHM6Ly9wMTktd2ViY2FzdC50aWt0b2tjZG4uY29tL3dlYmNhc3QtdmEvZ3JhZGVfYmFkZ2VfaWNvbl9saXRlX2x2MTVfdjIucG5nfnRwbHYtb2JqLmltYWdlEix3ZWJjYXN0LXZhL2dyYWRlX2JhZGdlX2ljb25fbGl0ZV9sdjE1X3YyLnBuZzrpAnNzbG9jYWw6Ly93ZWJjYXN0X2x5bnh2aWV3X3BvcHVwP3VzZV9zcGFyaz0xJnVybD1odHRwcyUzQSUyRiUyRmxmMTYtZ2Vja28tc291cmNlLnRpa3Rva2Nkbi5jb20lMkZvYmolMkZieXRlLWd1cmQtc291cmNlLXNnJTJGdGlrdG9rJTJGZmUlMkZsaXZlJTJGdGlrdG9rX2xpdmVfcmV2ZW51ZV91c2VyX2xldmVsX21haW4lMkZzcmMlMkZwYWdlcyUyRnByaXZpbGVnZSUyRnBhbmVsJTJGdGVtcGxhdGUuanMmaGlkZV9zdGF0dXNfYmFyPTAmaGlkZV9uYXZfYmFyPTEmY29udGFpbmVyX2JnX2NvbG9yPTAwMDAwMDAwJmhlaWdodD05MCUyNSZiZGhtX2JpZD10aWt0b2tfbGl2ZV9yZXZlbnVlX3VzZXJfbGV2ZWxfbWFpbiZ1c2VfZm9yZXN0PTFaDQoAEgkjQjM0NzdFRkZiDQoAEgkjQjM0NzdFRkZ4DggEEBQYCCABUukCc3Nsb2NhbDovL3dlYmNhc3RfbHlueHZpZXdfcG9wdXA/dXNlX3NwYXJrPTEmdXJsPWh0dHBzJTNBJTJGJTJGbGYxNi1nZWNrby1zb3VyY2UudGlrdG9rY2RuLmNvbSUyRm9iaiUyRmJ5dGUtZ3VyZC1zb3VyY2Utc2clMkZ0aWt0b2slMkZmZSUyRmxpdmUlMkZ0aWt0b2tfbGl2ZV9yZXZlbnVlX3VzZXJfbGV2ZWxfbWFpbiUyRnNyYyUyRnBhZ2VzJTJGcHJpdmlsZWdlJTJGcGFuZWwlMkZ0ZW1wbGF0ZS5qcyZoaWRlX3N0YXR1c19iYXI9MCZoaWRlX25hdl9iYXI9MSZjb250YWluZXJfYmdfY29sb3I9MDAwMDAwMDAmaGVpZ2h0PTkwJTI1JmJkaG1fYmlkPXRpa3Rva19saXZlX3JldmVudWVfdXNlcl9sZXZlbF9tYWluJnVzZV9mb3Jlc3Q9MVgBCIWIqq7S2ZzAXkqDBQrIAWh0dHBzOi8vcDE2LXNpZ24tdXNlYXN0MmEudGlrdG9rY2RuLmNvbS90b3MtdXNlYXN0MmEtYXZ0LTAwNjgtZXV0dHAvNmY3ODlhZDg4ZTk2ZGNlOGMxOWM5ZmRkYTUxMTRlOTh+dHBsdi10aWt0b2stc2hyaW5rOjcyOjcyLndlYnA/eC1leHBpcmVzPTE2OTI4OTY0MDAmeC1zaWduYXR1cmU9dDM0bk9iWWhFcndwU1pzMiUyRlgwJTJGcTVMJTJGTDJZJTNECrYBaHR0cHM6Ly9wMTYtc2lnbi11c2Vhc3QyYS50aWt0b2tjZG4uY29tL3Rvcy11c2Vhc3QyYS1hdnQtMDA2OC1ldXR0cC82Zjc4OWFkODhlOTZkY2U4YzE5YzlmZGRhNTExNGU5OH5jNV8xMDB4MTAwLndlYnA/eC1leHBpcmVzPTE2OTI4OTY0MDAmeC1zaWduYXR1cmU9MUU3M1ZveDRaMjF6JTJGY2djb0NKODlTdXNJZm8lM0QKtgFodHRwczovL3AxNi1zaWduLXVzZWFzdDJhLnRpa3Rva2Nkbi5jb20vdG9zLXVzZWFzdDJhLWF2dC0wMDY4LWV1dHRwLzZmNzg5YWQ4OGU5NmRjZThjMTljOWZkZGE1MTE0ZTk4fmM1XzEwMHgxMDAuanBlZz94LWV4cGlyZXM9MTY5Mjg5NjQwMCZ4LXNpZ25hdHVyZT1HJTJCT2FPZzllREY0V3R2SlRJVWd2bG54c1lKayUzRBJEMTAweDEwMC90b3MtdXNlYXN0MmEtYXZ0LTAwNjgtZXV0dHAvNmY3ODlhZDg4ZTk2ZGNlOGMxOWM5ZmRkYTUxMTRlOTi6AUoIhYCx8IeziMtcGIGJxvKhMVIHYW5kcm9pZFoGMzAwOTA0IJ6KxvKhMSiiiMbyoTEwuIzG8qExOF9AhYCx8IeziMtcSM2AxvKhMZACARgBIAGCASIyMDIzMDgyMjE3MzYxMjM1QTlFQjBEMDk4RUUwMjVFNTZFmgEAwAH///////////8B \ No newline at end of file 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 b59b8c5..0a08d29 100644 --- a/TestApplication/src/main/java/io/github/jwdeveloper/tiktok/Main.java +++ b/TestApplication/src/main/java/io/github/jwdeveloper/tiktok/Main.java @@ -23,7 +23,7 @@ public class Main { .onEmote(Main::onEmote) .onError(tikTokErrorEvent -> { - // tikTokErrorEvent.getException().printStackTrace(); + // tikTokErrorEvent.getException().printStackTrace(); }) .buildAndRun(); @@ -49,8 +49,7 @@ public class Main { } private static void onComment(TikTokCommentEvent e) { - print("DUPA: "+e.getText()); - // print(e.getUser().getUniqueId(), e.getText()); + print(e.getUser().getUniqueId(), e.getText()); } private static void onFollow(TikTokFollowEvent e) { @@ -83,6 +82,6 @@ public class Main { for (var message : messages) { sb.append(message).append(" "); } - System.out.println(sb.toString()); + System.out.println(sb); } } \ No newline at end of file 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 aaac433..e76af9a 100644 --- a/TestApplication/src/main/java/io/github/jwdeveloper/tiktok/SimpleExample.java +++ b/TestApplication/src/main/java/io/github/jwdeveloper/tiktok/SimpleExample.java @@ -1,12 +1,14 @@ package io.github.jwdeveloper.tiktok; +import java.io.IOException; + public class SimpleExample { - public static void main(String[] args) { + public static void main(String[] args) throws IOException { // Username of someone who is currently live - var tiktokUsername = "officialgeilegisela"; + var tiktokUsername = "szwagierkaqueen"; TikTokLive.newClient(tiktokUsername) - .clientSettings(settings -> + .configure(settings -> { }) .onConnected(event -> @@ -19,12 +21,13 @@ public class SimpleExample { }) .onComment(event -> { - System.out.println(event.getUser().getUniqueId() + ": " + event.getText()); + System.out.println(event.getUser().getUniqueId() + ": " + event.getText()); }) .onError(event -> { event.getException().printStackTrace(); }) .buildAndRun(); + System.in.read(); } }