mirror of
https://github.com/jwdeveloper/TikTokLiveJava.git
synced 2026-02-28 01:09:40 -05:00
Compare commits
26 Commits
0.0.12-Rel
...
0.0.15-Rel
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
818c4cb364 | ||
|
|
911e2b12a5 | ||
|
|
1aff710523 | ||
|
|
c0f8e6d904 | ||
|
|
b059afd621 | ||
|
|
1275878822 | ||
|
|
761f3ab633 | ||
|
|
66def92316 | ||
|
|
cc85d7c124 | ||
|
|
384cfade5a | ||
|
|
483dceadcf | ||
|
|
5f8cba5126 | ||
|
|
f9966c9a5f | ||
|
|
48a79736ad | ||
|
|
eb82d0df78 | ||
|
|
4ed821925d | ||
|
|
6e9244aa67 | ||
|
|
fadb1ab267 | ||
|
|
4273375eb9 | ||
|
|
3daeee6316 | ||
|
|
cde38df1b3 | ||
|
|
15d6351d65 | ||
|
|
44ba999b83 | ||
|
|
5cf0d30962 | ||
|
|
71ebc6e05e | ||
|
|
c6d09927a0 |
2
.github/workflows/maven-publish.yml
vendored
2
.github/workflows/maven-publish.yml
vendored
@@ -1,4 +1,4 @@
|
|||||||
name: Publish Artifacts
|
name: Publish New Version
|
||||||
|
|
||||||
on:
|
on:
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|||||||
81
.gitignore
vendored
81
.gitignore
vendored
@@ -1,3 +1,82 @@
|
|||||||
# Project exclude paths
|
# Project exclude paths
|
||||||
/API/target/
|
/API/target/
|
||||||
/Client/target/
|
/Client/target/
|
||||||
|
*.db
|
||||||
|
|
||||||
|
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
|
||||||
|
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
|
||||||
|
|
||||||
|
# User-specific stuff
|
||||||
|
.idea/**/workspace.xml
|
||||||
|
.idea/**/tasks.xml
|
||||||
|
.idea/**/usage.statistics.xml
|
||||||
|
.idea/**/dictionaries
|
||||||
|
.idea/**/shelf
|
||||||
|
|
||||||
|
# AWS User-specific
|
||||||
|
.idea/**/aws.xml
|
||||||
|
|
||||||
|
# Generated files
|
||||||
|
.idea/**/contentModel.xml
|
||||||
|
|
||||||
|
# Sensitive or high-churn files
|
||||||
|
.idea/**/dataSources/
|
||||||
|
.idea/**/dataSources.ids
|
||||||
|
.idea/**/dataSources.local.xml
|
||||||
|
.idea/**/sqlDataSources.xml
|
||||||
|
.idea/**/dynamic.xml
|
||||||
|
.idea/**/uiDesigner.xml
|
||||||
|
.idea/**/dbnavigator.xml
|
||||||
|
|
||||||
|
# Gradle
|
||||||
|
.idea/**/gradle.xml
|
||||||
|
.idea/**/libraries
|
||||||
|
|
||||||
|
# Gradle and Maven with auto-import
|
||||||
|
# When using Gradle or Maven with auto-import, you should exclude module files,
|
||||||
|
# since they will be recreated, and may cause churn. Uncomment if using
|
||||||
|
# auto-import.
|
||||||
|
# .idea/artifacts
|
||||||
|
# .idea/compiler.xml
|
||||||
|
# .idea/jarRepositories.xml
|
||||||
|
# .idea/modules.xml
|
||||||
|
# .idea/*.iml
|
||||||
|
# .idea/modules
|
||||||
|
# *.iml
|
||||||
|
# *.ipr
|
||||||
|
|
||||||
|
# CMake
|
||||||
|
cmake-build-*/
|
||||||
|
|
||||||
|
# Mongo Explorer plugin
|
||||||
|
.idea/**/mongoSettings.xml
|
||||||
|
|
||||||
|
# File-based project format
|
||||||
|
*.iws
|
||||||
|
|
||||||
|
# IntelliJ
|
||||||
|
out/
|
||||||
|
|
||||||
|
# mpeltonen/sbt-idea plugin
|
||||||
|
.idea_modules/
|
||||||
|
|
||||||
|
# JIRA plugin
|
||||||
|
atlassian-ide-plugin.xml
|
||||||
|
|
||||||
|
# Cursive Clojure plugin
|
||||||
|
.idea/replstate.xml
|
||||||
|
|
||||||
|
# SonarLint plugin
|
||||||
|
.idea/sonarlint/
|
||||||
|
|
||||||
|
# Crashlytics plugin (for Android Studio and IntelliJ)
|
||||||
|
com_crashlytics_export_strings.xml
|
||||||
|
crashlytics.properties
|
||||||
|
crashlytics-build.properties
|
||||||
|
fabric.properties
|
||||||
|
|
||||||
|
# Editor-based Rest Client
|
||||||
|
.idea/httpRequests
|
||||||
|
|
||||||
|
# Android studio 3.1+ serialized cache file
|
||||||
|
.idea/caches/build_file_checksums.ser
|
||||||
@@ -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>0.0.11-Release</version>
|
<version>0.0.14-Release</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<artifactId>API</artifactId>
|
<artifactId>API</artifactId>
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
package io.github.jwdeveloper.tiktok.events;
|
package io.github.jwdeveloper.tiktok.events;
|
||||||
|
|
||||||
import io.github.jwdeveloper.tiktok.events.messages.*;
|
import io.github.jwdeveloper.tiktok.events.messages.*;
|
||||||
import java.util.function.Consumer;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public interface TikTokEventBuilder<T> {
|
public interface TikTokEventBuilder<T> {
|
||||||
@@ -89,6 +87,9 @@ public interface TikTokEventBuilder<T> {
|
|||||||
T onUnhandledControl(TikTokEventConsumer<TikTokUnhandledControlEvent> event);
|
T onUnhandledControl(TikTokEventConsumer<TikTokUnhandledControlEvent> event);
|
||||||
|
|
||||||
T onEvent(TikTokEventConsumer<TikTokEvent> event);
|
T onEvent(TikTokEventConsumer<TikTokEvent> event);
|
||||||
|
|
||||||
|
T onWebsocketMessage(TikTokEventConsumer<TikTokWebsocketMessageEvent> event);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
package io.github.jwdeveloper.tiktok.events.messages;
|
||||||
|
|
||||||
|
import io.github.jwdeveloper.tiktok.events.TikTokEvent;
|
||||||
|
import io.github.jwdeveloper.tiktok.messages.WebcastResponse;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Happens when TikTok websocket receive message from server
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class TikTokWebsocketMessageEvent extends TikTokEvent
|
||||||
|
{
|
||||||
|
private TikTokEvent event;
|
||||||
|
|
||||||
|
private WebcastResponse.Message message;
|
||||||
|
}
|
||||||
@@ -21,13 +21,18 @@ public class TikTokLiveMessageException extends TikTokLiveException {
|
|||||||
this.webcastResponse = webcastResponse;
|
this.webcastResponse = webcastResponse;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void messageToBase64()
|
public String messageName()
|
||||||
{
|
{
|
||||||
var decoded = Base64.getEncoder().encodeToString(webcastMessage.getBinary().toByteArray());
|
return webcastMessage.getType();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void webcastResponseToBase64()
|
public String messageToBase64()
|
||||||
{
|
{
|
||||||
var decoded = Base64.getEncoder().encodeToString(webcastResponse.toByteArray());
|
return Base64.getEncoder().encodeToString(webcastMessage.getBinary().toByteArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
public String webcastResponseToBase64()
|
||||||
|
{
|
||||||
|
return Base64.getEncoder().encodeToString(webcastResponse.toByteArray());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package io.github.jwdeveloper.tiktok.live;
|
|||||||
public interface LiveRoomInfo
|
public interface LiveRoomInfo
|
||||||
{
|
{
|
||||||
int getViewersCount();
|
int getViewersCount();
|
||||||
|
|
||||||
String getRoomId();
|
String getRoomId();
|
||||||
String getUserName();
|
String getUserName();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,38 @@
|
|||||||
|
package io.github.jwdeveloper.tiktok.utils;
|
||||||
|
|
||||||
|
import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveException;
|
||||||
|
|
||||||
|
public class CancelationToken
|
||||||
|
{
|
||||||
|
private boolean isCanceled =false;
|
||||||
|
|
||||||
|
public void cancel()
|
||||||
|
{
|
||||||
|
isCanceled =true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isCancel()
|
||||||
|
{
|
||||||
|
|
||||||
|
return isCanceled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void throwIfCancel()
|
||||||
|
{
|
||||||
|
if(!isCanceled)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
throw new TikTokLiveException("Token requested cancelation");
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isNotCancel()
|
||||||
|
{
|
||||||
|
return !isCancel();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CancelationToken create()
|
||||||
|
{
|
||||||
|
return new CancelationToken();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -414,13 +414,16 @@ message User {
|
|||||||
Picture profilePicture = 9; // Avatar
|
Picture profilePicture = 9; // Avatar
|
||||||
Picture picture720 = 10; // 720p
|
Picture picture720 = 10; // 720p
|
||||||
Picture picture1080 = 11; // 1080p
|
Picture picture1080 = 11; // 1080p
|
||||||
uint32 data2 = 15;
|
int32 status = 15;
|
||||||
uint64 data3 = 16;
|
int64 createTime = 16;
|
||||||
|
int64 modifyTime = 17;
|
||||||
|
int32 secret = 18;
|
||||||
|
string shareQrcodeUri = 19;
|
||||||
repeated Picture additionalPictures = 21;
|
repeated Picture additionalPictures = 21;
|
||||||
FollowerData followerData = 22;
|
FollowerData followerData = 22;
|
||||||
string userString1 = 23;
|
// string userString1 = 23;
|
||||||
UserRanking userRank1 = 25;
|
UserRanking userRank1 = 25;
|
||||||
string userString2 = 32;
|
// string userString2 = 32;
|
||||||
uint64 data4 = 37;
|
uint64 data4 = 37;
|
||||||
string uniqueId = 38; // @-ID for user
|
string uniqueId = 38; // @-ID for user
|
||||||
string data5 = 46;
|
string data5 = 46;
|
||||||
|
|||||||
@@ -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>0.0.11-Release</version>
|
<version>0.0.14-Release</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
@@ -29,6 +29,23 @@
|
|||||||
<artifactId>protobuf-java</artifactId>
|
<artifactId>protobuf-java</artifactId>
|
||||||
<version>3.24.1</version>
|
<version>3.24.1</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.slf4j</groupId>
|
||||||
|
<artifactId>slf4j-simple</artifactId>
|
||||||
|
<version>2.0.7</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.java-websocket</groupId>
|
||||||
|
<artifactId>Java-WebSocket</artifactId>
|
||||||
|
<version>1.5.4</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.slf4j</groupId>
|
||||||
|
<artifactId>slf4j-simple</artifactId>
|
||||||
|
<version>2.0.7</version>
|
||||||
|
<scope>runtime</scope>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import io.github.jwdeveloper.tiktok.http.TikTokCookieJar;
|
|||||||
import io.github.jwdeveloper.tiktok.http.TikTokHttpApiClient;
|
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.utils.CancelationToken;
|
||||||
import io.github.jwdeveloper.tiktok.websocket.TikTokWebSocketClient;
|
import io.github.jwdeveloper.tiktok.websocket.TikTokWebSocketClient;
|
||||||
|
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
@@ -70,7 +71,6 @@ public class TikTokLiveClientBuilder implements TikTokEventBuilder<TikTokLiveCli
|
|||||||
var tiktokRoomInfo = new TikTokRoomInfo();
|
var tiktokRoomInfo = new TikTokRoomInfo();
|
||||||
tiktokRoomInfo.setUserName(clientSettings.getHostName());
|
tiktokRoomInfo.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, requestFactory);
|
var apiClient = new TikTokHttpApiClient(cookieJar, requestFactory);
|
||||||
@@ -79,7 +79,6 @@ public class TikTokLiveClientBuilder implements TikTokEventBuilder<TikTokLiveCli
|
|||||||
var webResponseHandler = new TikTokMessageHandlerRegistration(tikTokEventHandler, clientSettings, logger, giftManager, tiktokRoomInfo);
|
var webResponseHandler = new TikTokMessageHandlerRegistration(tikTokEventHandler, clientSettings, logger, giftManager, tiktokRoomInfo);
|
||||||
var webSocketClient = new TikTokWebSocketClient(logger,
|
var webSocketClient = new TikTokWebSocketClient(logger,
|
||||||
cookieJar,
|
cookieJar,
|
||||||
requestFactory,
|
|
||||||
clientSettings,
|
clientSettings,
|
||||||
webResponseHandler,
|
webResponseHandler,
|
||||||
tikTokEventHandler);
|
tikTokEventHandler);
|
||||||
@@ -319,6 +318,12 @@ public class TikTokLiveClientBuilder implements TikTokEventBuilder<TikTokLiveCli
|
|||||||
tikTokEventHandler.subscribe(TikTokEvent.class, event);
|
tikTokEventHandler.subscribe(TikTokEvent.class, event);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TikTokLiveClientBuilder onWebsocketMessage(TikTokEventConsumer<TikTokWebsocketMessageEvent> event) {
|
||||||
|
tikTokEventHandler.subscribe(TikTokWebsocketMessageEvent.class, event);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import io.github.jwdeveloper.tiktok.ClientSettings;
|
|||||||
import io.github.jwdeveloper.tiktok.TikTokLiveClient;
|
import io.github.jwdeveloper.tiktok.TikTokLiveClient;
|
||||||
import io.github.jwdeveloper.tiktok.events.TikTokEvent;
|
import io.github.jwdeveloper.tiktok.events.TikTokEvent;
|
||||||
import io.github.jwdeveloper.tiktok.events.messages.TikTokErrorEvent;
|
import io.github.jwdeveloper.tiktok.events.messages.TikTokErrorEvent;
|
||||||
|
import io.github.jwdeveloper.tiktok.events.messages.TikTokWebsocketMessageEvent;
|
||||||
import io.github.jwdeveloper.tiktok.events.messages.TikTokUnhandledEvent;
|
import io.github.jwdeveloper.tiktok.events.messages.TikTokUnhandledEvent;
|
||||||
import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveMessageException;
|
import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveMessageException;
|
||||||
import io.github.jwdeveloper.tiktok.exceptions.TikTokMessageMappingException;
|
import io.github.jwdeveloper.tiktok.exceptions.TikTokMessageMappingException;
|
||||||
@@ -69,6 +70,7 @@ public abstract class TikTokMessageHandler {
|
|||||||
}
|
}
|
||||||
var handler = handlers.get(message.getType());
|
var handler = handlers.get(message.getType());
|
||||||
var tiktokEvent = handler.handle(message);
|
var tiktokEvent = handler.handle(message);
|
||||||
|
tikTokEventHandler.publish(client, new TikTokWebsocketMessageEvent(tiktokEvent, message));
|
||||||
tikTokEventHandler.publish(client, tiktokEvent);
|
tikTokEventHandler.publish(client, tiktokEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -33,8 +33,8 @@ public class TikTokMessageHandlerRegistration extends TikTokMessageHandler {
|
|||||||
public void init() {
|
public void init() {
|
||||||
|
|
||||||
//ConnectionEvents events
|
//ConnectionEvents events
|
||||||
register(WebcastControlMessage.class, TikTokRoomMessageEvent.class);
|
register(WebcastControlMessage.class, this::handleWebcastControlMessage);
|
||||||
register(SystemMessage.class, this::handleWebcastControlMessage);
|
register(SystemMessage.class,TikTokRoomMessageEvent.class);
|
||||||
|
|
||||||
|
|
||||||
//Room status events
|
//Room status events
|
||||||
@@ -105,16 +105,18 @@ public class TikTokMessageHandlerRegistration extends TikTokMessageHandler {
|
|||||||
private TikTokEvent handleSocialMedia(WebcastResponse.Message msg) {
|
private TikTokEvent handleSocialMedia(WebcastResponse.Message msg) {
|
||||||
var message = WebcastSocialMessage.parseFrom(msg.getBinary());
|
var message = WebcastSocialMessage.parseFrom(msg.getBinary());
|
||||||
|
|
||||||
String type = message.getHeader().getSocialData().getType();
|
var socialType = message.getHeader().getSocialData().getType();
|
||||||
Pattern pattern = Pattern.compile("\\d+");
|
var pattern = Pattern.compile("pm_mt_guidance_viewer_([0-9]+)_share");
|
||||||
Matcher matcher = pattern.matcher(type);
|
var matcher = pattern.matcher(socialType);
|
||||||
if (matcher.find()) {
|
|
||||||
|
if (matcher.find())
|
||||||
|
{
|
||||||
var value = matcher.group(0);
|
var value = matcher.group(0);
|
||||||
var number = Integer.parseInt(value);
|
var number = Integer.parseInt(value);
|
||||||
return new TikTokShareEvent(message, number);
|
return new TikTokShareEvent(message, number);
|
||||||
}
|
}
|
||||||
|
|
||||||
var socialType = message.getHeader().getSocialData().getType();
|
|
||||||
return switch (socialType) {
|
return switch (socialType) {
|
||||||
case SocialTypes.LikeType -> new TikTokLikeEvent(message);
|
case SocialTypes.LikeType -> new TikTokLikeEvent(message);
|
||||||
case SocialTypes.FollowType -> new TikTokFollowEvent(message);
|
case SocialTypes.FollowType -> new TikTokFollowEvent(message);
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ public class TikTokHttpApiClient {
|
|||||||
|
|
||||||
var fullUrl = HttpUtils.parseParameters(url,parameters);
|
var fullUrl = HttpUtils.parseParameters(url,parameters);
|
||||||
var singHeaders = new TreeMap<String,Object>();
|
var singHeaders = new TreeMap<String,Object>();
|
||||||
singHeaders.put("client", "ttlive-net");
|
singHeaders.put("client", "ttlive-java");
|
||||||
singHeaders.put("uuc", 1);
|
singHeaders.put("uuc", 1);
|
||||||
singHeaders.put("url", fullUrl);
|
singHeaders.put("url", fullUrl);
|
||||||
|
|
||||||
|
|||||||
@@ -11,10 +11,10 @@ import io.github.jwdeveloper.tiktok.http.HttpUtils;
|
|||||||
import io.github.jwdeveloper.tiktok.http.TikTokCookieJar;
|
import io.github.jwdeveloper.tiktok.http.TikTokCookieJar;
|
||||||
import io.github.jwdeveloper.tiktok.http.TikTokHttpRequestFactory;
|
import io.github.jwdeveloper.tiktok.http.TikTokHttpRequestFactory;
|
||||||
import io.github.jwdeveloper.tiktok.messages.WebcastResponse;
|
import io.github.jwdeveloper.tiktok.messages.WebcastResponse;
|
||||||
|
import org.java_websocket.client.WebSocketClient;
|
||||||
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.net.http.WebSocket;
|
import java.net.http.WebSocket;
|
||||||
import java.time.Duration;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.TreeMap;
|
import java.util.TreeMap;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
@@ -23,24 +23,21 @@ public class TikTokWebSocketClient {
|
|||||||
private final Logger logger;
|
private final Logger logger;
|
||||||
private final ClientSettings clientSettings;
|
private final ClientSettings clientSettings;
|
||||||
private final TikTokCookieJar tikTokCookieJar;
|
private final TikTokCookieJar tikTokCookieJar;
|
||||||
private final TikTokHttpRequestFactory factory;
|
|
||||||
private final TikTokMessageHandlerRegistration webResponseHandler;
|
private final TikTokMessageHandlerRegistration webResponseHandler;
|
||||||
private final TikTokEventHandler tikTokEventHandler;
|
private final TikTokEventHandler tikTokEventHandler;
|
||||||
|
private WebSocketClient webSocketClient;
|
||||||
private WebSocket webSocket;
|
|
||||||
private boolean isConnected;
|
|
||||||
private TikTokLiveClient tikTokLiveClient;
|
private TikTokLiveClient tikTokLiveClient;
|
||||||
|
private TikTokWebSocketPingingTask pingingTask;
|
||||||
|
private boolean isConnected;
|
||||||
|
|
||||||
public TikTokWebSocketClient(Logger logger,
|
public TikTokWebSocketClient(Logger logger,
|
||||||
TikTokCookieJar tikTokCookieJar,
|
TikTokCookieJar tikTokCookieJar,
|
||||||
TikTokHttpRequestFactory factory,
|
|
||||||
ClientSettings clientSettings,
|
ClientSettings clientSettings,
|
||||||
TikTokMessageHandlerRegistration webResponseHandler,
|
TikTokMessageHandlerRegistration webResponseHandler,
|
||||||
TikTokEventHandler tikTokEventHandler) {
|
TikTokEventHandler tikTokEventHandler) {
|
||||||
this.logger = logger;
|
this.logger = logger;
|
||||||
this.tikTokCookieJar = tikTokCookieJar;
|
this.tikTokCookieJar = tikTokCookieJar;
|
||||||
this.clientSettings = clientSettings;
|
this.clientSettings = clientSettings;
|
||||||
this.factory = factory;
|
|
||||||
this.webResponseHandler = webResponseHandler;
|
this.webResponseHandler = webResponseHandler;
|
||||||
this.tikTokEventHandler = tikTokEventHandler;
|
this.tikTokEventHandler = tikTokEventHandler;
|
||||||
isConnected = false;
|
isConnected = false;
|
||||||
@@ -56,13 +53,19 @@ public class TikTokWebSocketClient {
|
|||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
var url = getWebSocketUrl(webcastResponse);
|
var url = getWebSocketUrl(webcastResponse);
|
||||||
if (clientSettings.isHandleExistingMessagesOnConnect())
|
if (clientSettings.isHandleExistingMessagesOnConnect()) {
|
||||||
{
|
|
||||||
logger.info("Handling existing messages");
|
logger.info("Handling existing messages");
|
||||||
webResponseHandler.handle(tikTokLiveClient, webcastResponse);
|
webResponseHandler.handle(tikTokLiveClient, webcastResponse);
|
||||||
}
|
}
|
||||||
webSocket = startWebSocket(url);
|
webSocketClient = startWebSocket(url);
|
||||||
} catch (Exception e) {
|
webSocketClient.connect();
|
||||||
|
|
||||||
|
pingingTask = new TikTokWebSocketPingingTask();
|
||||||
|
pingingTask.run(webSocketClient);
|
||||||
|
isConnected = true;
|
||||||
|
} catch (Exception e)
|
||||||
|
{
|
||||||
|
isConnected =false;
|
||||||
throw new TikTokLiveException("Failed to connect to the websocket", e);
|
throw new TikTokLiveException("Failed to connect to the websocket", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -82,20 +85,27 @@ public class TikTokWebSocketClient {
|
|||||||
return HttpUtils.parseParametersEncode(url, clone);
|
return HttpUtils.parseParametersEncode(url, clone);
|
||||||
}
|
}
|
||||||
|
|
||||||
private WebSocket startWebSocket(String url) throws Exception {
|
private WebSocketClient startWebSocket(String url) {
|
||||||
var cookie = tikTokCookieJar.parseCookies();
|
var cookie = tikTokCookieJar.parseCookies();
|
||||||
var map = new HashMap<String, String>();
|
var map = new HashMap<String, String>();
|
||||||
map.put("Cookie", cookie);
|
map.put("Cookie", cookie);
|
||||||
return factory.openSocket()
|
return new TikTokWebSocketListener(URI.create(url),
|
||||||
.subprotocols("echo-protocol")
|
map,
|
||||||
.connectTimeout(Duration.ofSeconds(15))
|
3000,
|
||||||
.header("Cookie", cookie)
|
webResponseHandler,
|
||||||
.buildAsync(URI.create(url), new TikTokWebSocketListener(webResponseHandler, tikTokEventHandler, tikTokLiveClient)).get();
|
tikTokEventHandler,
|
||||||
|
tikTokLiveClient);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void stop() {
|
|
||||||
if (isConnected && webSocket != null) {
|
|
||||||
webSocket.sendClose(WebSocket.NORMAL_CLOSURE, "ok");
|
public void stop()
|
||||||
|
{
|
||||||
|
if (isConnected && webSocketClient != null) {
|
||||||
|
webSocketClient.close(1);
|
||||||
}
|
}
|
||||||
|
webSocketClient = null;
|
||||||
|
pingingTask = null;
|
||||||
|
isConnected = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package io.github.jwdeveloper.tiktok.websocket;
|
package io.github.jwdeveloper.tiktok.websocket;
|
||||||
|
|
||||||
|
|
||||||
import com.google.protobuf.ByteString;
|
import com.google.protobuf.ByteString;
|
||||||
import io.github.jwdeveloper.tiktok.TikTokLiveClient;
|
import io.github.jwdeveloper.tiktok.TikTokLiveClient;
|
||||||
import io.github.jwdeveloper.tiktok.events.messages.TikTokConnectedEvent;
|
import io.github.jwdeveloper.tiktok.events.messages.TikTokConnectedEvent;
|
||||||
@@ -12,71 +11,71 @@ import io.github.jwdeveloper.tiktok.handlers.TikTokMessageHandlerRegistration;
|
|||||||
import io.github.jwdeveloper.tiktok.messages.WebcastResponse;
|
import io.github.jwdeveloper.tiktok.messages.WebcastResponse;
|
||||||
import io.github.jwdeveloper.tiktok.messages.WebcastWebsocketAck;
|
import io.github.jwdeveloper.tiktok.messages.WebcastWebsocketAck;
|
||||||
import io.github.jwdeveloper.tiktok.messages.WebcastWebsocketMessage;
|
import io.github.jwdeveloper.tiktok.messages.WebcastWebsocketMessage;
|
||||||
|
import org.java_websocket.client.WebSocketClient;
|
||||||
|
import org.java_websocket.drafts.Draft_6455;
|
||||||
|
import org.java_websocket.handshake.ServerHandshake;
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.net.URI;
|
||||||
import java.net.http.WebSocket;
|
import java.net.http.WebSocket;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.concurrent.CompletionStage;
|
|
||||||
|
|
||||||
|
public class TikTokWebSocketListener extends WebSocketClient {
|
||||||
|
|
||||||
public class TikTokWebSocketListener implements java.net.http.WebSocket.Listener {
|
|
||||||
|
|
||||||
private final ByteArrayOutputStream accumulatedData = new ByteArrayOutputStream();
|
|
||||||
private final TikTokMessageHandlerRegistration webResponseHandler;
|
private final TikTokMessageHandlerRegistration webResponseHandler;
|
||||||
private final TikTokEventHandler tikTokEventHandler;
|
private final TikTokEventHandler tikTokEventHandler;
|
||||||
private final TikTokLiveClient tikTokLiveClient;
|
private final TikTokLiveClient tikTokLiveClient;
|
||||||
|
|
||||||
public TikTokWebSocketListener(TikTokMessageHandlerRegistration webResponseHandler,
|
public TikTokWebSocketListener(URI serverUri,
|
||||||
|
Map<String, String> httpHeaders,
|
||||||
|
int connectTimeout,
|
||||||
|
TikTokMessageHandlerRegistration webResponseHandler,
|
||||||
TikTokEventHandler tikTokEventHandler,
|
TikTokEventHandler tikTokEventHandler,
|
||||||
TikTokLiveClient tikTokLiveClient) {
|
TikTokLiveClient tikTokLiveClient) {
|
||||||
|
super(serverUri, new Draft_6455(), httpHeaders,connectTimeout);
|
||||||
this.webResponseHandler = webResponseHandler;
|
this.webResponseHandler = webResponseHandler;
|
||||||
this.tikTokEventHandler = tikTokEventHandler;
|
this.tikTokEventHandler = tikTokEventHandler;
|
||||||
this.tikTokLiveClient = tikTokLiveClient;
|
this.tikTokLiveClient = tikTokLiveClient;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompletionStage<?> onBinary(WebSocket webSocket, ByteBuffer data, boolean last) {
|
public void onOpen(ServerHandshake serverHandshake) {
|
||||||
|
tikTokEventHandler.publish(tikTokLiveClient,new TikTokConnectedEvent());
|
||||||
|
sendPing();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onMessage(ByteBuffer bytes)
|
||||||
|
{
|
||||||
try {
|
try {
|
||||||
var bytes = new byte[data.remaining()];
|
handleBinary(bytes.array());
|
||||||
data.get(bytes);
|
|
||||||
accumulatedData.write(bytes);
|
|
||||||
if (last) {
|
|
||||||
handleBinary(webSocket, accumulatedData.toByteArray());
|
|
||||||
accumulatedData.reset();
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
tikTokEventHandler.publish(tikTokLiveClient, new TikTokErrorEvent(e));
|
tikTokEventHandler.publish(tikTokLiveClient, new TikTokErrorEvent(e));
|
||||||
}
|
}
|
||||||
webSocket.request(1);
|
sendPing();
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onOpen(java.net.http.WebSocket webSocket) {
|
public void onClose(int i, String s, boolean b) {
|
||||||
tikTokEventHandler.publish(tikTokLiveClient,new TikTokConnectedEvent());
|
|
||||||
webSocket.request(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onError(java.net.http.WebSocket webSocket, Throwable error) {
|
|
||||||
tikTokEventHandler.publish(tikTokLiveClient,new TikTokErrorEvent(error));
|
|
||||||
webSocket.request(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public CompletionStage<?> onClose(java.net.http.WebSocket webSocket, int statusCode, String reason) {
|
|
||||||
tikTokEventHandler.publish(tikTokLiveClient,new TikTokDisconnectedEvent());
|
tikTokEventHandler.publish(tikTokLiveClient,new TikTokDisconnectedEvent());
|
||||||
return java.net.http.WebSocket.Listener.super.onClose(webSocket, statusCode, reason);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleBinary(WebSocket webSocket, byte[] buffer) {
|
@Override
|
||||||
|
public void onError(Exception error) {
|
||||||
|
tikTokEventHandler.publish(tikTokLiveClient,new TikTokErrorEvent(error));
|
||||||
|
sendPing();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleBinary(byte[] buffer) {
|
||||||
var websocketMessageOptional = getWebcastWebsocketMessage(buffer);
|
var websocketMessageOptional = getWebcastWebsocketMessage(buffer);
|
||||||
if (websocketMessageOptional.isEmpty()) {
|
if (websocketMessageOptional.isEmpty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var websocketMessage = websocketMessageOptional.get();
|
var websocketMessage = websocketMessageOptional.get();
|
||||||
sendAckId(webSocket, websocketMessage.getId());
|
sendAckId(websocketMessage.getId());
|
||||||
|
|
||||||
var webResponse = getWebResponseMessage(websocketMessage.getBinary());
|
var webResponse = getWebResponseMessage(websocketMessage.getBinary());
|
||||||
webResponseHandler.handle(tikTokLiveClient, webResponse);
|
webResponseHandler.handle(tikTokLiveClient, webResponse);
|
||||||
@@ -102,25 +101,21 @@ public class TikTokWebSocketListener implements java.net.http.WebSocket.Listener
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void pingTask(WebSocket webSocket) throws InterruptedException {
|
|
||||||
while (true) {
|
|
||||||
byte[] message = new byte[]{58, 2, 104, 98};
|
|
||||||
ByteBuffer buffer = ByteBuffer.wrap(message);
|
|
||||||
while (buffer.hasRemaining()) {
|
|
||||||
webSocket.sendPing(buffer);
|
|
||||||
}
|
|
||||||
buffer.clear();
|
|
||||||
Thread.sleep(10);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void sendAckId(WebSocket webSocket, long id) {
|
|
||||||
|
private void sendAckId(long id) {
|
||||||
var serverInfo = WebcastWebsocketAck
|
var serverInfo = WebcastWebsocketAck
|
||||||
.newBuilder()
|
.newBuilder()
|
||||||
.setType("ack")
|
.setType("ack")
|
||||||
.setId(id)
|
.setId(id)
|
||||||
.build();
|
.build();
|
||||||
webSocket.sendBinary(serverInfo.toByteString().asReadOnlyByteBuffer(), true);
|
send(serverInfo.toByteString().asReadOnlyByteBuffer());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onMessage(String s) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,58 @@
|
|||||||
|
package io.github.jwdeveloper.tiktok.websocket;
|
||||||
|
|
||||||
|
import org.java_websocket.WebSocket;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
public class TikTokWebSocketPingingTask
|
||||||
|
{
|
||||||
|
private Thread thread;
|
||||||
|
|
||||||
|
private boolean isRunning = false;
|
||||||
|
private final int MIN_TIMEOUT = 5;
|
||||||
|
private final int MAX_TIMEOUT = 100;
|
||||||
|
|
||||||
|
|
||||||
|
public void run(WebSocket webSocket)
|
||||||
|
{
|
||||||
|
var thread = new Thread(() ->
|
||||||
|
{
|
||||||
|
pingTask(webSocket);
|
||||||
|
});
|
||||||
|
isRunning =true;
|
||||||
|
thread.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void stop()
|
||||||
|
{
|
||||||
|
if(thread != null)
|
||||||
|
{
|
||||||
|
thread.interrupt();
|
||||||
|
}
|
||||||
|
isRunning = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void pingTask(WebSocket webSocket)
|
||||||
|
{
|
||||||
|
var random = new Random();
|
||||||
|
while (isRunning)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if(!webSocket.isOpen())
|
||||||
|
{
|
||||||
|
Thread.sleep(100);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
webSocket.sendPing();
|
||||||
|
var timeout = random.nextInt(MAX_TIMEOUT)+MIN_TIMEOUT;
|
||||||
|
Thread.sleep(timeout);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
isRunning = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -40,4 +40,10 @@ public class ParseMessagesTests extends TikTokBaseTest
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void ShouldParseMessageWebcastMemberMessage() throws InvalidProtocolBufferException {
|
||||||
|
var bytes = getFileBytesUtf("WebcastMemberMessage.bin");
|
||||||
|
var message = WebcastMemberMessage.parseFrom(bytes);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
1
Client/src/test/resources/WebcastMemberMessage.bin
Normal file
1
Client/src/test/resources/WebcastMemberMessage.bin
Normal file
File diff suppressed because one or more lines are too long
74
README.md
74
README.md
@@ -1,12 +1,13 @@
|
|||||||
[](https://jitpack.io/#jwdeveloper/TikTok-Live-Java)
|
[](https://jitpack.io/#jwdeveloper/TikTok-Live-Java)
|
||||||
|
|
||||||
|
|
||||||
# TikTok-Live-Java
|
# TikTokLive 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 [TikTokLive](https://github.com/isaackogan/TikTokLive) 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.
|
||||||
|
|
||||||
|
Join the support [discord](https://discord.gg/e2XwPNTBBr) and visit the `#java-support` channel for questions, contributions and ideas. Feel free to make pull requests with missing/new features, fixes, etc
|
||||||
|
|
||||||
Do you prefer other programming languages?
|
Do you prefer other programming languages?
|
||||||
- **Node** orginal: [TikTok-Live-Connector](https://github.com/isaackogan/TikTok-Live-Connector) by [@isaackogan](https://github.com/isaackogan)
|
- **Node** orginal: [TikTok-Live-Connector](https://github.com/isaackogan/TikTok-Live-Connector) by [@zerodytrash](https://github.com/zerodytrash)
|
||||||
- **Python** rewrite: [TikTokLive](https://github.com/isaackogan/TikTokLive) by [@isaackogan](https://github.com/isaackogan)
|
- **Python** rewrite: [TikTokLive](https://github.com/isaackogan/TikTokLive) by [@isaackogan](https://github.com/isaackogan)
|
||||||
- **Go** rewrite: [GoTikTokLive](https://github.com/Davincible/gotiktoklive) by [@Davincible](https://github.com/Davincible)
|
- **Go** rewrite: [GoTikTokLive](https://github.com/Davincible/gotiktoklive) by [@Davincible](https://github.com/Davincible)
|
||||||
- **C#** rewrite: [TikTokLiveSharp](https://github.com/frankvHoof93/TikTokLiveSharp) by [@frankvHoof93](https://github.com/frankvHoof93)
|
- **C#** rewrite: [TikTokLiveSharp](https://github.com/frankvHoof93/TikTokLiveSharp) by [@frankvHoof93](https://github.com/frankvHoof93)
|
||||||
@@ -15,10 +16,9 @@ Do you prefer other programming languages?
|
|||||||
|
|
||||||
#### Overview
|
#### Overview
|
||||||
- [Getting started](#getting-started)
|
- [Getting started](#getting-started)
|
||||||
- [Params and options](#params-and-options)
|
- [Configuration](#configuration)
|
||||||
- [Methods](#methods)
|
- [Methods](#methods)
|
||||||
- [Events](#events)
|
- [Events](#events)
|
||||||
- [Examples](#examples)
|
|
||||||
- [Contributing](#contributing)
|
- [Contributing](#contributing)
|
||||||
|
|
||||||
## Getting started
|
## Getting started
|
||||||
@@ -32,27 +32,19 @@ Do you prefer other programming languages?
|
|||||||
<url>https://jitpack.io</url>
|
<url>https://jitpack.io</url>
|
||||||
</repository>
|
</repository>
|
||||||
</repositories>
|
</repositories>
|
||||||
```
|
|
||||||
|
|
||||||
```xml
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.google.protobuf</groupId>
|
<groupId>com.github.jwdeveloper.TikTok-Live-Java</groupId>
|
||||||
<artifactId>protobuf-java</artifactId>
|
<artifactId>Client</artifactId>
|
||||||
<version>3.24.1</version>
|
<version>0.0.14-Release</version>
|
||||||
|
<scope>compile</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.google.code.gson</groupId>
|
<groupId>com.google.code.gson</groupId>
|
||||||
<artifactId>gson</artifactId>
|
<artifactId>gson</artifactId>
|
||||||
<version>2.10.1</version>
|
<version>2.10.1</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.github.jwdeveloper</groupId>
|
|
||||||
<artifactId>TikTok-Live-Java</artifactId>
|
|
||||||
<version>0.0.11-Release</version>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -65,23 +57,28 @@ Do you prefer other programming languages?
|
|||||||
var tiktokUsername = "jwdevtiktok";
|
var tiktokUsername = "jwdevtiktok";
|
||||||
|
|
||||||
TikTokLive.newClient(tiktokUsername)
|
TikTokLive.newClient(tiktokUsername)
|
||||||
.onConnected(event ->
|
.onConnected((client, event) ->
|
||||||
{
|
{
|
||||||
System.out.println("Connected");
|
System.out.println("Connected");
|
||||||
})
|
})
|
||||||
.onJoin(event ->
|
.onJoin((client, event) ->
|
||||||
{
|
{
|
||||||
System.out.println("User joined -> " + event.getUser().getNickName());
|
System.out.println("User joined -> " + event.getUser().getNickName());
|
||||||
})
|
})
|
||||||
.onComment(event ->
|
.onComment((client, event) ->
|
||||||
{
|
{
|
||||||
System.out.println(event.getUser().getUniqueId() + ": " + event.getText());
|
System.out.println(event.getUser().getUniqueId() + ": " + event.getText());
|
||||||
})
|
})
|
||||||
.onError(event ->
|
.onEvent((client, event) ->
|
||||||
|
{
|
||||||
|
System.out.println("Viewers count: "+client.getRoomInfo().getViewersCount());
|
||||||
|
})
|
||||||
|
.onError((client, event) ->
|
||||||
{
|
{
|
||||||
event.getException().printStackTrace();
|
event.getException().printStackTrace();
|
||||||
})
|
})
|
||||||
.buildAndRun();
|
.buildAndRun();
|
||||||
|
System.in.read();
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
## Configuration
|
## Configuration
|
||||||
@@ -90,35 +87,36 @@ Do you prefer other programming languages?
|
|||||||
public class ConfigurationExample
|
public class ConfigurationExample
|
||||||
{
|
{
|
||||||
public static void main(String[] args) throws IOException {
|
public static void main(String[] args) throws IOException {
|
||||||
|
var tiktokUsername = "jwdevtiktok";
|
||||||
TikTokLive.newClient("jwdevtiktok")
|
TikTokLive.newClient(tiktokUsername)
|
||||||
.configure(clientSettings ->
|
.configure(clientSettings ->
|
||||||
{
|
{
|
||||||
clientSettings.setHostName("jwdevtiktok"); //tiktok user
|
clientSettings.setHostName(Main.TEST_TIKTOK_USER); // TikTok user name
|
||||||
clientSettings.setClientLanguage("en"); //language
|
clientSettings.setClientLanguage("en"); // Language
|
||||||
clientSettings.setTimeout(Duration.ofSeconds(2)); //connection timeout
|
clientSettings.setTimeout(Duration.ofSeconds(2)); // Connection timeout
|
||||||
clientSettings.setLogLevel(Level.ALL); //log level
|
clientSettings.setLogLevel(Level.ALL); // Log level
|
||||||
clientSettings.setDownloadGiftInfo(true); //TODO
|
clientSettings.setDownloadGiftInfo(true); // Downloading meta information about gifts. You can access it by client.getGiftManager().getGiftsInfo();
|
||||||
clientSettings.setCheckForUnparsedData(true); //TODO
|
clientSettings.setPrintMessageData(true); // Printing TikTok Protocol buffer messages in Base64 format
|
||||||
clientSettings.setPollingInterval(Duration.ofSeconds(1)); //TODO
|
clientSettings.setPrintToConsole(true); // Printing all logs to console even if log level is Level.OFF
|
||||||
clientSettings.setPrintMessageData(true); //TODO
|
clientSettings.setHandleExistingMessagesOnConnect(true); // Invokes all TikTok events that had occurred before connection
|
||||||
clientSettings.setPrintToConsole(true); //TODO
|
clientSettings.setRetryOnConnectionFailure(true); // Reconnecting if TikTok user is offline
|
||||||
clientSettings.setHandleExistingMessagesOnConnect(true); //TODO
|
clientSettings.setRetryConnectionTimeout(Duration.ofSeconds(1)); // Timeout before next reconnection
|
||||||
clientSettings.setRetryOnConnectionFailure(true); //TODO
|
|
||||||
})
|
})
|
||||||
.buildAndRun();
|
.buildAndRun();
|
||||||
|
System.in.read();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Methods
|
## Methods
|
||||||
A `TikTokLive` object contains the following methods.
|
A `client (LiveClient)` object contains the following methods.
|
||||||
|
|
||||||
| Method Name | Description |
|
| Method Name | Description |
|
||||||
| ----------- | ----------- |
|
| ----------- | ----------- |
|
||||||
| connect | Connects to the live stream chat.<br>Returns a `Promise` which will be resolved when the connection is successfully established. |
|
| connect | Connects to the live stream. |
|
||||||
| disconnect | Disconnects the connection. |
|
| disconnect | Disconnects the connection. |
|
||||||
|
| getGiftManager | Gets the meta informations about all gifts. |
|
||||||
| getRoomInfo | Gets the current room info from TikTok API including streamer info, room status and statistics. |
|
| getRoomInfo | Gets the current room info from TikTok API including streamer info, room status and statistics. |
|
||||||
|
|
||||||
## Events
|
## Events
|
||||||
|
|||||||
@@ -2,11 +2,48 @@
|
|||||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
|
||||||
|
<!-- READ ME
|
||||||
|
This POM file is configured to run only inside TikTokLiveJava project
|
||||||
|
In case you have copied it follows this stets to fix console errors
|
||||||
|
|
||||||
|
1. Remember to remove
|
||||||
|
<parent>
|
||||||
|
<artifactId>TikTokLiveJava</artifactId>
|
||||||
|
<groupId>io.github.jwdeveloper.tiktok</groupId>
|
||||||
|
<version>0.0.13-Release</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
2. Paste
|
||||||
|
<repositories>
|
||||||
|
<repository>
|
||||||
|
<id>jitpack.io</id>
|
||||||
|
<url>https://jitpack.io</url>
|
||||||
|
</repository>
|
||||||
|
</repositories>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.github.jwdeveloper.TikTok-Live-Java</groupId>
|
||||||
|
<artifactId>Client</artifactId>
|
||||||
|
<version>0.0.14-Release</version> <- Change with latest version of TikTokJava
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.google.code.gson</groupId>
|
||||||
|
<artifactId>gson</artifactId>
|
||||||
|
<version>2.10.1</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
I hope it will help you :)
|
||||||
|
-->
|
||||||
|
|
||||||
<parent>
|
<parent>
|
||||||
<artifactId>TikTokLiveJava</artifactId>
|
<artifactId>TikTokLiveJava</artifactId>
|
||||||
<groupId>io.github.jwdeveloper.tiktok</groupId>
|
<groupId>io.github.jwdeveloper.tiktok</groupId>
|
||||||
<version>0.0.11-Release</version>
|
<version>0.0.14-Release</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
<artifactId>TestApplication</artifactId>
|
<artifactId>TestApplication</artifactId>
|
||||||
|
|||||||
@@ -4,13 +4,19 @@ import io.github.jwdeveloper.tiktok.events.messages.*;
|
|||||||
import io.github.jwdeveloper.tiktok.live.LiveClient;
|
import io.github.jwdeveloper.tiktok.live.LiveClient;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.time.Duration;
|
||||||
|
|
||||||
public class Main {
|
public class Main {
|
||||||
|
|
||||||
public static String TEST_TIKTOK_USER = "vadimpyrography";
|
public static String TEST_TIKTOK_USER = "olchik.m1";
|
||||||
|
|
||||||
public static void main(String[] args) throws IOException {
|
public static void main(String[] args) throws IOException {
|
||||||
var client = TikTokLive.newClient(TEST_TIKTOK_USER)
|
var client = TikTokLive.newClient(TEST_TIKTOK_USER)
|
||||||
|
.configure(clientSettings ->
|
||||||
|
{
|
||||||
|
clientSettings.setRetryConnectionTimeout(Duration.ofSeconds(5));
|
||||||
|
clientSettings.setRetryOnConnectionFailure(true);
|
||||||
|
})
|
||||||
.onConnected(Main::onConnected)
|
.onConnected(Main::onConnected)
|
||||||
.onDisconnected(Main::onDisconnected)
|
.onDisconnected(Main::onDisconnected)
|
||||||
.onRoomViewerData(Main::onViewerData)
|
.onRoomViewerData(Main::onViewerData)
|
||||||
@@ -26,9 +32,13 @@ public class Main {
|
|||||||
{
|
{
|
||||||
error.getException().printStackTrace();
|
error.getException().printStackTrace();
|
||||||
})
|
})
|
||||||
|
.onEvent((liveClient, event) ->
|
||||||
|
{
|
||||||
|
var viewers = liveClient.getRoomInfo().getViewersCount();
|
||||||
|
})
|
||||||
.buildAndRun();
|
.buildAndRun();
|
||||||
|
|
||||||
var viewers = client.getRoomInfo().getViewersCount();
|
|
||||||
System.in.read();
|
System.in.read();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,10 +6,15 @@ public class SimpleExample {
|
|||||||
public static void main(String[] args) throws IOException {
|
public static void main(String[] args) throws IOException {
|
||||||
|
|
||||||
TikTokLive.newClient(Main.TEST_TIKTOK_USER)
|
TikTokLive.newClient(Main.TEST_TIKTOK_USER)
|
||||||
|
.onFollow((liveClient, event) ->
|
||||||
|
{
|
||||||
|
System.out.println("Follow joined -> " + event.getNewFollower().getNickName());
|
||||||
|
})
|
||||||
.onConnected((client, event) ->
|
.onConnected((client, event) ->
|
||||||
{
|
{
|
||||||
System.out.println("Connected");
|
System.out.println("Connected");
|
||||||
})
|
})
|
||||||
|
|
||||||
.onJoin((client, event) ->
|
.onJoin((client, event) ->
|
||||||
{
|
{
|
||||||
System.out.println("User joined -> " + event.getUser().getNickName());
|
System.out.println("User joined -> " + event.getUser().getNickName());
|
||||||
|
|||||||
50
Tools-EventsCollector/pom.xml
Normal file
50
Tools-EventsCollector/pom.xml
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<parent>
|
||||||
|
<artifactId>TikTokLiveJava</artifactId>
|
||||||
|
<groupId>io.github.jwdeveloper.tiktok</groupId>
|
||||||
|
<version>0.0.14-Release</version>
|
||||||
|
</parent>
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<artifactId>Tools-EventsCollector</artifactId>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<maven.compiler.source>17</maven.compiler.source>
|
||||||
|
<maven.compiler.target>17</maven.compiler.target>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.xerial</groupId>
|
||||||
|
<artifactId>sqlite-jdbc</artifactId>
|
||||||
|
<version>3.34.0</version> <!-- Use the latest version available -->
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jdbi</groupId>
|
||||||
|
<artifactId>jdbi3-core</artifactId>
|
||||||
|
<version>3.23.0</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jdbi</groupId>
|
||||||
|
<artifactId>jdbi3-sqlobject</artifactId>
|
||||||
|
<version>3.23.0</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.slf4j</groupId>
|
||||||
|
<artifactId>slf4j-simple</artifactId>
|
||||||
|
<version>1.7.32</version> <!-- Use the latest version available -->
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.github.jwdeveloper.tiktok</groupId>
|
||||||
|
<artifactId>Client</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
|
||||||
|
</project>
|
||||||
@@ -0,0 +1,99 @@
|
|||||||
|
package io.github.jwdeveloper.tiktok.tools.collector;
|
||||||
|
|
||||||
|
import io.github.jwdeveloper.tiktok.TikTokLive;
|
||||||
|
import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveMessageException;
|
||||||
|
import io.github.jwdeveloper.tiktok.tools.collector.db.TikTokDatabase;
|
||||||
|
import io.github.jwdeveloper.tiktok.tools.collector.tables.ExceptionInfoModel;
|
||||||
|
import io.github.jwdeveloper.tiktok.tools.collector.tables.TikTokErrorModel;
|
||||||
|
import io.github.jwdeveloper.tiktok.tools.collector.tables.TikTokMessageModel;
|
||||||
|
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Base64;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class Main {
|
||||||
|
|
||||||
|
//https://protobuf-decoder.netlify.app/
|
||||||
|
/*
|
||||||
|
mia_tattoo
|
||||||
|
moniczkka
|
||||||
|
besin1276
|
||||||
|
*/
|
||||||
|
|
||||||
|
public static List<String> ignoredEvents;
|
||||||
|
|
||||||
|
public static void main(String[] args) throws SQLException {
|
||||||
|
|
||||||
|
ignoredEvents = List.of("TikTokJoinEvent","TikTokLikeEvent");
|
||||||
|
|
||||||
|
var db = new TikTokDatabase("test");
|
||||||
|
db.init();
|
||||||
|
|
||||||
|
var users = new ArrayList<String>();
|
||||||
|
users.add("mia_tattoo");
|
||||||
|
users.add("moniczkka");
|
||||||
|
users.add("besin1276");
|
||||||
|
|
||||||
|
for(var user : users)
|
||||||
|
{
|
||||||
|
runTikTokLiveInstance(user, db);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void runTikTokLiveInstance(String tiktokUser, TikTokDatabase tikTokDatabase)
|
||||||
|
{
|
||||||
|
|
||||||
|
TikTokLive.newClient(tiktokUser)
|
||||||
|
.onWebsocketMessage((liveClient, event) ->
|
||||||
|
{
|
||||||
|
var eventName = event.getEvent().getClass().getSimpleName();
|
||||||
|
|
||||||
|
if(ignoredEvents.contains(eventName))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var binary = Base64.getEncoder().encodeToString(event.getMessage().getBinary().toByteArray());
|
||||||
|
var model = TikTokMessageModel.builder()
|
||||||
|
.type("message")
|
||||||
|
.hostName(tiktokUser)
|
||||||
|
.eventName(eventName)
|
||||||
|
.eventContent(binary)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
tikTokDatabase.insertMessage(model);
|
||||||
|
System.out.println("EVENT: ["+tiktokUser+"] " + eventName);
|
||||||
|
})
|
||||||
|
.onError((liveClient, event) ->
|
||||||
|
{
|
||||||
|
var exception = event.getException();
|
||||||
|
var exceptionContent = ExceptionInfoModel.getStackTraceAsString(exception);
|
||||||
|
var builder = TikTokErrorModel.builder();
|
||||||
|
if (exception instanceof TikTokLiveMessageException ex) {
|
||||||
|
builder.hostName(tiktokUser)
|
||||||
|
.errorName(ex.messageName())
|
||||||
|
.errorType("error-message")
|
||||||
|
.exceptionContent(exceptionContent)
|
||||||
|
.message(ex.messageToBase64())
|
||||||
|
.response(ex.webcastResponseToBase64());
|
||||||
|
} else {
|
||||||
|
builder.hostName(tiktokUser)
|
||||||
|
.errorName(exception.getClass().getSimpleName())
|
||||||
|
.errorType("error-system")
|
||||||
|
.exceptionContent(exceptionContent)
|
||||||
|
.message("")
|
||||||
|
.response("");
|
||||||
|
}
|
||||||
|
|
||||||
|
var error = builder.build();
|
||||||
|
tikTokDatabase.insertError(error);
|
||||||
|
System.out.println("ERROR: "+error.getErrorName());
|
||||||
|
exception.printStackTrace();
|
||||||
|
|
||||||
|
})
|
||||||
|
.buildAndRun();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
package io.github.jwdeveloper.tiktok.tools.collector.db;
|
||||||
|
|
||||||
|
public class SqlConsts
|
||||||
|
{
|
||||||
|
public static String CREATE_MESSAGES_TABLE = """
|
||||||
|
CREATE TABLE IF NOT EXISTS TikTokMessageModel (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
hostName TEXT,
|
||||||
|
type TEXT,
|
||||||
|
eventName TEXT,
|
||||||
|
eventContent TEXT,
|
||||||
|
createdAt TEXT
|
||||||
|
);
|
||||||
|
""";
|
||||||
|
|
||||||
|
public static String CREATE_ERROR_TABLE = """
|
||||||
|
CREATE TABLE IF NOT EXISTS TikTokErrorModel (
|
||||||
|
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
hostName VARCHAR(255),
|
||||||
|
errorName VARCHAR(255),
|
||||||
|
errorType VARCHAR(255),
|
||||||
|
exceptionContent TEXT,
|
||||||
|
message TEXT,
|
||||||
|
response TEXT,
|
||||||
|
createdAt DATETIME
|
||||||
|
);
|
||||||
|
""";
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
package io.github.jwdeveloper.tiktok.tools.collector.db;
|
||||||
|
|
||||||
|
import io.github.jwdeveloper.tiktok.tools.collector.tables.TikTokErrorModel;
|
||||||
|
import io.github.jwdeveloper.tiktok.tools.collector.tables.TikTokMessageModel;
|
||||||
|
import org.jdbi.v3.core.Jdbi;
|
||||||
|
import org.jdbi.v3.sqlobject.SqlObjectPlugin;
|
||||||
|
|
||||||
|
import java.sql.Connection;
|
||||||
|
import java.sql.DriverManager;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
public class TikTokDatabase
|
||||||
|
{
|
||||||
|
private final String database;
|
||||||
|
private TikTokMessageModelDAO messagesTable;
|
||||||
|
private TikTokErrorModelDAO errorTable;
|
||||||
|
|
||||||
|
public TikTokDatabase(String database) {
|
||||||
|
this.database =database;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void init() throws SQLException {
|
||||||
|
var jdbcUrl ="jdbc:sqlite:"+database+".db";
|
||||||
|
var connection = DriverManager.getConnection(jdbcUrl);
|
||||||
|
Jdbi jdbi = Jdbi.create(jdbcUrl)
|
||||||
|
.installPlugin(new SqlObjectPlugin());
|
||||||
|
jdbi.useHandle(handle -> {
|
||||||
|
handle.execute(SqlConsts.CREATE_MESSAGES_TABLE);
|
||||||
|
handle.execute(SqlConsts.CREATE_ERROR_TABLE);
|
||||||
|
});
|
||||||
|
messagesTable = jdbi.onDemand(TikTokMessageModelDAO.class);
|
||||||
|
errorTable = jdbi.onDemand(TikTokErrorModelDAO.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void insertMessage(TikTokMessageModel message)
|
||||||
|
{
|
||||||
|
var dateFormat = new SimpleDateFormat("dd:MM:yyyy HH:mm:ss.SSS");
|
||||||
|
message.setCreatedAt(dateFormat.format(new Date()));
|
||||||
|
messagesTable.insertTikTokMessage(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void insertError(TikTokErrorModel message)
|
||||||
|
{
|
||||||
|
var dateFormat = new SimpleDateFormat("dd:MM:yyyy HH:mm:ss.SSS");
|
||||||
|
message.setCreatedAt(dateFormat.format(new Date()));
|
||||||
|
errorTable.insertTikTokMessage(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package io.github.jwdeveloper.tiktok.tools.collector.db;
|
||||||
|
|
||||||
|
import io.github.jwdeveloper.tiktok.tools.collector.tables.TikTokErrorModel;
|
||||||
|
|
||||||
|
import org.jdbi.v3.sqlobject.customizer.BindBean;
|
||||||
|
import org.jdbi.v3.sqlobject.statement.SqlUpdate;
|
||||||
|
|
||||||
|
public interface TikTokErrorModelDAO
|
||||||
|
{
|
||||||
|
@SqlUpdate("INSERT INTO TikTokErrorModel (hostName, errorName, errorType, exceptionContent, message, response, createdAt) " +
|
||||||
|
"VALUES (:hostName, :errorName, :errorType, :exceptionContent, :message, :response, :createdAt)")
|
||||||
|
void insertTikTokMessage(@BindBean TikTokErrorModel message);
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package io.github.jwdeveloper.tiktok.tools.collector.db;
|
||||||
|
|
||||||
|
import io.github.jwdeveloper.tiktok.tools.collector.tables.TikTokMessageModel;
|
||||||
|
import org.jdbi.v3.sqlobject.customizer.BindBean;
|
||||||
|
import org.jdbi.v3.sqlobject.statement.SqlUpdate;
|
||||||
|
|
||||||
|
public interface TikTokMessageModelDAO
|
||||||
|
{
|
||||||
|
@SqlUpdate("INSERT INTO TikTokMessageModel (hostName, eventName,type, eventContent, createdAt) " +
|
||||||
|
"VALUES (:hostName, :eventName, :type, :eventContent, :createdAt)")
|
||||||
|
void insertTikTokMessage(@BindBean TikTokMessageModel message);
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
package io.github.jwdeveloper.tiktok.tools.collector.tables;
|
||||||
|
|
||||||
|
import java.io.PrintWriter;
|
||||||
|
import java.io.StringWriter;
|
||||||
|
|
||||||
|
public class ExceptionInfoModel
|
||||||
|
{
|
||||||
|
private String message;
|
||||||
|
private String stackTrace;
|
||||||
|
|
||||||
|
public ExceptionInfoModel(Throwable throwable) {
|
||||||
|
this.message = throwable.getMessage();
|
||||||
|
this.stackTrace = getStackTraceAsString(throwable);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getStackTraceAsString(Throwable throwable) {
|
||||||
|
StringWriter sw = new StringWriter();
|
||||||
|
PrintWriter pw = new PrintWriter(sw);
|
||||||
|
throwable.printStackTrace(pw);
|
||||||
|
return sw.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Getters for message and stackTrace
|
||||||
|
public String getMessage() {
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getStackTrace() {
|
||||||
|
return stackTrace;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
package io.github.jwdeveloper.tiktok.tools.collector.tables;
|
||||||
|
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
public class TikTokErrorModel
|
||||||
|
{
|
||||||
|
private Integer id;
|
||||||
|
|
||||||
|
private String hostName;
|
||||||
|
|
||||||
|
private String errorName;
|
||||||
|
|
||||||
|
private String errorType;
|
||||||
|
|
||||||
|
private String exceptionContent;
|
||||||
|
|
||||||
|
private String message;
|
||||||
|
|
||||||
|
private String response;
|
||||||
|
|
||||||
|
private String createdAt;
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
package io.github.jwdeveloper.tiktok.tools.collector.tables;
|
||||||
|
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
public class TikTokMessageModel
|
||||||
|
{
|
||||||
|
private Integer id;
|
||||||
|
|
||||||
|
private String hostName;
|
||||||
|
|
||||||
|
private String eventName;
|
||||||
|
|
||||||
|
private String type;
|
||||||
|
|
||||||
|
private String eventContent;
|
||||||
|
|
||||||
|
private String createdAt;
|
||||||
|
}
|
||||||
@@ -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>0.0.11-Release</version>
|
<version>0.0.14-Release</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
@@ -33,6 +33,11 @@
|
|||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
<scope>compile</scope>
|
<scope>compile</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jsoup</groupId>
|
||||||
|
<artifactId>jsoup</artifactId>
|
||||||
|
<version>1.13.1</version> <!-- Check for the latest version -->
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>io.github.jwdeveloper.tiktok</groupId>
|
<groupId>io.github.jwdeveloper.tiktok</groupId>
|
||||||
<artifactId>Client</artifactId>
|
<artifactId>Client</artifactId>
|
||||||
|
|||||||
@@ -0,0 +1,43 @@
|
|||||||
|
package io.github.jwdeveloper.tiktok.protocol;
|
||||||
|
|
||||||
|
|
||||||
|
import org.jsoup.Jsoup;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public class ProtocolGenerator
|
||||||
|
{
|
||||||
|
public static void main(String[] args) {
|
||||||
|
// Path to the HTML file
|
||||||
|
File htmlFile = new File("C:\\Users\\ja\\IdeaProjects\\TikTokLiveJava\\Tools\\src\\main\\resources\\page.html");
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Parse the HTML file with Jsoup
|
||||||
|
var doc = Jsoup.parse(htmlFile, "UTF-8");
|
||||||
|
|
||||||
|
// Find all script tags
|
||||||
|
var scriptTags = doc.select("script");
|
||||||
|
|
||||||
|
// Display all script tags
|
||||||
|
int counter = 1;
|
||||||
|
for (var scriptTag : scriptTags) {
|
||||||
|
String srcValue = scriptTag.attr("src");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if(!srcValue.contains("tiktok/webapp/main/webapp-live/"))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// Only print those script tags which have a 'src' attribute
|
||||||
|
if (!srcValue.isEmpty()) {
|
||||||
|
System.out.println("Script Tag " + counter + " src attribute: " + srcValue);
|
||||||
|
}
|
||||||
|
counter++;
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
8
pom.xml
8
pom.xml
@@ -7,12 +7,13 @@
|
|||||||
<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>0.0.11-Release</version>
|
<version>0.0.14-Release</version>
|
||||||
<modules>
|
<modules>
|
||||||
<module>API</module>
|
<module>API</module>
|
||||||
<module>Client</module>
|
<module>Client</module>
|
||||||
<module>Tools</module>
|
<module>Tools</module>
|
||||||
<module>TestApplication</module>
|
<module>TestApplication</module>
|
||||||
|
<module>Tools-EventsCollector</module>
|
||||||
</modules>
|
</modules>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
@@ -54,6 +55,7 @@
|
|||||||
<configuration>
|
<configuration>
|
||||||
<shadedArtifactAttached>true</shadedArtifactAttached>
|
<shadedArtifactAttached>true</shadedArtifactAttached>
|
||||||
<shadedClassifierName>all</shadedClassifierName>
|
<shadedClassifierName>all</shadedClassifierName>
|
||||||
|
<createDependencyReducedPom>false</createDependencyReducedPom>
|
||||||
<minimizeJar>true</minimizeJar>
|
<minimizeJar>true</minimizeJar>
|
||||||
<artifactSet>
|
<artifactSet>
|
||||||
<includes>
|
<includes>
|
||||||
@@ -64,8 +66,6 @@
|
|||||||
<filter>
|
<filter>
|
||||||
<artifact>*:*</artifact>
|
<artifact>*:*</artifact>
|
||||||
<excludes>
|
<excludes>
|
||||||
<exclude>**/proto/**</exclude>
|
|
||||||
<exclude>**/google/**</exclude>
|
|
||||||
<exclude>**/tiktokSchema.proto/**</exclude>
|
<exclude>**/tiktokSchema.proto/**</exclude>
|
||||||
</excludes>
|
</excludes>
|
||||||
</filter>
|
</filter>
|
||||||
@@ -99,6 +99,8 @@
|
|||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
|||||||
Reference in New Issue
Block a user