diff --git a/API/src/main/java/io/github/jwdeveloper/tiktok/data/settings/LiveClientSettings.java b/API/src/main/java/io/github/jwdeveloper/tiktok/data/settings/LiveClientSettings.java
index 3ac9b9d..0f141a9 100644
--- a/API/src/main/java/io/github/jwdeveloper/tiktok/data/settings/LiveClientSettings.java
+++ b/API/src/main/java/io/github/jwdeveloper/tiktok/data/settings/LiveClientSettings.java
@@ -86,9 +86,15 @@ public class LiveClientSettings {
private HttpClientSettings httpSettings;
/**
- * Optional: Sometimes not every messages from chat are send to TikTokLiveJava to fix this issue you can set sessionId
- * documentation how to obtain sessionId https://github.com/isaackogan/TikTok-Live-Connector#send-chat-messages
+ * Interval of time in milliseconds between pings to TikTok
+ * @apiNote Min: 250 (0.25 seconds), Default: 5000 (5 seconds)
*/
+ private long pingInterval = 5000;
+
+ /**
+ * Optional: Sometimes not every messages from chat are send to TikTokLiveJava to fix this issue you can set sessionId
+ * @see Documentation: How to obtain sessionId
+ */
private String sessionId;
/**
diff --git a/Client/src/main/java/io/github/jwdeveloper/tiktok/TikTokLive.java b/Client/src/main/java/io/github/jwdeveloper/tiktok/TikTokLive.java
index cde7406..204e9cb 100644
--- a/Client/src/main/java/io/github/jwdeveloper/tiktok/TikTokLive.java
+++ b/Client/src/main/java/io/github/jwdeveloper/tiktok/TikTokLive.java
@@ -28,7 +28,6 @@ import io.github.jwdeveloper.tiktok.http.LiveHttpClient;
import io.github.jwdeveloper.tiktok.live.GiftsManager;
import io.github.jwdeveloper.tiktok.live.builder.LiveClientBuilder;
-import java.util.List;
import java.util.concurrent.CompletableFuture;
public class TikTokLive {
@@ -102,14 +101,9 @@ public class TikTokLive {
* @return GiftsManager
*/
public static GiftsManager gifts() {
- if (giftsManager != null) {
- return giftsManager;
- }
- synchronized (GiftsManager.class)
- {
- if (giftsManager == null)
- {
- return new TikTokGiftsManager(requests().fetchGiftsData().getGifts());
+ if (giftsManager == null) {
+ synchronized (GiftsManager.class) {
+ giftsManager = new TikTokGiftsManager(requests().fetchGiftsData().getGifts());
}
}
return giftsManager;
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 e0e1fe4..d23aad5 100644
--- a/Client/src/main/java/io/github/jwdeveloper/tiktok/TikTokLiveClientBuilder.java
+++ b/Client/src/main/java/io/github/jwdeveloper/tiktok/TikTokLiveClientBuilder.java
@@ -96,6 +96,9 @@ public class TikTokLiveClientBuilder implements LiveClientBuilder {
if (clientSettings.getHostName().startsWith("@"))
clientSettings.setHostName(clientSettings.getHostName().substring(1));
+ if (clientSettings.getPingInterval() < 250)
+ throw new TikTokLiveException("Minimum allowed ping interval is 250 millseconds");
+
var httpSettings = clientSettings.getHttpSettings();
httpSettings.getParams().put("app_language", clientSettings.getClientLanguage());
httpSettings.getParams().put("webcast_language", clientSettings.getClientLanguage());
diff --git a/Client/src/main/java/io/github/jwdeveloper/tiktok/TikTokLiveHttpClient.java b/Client/src/main/java/io/github/jwdeveloper/tiktok/TikTokLiveHttpClient.java
index eadde29..0d1098d 100644
--- a/Client/src/main/java/io/github/jwdeveloper/tiktok/TikTokLiveHttpClient.java
+++ b/Client/src/main/java/io/github/jwdeveloper/tiktok/TikTokLiveHttpClient.java
@@ -83,7 +83,7 @@ public class TikTokLiveHttpClient implements LiveHttpClient
.toJsonResponse();
if (result.isFailure())
- throw new TikTokLiveRequestException("Unable to fetch gifts information's"+result.toStack());
+ throw new TikTokLiveRequestException("Unable to fetch gifts information's - "+result);
var json = result.getContent();
return giftsDataMapper.map(json);
@@ -111,10 +111,10 @@ public class TikTokLiveHttpClient implements LiveHttpClient
.toJsonResponse();
if (result.isFailure())
- throw new TikTokLiveRequestException("Unable to get information's about user"+result.toStack());
+ throw new TikTokLiveRequestException("Unable to get information's about user - "+result);
var json = result.getContent();
- return liveUserDataMapper.map(json);
+ return liveUserDataMapper.map(json, logger);
}
@Override
@@ -138,7 +138,7 @@ public class TikTokLiveHttpClient implements LiveHttpClient
.toJsonResponse();
if (result.isFailure())
- throw new TikTokLiveRequestException("Unable to get info about live room"+result.toStack());
+ throw new TikTokLiveRequestException("Unable to get info about live room - "+result);
var json = result.getContent();
return liveDataMapper.map(json);
@@ -153,7 +153,7 @@ public class TikTokLiveHttpClient implements LiveHttpClient
var resultHeader = ActionResult.of(credentialsResponse.headers().firstValue("x-set-tt-cookie"));
if (resultHeader.isFailure()) {
logger.warning("SignServer Headers: "+request.getRoomId()+" - "+credentialsResponse.headers().map());
- throw new TikTokSignServerException("Sign server did not return the x-set-tt-cookie header"+result.toStack());
+ throw new TikTokSignServerException("Sign server did not return the x-set-tt-cookie header - "+result);
}
var websocketCookie = resultHeader.getContent();
var webcastResponse = WebcastResponse.parseFrom(credentialsResponse.body());
@@ -169,7 +169,7 @@ public class TikTokLiveHttpClient implements LiveHttpClient
return new LiveConnectionData.Response(websocketCookie, webSocketUrl, webcastResponse);
} catch (InvalidProtocolBufferException e) {
- throw new TikTokSignServerException("Unable to parse websocket credentials response to WebcastResponse"+result.toStack());
+ throw new TikTokSignServerException("Unable to parse websocket credentials response to WebcastResponse - "+result);
}
}
@@ -197,7 +197,7 @@ public class TikTokLiveHttpClient implements LiveHttpClient
var result = builder.build().toResponse();
if (result.isFailure())
- throw new TikTokSignServerException("Unable to get websocket connection credentials"+result.toStack());
+ throw new TikTokSignServerException("Unable to get websocket connection credentials - "+result);
return result;
}
diff --git a/Client/src/main/java/io/github/jwdeveloper/tiktok/common/ActionResult.java b/Client/src/main/java/io/github/jwdeveloper/tiktok/common/ActionResult.java
index 34ab7b3..ac8cd60 100644
--- a/Client/src/main/java/io/github/jwdeveloper/tiktok/common/ActionResult.java
+++ b/Client/src/main/java/io/github/jwdeveloper/tiktok/common/ActionResult.java
@@ -1,6 +1,8 @@
package io.github.jwdeveloper.tiktok.common;
+import com.google.gson.*;
import lombok.Data;
+import lombok.experimental.Accessors;
import java.util.Optional;
import java.util.function.Function;
@@ -11,6 +13,8 @@ public class ActionResult {
private boolean success = true;
private T content;
private String message;
+ @Accessors(chain = true, fluent = true)
+ private ActionResult> previous;
protected ActionResult(T object) {
this.content = object;
@@ -41,8 +45,9 @@ public class ActionResult {
public boolean hasMessage() {
return message != null;
}
- public String toStack() {
- return hasMessage() ? " - "+message : "";
+
+ public boolean hasPrevious() {
+ return previous != null;
}
public boolean hasContent() {
@@ -84,4 +89,18 @@ public class ActionResult {
public static ActionResult failure() {
return failure(null);
}
+
+ public JsonObject toJson() {
+ JsonObject map = new JsonObject();
+ map.addProperty("success", success);
+ map.add("content", new Gson().toJsonTree(content));
+ map.addProperty("message", message);
+ map.add("previous", hasPrevious() ? previous.toJson() : null);
+ return map;
+ }
+
+ @Override
+ public String toString() {
+ return "ActionResult: "+new Gson().newBuilder().setPrettyPrinting().create().toJson(toJson());
+ }
}
\ No newline at end of file
diff --git a/Client/src/main/java/io/github/jwdeveloper/tiktok/common/ActionResultBuilder.java b/Client/src/main/java/io/github/jwdeveloper/tiktok/common/ActionResultBuilder.java
index 369d35f..f9383d9 100644
--- a/Client/src/main/java/io/github/jwdeveloper/tiktok/common/ActionResultBuilder.java
+++ b/Client/src/main/java/io/github/jwdeveloper/tiktok/common/ActionResultBuilder.java
@@ -1,5 +1,8 @@
package io.github.jwdeveloper.tiktok.common;
+import lombok.Setter;
+import lombok.experimental.Accessors;
+
import java.util.Arrays;
import java.util.stream.Collectors;
@@ -7,6 +10,8 @@ public class ActionResultBuilder
{
private final T content;
private String message;
+ @Setter @Accessors(fluent = true, chain = true)
+ private ActionResult> previous;
public ActionResultBuilder(T content) {
this.content = content;
@@ -18,10 +23,10 @@ public class ActionResultBuilder
}
public ActionResult success() {
- return ActionResult.success(content, message);
+ return ActionResult.success(content, message).previous(previous);
}
public ActionResult failure() {
- return ActionResult.success(content, message);
+ return ActionResult.success(content, message).previous(previous);
}
}
\ No newline at end of file
diff --git a/Client/src/main/java/io/github/jwdeveloper/tiktok/http/mappers/LiveUserDataMapper.java b/Client/src/main/java/io/github/jwdeveloper/tiktok/http/mappers/LiveUserDataMapper.java
index 6dd2aed..9b9cd4b 100644
--- a/Client/src/main/java/io/github/jwdeveloper/tiktok/http/mappers/LiveUserDataMapper.java
+++ b/Client/src/main/java/io/github/jwdeveloper/tiktok/http/mappers/LiveUserDataMapper.java
@@ -22,45 +22,52 @@
*/
package io.github.jwdeveloper.tiktok.http.mappers;
-import com.google.gson.JsonParser;
+import com.google.gson.*;
import io.github.jwdeveloper.tiktok.data.requests.LiveUserData;
import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveRequestException;
+import java.util.logging.Logger;
+
public class LiveUserDataMapper
{
- public LiveUserData.Response map(String json) {
- var jsonObject = JsonParser.parseString(json).getAsJsonObject();
+ public LiveUserData.Response map(String json, Logger logger) {
+ try {
+ var jsonObject = JsonParser.parseString(json).getAsJsonObject();
- var message = jsonObject.get("message").getAsString();
+ var message = jsonObject.get("message").getAsString();
- if (message.equals("params_error")) {
- throw new TikTokLiveRequestException("fetchRoomIdFromTiktokApi -> Unable to fetch roomID, contact the developer");
- }
- if (message.equals("user_not_found")) {
+ if (message.equals("params_error")) {
+ throw new TikTokLiveRequestException("fetchRoomIdFromTiktokApi -> Unable to fetch roomID, contact the developer");
+ }
+ if (message.equals("user_not_found")) {
+ return new LiveUserData.Response(json, LiveUserData.UserStatus.NotFound, "", -1);
+ }
+ //live -> status 2
+ //live paused -> 3
+ //not live -> status 4
+ var element = jsonObject.get("data");
+ if (element.isJsonNull()) {
+ return new LiveUserData.Response(json, LiveUserData.UserStatus.NotFound, "", -1);
+ }
+ var data = element.getAsJsonObject();
+ var user = data.getAsJsonObject("user");
+ var roomId = user.get("roomId").getAsString();
+ var status = user.get("status").getAsInt();
+
+ var liveRoom = data.getAsJsonObject("liveRoom");
+ long startTime = liveRoom.get("startTime").getAsLong();
+
+ var statusEnum = switch (status) {
+ case 2 -> LiveUserData.UserStatus.Live;
+ case 3 -> LiveUserData.UserStatus.LivePaused;
+ case 4 -> LiveUserData.UserStatus.Offline;
+ default -> LiveUserData.UserStatus.NotFound;
+ };
+
+ return new LiveUserData.Response(json, statusEnum, roomId, startTime);
+ } catch (JsonSyntaxException e) {
+ logger.warning("Malformed Json: '"+json+"' - Error Message: "+e.getMessage());
return new LiveUserData.Response(json, LiveUserData.UserStatus.NotFound, "", -1);
}
- //live -> status 2
- //live paused -> 3
- //not live -> status 4
- var element = jsonObject.get("data");
- if (element.isJsonNull()) {
- return new LiveUserData.Response(json, LiveUserData.UserStatus.NotFound, "", -1);
- }
- var data = element.getAsJsonObject();
- var user = data.getAsJsonObject("user");
- var roomId = user.get("roomId").getAsString();
- var status = user.get("status").getAsInt();
-
- var liveRoom = data.getAsJsonObject("liveRoom");
- long startTime = liveRoom.get("startTime").getAsLong();
-
- var statusEnum = switch (status) {
- case 2 -> LiveUserData.UserStatus.Live;
- case 3 -> LiveUserData.UserStatus.LivePaused;
- case 4 -> LiveUserData.UserStatus.Offline;
- default -> LiveUserData.UserStatus.NotFound;
- };
-
- return new LiveUserData.Response(json, statusEnum, roomId, startTime);
}
}
\ No newline at end of file
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 d3f0f19..d1c8a62 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
@@ -82,7 +82,7 @@ public class TikTokWebSocketClient implements SocketClient {
private void connectDefault() {
try {
webSocketClient.connect();
- pingingTask.run(webSocketClient);
+ pingingTask.run(webSocketClient, clientSettings.getPingInterval());
isConnected = true;
} catch (Exception e) {
isConnected = false;
@@ -112,7 +112,7 @@ public class TikTokWebSocketClient implements SocketClient {
proxySettings.remove();
continue;
}
- pingingTask.run(webSocketClient);
+ pingingTask.run(webSocketClient, clientSettings.getPingInterval());
isConnected = true;
break;
}
diff --git a/Client/src/main/java/io/github/jwdeveloper/tiktok/websocket/TikTokWebSocketPingingTask.java b/Client/src/main/java/io/github/jwdeveloper/tiktok/websocket/TikTokWebSocketPingingTask.java
index 90adbc4..e44987b 100644
--- a/Client/src/main/java/io/github/jwdeveloper/tiktok/websocket/TikTokWebSocketPingingTask.java
+++ b/Client/src/main/java/io/github/jwdeveloper/tiktok/websocket/TikTokWebSocketPingingTask.java
@@ -8,13 +8,13 @@ public class TikTokWebSocketPingingTask
{
private Thread thread;
private boolean isRunning = false;
- private final int MIN_TIMEOUT = 250;
- private final int MAX_TIMEOUT = 500;
+ private final int MAX_TIMEOUT = 250;
+ private final int SLEEP_TIME = 500;
- public void run(WebSocket webSocket)
+ public void run(WebSocket webSocket, long pingTaskTime)
{
stop();
- thread = new Thread(() -> pingTask(webSocket));
+ thread = new Thread(() -> pingTask(webSocket, pingTaskTime));
isRunning = true;
thread.start();
}
@@ -26,20 +26,18 @@ public class TikTokWebSocketPingingTask
isRunning = false;
}
-
- private void pingTask(WebSocket webSocket)
+ private void pingTask(WebSocket webSocket, long pingTaskTime)
{
var random = new Random();
while (isRunning) {
try {
if (!webSocket.isOpen()) {
- Thread.sleep(100);
+ Thread.sleep(SLEEP_TIME);
continue;
}
webSocket.sendPing();
- var timeout = random.nextInt(MAX_TIMEOUT)+MIN_TIMEOUT;
- Thread.sleep(timeout);
+ Thread.sleep(pingTaskTime+random.nextInt(MAX_TIMEOUT));
}
catch (Exception e) {
isRunning = false;
diff --git a/Examples/src/main/java/io/github/jwdeveloper/tiktok/CollectorExample.java b/Examples/src/main/java/io/github/jwdeveloper/tiktok/CollectorExample.java
index 9972bc7..aed2c8d 100644
--- a/Examples/src/main/java/io/github/jwdeveloper/tiktok/CollectorExample.java
+++ b/Examples/src/main/java/io/github/jwdeveloper/tiktok/CollectorExample.java
@@ -27,8 +27,7 @@ import io.github.jwdeveloper.tiktok.extension.collector.TikTokLiveCollector;
import java.io.File;
import java.io.IOException;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
public class CollectorExample {
@@ -60,4 +59,4 @@ public class CollectorExample {
System.in.read();
collector.disconnect();
}
-}
+}
\ No newline at end of file
diff --git a/extension-collector/src/main/java/io/github/jwdeveloper/tiktok/extension/collector/api/settings/mongo/MongoDataCollectorSettings.java b/extension-collector/src/main/java/io/github/jwdeveloper/tiktok/extension/collector/api/settings/mongo/MongoDataCollectorSettings.java
index 3d319ab..bca2564 100644
--- a/extension-collector/src/main/java/io/github/jwdeveloper/tiktok/extension/collector/api/settings/mongo/MongoDataCollectorSettings.java
+++ b/extension-collector/src/main/java/io/github/jwdeveloper/tiktok/extension/collector/api/settings/mongo/MongoDataCollectorSettings.java
@@ -29,7 +29,6 @@ import java.util.function.Consumer;
@Data
public class MongoDataCollectorSettings {
- @Setter
private String connectionUrl;
private String databaseName = "tiktok";