Compare commits

..

28 Commits

Author SHA1 Message Date
kohlerpop1
103ed7e3ed Changed isNotClosing to isOpen because if isOpen is false inside of any of the using methods, it throws an exception. 2024-03-31 20:19:24 -04:00
GitHub Action
67e70c34bc Update version in pom.xml 2024-03-03 21:42:11 +00:00
JW
786c24d267 Merge remote-tracking branch 'origin/master' 2024-03-03 22:40:11 +01:00
JW
966d2f65d8 - improve recorder 2024-03-03 22:39:44 +01:00
GitHub Action
7ba7143f5a Update version in pom.xml 2024-03-02 09:57:33 +00:00
JW
92fde03f2b - improve collector 2024-03-02 10:55:44 +01:00
GitHub Action
e058290118 Update version in pom.xml 2024-03-01 23:17:33 +00:00
David Kohler
d25741b229 Merge pull request #67 from jwdeveloper/develop-1.5.1
Fix for mapping of HttpResponse & HttpRequest and more!
2024-03-01 18:15:41 -05:00
kohlerpop1
560a8d7c3b Added IllegalStateException to LiveUserDataMapper to catch getAsJsonObject exception.
Created HttpRequestJsonMapper and HttpResponseJsonMapper for ActionResult gson parser.
2024-03-01 16:08:05 -05:00
GitHub Action
6178bc25cf Update version in pom.xml 2024-03-01 01:54:49 +00:00
Jacek W
48d1138754 MINOR 2024-03-01 02:53:04 +01:00
Jacek W
a5320db820 Merge pull request #63 from jwdeveloper/develop-1.5.0
Develop 1.5.0
2024-03-01 02:51:35 +01:00
JW
4e1ab35a60 Merge branch 'master' into develop-1.5.0
# Conflicts:
#	Tools-EventsCollector/pom.xml
#	Tools-EventsWebViewer/pom.xml
2024-03-01 02:50:35 +01:00
David Kohler
cef4972f37 Merge pull request #64 from jwdeveloper/develop-1.5.0-live-user-data-fix
Develop 1.5.0 live user data fix
2024-02-29 20:42:36 -05:00
JW
713c90a271 . 2024-03-01 02:42:23 +01:00
kohlerpop1
71853db5cc Merge remote-tracking branch 'origin/develop-1.5.0' into develop-1.5.0-live-user-data-fix
# Conflicts:
#	Client/src/main/java/io/github/jwdeveloper/tiktok/TikTokLiveClient.java
2024-02-29 20:38:53 -05:00
kohlerpop1
ef90d4cd58 Moved validation to TikTokLiveClientBuilder#validate! 2024-02-29 20:38:05 -05:00
Jacek W
dad4048bc0 Merge pull request #65 from jwdeveloper/develop-1.5.0-publishing-messages
- implementing publishing messages
2024-03-01 02:35:52 +01:00
kohlerpop1
9ba049d37a Fixed CollectorExample and removed useless @Setter in MongoDataCollectorSettings! 2024-02-29 20:27:41 -05:00
kohlerpop1
f7d657371b Merge remote-tracking branch 'origin/develop-1.5.0' into develop-1.5.0-live-user-data-fix
# Conflicts:
#	extension-collector/src/main/java/io/github/jwdeveloper/tiktok/extension/collector/api/settings/mongo/MongoDataCollectorSettings.java
2024-02-29 20:23:32 -05:00
JW
eea691a5aa - implementing publishing messages 2024-03-01 02:20:11 +01:00
Jacek W
a249ac0cdd Merge pull request #62 from jwdeveloper/develop-1.5.0-messages-to-file
Develop 1.5.0 messages to file
2024-03-01 01:53:21 +01:00
kohlerpop1
29631ac468 Fixed Live User Data Mapper throwing MalformedJsonException! 2024-02-29 19:19:23 -05:00
kohlerpop1
15c642297c Fixed Live User Data Mapper throwing MalformedJsonException! 2024-02-28 21:03:00 -05:00
GitHub Action
ead954dd27 Update version in pom.xml 2024-02-26 15:26:34 +00:00
Jacek W
e37b30ff12 MINOR 2024-02-26 16:20:47 +01:00
GitHub Action
7a5c00d99a Update version in pom.xml 2024-02-26 15:17:09 +00:00
Jacek W
407f51fa73 Merge pull request #59 from jwdeveloper/develop-1.4.0
MINOR update
2024-02-26 16:15:37 +01:00
32 changed files with 278 additions and 175 deletions

View File

@@ -5,7 +5,7 @@
<parent> <parent>
<artifactId>TikTokLiveJava</artifactId> <artifactId>TikTokLiveJava</artifactId>
<groupId>io.github.jwdeveloper.tiktok</groupId> <groupId>io.github.jwdeveloper.tiktok</groupId>
<version>1.3.0-Release</version> <version>1.5.3-Release</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<artifactId>API</artifactId> <artifactId>API</artifactId>

View File

@@ -86,9 +86,15 @@ public class LiveClientSettings {
private HttpClientSettings httpSettings; private HttpClientSettings httpSettings;
/** /**
* Optional: Sometimes not every messages from chat are send to TikTokLiveJava to fix this issue you can set sessionId * Interval of time in milliseconds between pings to TikTok
* documentation how to obtain sessionId https://github.com/isaackogan/TikTok-Live-Connector#send-chat-messages * @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 <a href="https://github.com/isaackogan/TikTok-Live-Connector#send-chat-messages">Documentation: How to obtain sessionId</a>
*/
private String sessionId; private String sessionId;
/** /**

View File

@@ -59,9 +59,16 @@ public interface LiveClient {
/** /**
* Use to manually invoke event * Use to manually invoke event
*/ */
void publishEvent(TikTokEvent event); void publishEvent(TikTokEvent event);
void publishMessage(String base64);
/**
* @param webcastMessageName name of TikTok protocol-buffer message
* @param payloadBase64 protocol-buffer message bytes payload
*/
void publishMessage(String webcastMessageName, String payloadBase64);
void publishMessage(String webcastMessageName, byte[] payload);
/** /**
* Get information about gifts * Get information about gifts

View File

@@ -5,7 +5,7 @@
<parent> <parent>
<artifactId>TikTokLiveJava</artifactId> <artifactId>TikTokLiveJava</artifactId>
<groupId>io.github.jwdeveloper.tiktok</groupId> <groupId>io.github.jwdeveloper.tiktok</groupId>
<version>1.3.0-Release</version> <version>1.5.3-Release</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -28,7 +28,6 @@ import io.github.jwdeveloper.tiktok.http.LiveHttpClient;
import io.github.jwdeveloper.tiktok.live.GiftsManager; import io.github.jwdeveloper.tiktok.live.GiftsManager;
import io.github.jwdeveloper.tiktok.live.builder.LiveClientBuilder; import io.github.jwdeveloper.tiktok.live.builder.LiveClientBuilder;
import java.util.List;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
public class TikTokLive { public class TikTokLive {
@@ -102,14 +101,9 @@ public class TikTokLive {
* @return GiftsManager * @return GiftsManager
*/ */
public static GiftsManager gifts() { public static GiftsManager gifts() {
if (giftsManager != null) { if (giftsManager == null) {
return giftsManager; synchronized (GiftsManager.class) {
} giftsManager = new TikTokGiftsManager(requests().fetchGiftsData().getGifts());
synchronized (GiftsManager.class)
{
if (giftsManager == null)
{
return new TikTokGiftsManager(requests().fetchGiftsData().getGifts());
} }
} }
return giftsManager; return giftsManager;

View File

@@ -22,6 +22,7 @@
*/ */
package io.github.jwdeveloper.tiktok; package io.github.jwdeveloper.tiktok;
import com.google.protobuf.ByteString;
import io.github.jwdeveloper.tiktok.data.events.TikTokDisconnectedEvent; import io.github.jwdeveloper.tiktok.data.events.TikTokDisconnectedEvent;
import io.github.jwdeveloper.tiktok.data.events.TikTokErrorEvent; import io.github.jwdeveloper.tiktok.data.events.TikTokErrorEvent;
import io.github.jwdeveloper.tiktok.data.events.TikTokReconnectingEvent; import io.github.jwdeveloper.tiktok.data.events.TikTokReconnectingEvent;
@@ -39,10 +40,12 @@ import io.github.jwdeveloper.tiktok.listener.TikTokListenersManager;
import io.github.jwdeveloper.tiktok.live.GiftsManager; import io.github.jwdeveloper.tiktok.live.GiftsManager;
import io.github.jwdeveloper.tiktok.live.LiveClient; import io.github.jwdeveloper.tiktok.live.LiveClient;
import io.github.jwdeveloper.tiktok.live.LiveRoomInfo; import io.github.jwdeveloper.tiktok.live.LiveRoomInfo;
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastResponse;
import io.github.jwdeveloper.tiktok.models.ConnectionState; import io.github.jwdeveloper.tiktok.models.ConnectionState;
import io.github.jwdeveloper.tiktok.data.settings.LiveClientSettings; import io.github.jwdeveloper.tiktok.data.settings.LiveClientSettings;
import io.github.jwdeveloper.tiktok.websocket.SocketClient; import io.github.jwdeveloper.tiktok.websocket.SocketClient;
import java.util.Base64;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.logging.Logger; import java.util.logging.Logger;
@@ -56,15 +59,19 @@ public class TikTokLiveClient implements LiveClient {
private final TikTokListenersManager listenersManager; private final TikTokListenersManager listenersManager;
private final Logger logger; private final Logger logger;
private final GiftsManager giftsManager; private final GiftsManager giftsManager;
private final TikTokLiveMessageHandler messageHandler;
public TikTokLiveClient(GiftsManager giftsManager, public TikTokLiveClient(
TikTokRoomInfo tikTokLiveMeta, TikTokLiveMessageHandler messageHandler,
LiveHttpClient tiktokHttpClient, GiftsManager giftsManager,
SocketClient webSocketClient, TikTokRoomInfo tikTokLiveMeta,
TikTokLiveEventHandler tikTokEventHandler, LiveHttpClient tiktokHttpClient,
LiveClientSettings clientSettings, SocketClient webSocketClient,
TikTokListenersManager listenersManager, TikTokLiveEventHandler tikTokEventHandler,
Logger logger) { LiveClientSettings clientSettings,
TikTokListenersManager listenersManager,
Logger logger) {
this.messageHandler = messageHandler;
this.giftsManager = giftsManager; this.giftsManager = giftsManager;
this.liveRoomInfo = tikTokLiveMeta; this.liveRoomInfo = tikTokLiveMeta;
this.httpClient = tiktokHttpClient; this.httpClient = tiktokHttpClient;
@@ -184,6 +191,20 @@ public class TikTokLiveClient implements LiveClient {
tikTokEventHandler.publish(this, event); tikTokEventHandler.publish(this, event);
} }
@Override
public void publishMessage(String webcastMessageName, String payloadBase64) {
this.publishMessage(webcastMessageName, Base64.getDecoder().decode(payloadBase64));
}
@Override
public void publishMessage(String webcastMessageName, byte[] payload) {
var builder = WebcastResponse.Message.newBuilder();
builder.setMethod(webcastMessageName);
builder.setPayload(ByteString.copyFrom(payload));
var message = builder.build();
messageHandler.handleSingleMessage(this, message);
}
@Override @Override
public GiftsManager getGiftManager() { public GiftsManager getGiftManager() {
return giftsManager; return giftsManager;

View File

@@ -96,6 +96,9 @@ public class TikTokLiveClientBuilder implements LiveClientBuilder {
if (clientSettings.getHostName().startsWith("@")) if (clientSettings.getHostName().startsWith("@"))
clientSettings.setHostName(clientSettings.getHostName().substring(1)); clientSettings.setHostName(clientSettings.getHostName().substring(1));
if (clientSettings.getPingInterval() < 250)
throw new TikTokLiveException("Minimum allowed ping interval is 250 millseconds");
var httpSettings = clientSettings.getHttpSettings(); var httpSettings = clientSettings.getHttpSettings();
httpSettings.getParams().put("app_language", clientSettings.getClientLanguage()); httpSettings.getParams().put("app_language", clientSettings.getClientLanguage());
httpSettings.getParams().put("webcast_language", clientSettings.getClientLanguage()); httpSettings.getParams().put("webcast_language", clientSettings.getClientLanguage());
@@ -129,6 +132,7 @@ public class TikTokLiveClientBuilder implements LiveClientBuilder {
eventHandler); eventHandler);
return new TikTokLiveClient( return new TikTokLiveClient(
messageHandler,
giftsManager, giftsManager,
tiktokRoomInfo, tiktokRoomInfo,
liveHttpClient, liveHttpClient,

View File

@@ -83,7 +83,7 @@ public class TikTokLiveHttpClient implements LiveHttpClient
.toJsonResponse(); .toJsonResponse();
if (result.isFailure()) 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(); var json = result.getContent();
return giftsDataMapper.map(json); return giftsDataMapper.map(json);
@@ -111,10 +111,10 @@ public class TikTokLiveHttpClient implements LiveHttpClient
.toJsonResponse(); .toJsonResponse();
if (result.isFailure()) 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(); var json = result.getContent();
return liveUserDataMapper.map(json); return liveUserDataMapper.map(json, logger);
} }
@Override @Override
@@ -138,7 +138,7 @@ public class TikTokLiveHttpClient implements LiveHttpClient
.toJsonResponse(); .toJsonResponse();
if (result.isFailure()) 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(); var json = result.getContent();
return liveDataMapper.map(json); return liveDataMapper.map(json);
@@ -153,7 +153,7 @@ public class TikTokLiveHttpClient implements LiveHttpClient
var resultHeader = ActionResult.of(credentialsResponse.headers().firstValue("x-set-tt-cookie")); var resultHeader = ActionResult.of(credentialsResponse.headers().firstValue("x-set-tt-cookie"));
if (resultHeader.isFailure()) { if (resultHeader.isFailure()) {
logger.warning("SignServer Headers: "+request.getRoomId()+" - "+credentialsResponse.headers().map()); 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 websocketCookie = resultHeader.getContent();
var webcastResponse = WebcastResponse.parseFrom(credentialsResponse.body()); var webcastResponse = WebcastResponse.parseFrom(credentialsResponse.body());
@@ -169,7 +169,7 @@ public class TikTokLiveHttpClient implements LiveHttpClient
return new LiveConnectionData.Response(websocketCookie, webSocketUrl, webcastResponse); return new LiveConnectionData.Response(websocketCookie, webSocketUrl, webcastResponse);
} catch (InvalidProtocolBufferException e) { } 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(); var result = builder.build().toResponse();
if (result.isFailure()) 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; return result;
} }

View File

@@ -1,16 +1,27 @@
package io.github.jwdeveloper.tiktok.common; package io.github.jwdeveloper.tiktok.common;
import com.google.gson.*;
import io.github.jwdeveloper.tiktok.http.mappers.*;
import lombok.Data; import lombok.Data;
import lombok.experimental.Accessors;
import java.net.http.*;
import java.util.Optional; import java.util.Optional;
import java.util.function.Function; import java.util.function.Function;
@Data @Data
public class ActionResult<T> { public class ActionResult<T> {
private static final Gson gson = new Gson().newBuilder().disableHtmlEscaping()
.registerTypeHierarchyAdapter(HttpResponse.class, new HttpResponseJsonMapper())
.registerTypeHierarchyAdapter(HttpRequest.class, new HttpRequestJsonMapper())
.setPrettyPrinting().create();
private boolean success = true; private boolean success = true;
private T content; private T content;
private String message; private String message;
@Accessors(chain = true, fluent = true)
private ActionResult<?> previous;
protected ActionResult(T object) { protected ActionResult(T object) {
this.content = object; this.content = object;
@@ -41,8 +52,9 @@ public class ActionResult<T> {
public boolean hasMessage() { public boolean hasMessage() {
return message != null; return message != null;
} }
public String toStack() {
return hasMessage() ? " - "+message : ""; public boolean hasPrevious() {
return previous != null;
} }
public boolean hasContent() { public boolean hasContent() {
@@ -84,4 +96,18 @@ public class ActionResult<T> {
public static <T> ActionResult<T> failure() { public static <T> ActionResult<T> failure() {
return failure(null); return failure(null);
} }
public JsonObject toJson() {
JsonObject map = new JsonObject();
map.addProperty("success", success);
map.add("content", gson.toJsonTree(content));
map.addProperty("message", message);
map.add("previous", hasPrevious() ? previous.toJson() : null);
return map;
}
@Override
public String toString() {
return "ActionResult: "+gson.toJson(toJson());
}
} }

View File

@@ -1,5 +1,8 @@
package io.github.jwdeveloper.tiktok.common; package io.github.jwdeveloper.tiktok.common;
import lombok.Setter;
import lombok.experimental.Accessors;
import java.util.Arrays; import java.util.Arrays;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@@ -7,6 +10,8 @@ public class ActionResultBuilder<T>
{ {
private final T content; private final T content;
private String message; private String message;
@Setter @Accessors(fluent = true, chain = true)
private ActionResult<?> previous;
public ActionResultBuilder(T content) { public ActionResultBuilder(T content) {
this.content = content; this.content = content;
@@ -18,10 +23,10 @@ public class ActionResultBuilder<T>
} }
public ActionResult<T> success() { public ActionResult<T> success() {
return ActionResult.success(content, message); return ActionResult.success(content, message).previous(previous);
} }
public ActionResult<T> failure() { public ActionResult<T> failure() {
return ActionResult.success(content, message); return ActionResult.success(content, message).previous(previous);
} }
} }

View File

@@ -0,0 +1,21 @@
package io.github.jwdeveloper.tiktok.http.mappers;
import com.google.gson.*;
import java.lang.reflect.Type;
import java.net.http.HttpRequest;
public class HttpRequestJsonMapper implements JsonSerializer<HttpRequest>
{
@Override
public JsonElement serialize(HttpRequest src, Type typeOfSrc, JsonSerializationContext context) {
JsonObject object = new JsonObject();
object.addProperty("method", src.method());
object.add("timeout", context.serialize(src.timeout().toString()));
object.addProperty("expectContinue", src.expectContinue());
object.add("uri", context.serialize(src.uri()));
object.add("version", context.serialize(src.version().toString()));
object.add("headers", context.serialize(src.headers().map()));
return object;
}
}

View File

@@ -0,0 +1,21 @@
package io.github.jwdeveloper.tiktok.http.mappers;
import com.google.gson.*;
import java.lang.reflect.Type;
import java.net.http.HttpResponse;
public class HttpResponseJsonMapper implements JsonSerializer<HttpResponse>
{
@Override
public JsonElement serialize(HttpResponse src, Type typeOfSrc, JsonSerializationContext context) {
JsonObject object = new JsonObject();
object.addProperty("statusCode", src.statusCode());
object.add("request", context.serialize(src.request()));
object.add("headers", context.serialize(src.headers().map()));
object.add("body", context.serialize(src.body()));
object.add("uri", context.serialize(src.uri().toString()));
object.add("version", context.serialize(src.version().toString()));
return object;
}
}

View File

@@ -22,45 +22,52 @@
*/ */
package io.github.jwdeveloper.tiktok.http.mappers; 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.data.requests.LiveUserData;
import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveRequestException; import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveRequestException;
import java.util.logging.Logger;
public class LiveUserDataMapper public class LiveUserDataMapper
{ {
public LiveUserData.Response map(String json) { public LiveUserData.Response map(String json, Logger logger) {
var jsonObject = JsonParser.parseString(json).getAsJsonObject(); try {
var jsonObject = JsonParser.parseString(json).getAsJsonObject();
var message = jsonObject.get("message").getAsString(); var message = jsonObject.get("message").getAsString();
if (message.equals("params_error")) { if (message.equals("params_error")) {
throw new TikTokLiveRequestException("fetchRoomIdFromTiktokApi -> Unable to fetch roomID, contact the developer"); throw new TikTokLiveRequestException("fetchRoomIdFromTiktokApi -> Unable to fetch roomID, contact the developer");
} }
if (message.equals("user_not_found")) { 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 | IllegalStateException e) {
logger.warning("Malformed Json: '"+json+"' - Error Message: "+e.getMessage());
return new LiveUserData.Response(json, LiveUserData.UserStatus.NotFound, "", -1); 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);
} }
} }

View File

@@ -82,7 +82,7 @@ public class TikTokWebSocketClient implements SocketClient {
private void connectDefault() { private void connectDefault() {
try { try {
webSocketClient.connect(); webSocketClient.connect();
pingingTask.run(webSocketClient); pingingTask.run(webSocketClient, clientSettings.getPingInterval());
isConnected = true; isConnected = true;
} catch (Exception e) { } catch (Exception e) {
isConnected = false; isConnected = false;
@@ -112,7 +112,7 @@ public class TikTokWebSocketClient implements SocketClient {
proxySettings.remove(); proxySettings.remove();
continue; continue;
} }
pingingTask.run(webSocketClient); pingingTask.run(webSocketClient, clientSettings.getPingInterval());
isConnected = true; isConnected = true;
break; break;
} }

View File

@@ -61,7 +61,7 @@ public class TikTokWebSocketListener extends WebSocketClient {
} catch (Exception e) { } catch (Exception e) {
tikTokEventHandler.publish(tikTokLiveClient, new TikTokErrorEvent(e)); tikTokEventHandler.publish(tikTokLiveClient, new TikTokErrorEvent(e));
} }
if (isNotClosing()) { if (isOpen()) {
sendPing(); sendPing();
} }
} }
@@ -79,8 +79,7 @@ public class TikTokWebSocketListener extends WebSocketClient {
pushFrameBuilder.setPayloadType("ack"); pushFrameBuilder.setPayloadType("ack");
pushFrameBuilder.setLogId(websocketPushFrame.getLogId()); pushFrameBuilder.setLogId(websocketPushFrame.getLogId());
pushFrameBuilder.setPayload(webcastResponse.getInternalExtBytes()); pushFrameBuilder.setPayload(webcastResponse.getInternalExtBytes());
if (isNotClosing()) if (isOpen()) {
{
this.send(pushFrameBuilder.build().toByteArray()); this.send(pushFrameBuilder.build().toByteArray());
} }
} }
@@ -90,7 +89,7 @@ public class TikTokWebSocketListener extends WebSocketClient {
@Override @Override
public void onOpen(ServerHandshake serverHandshake) { public void onOpen(ServerHandshake serverHandshake) {
tikTokEventHandler.publish(tikTokLiveClient, new TikTokConnectedEvent()); tikTokEventHandler.publish(tikTokLiveClient, new TikTokConnectedEvent());
if (isNotClosing()) { if (isOpen()) {
sendPing(); sendPing();
} }
} }
@@ -104,7 +103,7 @@ public class TikTokWebSocketListener extends WebSocketClient {
@Override @Override
public void onError(Exception error) { public void onError(Exception error) {
tikTokEventHandler.publish(tikTokLiveClient, new TikTokErrorEvent(error)); tikTokEventHandler.publish(tikTokLiveClient, new TikTokErrorEvent(error));
if (isNotClosing()) { if (isOpen()) {
sendPing(); sendPing();
} }
} }
@@ -129,10 +128,6 @@ public class TikTokWebSocketListener extends WebSocketClient {
} }
} }
private boolean isNotClosing() {
return !isClosed() && !isClosing();
}
@Override @Override
public void onMessage(String s) { public void onMessage(String s) {
// System.err.println(s); // System.err.println(s);

View File

@@ -8,13 +8,13 @@ public class TikTokWebSocketPingingTask
{ {
private Thread thread; private Thread thread;
private boolean isRunning = false; private boolean isRunning = false;
private final int MIN_TIMEOUT = 250; private final int MAX_TIMEOUT = 250;
private final int MAX_TIMEOUT = 500; private final int SLEEP_TIME = 500;
public void run(WebSocket webSocket) public void run(WebSocket webSocket, long pingTaskTime)
{ {
stop(); stop();
thread = new Thread(() -> pingTask(webSocket)); thread = new Thread(() -> pingTask(webSocket, pingTaskTime));
isRunning = true; isRunning = true;
thread.start(); thread.start();
} }
@@ -26,20 +26,18 @@ public class TikTokWebSocketPingingTask
isRunning = false; isRunning = false;
} }
private void pingTask(WebSocket webSocket, long pingTaskTime)
private void pingTask(WebSocket webSocket)
{ {
var random = new Random(); var random = new Random();
while (isRunning) { while (isRunning) {
try { try {
if (!webSocket.isOpen()) { if (!webSocket.isOpen()) {
Thread.sleep(100); Thread.sleep(SLEEP_TIME);
continue; continue;
} }
webSocket.sendPing(); webSocket.sendPing();
var timeout = random.nextInt(MAX_TIMEOUT)+MIN_TIMEOUT; Thread.sleep(pingTaskTime+random.nextInt(MAX_TIMEOUT));
Thread.sleep(timeout);
} }
catch (Exception e) { catch (Exception e) {
isRunning = false; isRunning = false;

View File

@@ -41,7 +41,7 @@
<parent> <parent>
<artifactId>TikTokLiveJava</artifactId> <artifactId>TikTokLiveJava</artifactId>
<groupId>io.github.jwdeveloper.tiktok</groupId> <groupId>io.github.jwdeveloper.tiktok</groupId>
<version>1.3.0-Release</version> <version>1.5.3-Release</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
@@ -75,7 +75,7 @@
<dependency> <dependency>
<groupId>io.github.jwdeveloper.tiktok</groupId> <groupId>io.github.jwdeveloper.tiktok</groupId>
<artifactId>extension-collector</artifactId> <artifactId>extension-collector</artifactId>
<version>1.3.0-Release</version> <version>1.5.3-Release</version>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
</dependencies> </dependencies>

View File

@@ -25,24 +25,18 @@ package io.github.jwdeveloper.tiktok;
import io.github.jwdeveloper.tiktok.extension.collector.TikTokLiveCollector; import io.github.jwdeveloper.tiktok.extension.collector.TikTokLiveCollector;
import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.util.List; import java.util.*;
import java.util.Map;
public class CollectorExample { public class CollectorExample {
private static String mongoUser;
private static String mongoPassword;
private static String mongoDatabase;
public static void main(String[] args) throws IOException { public static void main(String[] args) throws IOException {
var collector = TikTokLiveCollector.useMongo(settings -> var path = "C:\\Users\\ja\\IdeaProjects\\TikTokLiveJava\\Examples\\src\\main\\resources";
var collector = TikTokLiveCollector.useFile(settings ->
{ {
settings.setConnectionUrl("mongodb+srv://" + mongoUser + ":" + mongoPassword + "@" + mongoDatabase + "/?retryWrites=true&w=majority"); settings.setParentFile(new File(path));
}); });
collector.connect(); collector.connect();
@@ -58,18 +52,11 @@ public class CollectorExample {
{ {
event.getException().printStackTrace(); event.getException().printStackTrace();
}) })
.addListener(collector.newListener(additionalDataFields, document -> .addListener(collector.newListener(additionalDataFields))
{
//filtering document data before it is inserted to database
if (document.get("dataType") == "message") {
return false;
}
return true;
}))
.buildAndConnectAsync(); .buildAndConnectAsync();
} }
System.in.read(); System.in.read();
collector.disconnect(); collector.disconnect();
} }
} }

View File

@@ -1,7 +1,6 @@
package io.github.jwdeveloper.tiktok; package io.github.jwdeveloper.tiktok;
import io.github.jwdeveloper.tiktok.data.events.TikTokCommentEvent; import io.github.jwdeveloper.tiktok.data.events.TikTokCommentEvent;
import io.github.jwdeveloper.tiktok.data.events.TikTokSubNotifyEvent;
import io.github.jwdeveloper.tiktok.data.events.TikTokSubscribeEvent; import io.github.jwdeveloper.tiktok.data.events.TikTokSubscribeEvent;
import io.github.jwdeveloper.tiktok.data.events.gift.TikTokGiftComboEvent; import io.github.jwdeveloper.tiktok.data.events.gift.TikTokGiftComboEvent;
import io.github.jwdeveloper.tiktok.data.events.gift.TikTokGiftEvent; import io.github.jwdeveloper.tiktok.data.events.gift.TikTokGiftEvent;
@@ -11,7 +10,9 @@ import io.github.jwdeveloper.tiktok.data.events.social.TikTokLikeEvent;
import io.github.jwdeveloper.tiktok.data.models.gifts.GiftComboStateType; import io.github.jwdeveloper.tiktok.data.models.gifts.GiftComboStateType;
import io.github.jwdeveloper.tiktok.live.LiveClient; import io.github.jwdeveloper.tiktok.live.LiveClient;
public class Events_And_Gifts_Testing_Example { public class Events_And_Gifts_Testing_Example
{
public static void main(String[] args) { public static void main(String[] args) {
LiveClient client = TikTokLive.newClient(ConnectionExample.TIKTOK_HOSTNAME) LiveClient client = TikTokLive.newClient(ConnectionExample.TIKTOK_HOSTNAME)
.configure(liveClientSettings -> .configure(liveClientSettings ->
@@ -35,6 +36,10 @@ public class Events_And_Gifts_Testing_Example {
{ {
liveClient.getLogger().info("New fake Gift: " + event.getGift()); liveClient.getLogger().info("New fake Gift: " + event.getGift());
}) })
.onLike((liveClient, event) ->
{
liveClient.getLogger().info("New fake Like event: " + event.getLikes());
})
.build(); .build();
var gifts = TikTokLive.gifts(); var gifts = TikTokLive.gifts();
@@ -57,11 +62,13 @@ public class Events_And_Gifts_Testing_Example {
client.publishEvent(fakeMessage); client.publishEvent(fakeMessage);
client.publishEvent(fakeSubscriber); client.publishEvent(fakeSubscriber);
client.publishEvent(fakeFollow); client.publishEvent(fakeFollow);
client.publishEvent(fakeLike);
client.publishEvent(fakeJoin); client.publishEvent(fakeJoin);
client.publishEvent(fakeLike);
client.publishMessage("WebcastLikeMessage", webcastLikeMessageBase64);
client.disconnect(); client.disconnect();
} }
private static final String webcastLikeMessageBase64 = "SAFSBRABGKwCUgcIAhABGKwCCv8BUAFYAbABA7gBARCflqWWo8Ha72UgzoPZhd8xQrwBGg4gkAMKCSNmZmZmZmZmZiJ/qgF6CngIhYjjgPWJv7RgGhDwnZKm8J2TjvCdk47wk4WTsgIKa3lsbGVlaGFsbPICTE1TNHdMakFCQUFBQXUyX21LNEw4WGJYa3lNaUFvZzJUTnNmVjk5N09WM2tpQ3NCTkNjYWkwcWxIcUt0Q3B0UGU1N2RLYVhxb0xWSXoICwoQcG1fbXRfbXNnX3ZpZXdlchIXezA6dXNlcn0gbGlrZWQgdGhlIExJVkVIAQoSV2ViY2FzdExpa2VNZXNzYWdlGIaWvY+RhdjvZTABwAEBEA8Y+Voq7RCyAQYImwEQjwK6AQCCAgDyAkxNUzR3TGpBQkFBQUF1Ml9tSzRMOFhiWGt5TWlBb2cyVE5zZlY5OTdPVjNraUNzQk5DY2FpMHFsSHFLdENwdFBlNTdkS2FYcW9MVkl6ggTqCLoBnwUqBggBEAEYIFoNCgASCSNCMzQ3N0VGRoABDwgEEtgEEix3ZWJjYXN0LXZhL2dyYWRlX2JhZGdlX2ljb25fbGl0ZV9sdjE1X3YyLnBuZzrpAnNzbG9jYWw6Ly93ZWJjYXN0X2x5bnh2aWV3X3BvcHVwP3VzZV9zcGFyaz0xJnVybD1odHRwcyUzQSUyRiUyRmxmMTYtZ2Vja28tc291cmNlLnRpa3Rva2Nkbi5jb20lMkZvYmolMkZieXRlLWd1cmQtc291cmNlLXNnJTJGdGlrdG9rJTJGZmUlMkZsaXZlJTJGdGlrdG9rX2xpdmVfcmV2ZW51ZV91c2VyX2xldmVsX21haW4lMkZzcmMlMkZwYWdlcyUyRnByaXZpbGVnZSUyRnBhbmVsJTJGdGVtcGxhdGUuanMmaGlkZV9zdGF0dXNfYmFyPTAmaGlkZV9uYXZfYmFyPTEmY29udGFpbmVyX2JnX2NvbG9yPTAwMDAwMDAwJmhlaWdodD05MCUyNSZiZGhtX2JpZD10aWt0b2tfbGl2ZV9yZXZlbnVlX3VzZXJfbGV2ZWxfbWFpbiZ1c2VfZm9yZXN0PTEKXWh0dHBzOi8vcDE2LXdlYmNhc3QudGlrdG9rY2RuLmNvbS93ZWJjYXN0LXZhL2dyYWRlX2JhZGdlX2ljb25fbGl0ZV9sdjE1X3YyLnBuZ350cGx2LW9iai5pbWFnZQpdaHR0cHM6Ly9wMTktd2ViY2FzdC50aWt0b2tjZG4uY29tL3dlYmNhc3QtdmEvZ3JhZGVfYmFkZ2VfaWNvbl9saXRlX2x2MTVfdjIucG5nfnRwbHYtb2JqLmltYWdlIgIxNTIAOgYaAhIAIgBiDQoAEgkjQjM0NzdFRkZ4DqIBBggBEAEYIAgEEBQYCCABUukCc3Nsb2NhbDovL3dlYmNhc3RfbHlueHZpZXdfcG9wdXA/dXNlX3NwYXJrPTEmdXJsPWh0dHBzJTNBJTJGJTJGbGYxNi1nZWNrby1zb3VyY2UudGlrdG9rY2RuLmNvbSUyRm9iaiUyRmJ5dGUtZ3VyZC1zb3VyY2Utc2clMkZ0aWt0b2slMkZmZSUyRmxpdmUlMkZ0aWt0b2tfbGl2ZV9yZXZlbnVlX3VzZXJfbGV2ZWxfbWFpbiUyRnNyYyUyRnBhZ2VzJTJGcHJpdmlsZWdlJTJGcGFuZWwlMkZ0ZW1wbGF0ZS5qcyZoaWRlX3N0YXR1c19iYXI9MCZoaWRlX25hdl9iYXI9MSZjb250YWluZXJfYmdfY29sb3I9MDAwMDAwMDAmaGVpZ2h0PTkwJTI1JmJkaG1fYmlkPXRpa3Rva19saXZlX3JldmVudWVfdXNlcl9sZXZlbF9tYWluJnVzZV9mb3Jlc3Q9MVgBYk8qAjE1CgEyEhM3MTM4MzgxNzQ3MjkyNTQyNzU2GgEwIi5tb2NrX2ZpeF93aWR0aF90cmFuc3BhcmVudF83MTM4MzgxNzQ3MjkyNTQyNzU2CIWI44D1ib+0YBoQ8J2SpvCdk47wnZOO8JOFk0r1BhJBMTAweDEwMC90b3MtdXNlYXN0OC1hdnQtMDA2OC10eDIvNjY0NmM4NjZjMzI1MWEwOTY3NjhiYjY4OTUyODVjMzEK0gFodHRwczovL3AxOS1wdS1zaWduLXVzZWFzdDgudGlrdG9rY2RuLXVzLmNvbS90b3MtdXNlYXN0OC1hdnQtMDA2OC10eDIvNjY0NmM4NjZjMzI1MWEwOTY3NjhiYjY4OTUyODVjMzF+dHBsdi10aWt0b2stc2hyaW5rOjcyOjcyLndlYnA/bGszcz1hNWQ0ODA3OCZ4LWV4cGlyZXM9MTcwOTMxMjQwMCZ4LXNpZ25hdHVyZT1VMlNEbUk3Z3R5RW9rMlBlWFdmeTNsM1F6NlElM0QKyAFodHRwczovL3AxNi1wdS1zaWduLXVzZWFzdDgudGlrdG9rY2RuLXVzLmNvbS90b3MtdXNlYXN0OC1hdnQtMDA2OC10eDIvNjY0NmM4NjZjMzI1MWEwOTY3NjhiYjY4OTUyODVjMzF+YzVfMTAweDEwMC53ZWJwP2xrM3M9YTVkNDgwNzgmeC1leHBpcmVzPTE3MDkzMTI0MDAmeC1zaWduYXR1cmU9aWNWZEVZa0FnWkYlMkZ2WU5OTSUyRlVNMzE2eG9HdyUzRArGAWh0dHBzOi8vcDE5LXB1LXNpZ24tdXNlYXN0OC50aWt0b2tjZG4tdXMuY29tL3Rvcy11c2Vhc3Q4LWF2dC0wMDY4LXR4Mi82NjQ2Yzg2NmMzMjUxYTA5Njc2OGJiNjg5NTI4NWMzMX5jNV8xMDB4MTAwLndlYnA/bGszcz1hNWQ0ODA3OCZ4LWV4cGlyZXM9MTcwOTMxMjQwMCZ4LXNpZ25hdHVyZT1PQzdBQ3htQUklMkJsYlp4RkVuWktJT1RyRExGUSUzRArGAWh0dHBzOi8vcDE2LXB1LXNpZ24tdXNlYXN0OC50aWt0b2tjZG4tdXMuY29tL3Rvcy11c2Vhc3Q4LWF2dC0wMDY4LXR4Mi82NjQ2Yzg2NmMzMjUxYTA5Njc2OGJiNjg5NTI4NWMzMX5jNV8xMDB4MTAwLmpwZWc/bGszcz1hNWQ0ODA3OCZ4LWV4cGlyZXM9MTcwOTMxMjQwMCZ4LXNpZ25hdHVyZT02YUwlMkZNZWtOeHg5NXlvVTVLOTZON0xwRUlNdyUzRLICCmt5bGxlZWhhbGxCyQEIgojG1pKb0clgErwBChBwbV9tdF9tc2dfdmlld2VyEhd7MDp1c2VyfSBsaWtlZCB0aGUgTElWRRoOCgkjZmZmZmZmZmYgkAMifwgLqgF6CngIhYjjgPWJv7RgGhDwnZKm8J2TjvCdk47wk4WTsgIKa3lsbGVlaGFsbPICTE1TNHdMakFCQUFBQXUyX21LNEw4WGJYa3lNaUFvZzJUTnNmVjk5N09WM2tpQ3NCTkNjYWkwcWxIcUt0Q3B0UGU1N2RLYVhxb0xWSXo=";
} }

View File

@@ -70,7 +70,7 @@ Maven
<dependency> <dependency>
<groupId>com.github.jwdeveloper.TikTok-Live-Java</groupId> <groupId>com.github.jwdeveloper.TikTok-Live-Java</groupId>
<artifactId>Client</artifactId> <artifactId>Client</artifactId>
<version>1.3.0-Release</version> <version>1.5.0-Release</version>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
</dependencies> </dependencies>
@@ -87,7 +87,7 @@ dependencyResolutionManagement {
} }
dependencies { dependencies {
implementation 'com.github.jwdeveloper.TikTok-Live-Java:Client:1.1.0-Release' implementation 'com.github.jwdeveloper.TikTok-Live-Java:Client:1.5.0-Release'
} }
``` ```

View File

@@ -5,7 +5,7 @@
<parent> <parent>
<artifactId>TikTokLiveJava</artifactId> <artifactId>TikTokLiveJava</artifactId>
<groupId>io.github.jwdeveloper.tiktok</groupId> <groupId>io.github.jwdeveloper.tiktok</groupId>
<version>1.3.0-Release</version> <version>1.5.3-Release</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -6,7 +6,7 @@
<parent> <parent>
<groupId>io.github.jwdeveloper.tiktok</groupId> <groupId>io.github.jwdeveloper.tiktok</groupId>
<artifactId>TikTokLiveJava</artifactId> <artifactId>TikTokLiveJava</artifactId>
<version>1.3.0-Release</version> <version>1.5.3-Release</version>
</parent> </parent>
@@ -33,7 +33,7 @@
<dependency> <dependency>
<groupId>io.github.jwdeveloper.tiktok</groupId> <groupId>io.github.jwdeveloper.tiktok</groupId>
<artifactId>API</artifactId> <artifactId>API</artifactId>
<version>1.3.0-Release</version> <version>1.5.3-Release</version>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
</dependencies> </dependencies>

View File

@@ -0,0 +1,8 @@
package io.github.jwdeveloper.tiktok.extension.collector.api;
import io.github.jwdeveloper.tiktok.live.LiveClient;
import org.bson.Document;
public interface CollectorEvent {
boolean execute(LiveClient client, Document document);
}

View File

@@ -1,5 +1,6 @@
package io.github.jwdeveloper.tiktok.extension.collector.api.settings; package io.github.jwdeveloper.tiktok.extension.collector.api.settings;
import io.github.jwdeveloper.tiktok.extension.collector.api.CollectorEvent;
import lombok.Data; import lombok.Data;
import org.bson.Document; import org.bson.Document;
@@ -9,5 +10,5 @@ import java.util.function.Function;
@Data @Data
public class CollectorListenerSettings { public class CollectorListenerSettings {
private Map<String, Object> extraFields; private Map<String, Object> extraFields;
private Function<Document, Boolean> filter; private CollectorEvent filter;
} }

View File

@@ -29,7 +29,6 @@ import java.util.function.Consumer;
@Data @Data
public class MongoDataCollectorSettings { public class MongoDataCollectorSettings {
@Setter
private String connectionUrl; private String connectionUrl;
private String databaseName = "tiktok"; private String databaseName = "tiktok";

View File

@@ -22,6 +22,7 @@
*/ */
package io.github.jwdeveloper.tiktok.extension.collector.impl; package io.github.jwdeveloper.tiktok.extension.collector.impl;
import io.github.jwdeveloper.tiktok.extension.collector.api.CollectorEvent;
import io.github.jwdeveloper.tiktok.extension.collector.api.Storage; import io.github.jwdeveloper.tiktok.extension.collector.api.Storage;
import io.github.jwdeveloper.tiktok.extension.collector.api.settings.CollectorListenerSettings; import io.github.jwdeveloper.tiktok.extension.collector.api.settings.CollectorListenerSettings;
import org.bson.Document; import org.bson.Document;
@@ -40,6 +41,7 @@ public class DataCollector {
public void connect() { public void connect() {
storage.connect(); storage.connect();
} }
public void disconnect() { public void disconnect() {
storage.disconnect(); storage.disconnect();
} }
@@ -49,11 +51,11 @@ public class DataCollector {
} }
public DataCollectorListener newListener(Map<String, Object> additionalFields) { public DataCollectorListener newListener(Map<String, Object> additionalFields) {
return newListener(additionalFields, (e) -> true); return newListener(additionalFields, (live, document) -> true);
} }
public DataCollectorListener newListener(Map<String, Object> additionalFields, public DataCollectorListener newListener(Map<String, Object> additionalFields,
Function<Document, Boolean> filter) { CollectorEvent filter) {
var settings = new CollectorListenerSettings(); var settings = new CollectorListenerSettings();
settings.setExtraFields(additionalFields); settings.setExtraFields(additionalFields);
settings.setFilter(filter); settings.setFilter(filter);

View File

@@ -17,13 +17,13 @@ import org.bson.Document;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.io.StringWriter; import java.io.StringWriter;
import java.util.Base64; import java.util.Base64;
import java.util.UUID; import java.util.Date;
public class DataCollectorListener implements LiveDataCollector { public class DataCollectorListener implements LiveDataCollector {
private final Storage storage; private final Storage storage;
private final CollectorListenerSettings settings; private final CollectorListenerSettings settings;
private String sessionId; private String roomId;
private String userName; private String userName;
public DataCollectorListener(Storage collection, CollectorListenerSettings settings) { public DataCollectorListener(Storage collection, CollectorListenerSettings settings) {
@@ -41,44 +41,42 @@ public class DataCollectorListener implements LiveDataCollector {
@TikTokEventObserver @TikTokEventObserver
private void onEvent(LiveClient liveClient, TikTokEvent event) { private void onEvent(LiveClient liveClient, TikTokEvent event) {
if (event instanceof TikTokConnectingEvent) { if (event instanceof TikTokConnectingEvent) {
sessionId = UUID.randomUUID().toString();
userName = liveClient.getRoomInfo().getHostName(); userName = liveClient.getRoomInfo().getHostName();
roomId = liveClient.getRoomInfo().getRoomId();
} }
if (event instanceof TikTokErrorEvent) { if (event instanceof TikTokErrorEvent) {
return; return;
} }
includeEvent(event); includeEvent(liveClient, event);
} }
@TikTokEventObserver @TikTokEventObserver
private void onError(LiveClient liveClient, TikTokErrorEvent event) { private void onError(LiveClient liveClient, TikTokErrorEvent event) {
event.getException().printStackTrace(); event.getException().printStackTrace();
includeError(event); includeError(liveClient, event);
} }
private void includeResponse(LiveClient liveClient, WebcastResponse message) { private void includeResponse(LiveClient liveClient, WebcastResponse message) {
var messageContent = Base64.getEncoder().encodeToString(message.toByteArray()); var messageContent = Base64.getEncoder().encodeToString(message.toByteArray());
insertDocument(createDocument("response", "webcast", messageContent)); insertDocument(liveClient, createDocument("response", "webcast", messageContent));
} }
private void includeMessage(LiveClient liveClient, WebcastResponse.Message message) { private void includeMessage(LiveClient liveClient, WebcastResponse.Message message) {
var method = message.getMethod(); var method = message.getMethod();
var messageContent = Base64.getEncoder().encodeToString(message.getPayload().toByteArray()); var messageContent = Base64.getEncoder().encodeToString(message.getPayload().toByteArray());
insertDocument(liveClient, createDocument("message", method, messageContent));
insertDocument(createDocument("message", method, messageContent));
} }
private void includeEvent(TikTokEvent event) { private void includeEvent(LiveClient client, TikTokEvent event) {
var json = JsonUtil.toJson(event); var json = JsonUtil.toJson(event);
var content = Base64.getEncoder().encodeToString(json.getBytes()); var content = Base64.getEncoder().encodeToString(json.getBytes());
var name = event.getClass().getSimpleName(); var name = event.getClass().getSimpleName();
insertDocument(createDocument("event", name, content)); insertDocument(client, createDocument("event", name, content));
} }
private void includeError(TikTokErrorEvent event) { private void includeError(LiveClient client, TikTokErrorEvent event) {
var exception = event.getException(); var exception = event.getException();
var exceptionName = event.getException().getClass().getSimpleName(); var exceptionName = event.getException().getClass().getSimpleName();
@@ -86,18 +84,18 @@ public class DataCollectorListener implements LiveDataCollector {
var pw = new PrintWriter(sw); var pw = new PrintWriter(sw);
event.getException().printStackTrace(pw); event.getException().printStackTrace(pw);
var content = sw.toString(); var content = sw.toString();
var contentBase64 = Base64.getEncoder().encodeToString(content.getBytes());
var doc = createDocument("error", exceptionName, content); var doc = createDocument("error", exceptionName, contentBase64);
if (exception instanceof TikTokLiveMessageException ex) { if (exception instanceof TikTokLiveMessageException ex) {
doc.append("message", ex.messageToBase64()) doc.append("message", ex.messageToBase64())
.append("response", ex.webcastResponseToBase64()); .append("response", ex.webcastResponseToBase64());
} }
insertDocument(doc); insertDocument(client, doc);
} }
private void insertDocument(Document document) { private void insertDocument(LiveClient client, Document document) {
if (!settings.getFilter().apply(document)) { if (!settings.getFilter().execute(client, document)) {
return; return;
} }
storage.insert(document); storage.insert(document);
@@ -106,7 +104,7 @@ public class DataCollectorListener implements LiveDataCollector {
private Document createDocument(String dataType, String dataTypeName, String content) { private Document createDocument(String dataType, String dataTypeName, String content) {
var doc = new Document(); var doc = new Document();
doc.append("session", sessionId); doc.append("roomId", roomId);
for (var entry : settings.getExtraFields().entrySet()) { for (var entry : settings.getExtraFields().entrySet()) {
doc.append(entry.getKey(), entry.getValue()); doc.append(entry.getKey(), entry.getValue());
} }
@@ -114,6 +112,7 @@ public class DataCollectorListener implements LiveDataCollector {
doc.append("dataType", dataType); doc.append("dataType", dataType);
doc.append("dataTypeName", dataTypeName); doc.append("dataTypeName", dataTypeName);
doc.append("content", content); doc.append("content", content);
doc.append("createdAt", new Date());
return doc; return doc;
} }
} }

View File

@@ -3,6 +3,7 @@ package io.github.jwdeveloper.tiktok.extension.collector.impl.storages;
import io.github.jwdeveloper.tiktok.extension.collector.api.Storage; import io.github.jwdeveloper.tiktok.extension.collector.api.Storage;
import io.github.jwdeveloper.tiktok.extension.collector.api.settings.FileDataCollectorSettings; import io.github.jwdeveloper.tiktok.extension.collector.api.settings.FileDataCollectorSettings;
import org.bson.Document; import org.bson.Document;
import org.bson.json.JsonWriterSettings;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
@@ -29,11 +30,11 @@ public class FileStorage implements Storage {
@Override @Override
public void insert(Document document) { public void insert(Document document) {
var fileName = document.get("dataType") + ":" + document.get("dataTypeName") + ".json"; var fileName = document.get("dataType") + "_" + document.get("dataTypeName") + ".json";
try { try {
var file = new File(settings.getParentFile(), fileName); var file = new File(settings.getParentFile(), fileName);
file.createNewFile(); file.createNewFile();
Files.writeString(file.toPath(), document.toJson(), StandardOpenOption.APPEND); Files.writeString(file.toPath(), document.toJson(JsonWriterSettings.builder().indent(true).build()), StandardOpenOption.APPEND);
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
} }

View File

@@ -5,7 +5,7 @@
<parent> <parent>
<artifactId>TikTokLiveJava</artifactId> <artifactId>TikTokLiveJava</artifactId>
<groupId>io.github.jwdeveloper.tiktok</groupId> <groupId>io.github.jwdeveloper.tiktok</groupId>
<version>1.3.0-Release</version> <version>1.5.3-Release</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<artifactId>extension-recorder</artifactId> <artifactId>extension-recorder</artifactId>

View File

@@ -30,6 +30,7 @@ import io.github.jwdeveloper.tiktok.data.settings.LiveClientSettings;
import io.github.jwdeveloper.tiktok.extension.recorder.api.LiveRecorder; import io.github.jwdeveloper.tiktok.extension.recorder.api.LiveRecorder;
import io.github.jwdeveloper.tiktok.extension.recorder.impl.data.*; import io.github.jwdeveloper.tiktok.extension.recorder.impl.data.*;
import io.github.jwdeveloper.tiktok.extension.recorder.impl.enums.LiveQuality; import io.github.jwdeveloper.tiktok.extension.recorder.impl.enums.LiveQuality;
import io.github.jwdeveloper.tiktok.extension.recorder.impl.event.TikTokLiveRecorderStartedEvent;
import io.github.jwdeveloper.tiktok.live.LiveClient; import io.github.jwdeveloper.tiktok.live.LiveClient;
import io.github.jwdeveloper.tiktok.models.ConnectionState; import io.github.jwdeveloper.tiktok.models.ConnectionState;
@@ -60,7 +61,9 @@ public class RecorderListener implements LiveRecorder {
var json = event.getLiveData().getJson(); var json = event.getLiveData().getJson();
liveClient.getLogger().info("Searching for live download url"); liveClient.getLogger().info("Searching for live download url");
downloadData = settings.getPrepareDownloadData() != null ? settings.getPrepareDownloadData().apply(json) : mapToDownloadData(json); downloadData = settings.getPrepareDownloadData() != null ?
settings.getPrepareDownloadData().apply(json) :
mapToDownloadData(json);
if (downloadData.getDownloadLiveUrl().isEmpty()) if (downloadData.getDownloadLiveUrl().isEmpty())
liveClient.getLogger().warning("Unable to find download live url!"); liveClient.getLogger().warning("Unable to find download live url!");
@@ -72,8 +75,11 @@ public class RecorderListener implements LiveRecorder {
private void onConnected(LiveClient liveClient, TikTokConnectedEvent event) { private void onConnected(LiveClient liveClient, TikTokConnectedEvent event) {
if (isConnected()) if (isConnected())
return; return;
liveDownloadThread = new Thread(() -> { liveDownloadThread = new Thread(() -> {
try { try {
liveClient.getLogger().info("Recording started");
var url = new URL(downloadData.getFullUrl()); var url = new URL(downloadData.getFullUrl());
HttpsURLConnection connection = (HttpsURLConnection) url.openConnection(); HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
var headers = LiveClientSettings.DefaultRequestHeaders(); var headers = LiveClientSettings.DefaultRequestHeaders();
@@ -87,8 +93,8 @@ public class RecorderListener implements LiveRecorder {
file.createNewFile(); file.createNewFile();
try ( try (
var in = connection.getInputStream(); var in = connection.getInputStream();
var fos = new FileOutputStream(file) var fos = new FileOutputStream(file)
) { ) {
byte[] dataBuffer = new byte[1024]; byte[] dataBuffer = new byte[1024];
int bytesRead; int bytesRead;
@@ -98,13 +104,19 @@ public class RecorderListener implements LiveRecorder {
} }
} catch (IOException ignored) { } catch (IOException ignored) {
} finally { } finally {
liveClient.getLogger().severe("Stopped recording "+liveClient.getRoomInfo().getHostName()); liveClient.getLogger().severe("Stopped recording " + liveClient.getRoomInfo().getHostName());
} }
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
} }
}); });
var recordingStartedEvent = new TikTokLiveRecorderStartedEvent(downloadData);
liveClient.publishEvent(recordingStartedEvent);
if (recordingStartedEvent.isCanceled()) {
liveClient.getLogger().info("Recording cancelled");
return;
}
liveDownloadThread.start(); liveDownloadThread.start();
} }
@@ -120,32 +132,6 @@ public class RecorderListener implements LiveRecorder {
liveDownloadThread.interrupt(); liveDownloadThread.interrupt();
} }
private int terminateFfmpeg(final Process process) {
if (!process.isAlive()) {
// ffmpeg -version, do nothing
return process.exitValue();
}
// ffmpeg -f x11grab
System.out.println("About to destroy the child process...");
try (final OutputStreamWriter out = new OutputStreamWriter(process.getOutputStream(), UTF_8)) {
out.write('q');
} catch (final IOException ioe) {
ioe.printStackTrace();
}
try {
if (!process.waitFor(5L, TimeUnit.SECONDS)) {
process.destroy();
process.waitFor();
}
return process.exitValue();
} catch (InterruptedException ie) {
System.out.println("Interrupted");
ie.printStackTrace();
Thread.currentThread().interrupt();
return -1;
}
}
private DownloadData mapToDownloadData(String json) { private DownloadData mapToDownloadData(String json) {

View File

@@ -26,10 +26,18 @@ import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent;
import io.github.jwdeveloper.tiktok.extension.recorder.impl.data.DownloadData; import io.github.jwdeveloper.tiktok.extension.recorder.impl.data.DownloadData;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Data; import lombok.Data;
import lombok.Getter;
import lombok.Setter;
@AllArgsConstructor @AllArgsConstructor
@Data @Getter
public class TikTokLiveRecorderStartedEvent extends TikTokEvent public class TikTokLiveRecorderStartedEvent extends TikTokEvent {
{
DownloadData downloadData; DownloadData downloadData;
@Setter
boolean canceled;
public TikTokLiveRecorderStartedEvent(DownloadData downloadData) {
this.downloadData = downloadData;
}
} }

View File

@@ -7,7 +7,7 @@
<groupId>io.github.jwdeveloper.tiktok</groupId> <groupId>io.github.jwdeveloper.tiktok</groupId>
<artifactId>TikTokLiveJava</artifactId> <artifactId>TikTokLiveJava</artifactId>
<packaging>pom</packaging> <packaging>pom</packaging>
<version>1.3.0-Release</version> <version>1.5.3-Release</version>
<modules> <modules>
<module>API</module> <module>API</module>
<module>Client</module> <module>Client</module>