Merge remote-tracking branch 'origin/master'

This commit is contained in:
JW
2023-12-05 01:43:34 +01:00
16 changed files with 125 additions and 120 deletions

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.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>

View File

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

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.5-Release</version> <version>1.0.6-Release</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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.5-Release</version> <version>1.0.6-Release</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

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.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>

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.5-Release</version> <version>1.0.6-Release</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

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