Compare commits

...

25 Commits

Author SHA1 Message Date
JW
321b7c0eda Merge remote-tracking branch 'origin/master' 2023-08-22 20:47:33 +02:00
JW
26c7db8f99 Fix messages
- WebcastSocialMessage
  - ImDeleteMessage
2023-08-22 20:47:27 +02:00
JW
5f7ead2f05 Update README.md 2023-08-22 20:01:05 +02:00
GitHub Action
dffae3a521 Update version in pom.xml 2023-08-22 18:00:21 +00:00
JW
6254443755 Merge remote-tracking branch 'origin/master' 2023-08-22 19:58:51 +02:00
JW
c001eacbce Remove old test 2023-08-22 19:58:46 +02:00
JW
1bbb704d14 Update README.md 2023-08-22 19:54:56 +02:00
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
JW
32cb1e0d8f Update pom.xml 2023-08-22 17:39:22 +02:00
JW
3210707bce Update maven-publish.yml 2023-08-22 17:39:04 +02:00
JW
e7f9d6e9d5 Update maven-publish.yml 2023-08-22 17:38:48 +02:00
GitHub Action
03001d607d Update version in pom.xml 2023-08-22 15:33:39 +00:00
JW
cbabad0888 Update pom.xml 2023-08-22 17:32:34 +02:00
JW
09c531e9f4 Update maven-publish.yml 2023-08-22 17:32:17 +02:00
GitHub Action
997c8d399e Update version in pom.xml 2023-08-22 15:30:36 +00:00
JW
668f28e357 Update maven-publish.yml 2023-08-22 17:29:30 +02:00
JW
b332c2f5d8 Update pom.xml 2023-08-22 17:27:57 +02:00
GitHub Action
5be113cbc8 Update version in pom.xml 2023-08-22 15:26:05 +00:00
35 changed files with 276 additions and 255 deletions

View File

@@ -32,11 +32,10 @@ jobs:
change_path: "." change_path: "."
short_tags: false short_tags: false
bump_each_commit: false bump_each_commit: false
- name: 2.7 Update version in pom.xml (Release only) - name: 2.7 Update version in pom.xml (Release only)
run: mvn versions:set -DnewVersion=${{steps.version.outputs.version_tag}} -DprocessAllModules run: mvn versions:set -DnewVersion=${{steps.version.outputs.version_tag}}
- name: 3 Build with Maven - name: 3 Build with Maven
run: mvn package -P publish --file pom.xml run: mvn package -P publish --file pom.xml
@@ -74,6 +73,10 @@ jobs:
git config --local user.email "action@github.com" git config --local user.email "action@github.com"
git config --local user.name "GitHub Action" git config --local user.name "GitHub Action"
git add pom.xml git add pom.xml
git add API/pom.xml
git add Client/pom.xml
git add TestApplication/pom.xml
git add Tools/pom.xml
git commit -m "Update version in pom.xml" git commit -m "Update version in pom.xml"
- name: Push changes - name: Push changes
uses: ad-m/github-push-action@master uses: ad-m/github-push-action@master

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.0.0</version> <version>0.0.10-Release</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<artifactId>API</artifactId> <artifactId>API</artifactId>

View File

@@ -3,6 +3,8 @@ package io.github.jwdeveloper.tiktok;
import lombok.Data; import lombok.Data;
import java.time.Duration; import java.time.Duration;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level; import java.util.logging.Level;
@Data @Data
@@ -11,12 +13,12 @@ public class ClientSettings {
/// Timeout for Connections /// Timeout for Connections
/// </summary> /// </summary>
private Duration Timeout; private Duration timeout;
/// <summary> /// <summary>
/// Polling-Interval for Socket-Connection /// Polling-Interval for Socket-Connection
/// </summary /// </summary
private Duration PollingInterval; private Duration pollingInterval;
/// <summary> /// <summary>
/// Proxy for Connection /// Proxy for Connection
/// </summary> /// </summary>
@@ -26,46 +28,52 @@ public class ClientSettings {
/// ISO-Language for Client /// ISO-Language for Client
/// </summary> /// </summary>
private String ClientLanguage; private String clientLanguage;
/// <summary>
/// Size for Buffer for Socket-Connection
/// </summary>
private int SocketBufferSize;
/// <summary> /// <summary>
/// Whether to Retry if Connection Fails /// Whether to Retry if Connection Fails
/// </summary> /// </summary>
private boolean RetryOnConnectionFailure; private boolean retryOnConnectionFailure;
/// <summary> /// <summary>
/// Whether to handle Messages received from Room when Connecting /// Whether to handle Messages received from Room when Connecting
/// </summary> /// </summary>
private boolean HandleExistingMessagesOnConnect; private boolean handleExistingMessagesOnConnect;
/// <summary> /// <summary>
/// Whether to download List of Gifts for Room when Connecting /// Whether to download List of Gifts for Room when Connecting
/// </summary> /// </summary>
private boolean DownloadGiftInfo; private boolean downloadGiftInfo;
/// <summary> /// <summary>
/// Whether to print Logs to Console /// Whether to print Logs to Console
/// </summary> /// </summary>
private boolean PrintToConsole; private boolean printToConsole;
/// <summary> /// <summary>
/// LoggingLevel for Logs /// LoggingLevel for Logs
/// </summary> /// </summary>
private Level LogLevel; private Level logLevel;
/// <summary> /// <summary>
/// Whether to print Base64-Data for Messages to Console /// Whether to print Base64-Data for Messages to Console
/// </summary> /// </summary>
private boolean PrintMessageData; private boolean printMessageData;
/// <summary> /// <summary>
/// Whether to check Messages for Unparsed Data /// Whether to check Messages for Unparsed Data
/// </summary> /// </summary>
private boolean CheckForUnparsedData; private boolean checkForUnparsedData;
/// <summary>
/// Tiktok user name
/// </summary>
private String hostName;
/// <summary>
/// Parameters used in requests to tiktok api
/// </summary>
private Map<String, Object> clientParameters;
} }

View File

@@ -39,18 +39,17 @@ public class Constants {
public static ClientSettings DefaultClientSettings() { public static ClientSettings DefaultClientSettings() {
var clientSettings = new ClientSettings(); var clientSettings = new ClientSettings();
clientSettings.setTimeout(Duration.ofSeconds(DEFAULT_TIMEOUT)); clientSettings.setTimeout(Duration.ofSeconds(DEFAULT_TIMEOUT));
clientSettings.setPollingInterval(Duration.ofSeconds(DEFAULT_POLLTIME)); clientSettings.setPollingInterval(Duration.ofSeconds(DEFAULT_POLLTIME));
clientSettings.setClientLanguage("en-US"); clientSettings.setClientLanguage("en-US");
clientSettings.setHandleExistingMessagesOnConnect(true); clientSettings.setHandleExistingMessagesOnConnect(true);
clientSettings.setDownloadGiftInfo(true); clientSettings.setDownloadGiftInfo(true);
clientSettings.setRetryOnConnectionFailure(true); clientSettings.setRetryOnConnectionFailure(true);
clientSettings.setSocketBufferSize(500_000);
clientSettings.setPrintToConsole(true); clientSettings.setPrintToConsole(true);
clientSettings.setLogLevel(Level.ALL); clientSettings.setLogLevel(Level.ALL);
clientSettings.setCheckForUnparsedData(false); clientSettings.setCheckForUnparsedData(false);
clientSettings.setPrintMessageData(false); clientSettings.setPrintMessageData(false);
clientSettings.setClientParameters(Constants.DefaultClientParams());
return clientSettings; return clientSettings;
} }

View File

@@ -6,12 +6,10 @@ import lombok.Getter;
@Getter @Getter
public class TikTokIMDeleteEvent extends TikTokEvent { public class TikTokIMDeleteEvent extends TikTokEvent {
private final String data1; private final byte[] data;
private final String data2;
public TikTokIMDeleteEvent(WebcastImDeleteMessage msg) { public TikTokIMDeleteEvent(WebcastImDeleteMessage msg) {
super(msg.getHeader());; super(msg.getHeader());
data1 = msg.getData1(); data = msg.getData().toByteArray();
data2 = msg.getData2(); }
}
} }

View File

@@ -7,14 +7,14 @@ import java.util.List;
@Getter @Getter
public class Badge { public class Badge {
private final ComboBadge comboBadges; private ComboBadge comboBadges;
private final List<TextBadge> textBadges; private final List<TextBadge> textBadges;
private final List<ImageBadge> imageBadges; private final List<ImageBadge> imageBadges;
public Badge(io.github.jwdeveloper.tiktok.messages.Badge badge) { public Badge(io.github.jwdeveloper.tiktok.messages.Badge badge) {
textBadges = badge.getTextBadgesList().stream().map(b -> new TextBadge(b.getType(), b.getName())).toList(); 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(); 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 { message BadgeComplex {
uint32 data1 = 1; uint32 data1 = 1;
string imageUrl = 2; //string imageUrl = 2; Protocol message had invalid UTF-8
string data = 4; string data = 4;
DataContainer detail1 = 5; DataContainer detail1 = 5;
string data2 = 6; string data2 = 6;
@@ -377,7 +377,7 @@ message RankTextMessage {
// Links to Image-Files on the TikTok CDN // Links to Image-Files on the TikTok CDN
message Picture { message Picture {
repeated string urls = 1; // Usually has 3 different urls with different sizes/extensions 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 data1 = 3;
uint32 data2 = 4; uint32 data2 = 4;
string color = 5; string color = 5;
@@ -681,7 +681,7 @@ message WebcastGiftMessage {
uint32 data11 = 34; uint32 data11 = 34;
message GiftData1 { message GiftData1 {
string data1 = 1; // string data1 = 1; not working
uint32 data2 = 2; uint32 data2 = 2;
uint32 data3 = 3; uint32 data3 = 3;
} }
@@ -749,8 +749,7 @@ message WebcastHourlyRankMessage {
// Message related to Chat-moderation? // Message related to Chat-moderation?
message WebcastImDeleteMessage { message WebcastImDeleteMessage {
MessageHeader header = 1; MessageHeader header = 1;
string data1 = 2; bytes data = 3;
string data2 = 3;
} }
message WebcastInRoomBannerMessage { message WebcastInRoomBannerMessage {

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.0.0</version> <version>0.0.10-Release</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -8,6 +8,4 @@ public class TikTokLive
{ {
return new TikTokLiveClientBuilder(userName); return new TikTokLiveClientBuilder(userName);
} }
} }

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.LiveClient;
import io.github.jwdeveloper.tiktok.live.LiveRoomInfo; import io.github.jwdeveloper.tiktok.live.LiveRoomInfo;
import io.github.jwdeveloper.tiktok.live.TikTokRoomInfo; 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; import java.util.logging.Logger;
@@ -15,14 +15,14 @@ public class TikTokLiveClient implements LiveClient {
private final TikTokRoomInfo meta; private final TikTokRoomInfo meta;
private final TikTokGiftManager giftManager; private final TikTokGiftManager giftManager;
private final TikTokApiService apiClient; private final TikTokApiService apiClient;
private final TikTokWebsocketClient webSocketClient; private final TikTokWebSocketClient webSocketClient;
private final TikTokEventHandler tikTokEventHandler; private final TikTokEventHandler tikTokEventHandler;
private final Logger logger; private final Logger logger;
public TikTokLiveClient(TikTokRoomInfo tikTokLiveMeta, public TikTokLiveClient(TikTokRoomInfo tikTokLiveMeta,
TikTokApiService tikTokApiService, TikTokApiService tikTokApiService,
TikTokWebsocketClient webSocketClient, TikTokWebSocketClient webSocketClient,
TikTokGiftManager tikTokGiftManager, TikTokGiftManager tikTokGiftManager,
TikTokEventHandler tikTokEventHandler, TikTokEventHandler tikTokEventHandler,
Logger logger) { Logger logger) {
@@ -57,9 +57,9 @@ public class TikTokLiveClient implements LiveClient {
public void tryConnect() { public void tryConnect() {
if (meta.hasConnectionState(ConnectionState.CONNECTED)) if (meta.hasConnectionState(ConnectionState.CONNECTED))
throw new RuntimeException("Already connected"); throw new TikTokLiveException("Already connected");
if (meta.hasConnectionState(ConnectionState.CONNECTING)) if (meta.hasConnectionState(ConnectionState.CONNECTING))
throw new RuntimeException("Already connecting"); throw new TikTokLiveException("Already connecting");
logger.info("Connecting"); logger.info("Connecting");
setState(ConnectionState.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.http.TikTokHttpRequestFactory;
import io.github.jwdeveloper.tiktok.live.LiveClient; import io.github.jwdeveloper.tiktok.live.LiveClient;
import io.github.jwdeveloper.tiktok.live.TikTokRoomInfo; 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.time.Duration;
import java.util.Map;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.logging.Logger; import java.util.logging.Logger;
public class TikTokLiveClientBuilder implements TikTokEventBuilder<TikTokLiveClientBuilder> { public class TikTokLiveClientBuilder implements TikTokEventBuilder<TikTokLiveClientBuilder> {
private String userName;
private final ClientSettings clientSettings; private final ClientSettings clientSettings;
private Map<String, Object> clientParameters;
private final Logger logger; private final Logger logger;
private final TikTokEventHandler tikTokEventHandler; private final TikTokEventHandler tikTokEventHandler;
public TikTokLiveClientBuilder(String userName) { public TikTokLiveClientBuilder(String userName) {
this.tikTokEventHandler = new TikTokEventHandler(); this.tikTokEventHandler = new TikTokEventHandler();
this.userName = userName;
this.clientSettings = Constants.DefaultClientSettings(); this.clientSettings = Constants.DefaultClientSettings();
this.clientParameters = Constants.DefaultClientParams(); this.clientSettings.setHostName(userName);
this.logger = Logger.getLogger(TikTokLive.class.getName()); this.logger = Logger.getLogger(TikTokLive.class.getName());
} }
public TikTokLiveClientBuilder configure(Consumer<ClientSettings> consumer) {
public TikTokLiveClientBuilder clientSettings(Consumer<ClientSettings> consumer) {
consumer.accept(clientSettings); consumer.accept(clientSettings);
return this; 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() { private void validate() {
if (clientSettings.getTimeout() == null) { if (clientSettings.getTimeout() == null) {
@@ -70,21 +48,17 @@ public class TikTokLiveClientBuilder implements TikTokEventBuilder<TikTokLiveCli
clientSettings.setClientLanguage(Constants.DefaultClientSettings().getClientLanguage()); clientSettings.setClientLanguage(Constants.DefaultClientSettings().getClientLanguage());
} }
if (clientSettings.getSocketBufferSize() < 500_000) {
clientSettings.setSocketBufferSize(Constants.DefaultClientSettings().getSocketBufferSize());
if (clientSettings.getHostName() == null || clientSettings.getHostName() .equals("")) {
throw new RuntimeException("HostName can not be null");
} }
var params = clientSettings.getClientParameters();
params.put("app_language", clientSettings.getClientLanguage());
params.put("webcast_language", clientSettings.getClientLanguage());
if (userName == null || userName.equals("")) { logger.setLevel(clientSettings.getLogLevel());
throw new RuntimeException("UserName can not be null");
}
if (clientParameters == null) {
clientParameters = Constants.DefaultClientParams();
}
clientParameters.put("app_language", clientSettings.getClientLanguage());
clientParameters.put("webcast_language", clientSettings.getClientLanguage());
} }
public LiveClient build() { public LiveClient build() {
@@ -92,18 +66,17 @@ public class TikTokLiveClientBuilder implements TikTokEventBuilder<TikTokLiveCli
var meta = new TikTokRoomInfo(); var meta = new TikTokRoomInfo();
meta.setUserName(userName); meta.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, clientSettings, requestFactory); var apiClient = new TikTokHttpApiClient(cookieJar, requestFactory);
var apiService = new TikTokApiService(apiClient, logger, clientParameters); var apiService = new TikTokApiService(apiClient, logger, clientSettings);
var giftManager = new TikTokGiftManager(logger, apiService, clientSettings); var giftManager = new TikTokGiftManager(logger, apiService, clientSettings);
var webResponseHandler = new WebResponseHandler(tikTokEventHandler,giftManager); var webResponseHandler = new WebResponseHandler(tikTokEventHandler,giftManager);
var webSocketClient = new TikTokWebsocketClient(logger, var webSocketClient = new TikTokWebSocketClient(logger,
cookieJar, cookieJar,
clientParameters,
requestFactory, requestFactory,
clientSettings, clientSettings,
webResponseHandler, webResponseHandler,

View File

@@ -119,7 +119,7 @@ public class WebResponseHandler extends WebResponseHandlerBase {
var message = WebcastSocialMessage.parseFrom(msg.getBinary()); var message = WebcastSocialMessage.parseFrom(msg.getBinary());
String type = message.getHeader().getSocialData().getType(); String type = message.getHeader().getSocialData().getType();
Pattern pattern = Pattern.compile("pm_mt_guidance_viewer_([0-9]+)_share"); Pattern pattern = Pattern.compile("\\d+");
Matcher matcher = pattern.matcher(type); Matcher matcher = pattern.matcher(type);
if (matcher.find()) { if (matcher.find()) {
var value = matcher.group(0); var value = matcher.group(0);

View File

@@ -69,15 +69,16 @@ public abstract class WebResponseHandlerBase {
handleSingleMessage(message); handleSingleMessage(message);
} catch (Exception e) } catch (Exception e)
{ {
var decoded = Base64.getEncoder().encodeToString(message.getBinary().toByteArray()); 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)); tikTokEventHandler.publish(new TikTokErrorEvent(exception));
} }
} }
} }
private void handleSingleMessage(WebcastResponse.Message message) throws Exception { public void handleSingleMessage(WebcastResponse.Message message) throws Exception {
if (!handlers.containsKey(message.getType())) { if (!handlers.containsKey(message.getType())) {
tikTokEventHandler.publish(new TikTokUnhandledEvent(message)); tikTokEventHandler.publish(new TikTokUnhandledEvent(message));
return; return;

View File

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

View File

@@ -1,7 +1,9 @@
package io.github.jwdeveloper.tiktok.http; package io.github.jwdeveloper.tiktok.http;
import com.google.gson.Gson; import com.google.gson.Gson;
import io.github.jwdeveloper.tiktok.ClientSettings;
import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveException; 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.live.LiveRoomMeta;
import io.github.jwdeveloper.tiktok.models.gifts.TikTokGift; import io.github.jwdeveloper.tiktok.models.gifts.TikTokGift;
import io.github.jwdeveloper.tiktok.messages.WebcastResponse; import io.github.jwdeveloper.tiktok.messages.WebcastResponse;
@@ -15,12 +17,12 @@ import java.util.regex.Pattern;
public class TikTokApiService { public class TikTokApiService {
private final TikTokHttpApiClient apiClient; private final TikTokHttpApiClient apiClient;
private final Logger logger; 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.apiClient = apiClient;
this.logger = logger; this.logger = logger;
this.clientParams = clientParams; this.clientSettings = clientSettings;
} }
public String fetchRoomId(String userName) { public String fetchRoomId(String userName) {
@@ -29,7 +31,7 @@ public class TikTokApiService {
try { try {
html = apiClient.GetLivestreamPage(userName); html = apiClient.GetLivestreamPage(userName);
} catch (Exception e) { } 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]*)"); Pattern firstPattern = Pattern.compile("room_id=([0-9]*)");
@@ -51,7 +53,7 @@ public class TikTokApiService {
throw new TikTokLiveException("Unable to fetch room ID"); throw new TikTokLiveException("Unable to fetch room ID");
} }
clientParams.put("room_id", id); clientSettings.getClientParameters().put("room_id", id);
logger.info("RoomID -> "+id); logger.info("RoomID -> "+id);
return id; return id;
} }
@@ -60,7 +62,7 @@ public class TikTokApiService {
public LiveRoomMeta fetchRoomInfo() { public LiveRoomMeta fetchRoomInfo() {
logger.info("Fetch RoomInfo"); logger.info("Fetch RoomInfo");
try { try {
var response = apiClient.GetJObjectFromWebcastAPI("room/info/", clientParams); var response = apiClient.GetJObjectFromWebcastAPI("room/info/", clientSettings.getClientParameters());
if (!response.has("data")) { if (!response.has("data")) {
return new LiveRoomMeta(); return new LiveRoomMeta();
} }
@@ -78,7 +80,7 @@ public class TikTokApiService {
logger.info("RoomInfo status -> "+info.getStatus()); logger.info("RoomInfo status -> "+info.getStatus());
return info; return info;
} catch (Exception e) { } 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"); logger.info("Fetch ClientData");
try { try {
var response = apiClient.GetDeserializedMessage("im/fetch/", clientParams); var response = apiClient.GetDeserializedMessage("im/fetch/", clientSettings.getClientParameters());
clientParams.put("cursor",response.getCursor()); clientSettings.getClientParameters().put("cursor",response.getCursor());
clientParams.put("internal_ext", response.getAckIds()); clientSettings.getClientParameters().put("internal_ext", response.getAckIds());
return response; return response;
} }
catch (Exception e) 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() { public Map<Integer, TikTokGift> fetchAvailableGifts() {
try { try {
var response = apiClient.GetJObjectFromWebcastAPI("gift/list/", clientParams); var response = apiClient.GetJObjectFromWebcastAPI("gift/list/", clientSettings.getClientParameters());
if(!response.has("data")) if(!response.has("data"))
{ {
return new HashMap<>(); return new HashMap<>();
@@ -120,7 +122,7 @@ public class TikTokApiService {
} }
return gifts; return gifts;
} catch (Exception e) { } 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 com.google.gson.JsonParser;
import io.github.jwdeveloper.tiktok.ClientSettings; import io.github.jwdeveloper.tiktok.ClientSettings;
import io.github.jwdeveloper.tiktok.Constants; 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 io.github.jwdeveloper.tiktok.messages.WebcastResponse;
import java.net.URI; import java.net.URI;
@@ -16,27 +16,23 @@ import java.util.Map;
import java.util.TreeMap; import java.util.TreeMap;
public class TikTokHttpApiClient { public class TikTokHttpApiClient {
private final ClientSettings clientSettings;
private final TikTokHttpRequestFactory requestFactory; private final TikTokHttpRequestFactory requestFactory;
private final TikTokCookieJar tikTokCookieJar; private final TikTokCookieJar tikTokCookieJar;
public TikTokHttpApiClient(TikTokCookieJar tikTokCookieJar, TikTokHttpRequestFactory requestFactory) {
public TikTokHttpApiClient(TikTokCookieJar tikTokCookieJar, ClientSettings clientSettings, TikTokHttpRequestFactory requestFactory) {
this.clientSettings = clientSettings;
this.requestFactory = requestFactory; this.requestFactory = requestFactory;
this.tikTokCookieJar = tikTokCookieJar; this.tikTokCookieJar = tikTokCookieJar;
} }
public String GetLivestreamPage(String userName) { public String GetLivestreamPage(String userName) {
var url = Constants.TIKTOK_URL_WEB + "@" + userName + "/live/"; var url = Constants.TIKTOK_URL_WEB + "@" + userName + "/live/";
var get = getRequest(url, null, false); var get = getRequest(url, null);
return get; return get;
} }
public JsonObject GetJObjectFromWebcastAPI(String path, Map<String, Object> parameters) { 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 json = JsonParser.parseString(get);
var jsonObject = json.getAsJsonObject(); var jsonObject = json.getAsJsonObject();
return jsonObject; return jsonObject;
@@ -49,12 +45,11 @@ public class TikTokHttpApiClient {
} }
catch (Exception e) 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) {
private String getRequest(String url, Map<String, Object> parameters, boolean signURL) {
if (parameters == null) { if (parameters == null) {
parameters = new HashMap<>(); parameters = new HashMap<>();
} }
@@ -86,7 +81,7 @@ public class TikTokHttpApiClient {
} }
catch (Exception e) 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); requestFactory.setAgent(userAgent);
return signedUrl; return signedUrl;
} catch (Exception e) { } 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.Constants;
import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveRequestException;
import lombok.SneakyThrows; import lombok.SneakyThrows;
import java.net.CookieManager; import java.net.CookieManager;
import java.net.ProxySelector;
import java.net.URI; import java.net.URI;
import java.net.URLEncoder; import java.net.URLEncoder;
import java.net.http.HttpClient; import java.net.http.HttpClient;
@@ -18,24 +18,16 @@ import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
public class TikTokHttpRequestFactory implements TikTokHttpRequest public class TikTokHttpRequestFactory implements TikTokHttpRequest {
{ private final CookieManager cookieManager;
private CookieManager cookieManager; private final Map<String, String> defaultHeaders;
private HttpClient client; private final TikTokCookieJar tikTokCookieJar;
private final HttpClient client;
private Duration timeout;
private ProxySelector webProxy;
private String query; private String query;
private Boolean sent;
private Map<String, String> defaultHeaders;
private TikTokCookieJar tikTokCookieJar;
public TikTokHttpRequestFactory(TikTokCookieJar tikTokCookieJar) { public TikTokHttpRequestFactory(TikTokCookieJar tikTokCookieJar) {
cookieManager = new CookieManager();
this.tikTokCookieJar = tikTokCookieJar; this.tikTokCookieJar = tikTokCookieJar;
this.cookieManager = new CookieManager();
defaultHeaders = Constants.DefaultRequestHeaders(); defaultHeaders = Constants.DefaultRequestHeaders();
client = HttpClient.newBuilder() client = HttpClient.newBuilder()
.cookieHandler(cookieManager) .cookieHandler(cookieManager)
@@ -43,8 +35,7 @@ public class TikTokHttpRequestFactory implements TikTokHttpRequest
.build(); .build();
} }
public WebSocket.Builder openSocket() public WebSocket.Builder openSocket() {
{
return client.newWebSocketBuilder(); return client.newWebSocketBuilder();
} }
@@ -52,26 +43,21 @@ public class TikTokHttpRequestFactory implements TikTokHttpRequest
public String Get(String url) { public String Get(String url) {
var uri = URI.create(url); var uri = URI.create(url);
var request = HttpRequest.newBuilder().GET(); var request = HttpRequest.newBuilder().GET();
for(var header : defaultHeaders.entrySet())
{
//request.setHeader(header.getKey(),header.getValue());
}
if (query != null) { if (query != null) {
var baseUri = uri.toString(); var baseUri = uri.toString();
var requestUri = URI.create(baseUri + "?" + query); var requestUri = URI.create(baseUri + "?" + query);
request.uri(requestUri); request.uri(requestUri);
} }
return GetContent(request.build()); return GetContent(request.build());
} }
@SneakyThrows @SneakyThrows
public String Post(String url, HttpRequest.BodyPublisher data) { public String Post(String url, HttpRequest.BodyPublisher data) {
var uri = URI.create(url); var uri = URI.create(url);
var request = HttpRequest.newBuilder().POST(data); var request = HttpRequest.newBuilder().POST(data);
for(var header : defaultHeaders.entrySet()) for (var header : defaultHeaders.entrySet()) {
{ request.setHeader(header.getKey(), header.getValue());
request.setHeader(header.getKey(),header.getValue());
} }
if (query != null) { if (query != null) {
var baseUri = uri.toString(); var baseUri = uri.toString();
@@ -81,14 +67,12 @@ public class TikTokHttpRequestFactory implements TikTokHttpRequest
return GetContent(request.build()); return GetContent(request.build());
} }
public TikTokHttpRequest setHeader(String key, String value) public TikTokHttpRequest setHeader(String key, String value) {
{ defaultHeaders.put(key, value);
defaultHeaders.put(key,value);
return this; return this;
} }
public TikTokHttpRequest setAgent( String value) public TikTokHttpRequest setAgent(String value) {
{
defaultHeaders.put("User-Agent", value); defaultHeaders.put("User-Agent", value);
return this; return this;
} }
@@ -111,26 +95,18 @@ public class TikTokHttpRequestFactory implements TikTokHttpRequest
} }
private String GetContent(HttpRequest request) throws Exception { private String GetContent(HttpRequest request) throws Exception {
var response = client.send(request, HttpResponse.BodyHandlers.ofString()); var response = client.send(request, HttpResponse.BodyHandlers.ofString());
sent = true; if (response.statusCode() == 404) {
if (response.statusCode() == 404) throw new TikTokLiveRequestException("Request responded with 404 NOT_FOUND");
{
throw new RuntimeException("Request responded with 404 NOT_FOUND");
} }
if(response.statusCode() != 200) if (response.statusCode() != 200) {
{ throw new TikTokLiveRequestException("Request was unsuccessful " + response.statusCode());
throw new RuntimeException("Request was unsuccessful "+response.statusCode());
} }
var cookies = response.headers().allValues("Set-Cookie"); var cookies = response.headers().allValues("Set-Cookie");
for(var cookie : cookies) for (var cookie : cookies) {
{
var split = cookie.split(";")[0].split("="); var split = cookie.split(";")[0].split("=");
var uri = request.uri(); var uri = request.uri();
@@ -139,9 +115,9 @@ public class TikTokHttpRequestFactory implements TikTokHttpRequest
var value = split[1]; var value = split[1];
tikTokCookieJar.set(key, value); tikTokCookieJar.set(key, value);
var map = new HashMap<String,List<String>>(); var map = new HashMap<String, List<String>>();
map.put(key,List.of(value)); map.put(key, List.of(value));
cookieManager.put(uri,map); cookieManager.put(uri, map);
} }
return response.body(); return response.body();

View File

@@ -13,16 +13,13 @@ import io.github.jwdeveloper.tiktok.messages.WebcastResponse;
import java.net.URI; import java.net.URI;
import java.net.http.WebSocket; import java.net.http.WebSocket;
import java.nio.ByteBuffer;
import java.time.Duration; import java.time.Duration;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap; import java.util.TreeMap;
import java.util.logging.Logger; import java.util.logging.Logger;
public class TikTokWebsocketClient { public class TikTokWebSocketClient {
private final Logger logger; private final Logger logger;
private final Map<String, Object> clientParams;
private final ClientSettings clientSettings; private final ClientSettings clientSettings;
private final TikTokCookieJar tikTokCookieJar; private final TikTokCookieJar tikTokCookieJar;
private final TikTokHttpRequestFactory factory; private final TikTokHttpRequestFactory factory;
@@ -33,15 +30,13 @@ public class TikTokWebsocketClient {
private boolean isConnected; private boolean isConnected;
public TikTokWebsocketClient(Logger logger, public TikTokWebSocketClient(Logger logger,
TikTokCookieJar tikTokCookieJar, TikTokCookieJar tikTokCookieJar,
Map<String, Object> clientParams,
TikTokHttpRequestFactory factory, TikTokHttpRequestFactory factory,
ClientSettings clientSettings, ClientSettings clientSettings,
WebResponseHandler webResponseHandler, WebResponseHandler webResponseHandler,
TikTokEventHandler tikTokEventHandler) { TikTokEventHandler tikTokEventHandler) {
this.logger = logger; this.logger = logger;
this.clientParams = clientParams;
this.tikTokCookieJar = tikTokCookieJar; this.tikTokCookieJar = tikTokCookieJar;
this.clientSettings = clientSettings; this.clientSettings = clientSettings;
this.factory = factory; this.factory = factory;
@@ -78,7 +73,7 @@ public class TikTokWebsocketClient {
var headers = Constants.DefaultRequestHeaders(); var headers = Constants.DefaultRequestHeaders();
var clone = new TreeMap<>(clientParams); var clone = new TreeMap<>(clientSettings.getClientParameters());
clone.putAll(headers); clone.putAll(headers);
clone.put(name, value); clone.put(name, value);
var url = webcastResponse.getSocketUrl(); 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.common.TikTokBaseTest;
import io.github.jwdeveloper.tiktok.messages.*;
import org.junit.Test;
public class ParseMessagesTests extends TikTokBaseTest
{
@Test
public void ShouldParseMessageWebcastLikeMessage() throws InvalidProtocolBufferException {
var bytes = getFileBytesUtf("LikeMessage.bin");
var message = WebcastLikeMessage.parseFrom(bytes);
}
@Test
public void ShouldParseMessageWebcastGiftMessage() 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);
}
@Test
public void ShouldParseMessageWebcastImDeleteMessage() throws InvalidProtocolBufferException {
var bytes = getFileBytesUtf("MessageWebcastImDeleteMessage.bin");
var message = WebcastImDeleteMessage.parseFrom(bytes);
}
@Test
public void ShouldParseMessageWebcastSocialMessage() throws InvalidProtocolBufferException {
var bytes = getFileBytesUtf("MessageWebcastSocialMessage.bin");
var message = WebcastSocialMessage.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,32 @@
package io.github.jwdeveloper.tiktok;
import com.google.protobuf.InvalidProtocolBufferException;
import io.github.jwdeveloper.tiktok.common.TikTokBaseTest;
import io.github.jwdeveloper.tiktok.events.messages.*;
import io.github.jwdeveloper.tiktok.handlers.TikTokEventHandler;
import io.github.jwdeveloper.tiktok.handlers.WebResponseHandler;
import io.github.jwdeveloper.tiktok.messages.WebcastResponse;
import io.github.jwdeveloper.tiktok.messages.WebcastSocialMessage;
import io.github.jwdeveloper.tiktok.models.SocialTypes;
import org.junit.Before;
import org.junit.Test;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static org.mockito.Mockito.mock;
public class WebResponseHandlerTests extends TikTokBaseTest
{
public static WebResponseHandler sut;
@Before
public void before()
{
var mockEventHandler = mock(TikTokEventHandler.class);
var mockGiftManager = mock(TikTokGiftManager.class);
sut = new WebResponseHandler(mockEventHandler, mockGiftManager);
}
}

View File

@@ -0,0 +1,34 @@
package io.github.jwdeveloper.tiktok.common;
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

@@ -0,0 +1 @@
CjUKFldlYmNhc3RJbURlbGV0ZU1lc3NhZ2UQhZab+vyKvvJkGJKWhYz+o7DxZCC0sajzoTEwARoJhojH2ojIjaBk

View File

@@ -0,0 +1 @@
CskHMAFChgcaDgoJI2ZmZmZmZmZmIJADIp8GCAsSDgoJI2ZmZmZmZmZmIJADqgGJBgqGBgiFiNKIpZnf0WIaCm1yIEEuTC5GLkFK/wQKxgFodHRwczovL3AxNi1zaWduLXVzZWFzdDJhLnRpa3Rva2Nkbi5jb20vdG9zLXVzZWFzdDJhLWF2dC0wMDY4LWV1dHRwLzkxODE3OWQ4MzQ0YWZiYjk3OTAzYjYyMGQwOTg1ZGEzfnRwbHYtdGlrdG9rLXNocmluazo3Mjo3Mi53ZWJwP3gtZXhwaXJlcz0xNjkyOTAwMDAwJngtc2lnbmF0dXJlPUE0RmtOWDMlMkIxNiUyRjlxeENvR1JReEczNFRnRUUlM0QKtAFodHRwczovL3AxNi1zaWduLXVzZWFzdDJhLnRpa3Rva2Nkbi5jb20vdG9zLXVzZWFzdDJhLWF2dC0wMDY4LWV1dHRwLzkxODE3OWQ4MzQ0YWZiYjk3OTAzYjYyMGQwOTg1ZGEzfmM1XzEwMHgxMDAud2VicD94LWV4cGlyZXM9MTY5MjkwMDAwMCZ4LXNpZ25hdHVyZT1EOHlYQUhNVGxGeUR5N3dqT3BXRllrUlBBWnclM0QKtgFodHRwczovL3AxNi1zaWduLXVzZWFzdDJhLnRpa3Rva2Nkbi5jb20vdG9zLXVzZWFzdDJhLWF2dC0wMDY4LWV1dHRwLzkxODE3OWQ4MzQ0YWZiYjk3OTAzYjYyMGQwOTg1ZGEzfmM1XzEwMHgxMDAuanBlZz94LWV4cGlyZXM9MTY5MjkwMDAwMCZ4LXNpZ25hdHVyZT1IYkIwNk00N2Y0JTJGT29jUWxla0gwREdDdkY3MCUzRBJEMTAweDEwMC90b3MtdXNlYXN0MmEtYXZ0LTAwNjgtZXV0dHAvOTE4MTc5ZDgzNDRhZmJiOTc5MDNiNjIwZDA5ODVkYTOyAQgI9h8Qmw0YAboBAIICALICCy56YXBpc3l3YW5l8gJMTVM0d0xqQUJBQUFBYXdVMzNGbnBIYllkMHdra1djeC1DTnBzeDdXT0lqOXdtOTBwQ2tRUmZPekJuZVdZczdXT0plSm5GVU5kdFh0MwoecG1fbXRfZ3VpZGFuY2Vfdmlld2VyXzEwX3NoYXJlEjJ7MDp1c2VyfSBzaGFyZWQgdGhlIExJVkUgd2l0aCBtb3JlIHRoYW4gMTAgZnJpZW5kc1ACsAEFwAECChRXZWJjYXN0U29jaWFsTWVzc2FnZRCglsC+2OG+8mQYoJaZxvrevPJkIOTf0vOhMUgBuAECEoYGSv8ECsYBaHR0cHM6Ly9wMTYtc2lnbi11c2Vhc3QyYS50aWt0b2tjZG4uY29tL3Rvcy11c2Vhc3QyYS1hdnQtMDA2OC1ldXR0cC85MTgxNzlkODM0NGFmYmI5NzkwM2I2MjBkMDk4NWRhM350cGx2LXRpa3Rvay1zaHJpbms6NzI6NzIud2VicD94LWV4cGlyZXM9MTY5MjkwMDAwMCZ4LXNpZ25hdHVyZT1BNEZrTlgzJTJCMTYlMkY5cXhDb0dSUXhHMzRUZ0VFJTNECrQBaHR0cHM6Ly9wMTYtc2lnbi11c2Vhc3QyYS50aWt0b2tjZG4uY29tL3Rvcy11c2Vhc3QyYS1hdnQtMDA2OC1ldXR0cC85MTgxNzlkODM0NGFmYmI5NzkwM2I2MjBkMDk4NWRhM35jNV8xMDB4MTAwLndlYnA/eC1leHBpcmVzPTE2OTI5MDAwMDAmeC1zaWduYXR1cmU9RDh5WEFITVRsRnlEeTd3ak9wV0ZZa1JQQVp3JTNECrYBaHR0cHM6Ly9wMTYtc2lnbi11c2Vhc3QyYS50aWt0b2tjZG4uY29tL3Rvcy11c2Vhc3QyYS1hdnQtMDA2OC1ldXR0cC85MTgxNzlkODM0NGFmYmI5NzkwM2I2MjBkMDk4NWRhM35jNV8xMDB4MTAwLmpwZWc/eC1leHBpcmVzPTE2OTI5MDAwMDAmeC1zaWduYXR1cmU9SGJCMDZNNDdmNCUyRk9vY1FsZWtIMERHQ3ZGNzAlM0QSRDEwMHgxMDAvdG9zLXVzZWFzdDJhLWF2dC0wMDY4LWV1dHRwLzkxODE3OWQ4MzQ0YWZiYjk3OTAzYjYyMGQwOTg1ZGEzsgEIEJsNGAEI9h+6AQCCAgCyAgsuemFwaXN5d2FuZfICTE1TNHdMakFCQUFBQWF3VTMzRm5wSGJZZDB3a2tXY3gtQ05wc3g3V09Jajl3bTkwcENrUVJmT3pCbmVXWXM3V09KZUpuRlVOZHRYdDMIhYjSiKWZ39FiGgptciBBLkwuRi5BGAEgAyoCLTFAGQ==

View File

@@ -1,32 +0,0 @@
 ŔĆł»„ÖF¸E *
compress_typenone2pb:msgBš
Ű
WebcastLikeMessageş

WebcastLikeMessageˇ¤ŚöÍííd żÚřęëíd0
pm_mt_msg_viewer{0:user} liked the LIVE
#ffffffff "
Ş}
{ ˆ•ÉÔëdhulajnoga czek˛hulajnoga.czek5ňLMS4wLjABAAAAx4-lIrRjH0pMT0D3laROVsnU-4u6P1tN4td82AQTCHjKZ-CHaF_DluNSFQQp1s4DHP°¸Ŕ ĆĐŇź1†q*Ü ˆ•ÉÔëdhulajnoga czek˛ş ˛hulajnoga.czek5J˙
Čhttps://p16-sign-useast2a.tiktokcdn.com/tos-useast2a-avt-0068-euttp/26aa68e29831ff0c9d4fb37875efffdd~tplv-tiktok-shrink:72:72.webp?x-expires=1692291600&x-signature=Z2ZM2T%2FckIxKSj%2BJY%2BONoypyMwo%3D
´https://p16-sign-useast2a.tiktokcdn.com/tos-useast2a-avt-0068-euttp/26aa68e29831ff0c9d4fb37875efffdd~c5_100x100.webp?x-expires=1692291600&x-signature=gJgrVHIZWnVCif4Z6gXuhnl1pn8%3D
´https://p16-sign-useast2a.tiktokcdn.com/tos-useast2a-avt-0068-euttp/26aa68e29831ff0c9d4fb37875efffdd~c5_100x100.jpeg?x-expires=1692291600&x-signature=ITqTLj6v7UVl12HeeGa6a6FYNpc%3DD100x100/tos-useast2a-avt-0068-euttp/26aa68e29831ff0c9d4fb37875efffddŞ0 ňLMS4wLjABAAAAx4-lIrRjH0pMT0D3laROVsnU-4u6P1tN4td82AQTCHjKZ-CHaF_DluNSFQQp1s4DîR„sslocal://webcast_webview_popup?gravity=bottom&show_mask=1&url=https%3A%2F%2Flf16-web.tiktokcdn.com%2Fobj%2Fies-hotsoon-draft-sg%2Ftiktok-live-faq%2Ftiktok_live_revenue_new_gifter_details.html&web_bg_color=FFFFFF&height=60%25&mask_bg_color=000000b3&use_spark=1b:"10000037267585271263611681*0
27154120369731914523 pm_mt_live_ng_im
New gifter( Ü sslocal://webcast_lynxview_popup?use_spark=1&url=https%3A%2F%2Flf16-gecko-source.tiktokcdn.com%2Fobj%2Fbyte-gurd-source-sg%2Ftiktok%2Ffe%2Flive%2Ftiktok_live_revenue_user_level_main%2Fsrc%2Fpages%2Fprivilege%2Fpanel%2Ftemplate.js&hide_status_bar=0&hide_nav_bar=1&container_bg_color=00000000&height=90%25&bdhm_bid=tiktok_live_revenue_user_level_main&use_forest=1XbN
271383811767874578280".mock_fix_width_transparent_7138381176787457828*Ő+webcast-va/grade_badge_icon_lite_lv1_v1.png:ésslocal://webcast_lynxview_popup?use_spark=1&url=https%3A%2F%2Flf16-gecko-source.tiktokcdn.com%2Fobj%2Fbyte-gurd-source-sg%2Ftiktok%2Ffe%2Flive%2Ftiktok_live_revenue_user_level_main%2Fsrc%2Fpages%2Fprivilege%2Fpanel%2Ftemplate.js&hide_status_bar=0&hide_nav_bar=1&container_bg_color=00000000&height=90%25&bdhm_bid=tiktok_live_revenue_user_level_main&use_forest=1
\https://p16-webcast.tiktokcdn.com/webcast-va/grade_badge_icon_lite_lv1_v1.png~tplv-obj.image
\https://p19-webcast.tiktokcdn.com/webcast-va/grade_badge_icon_lite_lv1_v1.png~tplv-obj.image"2* b
 #99789EE7x2 : " Z
 #99789EE7€÷( R„sslocal://webcast_webview_popup?gravity=bottom&show_mask=1&url=https%3A%2F%2Flf16-web.tiktokcdn.com%2Fobj%2Fies-hotsoon-draft-sg%2Ftiktok-live-faq%2Ftiktok_live_revenue_new_gifter_details.html&web_bg_color=FFFFFF&height=60%25&mask_bg_color=000000b3&use_spark=1Xb:
271541203697319145231"10000037267585271263611681*¦x ˆŰ 0:„sslocal://webcast_webview_popup?gravity=bottom&show_mask=1&url=https%3A%2F%2Flf16-web.tiktokcdn.com%2Fobj%2Fies-hotsoon-draft-sg%2Ftiktok-live-faq%2Ftiktok_live_revenue_new_gifter_details.html&web_bg_color=FFFFFF&height=60%25&mask_bg_color=000000b3&use_spark=1
Shttps://p16-webcast.tiktokcdn.com/webcast-va/new_gifter_badge_v3.png~tplv-obj.image
Shttps://p19-webcast.tiktokcdn.com/webcast-va/new_gifter_badge_v3.png~tplv-obj.image"webcast-va/new_gifter_badge_v3.png
pm_mt_live_ng_im
New gifterZ
 #803F3F3Fb
 #803F3F3FˆË”ʍÁcŔ
pm_mt_msg_viewer{0:user} liked the LIVE
#ffffffff "
Ş}
{˛hulajnoga.czek5ňLMS4wLjABAAAAx4-lIrRjH0pMT0D3laROVsnU-4u6P1tN4td82AQTCHjKZ-CHaF_DluNSFQQp1s4D ˆ•ÉÔëdhulajnoga czekHˇ¤ŚöÍííd)1692120689751_7267603020139989890_1_1_0_0č ×ŘŇź1*-@H

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 # 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. 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 ## Getting started
1. Install the package via Maven (dependecies will be simplify in future) 1. Install the package via Maven
```xml ```xml
<repositories> <repositories>
@@ -32,7 +35,8 @@ Do you prefer other programming languages?
``` ```
```xml ```xml
<dependency> <dependencies>
<dependency>
<groupId>com.google.protobuf</groupId> <groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId> <artifactId>protobuf-java</artifactId>
<version>3.24.1</version> <version>3.24.1</version>
@@ -45,16 +49,11 @@ Do you prefer other programming languages?
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.github.jwdeveloper.TikTok-Live-Java</groupId> <groupId>com.github.jwdeveloper</groupId>
<artifactId>API</artifactId> <artifactId>TikTok-Live-Java</artifactId>
<version>0.0.4-Release</version> <version>0.0.10-Release</version>
</dependency>
<dependency>
<groupId>com.github.jwdeveloper.TikTok-Live-Java</groupId>
<artifactId>Client</artifactId>
<version>0.0.4-Release</version>
</dependency> </dependency>
</dependencies>
``` ```
2. Create your first chat connection 2. Create your first chat connection

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.0.0</version> <version>0.0.10-Release</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -6,7 +6,7 @@ import java.io.IOException;
public class Main { public class Main {
public static String TEST_USER_SUBJECT = "stiflerhub"; public static String TEST_USER_SUBJECT = "mr_cios";
public static void main(String[] args) throws IOException { public static void main(String[] args) throws IOException {
var client = TikTokLive.newClient(TEST_USER_SUBJECT) var client = TikTokLive.newClient(TEST_USER_SUBJECT)
@@ -23,7 +23,7 @@ public class Main {
.onEmote(Main::onEmote) .onEmote(Main::onEmote)
.onError(tikTokErrorEvent -> .onError(tikTokErrorEvent ->
{ {
// tikTokErrorEvent.getException().printStackTrace(); // tikTokErrorEvent.getException().printStackTrace();
}) })
.buildAndRun(); .buildAndRun();
@@ -49,8 +49,7 @@ public class Main {
} }
private static void onComment(TikTokCommentEvent e) { 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) { private static void onFollow(TikTokFollowEvent e) {
@@ -83,6 +82,6 @@ public class Main {
for (var message : messages) { for (var message : messages) {
sb.append(message).append(" "); sb.append(message).append(" ");
} }
System.out.println(sb.toString()); System.out.println(sb);
} }
} }

View File

@@ -1,12 +1,14 @@
package io.github.jwdeveloper.tiktok; package io.github.jwdeveloper.tiktok;
import java.io.IOException;
public class SimpleExample { public class SimpleExample {
public static void main(String[] args) { public static void main(String[] args) throws IOException {
// Username of someone who is currently live // Username of someone who is currently live
var tiktokUsername = "officialgeilegisela"; var tiktokUsername = "mr_cios";
TikTokLive.newClient(tiktokUsername) TikTokLive.newClient(tiktokUsername)
.clientSettings(settings -> .configure(settings ->
{ {
}) })
.onConnected(event -> .onConnected(event ->
@@ -19,12 +21,13 @@ public class SimpleExample {
}) })
.onComment(event -> .onComment(event ->
{ {
System.out.println(event.getUser().getUniqueId() + ": " + event.getText()); System.out.println(event.getUser().getUniqueId() + ": " + event.getText());
}) })
.onError(event -> .onError(event ->
{ {
event.getException().printStackTrace(); event.getException().printStackTrace();
}) })
.buildAndRun(); .buildAndRun();
System.in.read();
} }
} }

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.0.0</version> <version>0.0.10-Release</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

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.0.0</version> <version>0.0.10-Release</version>
<modules> <modules>
<module>API</module> <module>API</module>
<module>Client</module> <module>Client</module>