mirror of
https://github.com/jwdeveloper/TikTokLiveJava.git
synced 2026-02-27 16:59:39 -05:00
Compare commits
21 Commits
0.0.5-Rele
...
0.0.10-Rel
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6254443755 | ||
|
|
c001eacbce | ||
|
|
1bbb704d14 | ||
|
|
8c3a5c6627 | ||
|
|
470b154c5e | ||
|
|
2391b12598 | ||
|
|
cb68050e24 | ||
|
|
a9e347b8da | ||
|
|
73823c82ea | ||
|
|
e0542d39af | ||
|
|
d33dab0a98 | ||
|
|
32cb1e0d8f | ||
|
|
3210707bce | ||
|
|
e7f9d6e9d5 | ||
|
|
03001d607d | ||
|
|
cbabad0888 | ||
|
|
09c531e9f4 | ||
|
|
997c8d399e | ||
|
|
668f28e357 | ||
|
|
b332c2f5d8 | ||
|
|
5be113cbc8 |
7
.github/workflows/maven-publish.yml
vendored
7
.github/workflows/maven-publish.yml
vendored
@@ -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
|
||||||
|
|||||||
@@ -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.8-Release</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<artifactId>API</artifactId>
|
<artifactId>API</artifactId>
|
||||||
|
|||||||
@@ -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,49 @@ public class ClientSettings {
|
|||||||
/// ISO-Language for Client
|
/// ISO-Language for Client
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
||||||
private String ClientLanguage;
|
private String clientLanguage;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Size for Buffer for Socket-Connection
|
/// Size for Buffer for Socket-Connection
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
||||||
private int SocketBufferSize;
|
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;
|
||||||
|
|
||||||
|
private String hostName;
|
||||||
|
|
||||||
|
private Map<String, Object> clientParameters;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -39,7 +39,6 @@ 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");
|
||||||
@@ -51,6 +50,7 @@ public class Constants {
|
|||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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.8-Release</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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) {
|
||||||
@@ -75,16 +53,13 @@ public class TikTokLiveClientBuilder implements TikTokEventBuilder<TikTokLiveCli
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (userName == null || userName.equals("")) {
|
if (clientSettings.getHostName() == null || clientSettings.getHostName() .equals("")) {
|
||||||
throw new RuntimeException("UserName can not be null");
|
throw new RuntimeException("HostName can not be null");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (clientParameters == null) {
|
var params = clientSettings.getClientParameters();
|
||||||
clientParameters = Constants.DefaultClientParams();
|
params.put("app_language", clientSettings.getClientLanguage());
|
||||||
}
|
params.put("webcast_language", clientSettings.getClientLanguage());
|
||||||
|
|
||||||
clientParameters.put("app_language", clientSettings.getClientLanguage());
|
|
||||||
clientParameters.put("webcast_language", clientSettings.getClientLanguage());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public LiveClient build() {
|
public LiveClient build() {
|
||||||
@@ -92,18 +67,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,
|
||||||
|
|||||||
@@ -69,9 +69,10 @@ 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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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();
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
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 org.junit.Test;
|
||||||
|
|
||||||
|
public class ParseMessagesTests extends TikTokBaseTest
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
@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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -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());
|
|
||||||
}*/
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
1
Client/src/test/resources/LikeMessage.bin
Normal file
1
Client/src/test/resources/LikeMessage.bin
Normal file
File diff suppressed because one or more lines are too long
1
Client/src/test/resources/MessageWebcastChatMessage.bin
Normal file
1
Client/src/test/resources/MessageWebcastChatMessage.bin
Normal file
File diff suppressed because one or more lines are too long
1
Client/src/test/resources/MessageWebcastGiftMessage.bin
Normal file
1
Client/src/test/resources/MessageWebcastGiftMessage.bin
Normal file
File diff suppressed because one or more lines are too long
@@ -1,32 +0,0 @@
|
|||||||
ŔĆł»›„ÖF¸E *
|
|
||||||
|
|
||||||
compress_typenone2pb:msgBš
|
|
||||||
Ű
|
|
||||||
WebcastLikeMessageş
|
|
||||||
|
|
||||||
WebcastLikeMessageˇ–¤ŚöÍííd –żÚřęëíd0BŔ
|
|
||||||
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
|
|
||||||
271541203697319145231Ş pm_mt_live_ng_im
|
|
||||||
New gifter( ‚Ü Ré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*2ş’Ő+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*0ş¦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
|
|
||||||
#803F3F3FBÍ†Ë”Ź¨Á‚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
|
|
||||||
21
README.md
21
README.md
@@ -1,3 +1,6 @@
|
|||||||
|
[](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.9-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
|
||||||
|
|||||||
@@ -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.8-Release</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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 = "szwagierkaqueen";
|
||||||
|
|
||||||
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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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.8-Release</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
|||||||
2
pom.xml
2
pom.xml
@@ -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.8-Release</version>
|
||||||
<modules>
|
<modules>
|
||||||
<module>API</module>
|
<module>API</module>
|
||||||
<module>Client</module>
|
<module>Client</module>
|
||||||
|
|||||||
Reference in New Issue
Block a user