mirror of
https://github.com/jwdeveloper/TikTokLiveJava.git
synced 2026-02-28 01:09:40 -05:00
Changes:
- Fixed bug: library was not working on certain java versions due to different WebSocket implementation. Instead of using java websocket api now there is `org.java-websocket`
This commit is contained in:
@@ -29,6 +29,23 @@
|
|||||||
<artifactId>protobuf-java</artifactId>
|
<artifactId>protobuf-java</artifactId>
|
||||||
<version>3.24.1</version>
|
<version>3.24.1</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.slf4j</groupId>
|
||||||
|
<artifactId>slf4j-simple</artifactId>
|
||||||
|
<version>2.0.7</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.java-websocket</groupId>
|
||||||
|
<artifactId>Java-WebSocket</artifactId>
|
||||||
|
<version>1.5.4</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.slf4j</groupId>
|
||||||
|
<artifactId>slf4j-simple</artifactId>
|
||||||
|
<version>2.0.7</version>
|
||||||
|
<scope>runtime</scope>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -70,7 +70,6 @@ public class TikTokLiveClientBuilder implements TikTokEventBuilder<TikTokLiveCli
|
|||||||
var tiktokRoomInfo = new TikTokRoomInfo();
|
var tiktokRoomInfo = new TikTokRoomInfo();
|
||||||
tiktokRoomInfo.setUserName(clientSettings.getHostName());
|
tiktokRoomInfo.setUserName(clientSettings.getHostName());
|
||||||
|
|
||||||
|
|
||||||
var cookieJar = new TikTokCookieJar();
|
var cookieJar = new TikTokCookieJar();
|
||||||
var requestFactory = new TikTokHttpRequestFactory(cookieJar);
|
var requestFactory = new TikTokHttpRequestFactory(cookieJar);
|
||||||
var apiClient = new TikTokHttpApiClient(cookieJar, requestFactory);
|
var apiClient = new TikTokHttpApiClient(cookieJar, requestFactory);
|
||||||
@@ -79,7 +78,6 @@ public class TikTokLiveClientBuilder implements TikTokEventBuilder<TikTokLiveCli
|
|||||||
var webResponseHandler = new TikTokMessageHandlerRegistration(tikTokEventHandler, clientSettings, logger, giftManager, tiktokRoomInfo);
|
var webResponseHandler = new TikTokMessageHandlerRegistration(tikTokEventHandler, clientSettings, logger, giftManager, tiktokRoomInfo);
|
||||||
var webSocketClient = new TikTokWebSocketClient(logger,
|
var webSocketClient = new TikTokWebSocketClient(logger,
|
||||||
cookieJar,
|
cookieJar,
|
||||||
requestFactory,
|
|
||||||
clientSettings,
|
clientSettings,
|
||||||
webResponseHandler,
|
webResponseHandler,
|
||||||
tikTokEventHandler);
|
tikTokEventHandler);
|
||||||
|
|||||||
@@ -11,10 +11,10 @@ import io.github.jwdeveloper.tiktok.http.HttpUtils;
|
|||||||
import io.github.jwdeveloper.tiktok.http.TikTokCookieJar;
|
import io.github.jwdeveloper.tiktok.http.TikTokCookieJar;
|
||||||
import io.github.jwdeveloper.tiktok.http.TikTokHttpRequestFactory;
|
import io.github.jwdeveloper.tiktok.http.TikTokHttpRequestFactory;
|
||||||
import io.github.jwdeveloper.tiktok.messages.WebcastResponse;
|
import io.github.jwdeveloper.tiktok.messages.WebcastResponse;
|
||||||
|
import org.java_websocket.client.WebSocketClient;
|
||||||
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.net.http.WebSocket;
|
import java.net.http.WebSocket;
|
||||||
import java.time.Duration;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.TreeMap;
|
import java.util.TreeMap;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
@@ -23,24 +23,21 @@ public class TikTokWebSocketClient {
|
|||||||
private final Logger logger;
|
private final Logger logger;
|
||||||
private final ClientSettings clientSettings;
|
private final ClientSettings clientSettings;
|
||||||
private final TikTokCookieJar tikTokCookieJar;
|
private final TikTokCookieJar tikTokCookieJar;
|
||||||
private final TikTokHttpRequestFactory factory;
|
|
||||||
private final TikTokMessageHandlerRegistration webResponseHandler;
|
private final TikTokMessageHandlerRegistration webResponseHandler;
|
||||||
private final TikTokEventHandler tikTokEventHandler;
|
private final TikTokEventHandler tikTokEventHandler;
|
||||||
|
|
||||||
private WebSocket webSocket;
|
private WebSocketClient webSocketClient;
|
||||||
private boolean isConnected;
|
private boolean isConnected;
|
||||||
private TikTokLiveClient tikTokLiveClient;
|
private TikTokLiveClient tikTokLiveClient;
|
||||||
|
|
||||||
public TikTokWebSocketClient(Logger logger,
|
public TikTokWebSocketClient(Logger logger,
|
||||||
TikTokCookieJar tikTokCookieJar,
|
TikTokCookieJar tikTokCookieJar,
|
||||||
TikTokHttpRequestFactory factory,
|
|
||||||
ClientSettings clientSettings,
|
ClientSettings clientSettings,
|
||||||
TikTokMessageHandlerRegistration webResponseHandler,
|
TikTokMessageHandlerRegistration webResponseHandler,
|
||||||
TikTokEventHandler tikTokEventHandler) {
|
TikTokEventHandler tikTokEventHandler) {
|
||||||
this.logger = logger;
|
this.logger = logger;
|
||||||
this.tikTokCookieJar = tikTokCookieJar;
|
this.tikTokCookieJar = tikTokCookieJar;
|
||||||
this.clientSettings = clientSettings;
|
this.clientSettings = clientSettings;
|
||||||
this.factory = factory;
|
|
||||||
this.webResponseHandler = webResponseHandler;
|
this.webResponseHandler = webResponseHandler;
|
||||||
this.tikTokEventHandler = tikTokEventHandler;
|
this.tikTokEventHandler = tikTokEventHandler;
|
||||||
isConnected = false;
|
isConnected = false;
|
||||||
@@ -56,12 +53,12 @@ public class TikTokWebSocketClient {
|
|||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
var url = getWebSocketUrl(webcastResponse);
|
var url = getWebSocketUrl(webcastResponse);
|
||||||
if (clientSettings.isHandleExistingMessagesOnConnect())
|
if (clientSettings.isHandleExistingMessagesOnConnect()) {
|
||||||
{
|
|
||||||
logger.info("Handling existing messages");
|
logger.info("Handling existing messages");
|
||||||
webResponseHandler.handle(tikTokLiveClient, webcastResponse);
|
webResponseHandler.handle(tikTokLiveClient, webcastResponse);
|
||||||
}
|
}
|
||||||
webSocket = startWebSocket(url);
|
webSocketClient = startWebSocket(url);
|
||||||
|
webSocketClient.connect();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new TikTokLiveException("Failed to connect to the websocket", e);
|
throw new TikTokLiveException("Failed to connect to the websocket", e);
|
||||||
}
|
}
|
||||||
@@ -82,20 +79,19 @@ public class TikTokWebSocketClient {
|
|||||||
return HttpUtils.parseParametersEncode(url, clone);
|
return HttpUtils.parseParametersEncode(url, clone);
|
||||||
}
|
}
|
||||||
|
|
||||||
private WebSocket startWebSocket(String url) throws Exception {
|
private WebSocketClient startWebSocket(String url) {
|
||||||
var cookie = tikTokCookieJar.parseCookies();
|
var cookie = tikTokCookieJar.parseCookies();
|
||||||
var map = new HashMap<String, String>();
|
var map = new HashMap<String, String>();
|
||||||
map.put("Cookie", cookie);
|
map.put("Cookie", cookie);
|
||||||
return factory.openSocket()
|
|
||||||
.subprotocols("echo-protocol")
|
return new TikTokWebSocketListener(URI.create(url), map, 3000, webResponseHandler, tikTokEventHandler, tikTokLiveClient);
|
||||||
.connectTimeout(Duration.ofSeconds(15))
|
|
||||||
.header("Cookie", cookie)
|
|
||||||
.buildAsync(URI.create(url), new TikTokWebSocketListener(webResponseHandler, tikTokEventHandler, tikTokLiveClient)).get();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public void stop() {
|
public void stop() {
|
||||||
if (isConnected && webSocket != null) {
|
if (isConnected && webSocketClient != null) {
|
||||||
webSocket.sendClose(WebSocket.NORMAL_CLOSURE, "ok");
|
webSocketClient.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package io.github.jwdeveloper.tiktok.websocket;
|
package io.github.jwdeveloper.tiktok.websocket;
|
||||||
|
|
||||||
|
|
||||||
import com.google.protobuf.ByteString;
|
import com.google.protobuf.ByteString;
|
||||||
import io.github.jwdeveloper.tiktok.TikTokLiveClient;
|
import io.github.jwdeveloper.tiktok.TikTokLiveClient;
|
||||||
import io.github.jwdeveloper.tiktok.events.messages.TikTokConnectedEvent;
|
import io.github.jwdeveloper.tiktok.events.messages.TikTokConnectedEvent;
|
||||||
@@ -12,71 +11,71 @@ import io.github.jwdeveloper.tiktok.handlers.TikTokMessageHandlerRegistration;
|
|||||||
import io.github.jwdeveloper.tiktok.messages.WebcastResponse;
|
import io.github.jwdeveloper.tiktok.messages.WebcastResponse;
|
||||||
import io.github.jwdeveloper.tiktok.messages.WebcastWebsocketAck;
|
import io.github.jwdeveloper.tiktok.messages.WebcastWebsocketAck;
|
||||||
import io.github.jwdeveloper.tiktok.messages.WebcastWebsocketMessage;
|
import io.github.jwdeveloper.tiktok.messages.WebcastWebsocketMessage;
|
||||||
|
import org.java_websocket.client.WebSocketClient;
|
||||||
|
import org.java_websocket.drafts.Draft_6455;
|
||||||
|
import org.java_websocket.handshake.ServerHandshake;
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.net.URI;
|
||||||
import java.net.http.WebSocket;
|
import java.net.http.WebSocket;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.concurrent.CompletionStage;
|
|
||||||
|
|
||||||
|
public class TikTokWebSocketListener extends WebSocketClient {
|
||||||
|
|
||||||
public class TikTokWebSocketListener implements java.net.http.WebSocket.Listener {
|
|
||||||
|
|
||||||
private final ByteArrayOutputStream accumulatedData = new ByteArrayOutputStream();
|
|
||||||
private final TikTokMessageHandlerRegistration webResponseHandler;
|
private final TikTokMessageHandlerRegistration webResponseHandler;
|
||||||
private final TikTokEventHandler tikTokEventHandler;
|
private final TikTokEventHandler tikTokEventHandler;
|
||||||
private final TikTokLiveClient tikTokLiveClient;
|
private final TikTokLiveClient tikTokLiveClient;
|
||||||
|
|
||||||
public TikTokWebSocketListener(TikTokMessageHandlerRegistration webResponseHandler,
|
public TikTokWebSocketListener(URI serverUri,
|
||||||
|
Map<String, String> httpHeaders,
|
||||||
|
int connectTimeout,
|
||||||
|
TikTokMessageHandlerRegistration webResponseHandler,
|
||||||
TikTokEventHandler tikTokEventHandler,
|
TikTokEventHandler tikTokEventHandler,
|
||||||
TikTokLiveClient tikTokLiveClient) {
|
TikTokLiveClient tikTokLiveClient) {
|
||||||
|
super(serverUri, new Draft_6455(), httpHeaders,connectTimeout);
|
||||||
this.webResponseHandler = webResponseHandler;
|
this.webResponseHandler = webResponseHandler;
|
||||||
this.tikTokEventHandler = tikTokEventHandler;
|
this.tikTokEventHandler = tikTokEventHandler;
|
||||||
this.tikTokLiveClient = tikTokLiveClient;
|
this.tikTokLiveClient = tikTokLiveClient;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompletionStage<?> onBinary(WebSocket webSocket, ByteBuffer data, boolean last) {
|
public void onOpen(ServerHandshake serverHandshake) {
|
||||||
|
tikTokEventHandler.publish(tikTokLiveClient,new TikTokConnectedEvent());
|
||||||
|
sendPing();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onMessage(ByteBuffer bytes)
|
||||||
|
{
|
||||||
try {
|
try {
|
||||||
var bytes = new byte[data.remaining()];
|
handleBinary(bytes.array());
|
||||||
data.get(bytes);
|
|
||||||
accumulatedData.write(bytes);
|
|
||||||
if (last) {
|
|
||||||
handleBinary(webSocket, accumulatedData.toByteArray());
|
|
||||||
accumulatedData.reset();
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
tikTokEventHandler.publish(tikTokLiveClient, new TikTokErrorEvent(e));
|
tikTokEventHandler.publish(tikTokLiveClient, new TikTokErrorEvent(e));
|
||||||
}
|
}
|
||||||
webSocket.request(1);
|
sendPing();
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onOpen(java.net.http.WebSocket webSocket) {
|
public void onClose(int i, String s, boolean b) {
|
||||||
tikTokEventHandler.publish(tikTokLiveClient,new TikTokConnectedEvent());
|
|
||||||
webSocket.request(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onError(java.net.http.WebSocket webSocket, Throwable error) {
|
|
||||||
tikTokEventHandler.publish(tikTokLiveClient,new TikTokErrorEvent(error));
|
|
||||||
webSocket.request(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public CompletionStage<?> onClose(java.net.http.WebSocket webSocket, int statusCode, String reason) {
|
|
||||||
tikTokEventHandler.publish(tikTokLiveClient,new TikTokDisconnectedEvent());
|
tikTokEventHandler.publish(tikTokLiveClient,new TikTokDisconnectedEvent());
|
||||||
return java.net.http.WebSocket.Listener.super.onClose(webSocket, statusCode, reason);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleBinary(WebSocket webSocket, byte[] buffer) {
|
@Override
|
||||||
|
public void onError(Exception error) {
|
||||||
|
tikTokEventHandler.publish(tikTokLiveClient,new TikTokErrorEvent(error));
|
||||||
|
sendPing();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleBinary(byte[] buffer) {
|
||||||
var websocketMessageOptional = getWebcastWebsocketMessage(buffer);
|
var websocketMessageOptional = getWebcastWebsocketMessage(buffer);
|
||||||
if (websocketMessageOptional.isEmpty()) {
|
if (websocketMessageOptional.isEmpty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var websocketMessage = websocketMessageOptional.get();
|
var websocketMessage = websocketMessageOptional.get();
|
||||||
sendAckId(webSocket, websocketMessage.getId());
|
sendAckId(websocketMessage.getId());
|
||||||
|
|
||||||
var webResponse = getWebResponseMessage(websocketMessage.getBinary());
|
var webResponse = getWebResponseMessage(websocketMessage.getBinary());
|
||||||
webResponseHandler.handle(tikTokLiveClient, webResponse);
|
webResponseHandler.handle(tikTokLiveClient, webResponse);
|
||||||
@@ -114,13 +113,19 @@ public class TikTokWebSocketListener implements java.net.http.WebSocket.Listener
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sendAckId(WebSocket webSocket, long id) {
|
private void sendAckId(long id) {
|
||||||
var serverInfo = WebcastWebsocketAck
|
var serverInfo = WebcastWebsocketAck
|
||||||
.newBuilder()
|
.newBuilder()
|
||||||
.setType("ack")
|
.setType("ack")
|
||||||
.setId(id)
|
.setId(id)
|
||||||
.build();
|
.build();
|
||||||
webSocket.sendBinary(serverInfo.toByteString().asReadOnlyByteBuffer(), true);
|
send(serverInfo.toByteString().asReadOnlyByteBuffer());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onMessage(String s) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import java.io.IOException;
|
|||||||
|
|
||||||
public class Main {
|
public class Main {
|
||||||
|
|
||||||
public static String TEST_TIKTOK_USER = "vadimpyrography";
|
public static String TEST_TIKTOK_USER = "dmikl_";
|
||||||
|
|
||||||
public static void main(String[] args) throws IOException {
|
public static void main(String[] args) throws IOException {
|
||||||
var client = TikTokLive.newClient(TEST_TIKTOK_USER)
|
var client = TikTokLive.newClient(TEST_TIKTOK_USER)
|
||||||
|
|||||||
5
pom.xml
5
pom.xml
@@ -54,6 +54,7 @@
|
|||||||
<configuration>
|
<configuration>
|
||||||
<shadedArtifactAttached>true</shadedArtifactAttached>
|
<shadedArtifactAttached>true</shadedArtifactAttached>
|
||||||
<shadedClassifierName>all</shadedClassifierName>
|
<shadedClassifierName>all</shadedClassifierName>
|
||||||
|
<createDependencyReducedPom>false</createDependencyReducedPom>
|
||||||
<minimizeJar>true</minimizeJar>
|
<minimizeJar>true</minimizeJar>
|
||||||
<artifactSet>
|
<artifactSet>
|
||||||
<includes>
|
<includes>
|
||||||
@@ -64,8 +65,6 @@
|
|||||||
<filter>
|
<filter>
|
||||||
<artifact>*:*</artifact>
|
<artifact>*:*</artifact>
|
||||||
<excludes>
|
<excludes>
|
||||||
<exclude>**/proto/**</exclude>
|
|
||||||
<exclude>**/google/**</exclude>
|
|
||||||
<exclude>**/tiktokSchema.proto/**</exclude>
|
<exclude>**/tiktokSchema.proto/**</exclude>
|
||||||
</excludes>
|
</excludes>
|
||||||
</filter>
|
</filter>
|
||||||
@@ -99,6 +98,8 @@
|
|||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
|||||||
Reference in New Issue
Block a user