Compare commits

..

8 Commits

Author SHA1 Message Date
JW
8c3a5c6627 Remove old test 2023-08-22 19:54:10 +02:00
JW
470b154c5e Merge remote-tracking branch 'origin/master' 2023-08-22 19:53:39 +02:00
JW
2391b12598 Fix Message parsing for
- LikeMessage
- MessageWebcastGiftMessage
- MessageWebcastChatMessage
2023-08-22 19:53:33 +02:00
JW
cb68050e24 Update README.md 2023-08-22 19:14:46 +02:00
JW
a9e347b8da Update README.md 2023-08-22 17:50:22 +02:00
JW
73823c82ea Update README.md 2023-08-22 17:49:35 +02:00
JW
e0542d39af Update README.md 2023-08-22 17:46:42 +02:00
GitHub Action
d33dab0a98 Update version in pom.xml 2023-08-22 15:40:34 +00:00
27 changed files with 218 additions and 198 deletions

View File

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

View File

@@ -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
/// </summary>
private Duration Timeout;
private Duration timeout;
/// <summary>
/// Polling-Interval for Socket-Connection
/// </summary
private Duration PollingInterval;
private Duration pollingInterval;
/// <summary>
/// Proxy for Connection
/// </summary>
@@ -26,46 +28,49 @@ public class ClientSettings {
/// ISO-Language for Client
/// </summary>
private String ClientLanguage;
private String clientLanguage;
/// <summary>
/// Size for Buffer for Socket-Connection
/// </summary>
private int SocketBufferSize;
private int socketBufferSize;
/// <summary>
/// Whether to Retry if Connection Fails
/// </summary>
private boolean RetryOnConnectionFailure;
private boolean retryOnConnectionFailure;
/// <summary>
/// Whether to handle Messages received from Room when Connecting
/// </summary>
private boolean HandleExistingMessagesOnConnect;
private boolean handleExistingMessagesOnConnect;
/// <summary>
/// Whether to download List of Gifts for Room when Connecting
/// </summary>
private boolean DownloadGiftInfo;
private boolean downloadGiftInfo;
/// <summary>
/// Whether to print Logs to Console
/// </summary>
private boolean PrintToConsole;
private boolean printToConsole;
/// <summary>
/// LoggingLevel for Logs
/// </summary>
private Level LogLevel;
private Level logLevel;
/// <summary>
/// Whether to print Base64-Data for Messages to Console
/// </summary>
private boolean PrintMessageData;
private boolean printMessageData;
/// <summary>
/// Whether to check Messages for Unparsed Data
/// </summary>
private boolean CheckForUnparsedData;
private boolean checkForUnparsedData;
private String hostName;
private Map<String, Object> clientParameters;
}

View File

@@ -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;
}

View File

@@ -7,14 +7,14 @@ import java.util.List;
@Getter
public class Badge {
private final ComboBadge comboBadges;
private ComboBadge comboBadges;
private final List<TextBadge> textBadges;
private final List<ImageBadge> 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());
}

View File

@@ -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);
}
}

View File

@@ -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;
}

View File

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

View File

@@ -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);

View File

@@ -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<TikTokLiveClientBuilder> {
private String userName;
private final ClientSettings clientSettings;
private Map<String, Object> 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<ClientSettings> consumer) {
public TikTokLiveClientBuilder configure(Consumer<ClientSettings> consumer) {
consumer.accept(clientSettings);
return this;
}
public TikTokLiveClientBuilder hostUserName(String userName) {
this.userName = userName;
return this;
}
public TikTokLiveClientBuilder clientParameters(Map<String, Object> 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<TikTokLiveCli
}
if (userName == null || userName.equals("")) {
throw new RuntimeException("UserName can not be null");
if (clientSettings.getHostName() == null || clientSettings.getHostName() .equals("")) {
throw new RuntimeException("HostName can not be null");
}
if (clientParameters == null) {
clientParameters = Constants.DefaultClientParams();
}
clientParameters.put("app_language", clientSettings.getClientLanguage());
clientParameters.put("webcast_language", clientSettings.getClientLanguage());
var params = clientSettings.getClientParameters();
params.put("app_language", clientSettings.getClientLanguage());
params.put("webcast_language", clientSettings.getClientLanguage());
}
public LiveClient build() {
@@ -92,18 +67,17 @@ public class TikTokLiveClientBuilder implements TikTokEventBuilder<TikTokLiveCli
var meta = new TikTokRoomInfo();
meta.setUserName(userName);
meta.setUserName(clientSettings.getHostName());
var cookieJar = new TikTokCookieJar();
var requestFactory = new TikTokHttpRequestFactory(cookieJar);
var apiClient = new TikTokHttpApiClient(cookieJar, clientSettings, requestFactory);
var apiService = new TikTokApiService(apiClient, logger, clientParameters);
var apiClient = new TikTokHttpApiClient(cookieJar, requestFactory);
var apiService = new TikTokApiService(apiClient, logger, clientSettings);
var giftManager = new TikTokGiftManager(logger, apiService, clientSettings);
var webResponseHandler = new WebResponseHandler(tikTokEventHandler,giftManager);
var webSocketClient = new TikTokWebsocketClient(logger,
var webSocketClient = new TikTokWebSocketClient(logger,
cookieJar,
clientParameters,
requestFactory,
clientSettings,
webResponseHandler,

View File

@@ -69,9 +69,10 @@ public abstract class WebResponseHandlerBase {
handleSingleMessage(message);
} catch (Exception e)
{
var decoded = Base64.getEncoder().encodeToString(message.getBinary().toByteArray());
var exception = new TikTokLiveException("Error whilst Handling Message. Stopping Client. Final Message: \n"+decoded, e);
var exception = new TikTokLiveException("Error whilst Handling Message"+message.getType()+": \n"+decoded, e);
tikTokEventHandler.publish(new TikTokErrorEvent(exception));
}
}

View File

@@ -44,8 +44,8 @@ public class HttpUtils
builder.append("&");
}
final String encodedKey = URLEncoder.encode(param.getKey().toString(), StandardCharsets.UTF_8.toString());
final String encodedValue = URLEncoder.encode(param.getValue().toString(), StandardCharsets.UTF_8.toString());
final String encodedKey = URLEncoder.encode(param.getKey(), StandardCharsets.UTF_8);
final String encodedValue = URLEncoder.encode(param.getValue().toString(), StandardCharsets.UTF_8);
builder.append(encodedKey).append("=").append(encodedValue);
first = true;
}

View File

@@ -1,7 +1,9 @@
package io.github.jwdeveloper.tiktok.http;
import com.google.gson.Gson;
import io.github.jwdeveloper.tiktok.ClientSettings;
import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveException;
import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveRequestException;
import io.github.jwdeveloper.tiktok.live.LiveRoomMeta;
import io.github.jwdeveloper.tiktok.models.gifts.TikTokGift;
import io.github.jwdeveloper.tiktok.messages.WebcastResponse;
@@ -15,12 +17,12 @@ import java.util.regex.Pattern;
public class TikTokApiService {
private final TikTokHttpApiClient apiClient;
private final Logger logger;
private final Map<String, Object> clientParams;
private final ClientSettings clientSettings;
public TikTokApiService(TikTokHttpApiClient apiClient, Logger logger, Map<String, Object> clientParams) {
public TikTokApiService(TikTokHttpApiClient apiClient, Logger logger, ClientSettings clientSettings) {
this.apiClient = apiClient;
this.logger = logger;
this.clientParams = clientParams;
this.clientSettings = clientSettings;
}
public String fetchRoomId(String userName) {
@@ -29,7 +31,7 @@ public class TikTokApiService {
try {
html = apiClient.GetLivestreamPage(userName);
} catch (Exception e) {
throw new RuntimeException("Failed to fetch room id from WebCast, see stacktrace for more info.", e);
throw new TikTokLiveRequestException("Failed to fetch room id from WebCast, see stacktrace for more info.", e);
}
Pattern firstPattern = Pattern.compile("room_id=([0-9]*)");
@@ -51,7 +53,7 @@ public class TikTokApiService {
throw new TikTokLiveException("Unable to fetch room ID");
}
clientParams.put("room_id", id);
clientSettings.getClientParameters().put("room_id", id);
logger.info("RoomID -> "+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<Integer, TikTokGift> 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);
}
}
}

View File

@@ -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<String, Object> 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<String, Object> parameters, boolean signURL) {
private String getRequest(String url, Map<String, Object> 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);
}
}

View File

@@ -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<String, String> defaultHeaders;
private final TikTokCookieJar tikTokCookieJar;
private final HttpClient client;
private String query;
private Boolean sent;
private Map<String, String> 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<String,List<String>>();
map.put(key,List.of(value));
cookieManager.put(uri,map);
var map = new HashMap<String, List<String>>();
map.put(key, List.of(value));
cookieManager.put(uri, map);
}
return response.body();

View File

@@ -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<String, Object> 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<String, Object> 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();

View File

@@ -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);
}
}

View File

@@ -1,30 +0,0 @@
package io.github.jwdeveloper.tiktok;
import com.google.protobuf.InvalidProtocolBufferException;
import io.github.jwdeveloper.tiktok.messages.WebcastWebsocketMessage;
import org.junit.Test;
import java.io.IOException;
public class SerializeWebMessageTest
{
@Test
public void WebcastWebsocketMessage()
{
/*
try (var str = getClass().getClassLoader().getResourceAsStream("WebcastWebsocketMessage.bin"))
{
var bytes = str.readAllBytes();
var person = WebcastWebsocketMessage.parseFrom(bytes);
System.out.println("id: " + person.getId());
System.out.println("type: " + person.getType());
System.out.println("binary: " + person.getBinary().size());
// System.out.println("Email: " + person.getEmail());
} catch (InvalidProtocolBufferException e) {
System.out.println("Error parsing the protobuf message: " + e.getMessage());
e.printStackTrace();
} catch (IOException e) {
System.out.println("Error reading the file: " + e.getMessage());
}*/
}
}

View File

@@ -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);
}
}
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,3 +1,6 @@
[![](https://jitpack.io/v/jwdeveloper/TikTok-Live-Java.svg)](https://jitpack.io/#jwdeveloper/TikTok-Live-Java)
# TikTok-Live-Java
A Java library based on [TikTok-Connector](https://github.com/isaackogan/TikTok-Live-Connector) and [TikTokLiveSharp](https://github.com/sebheron/TikTokLiveSharp). Use it to receive live stream events such as comments and gifts in realtime from [TikTok LIVE](https://www.tiktok.com/live) by connecting to TikTok's internal WebCast push service. The package includes a wrapper that connects to the WebCast service using just the username (`uniqueId`). This allows you to connect to your own live chat as well as the live chat of other streamers. No credentials are required. Besides [Chat Comments](#chat), other events such as [Members Joining](#member), [Gifts](#gift), [Subscriptions](#subscribe), [Viewers](#roomuser), [Follows](#social), [Shares](#social), [Questions](#questionnew), [Likes](#like) and [Battles](#linkmicbattle) can be tracked. You can also send [automatic messages](#send-chat-messages) into the chat by providing your Session ID.
@@ -20,7 +23,7 @@ Do you prefer other programming languages?
## Getting started
1. Install the package via Maven (dependecies will be simplify in future)
1. Install the package via Maven
```xml
<repositories>
@@ -32,7 +35,8 @@ Do you prefer other programming languages?
```
```xml
<dependency>
<dependencies>
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>3.24.1</version>
@@ -45,16 +49,11 @@ Do you prefer other programming languages?
</dependency>
<dependency>
<groupId>com.github.jwdeveloper.TikTok-Live-Java</groupId>
<artifactId>API</artifactId>
<version>0.0.4-Release</version>
</dependency>
<dependency>
<groupId>com.github.jwdeveloper.TikTok-Live-Java</groupId>
<artifactId>Client</artifactId>
<version>0.0.4-Release</version>
<groupId>com.github.jwdeveloper</groupId>
<artifactId>TikTok-Live-Java</artifactId>
<version>0.0.8-Release</version>
</dependency>
</dependencies>
```
2. Create your first chat connection

View File

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

View File

@@ -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);
}
}

View File

@@ -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();
}
}

View File

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

View File

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