mirror of
https://github.com/jwdeveloper/TikTokLiveJava.git
synced 2026-02-27 08:49:40 -05:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
@@ -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.5-Release</version>
|
<version>1.0.6-Release</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<artifactId>API</artifactId>
|
<artifactId>API</artifactId>
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package io.github.jwdeveloper.tiktok.data.dto;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class TikTokUserInfo
|
||||||
|
{
|
||||||
|
UserStatus userStatus;
|
||||||
|
|
||||||
|
String roomId;
|
||||||
|
|
||||||
|
public enum UserStatus
|
||||||
|
{
|
||||||
|
NotFound,
|
||||||
|
Offline,
|
||||||
|
LivePaused,
|
||||||
|
Live
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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.5-Release</version>
|
<version>1.0.6-Release</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
|||||||
@@ -93,8 +93,7 @@ public class TikTokLiveClient implements LiveClient {
|
|||||||
public void connect() {
|
public void connect() {
|
||||||
try {
|
try {
|
||||||
tryConnect();
|
tryConnect();
|
||||||
} catch (TikTokLiveException e)
|
} catch (TikTokLiveException e) {
|
||||||
{
|
|
||||||
setState(ConnectionState.DISCONNECTED);
|
setState(ConnectionState.DISCONNECTED);
|
||||||
tikTokEventHandler.publish(this, new TikTokErrorEvent(e));
|
tikTokEventHandler.publish(this, new TikTokErrorEvent(e));
|
||||||
tikTokEventHandler.publish(this, new TikTokDisconnectedEvent());
|
tikTokEventHandler.publish(this, new TikTokDisconnectedEvent());
|
||||||
@@ -109,6 +108,10 @@ public class TikTokLiveClient implements LiveClient {
|
|||||||
this.connect();
|
this.connect();
|
||||||
}
|
}
|
||||||
throw e;
|
throw e;
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.info("Unhandled exception report this bug to github https://github.com/jwdeveloper/TikTokLiveJava/issues");
|
||||||
|
this.disconnect();
|
||||||
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -156,7 +159,7 @@ public class TikTokLiveClient implements LiveClient {
|
|||||||
var clientData = apiService.fetchClientData();
|
var clientData = apiService.fetchClientData();
|
||||||
webSocketClient.start(clientData, this);
|
webSocketClient.start(clientData, this);
|
||||||
setState(ConnectionState.CONNECTED);
|
setState(ConnectionState.CONNECTED);
|
||||||
tikTokEventHandler.publish(this,new TikTokRoomInfoEvent(liveRoomInfo));
|
tikTokEventHandler.publish(this, new TikTokRoomInfoEvent(liveRoomInfo));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,7 @@
|
|||||||
package io.github.jwdeveloper.tiktok.http;
|
package io.github.jwdeveloper.tiktok.http;
|
||||||
|
|
||||||
import io.github.jwdeveloper.tiktok.ClientSettings;
|
import io.github.jwdeveloper.tiktok.ClientSettings;
|
||||||
import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveException;
|
import io.github.jwdeveloper.tiktok.data.dto.TikTokUserInfo;
|
||||||
import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveOfflineHostException;
|
import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveOfflineHostException;
|
||||||
import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveRequestException;
|
import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveRequestException;
|
||||||
import io.github.jwdeveloper.tiktok.live.LiveRoomMeta;
|
import io.github.jwdeveloper.tiktok.live.LiveRoomMeta;
|
||||||
@@ -57,62 +57,43 @@ public class TikTokApiService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public String fetchRoomId(String userName) {
|
public String fetchRoomId(String userName) {
|
||||||
var roomId = fetchRoomIdFromTiktokApi(userName);
|
var userInfo = fetchUserInfoFromTikTokApi(userName);
|
||||||
clientSettings.getClientParameters().put("room_id", roomId);
|
clientSettings.getClientParameters().put("room_id", userInfo.getRoomId());
|
||||||
logger.info("RoomID -> " + roomId);
|
logger.info("RoomID -> " + userInfo.getRoomId());
|
||||||
return roomId;
|
return userInfo.getRoomId();
|
||||||
}
|
}
|
||||||
|
|
||||||
private String fetchRoomIdFromTikTokPage(String userName)
|
public TikTokUserInfo fetchUserInfoFromTikTokApi(String userName) {
|
||||||
{
|
|
||||||
/* var roomId = RequestChain.<String>create()
|
|
||||||
.then(() -> fetchRoomIdFromTikTokPage(userName))
|
|
||||||
.then(() -> fetchRoomIdFromTiktokApi(userName))
|
|
||||||
.run();*/
|
|
||||||
logger.info("Fetching room ID");
|
|
||||||
String html;
|
|
||||||
try {
|
|
||||||
html = tiktokHttpClient.getLivestreamPage(userName);
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new TikTokLiveRequestException("Failed to fetch room id from WebCast, see stacktrace for more info.", e);
|
|
||||||
}
|
|
||||||
|
|
||||||
var firstPattern = Pattern.compile("room_id=([0-9]*)");
|
|
||||||
var firstMatcher = firstPattern.matcher(html);
|
|
||||||
var id = "";
|
|
||||||
|
|
||||||
if (firstMatcher.find()) {
|
|
||||||
id = firstMatcher.group(1);
|
|
||||||
} else {
|
|
||||||
var secondPattern = Pattern.compile("\"roomId\":\"([0-9]*)\"");
|
|
||||||
var secondMatcher = secondPattern.matcher(html);
|
|
||||||
|
|
||||||
if (secondMatcher.find()) {
|
|
||||||
id = secondMatcher.group(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (id.isEmpty()) {
|
|
||||||
throw new TikTokLiveOfflineHostException("Unable to fetch room ID, live host could be offline or name is misspelled");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
private String fetchRoomIdFromTiktokApi(String userName) {
|
|
||||||
|
|
||||||
var params = new HashMap<>(clientSettings.getClientParameters());
|
var params = new HashMap<>(clientSettings.getClientParameters());
|
||||||
params.put("uniqueId", userName);
|
params.put("uniqueId", userName);
|
||||||
params.put("sourceType", 54);
|
params.put("sourceType", 54);
|
||||||
var roomData = tiktokHttpClient.getJsonFromTikTokApi("api-live/user/room/", params);
|
var roomData = tiktokHttpClient.getJsonFromTikTokApi("api-live/user/room/", params);
|
||||||
|
|
||||||
|
var message = roomData.get("message").getAsString();
|
||||||
|
|
||||||
|
if (message.equals("params_error")) {
|
||||||
|
throw new TikTokLiveRequestException("fetchRoomIdFromTiktokApi -> Unable to fetch roomID, contact with developer");
|
||||||
|
}
|
||||||
|
if (message.equals("user_not_found")) {
|
||||||
|
return new TikTokUserInfo(TikTokUserInfo.UserStatus.NotFound, "");
|
||||||
|
}
|
||||||
|
//live -> status 2
|
||||||
|
//live paused -> 3
|
||||||
|
//not live -> status 4
|
||||||
var data = roomData.getAsJsonObject("data");
|
var data = roomData.getAsJsonObject("data");
|
||||||
var user =data.getAsJsonObject("user");
|
var user = data.getAsJsonObject("user");
|
||||||
var roomId = user.get("roomId").getAsString();
|
var roomId = user.get("roomId").getAsString();
|
||||||
|
var status = user.get("status").getAsInt();
|
||||||
|
|
||||||
|
var statusEnum = switch (status) {
|
||||||
|
case 2 -> TikTokUserInfo.UserStatus.Live;
|
||||||
|
case 3 -> TikTokUserInfo.UserStatus.LivePaused;
|
||||||
|
case 4 -> TikTokUserInfo.UserStatus.Offline;
|
||||||
|
default -> TikTokUserInfo.UserStatus.NotFound;
|
||||||
|
};
|
||||||
|
|
||||||
return roomId;
|
return new TikTokUserInfo(statusEnum, roomId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,15 @@
|
|||||||
package io.github.jwdeveloper.tiktok.http;
|
package io.github.jwdeveloper.tiktok.http;
|
||||||
|
|
||||||
|
import io.github.jwdeveloper.tiktok.ClientSettings;
|
||||||
|
import io.github.jwdeveloper.tiktok.Constants;
|
||||||
|
import io.github.jwdeveloper.tiktok.data.dto.TikTokUserInfo;
|
||||||
import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveRequestException;
|
import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveRequestException;
|
||||||
|
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
import java.util.logging.Logger;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
public class TikTokDataChecker
|
public class TikTokDataChecker {
|
||||||
{
|
|
||||||
|
|
||||||
public CompletableFuture<Boolean> isOnlineAsync(String hostName) {
|
public CompletableFuture<Boolean> isOnlineAsync(String hostName) {
|
||||||
return CompletableFuture.supplyAsync(() -> isOnline(hostName));
|
return CompletableFuture.supplyAsync(() -> isOnline(hostName));
|
||||||
@@ -17,63 +20,24 @@ public class TikTokDataChecker
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean isOnline(String hostName) {
|
public boolean isOnline(String hostName) {
|
||||||
var factory = new TikTokHttpRequestFactory(new TikTokCookieJar());
|
var data = getApiService().fetchUserInfoFromTikTokApi(hostName);
|
||||||
var url = getLiveUrl(hostName);
|
return data.getUserStatus() == TikTokUserInfo.UserStatus.Live ||
|
||||||
try {
|
data.getUserStatus() == TikTokUserInfo.UserStatus.LivePaused;
|
||||||
var response = factory.get(url);
|
|
||||||
var titleContent = extractTitleContent(response);
|
|
||||||
return isTitleLiveOnline(titleContent);
|
|
||||||
} catch (Exception e)
|
|
||||||
{
|
|
||||||
throw new TikTokLiveRequestException("Unable to make check live online request",e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isHostNameValid(String hostName) {
|
public boolean isHostNameValid(String hostName) {
|
||||||
var factory = new TikTokHttpRequestFactory(new TikTokCookieJar());
|
var data = getApiService().fetchUserInfoFromTikTokApi(hostName);
|
||||||
var url = getProfileUrl(hostName);
|
return data.getUserStatus() != TikTokUserInfo.UserStatus.NotFound;
|
||||||
try {
|
|
||||||
var response = factory.get(url);
|
|
||||||
var titleContent = extractTitleContent(response);
|
|
||||||
return isTitleHostNameValid(titleContent, hostName);
|
|
||||||
} catch (Exception e)
|
|
||||||
{
|
|
||||||
throw new TikTokLiveRequestException("Unable to make check host name valid request",e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isTitleLiveOnline(String title) {
|
public TikTokApiService getApiService() {
|
||||||
return title.contains("is LIVE");
|
var jar = new TikTokCookieJar();
|
||||||
|
var factory = new TikTokHttpRequestFactory(jar);
|
||||||
|
var client = new TikTokHttpClient(jar, factory);
|
||||||
|
var settings = new ClientSettings();
|
||||||
|
settings.setClientParameters(Constants.DefaultClientParams());
|
||||||
|
var apiService = new TikTokApiService(client, Logger.getGlobal(), settings);
|
||||||
|
return apiService;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isTitleHostNameValid(String title, String hostName)
|
|
||||||
{
|
|
||||||
return title.contains(hostName);
|
|
||||||
}
|
|
||||||
|
|
||||||
private String extractTitleContent(String html) {
|
|
||||||
var regex = "<title\\b[^>]*>(.*?)<\\/title>";
|
|
||||||
var pattern = Pattern.compile(regex);
|
|
||||||
var matcher = pattern.matcher(html);
|
|
||||||
if (matcher.find()) {
|
|
||||||
return matcher.group(1);
|
|
||||||
} else {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getLiveUrl(String hostName) {
|
|
||||||
var sb = new StringBuilder();
|
|
||||||
sb.append("https://www.tiktok.com/@");
|
|
||||||
sb.append(hostName);
|
|
||||||
sb.append("/live");
|
|
||||||
return sb.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getProfileUrl(String hostName) {
|
|
||||||
var sb = new StringBuilder();
|
|
||||||
sb.append("https://www.tiktok.com/@");
|
|
||||||
sb.append(hostName);
|
|
||||||
return sb.toString();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,14 +5,50 @@ import org.junit.jupiter.api.Test;
|
|||||||
|
|
||||||
public class TikTokLiveOnlineCheckerTest {
|
public class TikTokLiveOnlineCheckerTest {
|
||||||
|
|
||||||
private final String TARGET_USER = "bangbetmenygy";
|
public boolean enableTests = false;
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void shouldTestOnline() {
|
public void shouldTestOnline() {
|
||||||
|
|
||||||
|
if(!enableTests)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var TARGET_USER = "bangbetmenygy";
|
||||||
var sut = new TikTokDataChecker();
|
var sut = new TikTokDataChecker();
|
||||||
var result = sut.isOnline(TARGET_USER);
|
var result = sut.isOnline(TARGET_USER);
|
||||||
|
|
||||||
Assertions.assertTrue(result);
|
Assertions.assertTrue(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldBeOffline() {
|
||||||
|
|
||||||
|
var TARGET_USER = "dostawcavideo";
|
||||||
|
var sut = new TikTokDataChecker();
|
||||||
|
var result = sut.isOnline(TARGET_USER);
|
||||||
|
|
||||||
|
Assertions.assertFalse(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldBeValid() {
|
||||||
|
|
||||||
|
var TARGET_USER = "dostawcavideo";
|
||||||
|
var sut = new TikTokDataChecker();
|
||||||
|
var result = sut.isHostNameValid(TARGET_USER);
|
||||||
|
|
||||||
|
Assertions.assertTrue(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldNotBeValid() {
|
||||||
|
var TARGET_USER = "adadsdadadadadadadadddasdadsafafsafsafas";
|
||||||
|
var sut = new TikTokDataChecker();
|
||||||
|
var result = sut.isHostNameValid(TARGET_USER);
|
||||||
|
|
||||||
|
Assertions.assertFalse(result);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -41,7 +41,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>TikTokLiveJava</artifactId>
|
<artifactId>TikTokLiveJava</artifactId>
|
||||||
<groupId>io.github.jwdeveloper.tiktok</groupId>
|
<groupId>io.github.jwdeveloper.tiktok</groupId>
|
||||||
<version>1.0.5-Release</version>
|
<version>1.0.6-Release</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|||||||
@@ -31,25 +31,25 @@ import java.util.logging.Level;
|
|||||||
|
|
||||||
public class SimpleExample
|
public class SimpleExample
|
||||||
{
|
{
|
||||||
public static String TIKTOK_HOSTNAME = "bangbetmenygy";
|
public static String TIKTOK_HOSTNAME = "adasdsadadadasdasdsadasdasad";
|
||||||
public static void main(String[] args) throws IOException {
|
public static void main(String[] args) throws IOException {
|
||||||
|
|
||||||
showLogo();
|
showLogo();
|
||||||
// set tiktok username
|
// set tiktok username
|
||||||
|
|
||||||
/*
|
|
||||||
Optional checking if host name is correct
|
//Optional checking if host name is correct
|
||||||
if(TikTokLive.isHostNameValid(TIKTOK_HOSTNAME))
|
if(TikTokLive.isHostNameValid(TIKTOK_HOSTNAME))
|
||||||
{
|
{
|
||||||
System.out.println("Live is online!");
|
System.out.println("user name exists!");
|
||||||
}
|
}
|
||||||
|
|
||||||
Optional checking if live is online
|
//Optional checking if live is online
|
||||||
if(TikTokLive.isLiveOnline(TIKTOK_HOSTNAME))
|
if(TikTokLive.isLiveOnline(TIKTOK_HOSTNAME))
|
||||||
{
|
{
|
||||||
System.out.println("Live is online!");
|
System.out.println("Live is online!");
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
TikTokLive.newClient(SimpleExample.TIKTOK_HOSTNAME)
|
TikTokLive.newClient(SimpleExample.TIKTOK_HOSTNAME)
|
||||||
.configure(clientSettings ->
|
.configure(clientSettings ->
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ Do you prefer other programming languages?
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.github.jwdeveloper.TikTok-Live-Java</groupId>
|
<groupId>com.github.jwdeveloper.TikTok-Live-Java</groupId>
|
||||||
<artifactId>Client</artifactId>
|
<artifactId>Client</artifactId>
|
||||||
<version>1.0.5-Release</version>
|
<version>1.0.6-Release</version>
|
||||||
<scope>compile</scope>
|
<scope>compile</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|||||||
@@ -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.5-Release</version>
|
<version>1.0.6-Release</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
|||||||
@@ -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.5-Release</version>
|
<version>1.0.6-Release</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<artifactId>Tools-EventsWebViewer</artifactId>
|
<artifactId>Tools-EventsWebViewer</artifactId>
|
||||||
|
|||||||
@@ -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.5-Release</version>
|
<version>1.0.6-Release</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
|||||||
@@ -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.5-Release</version>
|
<version>1.0.6-Release</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
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.5-Release</version>
|
<version>1.0.6-Release</version>
|
||||||
<modules>
|
<modules>
|
||||||
<module>API</module>
|
<module>API</module>
|
||||||
<module>Client</module>
|
<module>Client</module>
|
||||||
|
|||||||
Reference in New Issue
Block a user