mirror of
https://github.com/jwdeveloper/TikTokLiveJava.git
synced 2026-02-28 01:09:40 -05:00
Compare commits
41 Commits
1.0.17-Rel
...
develop-1.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5794ff2a57 | ||
|
|
d471e87dd7 | ||
|
|
c89bcad894 | ||
|
|
c9a84c39df | ||
|
|
c1105f1324 | ||
|
|
243ce9bc94 | ||
|
|
4f141edb1a | ||
|
|
359a1508c7 | ||
|
|
bbfa7b410b | ||
|
|
6da40927d0 | ||
|
|
4d97fd9157 | ||
|
|
1ba51476d1 | ||
|
|
9ee5c89f64 | ||
|
|
ffabf098c0 | ||
|
|
7468fc2385 | ||
|
|
abbb557881 | ||
|
|
19c513afe6 | ||
|
|
283024a1d4 | ||
|
|
a0ac9e6d79 | ||
|
|
2385d1e75e | ||
|
|
c9c7f62d4a | ||
|
|
35ef95096d | ||
|
|
46bcfd6eb8 | ||
|
|
38b66395cb | ||
|
|
46e75dec1a | ||
|
|
749cfcf4a6 | ||
|
|
039f2b6a0b | ||
|
|
1a1860e35d | ||
|
|
8a4248daa3 | ||
|
|
ff5310f5bf | ||
|
|
9ddec45740 | ||
|
|
8a7b9e801b | ||
|
|
7b4590d0a1 | ||
|
|
2555edd86f | ||
|
|
a805844522 | ||
|
|
9da96b4417 | ||
|
|
12cf9e641b | ||
|
|
6bfa0b7745 | ||
|
|
cf9b882391 | ||
|
|
913d473442 | ||
|
|
72092bb56b |
@@ -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.16-Release</version>
|
<version>1.2.0-Release</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<artifactId>API</artifactId>
|
<artifactId>API</artifactId>
|
||||||
|
|||||||
@@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2023-2023 jwdeveloper jacekwoln@gmail.com
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
* a copy of this software and associated documentation files (the
|
||||||
|
* "Software"), to deal in the Software without restriction, including
|
||||||
|
* without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
* permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
* the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
package io.github.jwdeveloper.tiktok.data.events.control;
|
||||||
|
|
||||||
|
import io.github.jwdeveloper.tiktok.annotations.EventMeta;
|
||||||
|
import io.github.jwdeveloper.tiktok.annotations.EventType;
|
||||||
|
import io.github.jwdeveloper.tiktok.data.events.common.TikTokLiveClientEvent;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Triggered when client is connecting to live is successfully established.
|
||||||
|
*/
|
||||||
|
@EventMeta(eventType = EventType.Control)
|
||||||
|
public class TikTokConnectingEvent extends TikTokLiveClientEvent
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2023-2023 jwdeveloper jacekwoln@gmail.com
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
* a copy of this software and associated documentation files (the
|
||||||
|
* "Software"), to deal in the Software without restriction, including
|
||||||
|
* without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
* permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
* the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
package io.github.jwdeveloper.tiktok.data.events.control;
|
||||||
|
|
||||||
|
import io.github.jwdeveloper.tiktok.annotations.*;
|
||||||
|
import io.github.jwdeveloper.tiktok.data.events.common.TikTokLiveClientEvent;
|
||||||
|
import io.github.jwdeveloper.tiktok.data.requests.*;
|
||||||
|
import lombok.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Triggered before the connection is established.
|
||||||
|
*/
|
||||||
|
@EventMeta(eventType = EventType.Control)
|
||||||
|
public class TikTokPreConnectionEvent extends TikTokLiveClientEvent
|
||||||
|
{
|
||||||
|
@Getter private final LiveUserData.Response userData;
|
||||||
|
@Getter private final LiveData.Response roomData;
|
||||||
|
@Getter @Setter boolean cancelConnection = false;
|
||||||
|
|
||||||
|
public TikTokPreConnectionEvent(LiveUserData.Response userData, LiveData.Response liveData) {
|
||||||
|
this.userData = userData;
|
||||||
|
this.roomData = liveData;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2023-2023 jwdeveloper jacekwoln@gmail.com
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
* a copy of this software and associated documentation files (the
|
||||||
|
* "Software"), to deal in the Software without restriction, including
|
||||||
|
* without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
* permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
* the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
package io.github.jwdeveloper.tiktok.data.events.http;
|
||||||
|
|
||||||
|
import io.github.jwdeveloper.tiktok.annotations.EventMeta;
|
||||||
|
import io.github.jwdeveloper.tiktok.annotations.EventType;
|
||||||
|
import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent;
|
||||||
|
import io.github.jwdeveloper.tiktok.data.requests.LiveData;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@AllArgsConstructor
|
||||||
|
@EventMeta(eventType = EventType.Debug)
|
||||||
|
public class TikTokRoomDataResponseEvent extends TikTokEvent
|
||||||
|
{
|
||||||
|
private final LiveData.Response liveData;
|
||||||
|
}
|
||||||
@@ -44,6 +44,7 @@ public class LiveData {
|
|||||||
private int totalViewers;
|
private int totalViewers;
|
||||||
private boolean ageRestricted;
|
private boolean ageRestricted;
|
||||||
private User host;
|
private User host;
|
||||||
|
private LiveType liveType;
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum LiveStatus {
|
public enum LiveStatus {
|
||||||
@@ -51,4 +52,11 @@ public class LiveData {
|
|||||||
HostOnline,
|
HostOnline,
|
||||||
HostOffline,
|
HostOffline,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public enum LiveType {
|
||||||
|
SOLO,
|
||||||
|
BOX,
|
||||||
|
BATTLE,
|
||||||
|
CO_HOST
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -36,7 +36,6 @@ public class LiveClientSettings {
|
|||||||
/**
|
/**
|
||||||
* ISO-Language for Client
|
* ISO-Language for Client
|
||||||
*/
|
*/
|
||||||
|
|
||||||
private String clientLanguage;
|
private String clientLanguage;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -44,7 +43,6 @@ public class LiveClientSettings {
|
|||||||
*/
|
*/
|
||||||
private boolean retryOnConnectionFailure;
|
private boolean retryOnConnectionFailure;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Before retrying connect, wait for select amount of time
|
* Before retrying connect, wait for select amount of time
|
||||||
*/
|
*/
|
||||||
@@ -53,41 +51,39 @@ public class LiveClientSettings {
|
|||||||
/**
|
/**
|
||||||
* Whether to print Logs to Console
|
* Whether to print Logs to Console
|
||||||
*/
|
*/
|
||||||
|
|
||||||
private boolean printToConsole = true;
|
private boolean printToConsole = true;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* LoggingLevel for Logs
|
* LoggingLevel for Logs
|
||||||
*/
|
*/
|
||||||
private Level logLevel;
|
private Level logLevel;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Optional: Use it if you need to change TikTok live hostname in builder
|
* Optional: Use it if you need to change TikTok live hostname in builder
|
||||||
*/
|
*/
|
||||||
private String hostName;
|
private String hostName;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parameters used in requests to TikTok api
|
* Parameters used in requests to TikTok api
|
||||||
*/
|
*/
|
||||||
private HttpClientSettings httpSettings;
|
private HttpClientSettings httpSettings;
|
||||||
|
|
||||||
|
/**
|
||||||
/*
|
|
||||||
* Optional: Sometimes not every messages from chat are send to TikTokLiveJava to fix this issue you can set sessionId
|
* Optional: Sometimes not every messages from chat are send to TikTokLiveJava to fix this issue you can set sessionId
|
||||||
* documentation how to obtain sessionId https://github.com/isaackogan/TikTok-Live-Connector#send-chat-messages
|
* documentation how to obtain sessionId https://github.com/isaackogan/TikTok-Live-Connector#send-chat-messages
|
||||||
*/
|
*/
|
||||||
private String sessionId;
|
private String sessionId;
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* Optional: By default roomID is fetched before connect to live, but you can set it manually
|
* Optional: By default roomID is fetched before connect to live, but you can set it manually
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
private String roomId;
|
private String roomId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Optional: API Key for increased limit to signing server
|
||||||
|
*/
|
||||||
|
private String apiKey;
|
||||||
|
|
||||||
public static LiveClientSettings createDefault()
|
public static LiveClientSettings createDefault()
|
||||||
{
|
{
|
||||||
@@ -103,12 +99,10 @@ public class LiveClientSettings {
|
|||||||
clientSettings.setPrintToConsole(false);
|
clientSettings.setPrintToConsole(false);
|
||||||
clientSettings.setLogLevel(Level.ALL);
|
clientSettings.setLogLevel(Level.ALL);
|
||||||
|
|
||||||
|
|
||||||
clientSettings.setHttpSettings(httpSettings);
|
clientSettings.setHttpSettings(httpSettings);
|
||||||
return clientSettings;
|
return clientSettings;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default Parameters for HTTP-Request
|
* Default Parameters for HTTP-Request
|
||||||
*/
|
*/
|
||||||
@@ -147,11 +141,9 @@ public class LiveClientSettings {
|
|||||||
clientParams.put("webcast_sdk_version", "1.3.0");
|
clientParams.put("webcast_sdk_version", "1.3.0");
|
||||||
clientParams.put("update_version_code", "1.3.0");
|
clientParams.put("update_version_code", "1.3.0");
|
||||||
|
|
||||||
|
|
||||||
return clientParams;
|
return clientParams;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default Headers for HTTP-Request
|
* Default Headers for HTTP-Request
|
||||||
*/
|
*/
|
||||||
@@ -167,6 +159,4 @@ public class LiveClientSettings {
|
|||||||
headers.put("Accept-Language", "en-US,en; q=0.9");
|
headers.put("Accept-Language", "en-US,en; q=0.9");
|
||||||
return headers;
|
return headers;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -33,11 +33,10 @@ import java.util.function.Consumer;
|
|||||||
@Setter
|
@Setter
|
||||||
public class ProxyClientSettings implements Iterator<ProxyData>
|
public class ProxyClientSettings implements Iterator<ProxyData>
|
||||||
{
|
{
|
||||||
private boolean enabled, lastSuccess;
|
private boolean enabled, autoDiscard = true, fallback = true;
|
||||||
private Rotation rotation = Rotation.CONSECUTIVE;
|
private Rotation rotation = Rotation.CONSECUTIVE;
|
||||||
private final List<ProxyData> proxyList = new ArrayList<>();
|
private final List<ProxyData> proxyList = new ArrayList<>();
|
||||||
private int index = 0;
|
private int index = -1;
|
||||||
private boolean autoDiscard = true;
|
|
||||||
private Proxy.Type type = Proxy.Type.DIRECT;
|
private Proxy.Type type = Proxy.Type.DIRECT;
|
||||||
private Consumer<ProxyData> onProxyUpdated = x -> {};
|
private Consumer<ProxyData> onProxyUpdated = x -> {};
|
||||||
|
|
||||||
@@ -64,10 +63,6 @@ public class ProxyClientSettings implements Iterator<ProxyData>
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ProxyData next() {
|
public ProxyData next() {
|
||||||
return lastSuccess ? proxyList.get(index) : rotate();
|
|
||||||
}
|
|
||||||
|
|
||||||
public ProxyData rotate() {
|
|
||||||
var nextProxy = switch (rotation)
|
var nextProxy = switch (rotation)
|
||||||
{
|
{
|
||||||
case CONSECUTIVE -> {
|
case CONSECUTIVE -> {
|
||||||
@@ -78,7 +73,10 @@ public class ProxyClientSettings implements Iterator<ProxyData>
|
|||||||
index = new Random().nextInt(proxyList.size());
|
index = new Random().nextInt(proxyList.size());
|
||||||
yield proxyList.get(index).clone();
|
yield proxyList.get(index).clone();
|
||||||
}
|
}
|
||||||
case NONE -> proxyList.get(index).clone();
|
case NONE -> {
|
||||||
|
index = Math.max(index, 0);
|
||||||
|
yield proxyList.get(index).clone();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
onProxyUpdated.accept(nextProxy);
|
onProxyUpdated.accept(nextProxy);
|
||||||
return nextProxy;
|
return nextProxy;
|
||||||
@@ -98,6 +96,7 @@ public class ProxyClientSettings implements Iterator<ProxyData>
|
|||||||
this.index = index;
|
this.index = index;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ProxyClientSettings clone()
|
public ProxyClientSettings clone()
|
||||||
{
|
{
|
||||||
ProxyClientSettings settings = new ProxyClientSettings();
|
ProxyClientSettings settings = new ProxyClientSettings();
|
||||||
|
|||||||
@@ -23,7 +23,7 @@
|
|||||||
package io.github.jwdeveloper.tiktok.exceptions;
|
package io.github.jwdeveloper.tiktok.exceptions;
|
||||||
|
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* Happens while bad response from Http request to TikTok
|
* Happens while bad response from Http request to TikTok
|
||||||
*/
|
*/
|
||||||
public class TikTokLiveRequestException extends TikTokLiveException
|
public class TikTokLiveRequestException extends TikTokLiveException
|
||||||
|
|||||||
@@ -27,9 +27,8 @@ import io.github.jwdeveloper.tiktok.data.requests.LiveConnectionData;
|
|||||||
import io.github.jwdeveloper.tiktok.data.requests.LiveData;
|
import io.github.jwdeveloper.tiktok.data.requests.LiveData;
|
||||||
import io.github.jwdeveloper.tiktok.data.requests.LiveUserData;
|
import io.github.jwdeveloper.tiktok.data.requests.LiveUserData;
|
||||||
|
|
||||||
public interface LiveHttpClient {
|
public interface LiveHttpClient
|
||||||
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return list of gifts that are available in your country
|
* @return list of gifts that are available in your country
|
||||||
*/
|
*/
|
||||||
@@ -37,28 +36,32 @@ public interface LiveHttpClient {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns information about user that is having a livestream
|
* Returns information about user that is having a livestream
|
||||||
*
|
* @param userName name of user
|
||||||
* @param userName
|
* @return {@link LiveUserData.Response}
|
||||||
* @return
|
|
||||||
*/
|
*/
|
||||||
LiveUserData.Response fetchLiveUserData(String userName);
|
default LiveUserData.Response fetchLiveUserData(String userName) {
|
||||||
|
return fetchLiveUserData(new LiveUserData.Request(userName));
|
||||||
|
}
|
||||||
|
|
||||||
LiveUserData.Response fetchLiveUserData(LiveUserData.Request request);
|
LiveUserData.Response fetchLiveUserData(LiveUserData.Request request);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param roomId can be obtained from browsers cookies or by invoked fetchLiveUserData
|
* @param roomId can be obtained from browsers cookies or by invoked fetchLiveUserData
|
||||||
* @return
|
* @return {@link LiveData.Response}
|
||||||
*/
|
*/
|
||||||
LiveData.Response fetchLiveData(String roomId);
|
default LiveData.Response fetchLiveData(String roomId) {
|
||||||
|
return fetchLiveData(new LiveData.Request(roomId));
|
||||||
|
}
|
||||||
|
|
||||||
LiveData.Response fetchLiveData(LiveData.Request request);
|
LiveData.Response fetchLiveData(LiveData.Request request);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param roomId can be obtained from browsers cookies or by invoked fetchLiveUserData
|
* @param roomId can be obtained from browsers cookies or by invoked fetchLiveUserData
|
||||||
* @return
|
* @return {@link LiveConnectionData.Response}
|
||||||
*/
|
*/
|
||||||
LiveConnectionData.Response fetchLiveConnectionData(String roomId);
|
default LiveConnectionData.Response fetchLiveConnectionData(String roomId) {
|
||||||
|
return fetchLiveConnectionData(new LiveConnectionData.Request(roomId));
|
||||||
|
}
|
||||||
|
|
||||||
LiveConnectionData.Response fetchLiveConnectionData(LiveConnectionData.Request request);
|
LiveConnectionData.Response fetchLiveConnectionData(LiveConnectionData.Request request);
|
||||||
}
|
}
|
||||||
@@ -24,6 +24,7 @@ package io.github.jwdeveloper.tiktok.live.builder;
|
|||||||
|
|
||||||
import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent;
|
import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent;
|
||||||
import io.github.jwdeveloper.tiktok.data.events.*;
|
import io.github.jwdeveloper.tiktok.data.events.*;
|
||||||
|
import io.github.jwdeveloper.tiktok.data.events.control.TikTokPreConnectionEvent;
|
||||||
import io.github.jwdeveloper.tiktok.data.events.gift.TikTokGiftComboEvent;
|
import io.github.jwdeveloper.tiktok.data.events.gift.TikTokGiftComboEvent;
|
||||||
import io.github.jwdeveloper.tiktok.data.events.gift.TikTokGiftEvent;
|
import io.github.jwdeveloper.tiktok.data.events.gift.TikTokGiftEvent;
|
||||||
import io.github.jwdeveloper.tiktok.data.events.http.TikTokHttpResponseEvent;
|
import io.github.jwdeveloper.tiktok.data.events.http.TikTokHttpResponseEvent;
|
||||||
@@ -149,6 +150,13 @@ public interface EventsBuilder<T> {
|
|||||||
*/
|
*/
|
||||||
T onConnected(EventConsumer<TikTokConnectedEvent> action);
|
T onConnected(EventConsumer<TikTokConnectedEvent> action);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invoked before client has been successfully connected to live
|
||||||
|
* @param action
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
T onPreConnection(EventConsumer<TikTokPreConnectionEvent> action);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Invoked when client tries to reconnect
|
* Invoked when client tries to reconnect
|
||||||
* @param action
|
* @param action
|
||||||
@@ -216,5 +224,3 @@ public interface EventsBuilder<T> {
|
|||||||
|
|
||||||
//T onUnhandledControl(TikTokEventConsumer<TikTokUnhandledControlEvent> event);
|
//T onUnhandledControl(TikTokEventConsumer<TikTokUnhandledControlEvent> event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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.16-Release</version>
|
<version>1.2.0-Release</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
@@ -39,7 +39,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.java-websocket</groupId>
|
<groupId>org.java-websocket</groupId>
|
||||||
<artifactId>Java-WebSocket</artifactId>
|
<artifactId>Java-WebSocket</artifactId>
|
||||||
<version>1.5.4</version>
|
<version>1.5.5</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.testng</groupId>
|
<groupId>org.testng</groupId>
|
||||||
|
|||||||
@@ -50,7 +50,6 @@ public class TikTokLive {
|
|||||||
return requests().fetchLiveUserData(hostName).isLiveOnline();
|
return requests().fetchLiveUserData(hostName).isLiveOnline();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param hostName profile name of Tiktok user could be found in profile link
|
* @param hostName profile name of Tiktok user could be found in profile link
|
||||||
|
|||||||
@@ -26,12 +26,13 @@ import io.github.jwdeveloper.tiktok.data.events.TikTokDisconnectedEvent;
|
|||||||
import io.github.jwdeveloper.tiktok.data.events.TikTokErrorEvent;
|
import io.github.jwdeveloper.tiktok.data.events.TikTokErrorEvent;
|
||||||
import io.github.jwdeveloper.tiktok.data.events.TikTokReconnectingEvent;
|
import io.github.jwdeveloper.tiktok.data.events.TikTokReconnectingEvent;
|
||||||
import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent;
|
import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent;
|
||||||
|
import io.github.jwdeveloper.tiktok.data.events.control.*;
|
||||||
|
import io.github.jwdeveloper.tiktok.data.events.http.TikTokRoomDataResponseEvent;
|
||||||
import io.github.jwdeveloper.tiktok.data.events.room.TikTokRoomInfoEvent;
|
import io.github.jwdeveloper.tiktok.data.events.room.TikTokRoomInfoEvent;
|
||||||
import io.github.jwdeveloper.tiktok.data.requests.LiveConnectionData;
|
import io.github.jwdeveloper.tiktok.data.requests.LiveConnectionData;
|
||||||
import io.github.jwdeveloper.tiktok.data.requests.LiveData;
|
import io.github.jwdeveloper.tiktok.data.requests.LiveData;
|
||||||
import io.github.jwdeveloper.tiktok.data.requests.LiveUserData;
|
import io.github.jwdeveloper.tiktok.data.requests.LiveUserData;
|
||||||
import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveException;
|
import io.github.jwdeveloper.tiktok.exceptions.*;
|
||||||
import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveOfflineHostException;
|
|
||||||
import io.github.jwdeveloper.tiktok.gifts.TikTokGiftManager;
|
import io.github.jwdeveloper.tiktok.gifts.TikTokGiftManager;
|
||||||
import io.github.jwdeveloper.tiktok.listener.ListenersManager;
|
import io.github.jwdeveloper.tiktok.listener.ListenersManager;
|
||||||
import io.github.jwdeveloper.tiktok.listener.TikTokListenersManager;
|
import io.github.jwdeveloper.tiktok.listener.TikTokListenersManager;
|
||||||
@@ -120,26 +121,31 @@ public class TikTokLiveClient implements LiveClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
setState(ConnectionState.CONNECTING);
|
setState(ConnectionState.CONNECTING);
|
||||||
|
tikTokEventHandler.publish(this,new TikTokConnectingEvent());
|
||||||
var userDataRequest = new LiveUserData.Request(liveRoomInfo.getHostName());
|
var userDataRequest = new LiveUserData.Request(liveRoomInfo.getHostName());
|
||||||
var userData = httpClient.fetchLiveUserData(userDataRequest);
|
var userData = httpClient.fetchLiveUserData(userDataRequest);
|
||||||
liveRoomInfo.setStartTime(userData.getStartedAtTimeStamp());
|
liveRoomInfo.setStartTime(userData.getStartedAtTimeStamp());
|
||||||
liveRoomInfo.setRoomId(userData.getRoomId());
|
liveRoomInfo.setRoomId(userData.getRoomId());
|
||||||
if (userData.getUserStatus() == LiveUserData.UserStatus.Offline) {
|
|
||||||
throw new TikTokLiveOfflineHostException("User is offline: "+liveRoomInfo.getHostUser());
|
if (userData.getUserStatus() == LiveUserData.UserStatus.Offline)
|
||||||
}
|
throw new TikTokLiveOfflineHostException("User is offline: "+liveRoomInfo.getHostName());
|
||||||
if (userData.getUserStatus() == LiveUserData.UserStatus.NotFound) {
|
|
||||||
throw new TikTokLiveOfflineHostException("User not found: "+liveRoomInfo.getHostUser());
|
if (userData.getUserStatus() == LiveUserData.UserStatus.NotFound)
|
||||||
}
|
throw new TikTokLiveOfflineHostException("User not found: "+liveRoomInfo.getHostName());
|
||||||
|
|
||||||
var liveDataRequest = new LiveData.Request(userData.getRoomId());
|
var liveDataRequest = new LiveData.Request(userData.getRoomId());
|
||||||
var liveData = httpClient.fetchLiveData(liveDataRequest);
|
var liveData = httpClient.fetchLiveData(liveDataRequest);
|
||||||
if (liveData.getLiveStatus() == LiveData.LiveStatus.HostNotFound) {
|
|
||||||
throw new TikTokLiveOfflineHostException("LiveStream for Host name could not be found.");
|
if (liveData.isAgeRestricted())
|
||||||
}
|
throw new TikTokLiveException("Livestream for "+liveRoomInfo.getHostName()+" is 18+ or age restricted!");
|
||||||
if (liveData.getLiveStatus() == LiveData.LiveStatus.HostOffline) {
|
|
||||||
throw new TikTokLiveOfflineHostException("LiveStream for not be found, is the Host offline?");
|
if (liveData.getLiveStatus() == LiveData.LiveStatus.HostNotFound)
|
||||||
}
|
throw new TikTokLiveOfflineHostException("LiveStream for "+liveRoomInfo.getHostName()+" could not be found.");
|
||||||
|
|
||||||
|
if (liveData.getLiveStatus() == LiveData.LiveStatus.HostOffline)
|
||||||
|
throw new TikTokLiveOfflineHostException("LiveStream for "+liveRoomInfo.getHostName()+" not found, is the Host offline?");
|
||||||
|
|
||||||
|
tikTokEventHandler.publish(this, new TikTokRoomDataResponseEvent(liveData));
|
||||||
|
|
||||||
liveRoomInfo.setTitle(liveData.getTitle());
|
liveRoomInfo.setTitle(liveData.getTitle());
|
||||||
liveRoomInfo.setViewersCount(liveData.getViewers());
|
liveRoomInfo.setViewersCount(liveData.getViewers());
|
||||||
@@ -147,6 +153,11 @@ public class TikTokLiveClient implements LiveClient {
|
|||||||
liveRoomInfo.setAgeRestricted(liveData.isAgeRestricted());
|
liveRoomInfo.setAgeRestricted(liveData.isAgeRestricted());
|
||||||
liveRoomInfo.setHost(liveData.getHost());
|
liveRoomInfo.setHost(liveData.getHost());
|
||||||
|
|
||||||
|
var preconnectEvent = new TikTokPreConnectionEvent(userData, liveData);
|
||||||
|
tikTokEventHandler.publish(this, preconnectEvent);
|
||||||
|
if (preconnectEvent.isCancelConnection())
|
||||||
|
throw new TikTokLiveException("TikTokPreConnectionEvent cancelled connection!");
|
||||||
|
|
||||||
var liveConnectionRequest =new LiveConnectionData.Request(userData.getRoomId());
|
var liveConnectionRequest =new LiveConnectionData.Request(userData.getRoomId());
|
||||||
var liveConnectionData = httpClient.fetchLiveConnectionData(liveConnectionRequest);
|
var liveConnectionData = httpClient.fetchLiveConnectionData(liveConnectionRequest);
|
||||||
webSocketClient.start(liveConnectionData, this);
|
webSocketClient.start(liveConnectionData, this);
|
||||||
@@ -159,8 +170,8 @@ public class TikTokLiveClient implements LiveClient {
|
|||||||
if (liveRoomInfo.hasConnectionState(ConnectionState.DISCONNECTED)) {
|
if (liveRoomInfo.hasConnectionState(ConnectionState.DISCONNECTED)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
webSocketClient.stop();
|
|
||||||
setState(ConnectionState.DISCONNECTED);
|
setState(ConnectionState.DISCONNECTED);
|
||||||
|
webSocketClient.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setState(ConnectionState connectionState) {
|
private void setState(ConnectionState connectionState) {
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ package io.github.jwdeveloper.tiktok;
|
|||||||
|
|
||||||
import io.github.jwdeveloper.tiktok.data.events.*;
|
import io.github.jwdeveloper.tiktok.data.events.*;
|
||||||
import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent;
|
import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent;
|
||||||
|
import io.github.jwdeveloper.tiktok.data.events.control.TikTokPreConnectionEvent;
|
||||||
import io.github.jwdeveloper.tiktok.data.events.envelop.TikTokChestEvent;
|
import io.github.jwdeveloper.tiktok.data.events.envelop.TikTokChestEvent;
|
||||||
import io.github.jwdeveloper.tiktok.data.events.gift.TikTokGiftComboEvent;
|
import io.github.jwdeveloper.tiktok.data.events.gift.TikTokGiftComboEvent;
|
||||||
import io.github.jwdeveloper.tiktok.data.events.gift.TikTokGiftEvent;
|
import io.github.jwdeveloper.tiktok.data.events.gift.TikTokGiftEvent;
|
||||||
@@ -98,6 +99,7 @@ public class TikTokLiveClientBuilder implements LiveClientBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public TikTokLiveClientBuilder addListener(TikTokEventListener listener) {
|
public TikTokLiveClientBuilder addListener(TikTokEventListener listener) {
|
||||||
|
if (listener != null)
|
||||||
listeners.add(listener);
|
listeners.add(listener);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@@ -275,9 +277,7 @@ public class TikTokLiveClientBuilder implements LiveClientBuilder {
|
|||||||
return build().connectAsync();
|
return build().connectAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public TikTokLiveClientBuilder onUnhandledSocial(EventConsumer<TikTokUnhandledSocialEvent> event) {
|
||||||
public TikTokLiveClientBuilder onUnhandledSocial(
|
|
||||||
EventConsumer<TikTokUnhandledSocialEvent> event) {
|
|
||||||
tikTokEventHandler.subscribe(TikTokUnhandledSocialEvent.class, event);
|
tikTokEventHandler.subscribe(TikTokUnhandledSocialEvent.class, event);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@@ -289,8 +289,7 @@ public class TikTokLiveClientBuilder implements LiveClientBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public TikTokLiveClientBuilder onLinkMicFanTicket(
|
public TikTokLiveClientBuilder onLinkMicFanTicket(EventConsumer<TikTokLinkMicFanTicketEvent> event) {
|
||||||
EventConsumer<TikTokLinkMicFanTicketEvent> event) {
|
|
||||||
tikTokEventHandler.subscribe(TikTokLinkMicFanTicketEvent.class, event);
|
tikTokEventHandler.subscribe(TikTokLinkMicFanTicketEvent.class, event);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@@ -305,14 +304,12 @@ public class TikTokLiveClientBuilder implements LiveClientBuilder {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TikTokLiveClientBuilder onDetect(
|
public TikTokLiveClientBuilder onDetect(EventConsumer<TikTokDetectEvent> event) {
|
||||||
EventConsumer<TikTokDetectEvent> event) {
|
|
||||||
tikTokEventHandler.subscribe(TikTokDetectEvent.class, event);
|
tikTokEventHandler.subscribe(TikTokDetectEvent.class, event);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TikTokLiveClientBuilder onLinkLayer(
|
public TikTokLiveClientBuilder onLinkLayer(EventConsumer<TikTokLinkLayerEvent> event) {
|
||||||
EventConsumer<TikTokLinkLayerEvent> event) {
|
|
||||||
tikTokEventHandler.subscribe(TikTokLinkLayerEvent.class, event);
|
tikTokEventHandler.subscribe(TikTokLinkLayerEvent.class, event);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@@ -322,6 +319,11 @@ public class TikTokLiveClientBuilder implements LiveClientBuilder {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public TikTokLiveClientBuilder onPreConnection(EventConsumer<TikTokPreConnectionEvent> event) {
|
||||||
|
tikTokEventHandler.subscribe(TikTokPreConnectionEvent.class, event);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public TikTokLiveClientBuilder onCaption(EventConsumer<TikTokCaptionEvent> event) {
|
public TikTokLiveClientBuilder onCaption(EventConsumer<TikTokCaptionEvent> event) {
|
||||||
tikTokEventHandler.subscribe(TikTokCaptionEvent.class, event);
|
tikTokEventHandler.subscribe(TikTokCaptionEvent.class, event);
|
||||||
return this;
|
return this;
|
||||||
@@ -332,8 +334,7 @@ public class TikTokLiveClientBuilder implements LiveClientBuilder {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TikTokLiveClientBuilder onRoomPin(
|
public TikTokLiveClientBuilder onRoomPin(EventConsumer<TikTokRoomPinEvent> event) {
|
||||||
EventConsumer<TikTokRoomPinEvent> event) {
|
|
||||||
tikTokEventHandler.subscribe(TikTokRoomPinEvent.class, event);
|
tikTokEventHandler.subscribe(TikTokRoomPinEvent.class, event);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@@ -373,8 +374,7 @@ public class TikTokLiveClientBuilder implements LiveClientBuilder {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TikTokLiveClientBuilder onBarrage(
|
public TikTokLiveClientBuilder onBarrage(EventConsumer<TikTokBarrageEvent> event) {
|
||||||
EventConsumer<TikTokBarrageEvent> event) {
|
|
||||||
tikTokEventHandler.subscribe(TikTokBarrageEvent.class, event);
|
tikTokEventHandler.subscribe(TikTokBarrageEvent.class, event);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@@ -391,8 +391,7 @@ public class TikTokLiveClientBuilder implements LiveClientBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public TikTokLiveClientBuilder onLinkMicArmies(
|
public TikTokLiveClientBuilder onLinkMicArmies(EventConsumer<TikTokLinkMicArmiesEvent> event) {
|
||||||
EventConsumer<TikTokLinkMicArmiesEvent> event) {
|
|
||||||
tikTokEventHandler.subscribe(TikTokLinkMicArmiesEvent.class, event);
|
tikTokEventHandler.subscribe(TikTokLinkMicArmiesEvent.class, event);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@@ -402,20 +401,17 @@ public class TikTokLiveClientBuilder implements LiveClientBuilder {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TikTokLiveClientBuilder onUnauthorizedMember(
|
public TikTokLiveClientBuilder onUnauthorizedMember(EventConsumer<TikTokUnauthorizedMemberEvent> event) {
|
||||||
EventConsumer<TikTokUnauthorizedMemberEvent> event) {
|
|
||||||
tikTokEventHandler.subscribe(TikTokUnauthorizedMemberEvent.class, event);
|
tikTokEventHandler.subscribe(TikTokUnauthorizedMemberEvent.class, event);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TikTokLiveClientBuilder onInRoomBanner(
|
public TikTokLiveClientBuilder onInRoomBanner(EventConsumer<TikTokInRoomBannerEvent> event) {
|
||||||
EventConsumer<TikTokInRoomBannerEvent> event) {
|
|
||||||
tikTokEventHandler.subscribe(TikTokInRoomBannerEvent.class, event);
|
tikTokEventHandler.subscribe(TikTokInRoomBannerEvent.class, event);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TikTokLiveClientBuilder onLinkMicMethod(
|
public TikTokLiveClientBuilder onLinkMicMethod(EventConsumer<TikTokLinkMicMethodEvent> event) {
|
||||||
EventConsumer<TikTokLinkMicMethodEvent> event) {
|
|
||||||
tikTokEventHandler.subscribe(TikTokLinkMicMethodEvent.class, event);
|
tikTokEventHandler.subscribe(TikTokLinkMicMethodEvent.class, event);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@@ -487,8 +483,7 @@ public class TikTokLiveClientBuilder implements LiveClientBuilder {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TikTokLiveClientBuilder onUnhandledMember(
|
public TikTokLiveClientBuilder onUnhandledMember(EventConsumer<TikTokUnhandledMemberEvent> event) {
|
||||||
EventConsumer<TikTokUnhandledMemberEvent> event) {
|
|
||||||
tikTokEventHandler.subscribe(TikTokUnhandledMemberEvent.class, event);
|
tikTokEventHandler.subscribe(TikTokUnhandledMemberEvent.class, event);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@@ -498,20 +493,17 @@ public class TikTokLiveClientBuilder implements LiveClientBuilder {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TikTokLiveClientBuilder onLinkMicBattle(
|
public TikTokLiveClientBuilder onLinkMicBattle(EventConsumer<TikTokLinkMicBattleEvent> event) {
|
||||||
EventConsumer<TikTokLinkMicBattleEvent> event) {
|
|
||||||
tikTokEventHandler.subscribe(TikTokLinkMicBattleEvent.class, event);
|
tikTokEventHandler.subscribe(TikTokLinkMicBattleEvent.class, event);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TikTokLiveClientBuilder onDisconnected(
|
public TikTokLiveClientBuilder onDisconnected(EventConsumer<TikTokDisconnectedEvent> event) {
|
||||||
EventConsumer<TikTokDisconnectedEvent> event) {
|
|
||||||
tikTokEventHandler.subscribe(TikTokDisconnectedEvent.class, event);
|
tikTokEventHandler.subscribe(TikTokDisconnectedEvent.class, event);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TikTokLiveClientBuilder onUnhandledControl(
|
public TikTokLiveClientBuilder onUnhandledControl(EventConsumer<TikTokUnhandledControlEvent> event) {
|
||||||
EventConsumer<TikTokUnhandledControlEvent> event) {
|
|
||||||
tikTokEventHandler.subscribe(TikTokUnhandledControlEvent.class, event);
|
tikTokEventHandler.subscribe(TikTokUnhandledControlEvent.class, event);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,18 +36,17 @@ import java.util.Optional;
|
|||||||
public class TikTokLiveHttpClient implements LiveHttpClient {
|
public class TikTokLiveHttpClient implements LiveHttpClient {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Signing API by Isaac Kogan
|
* <a href="https://github-wiki-see.page/m/isaackogan/TikTokLive/wiki/All-About-Signatures">Signing API by Isaac Kogan</a>
|
||||||
* https://github-wiki-see.page/m/isaackogan/TikTokLive/wiki/All-About-Signatures
|
|
||||||
*/
|
*/
|
||||||
private static final String TIKTOK_SIGN_API = "https://tiktok.eulerstream.com/webcast/sign_url";
|
private static final String TIKTOK_SIGN_API = "https://tiktok.eulerstream.com/webcast/fetch";
|
||||||
private static final String TIKTOK_URL_WEB = "https://www.tiktok.com/";
|
private static final String TIKTOK_URL_WEB = "https://www.tiktok.com/";
|
||||||
private static final String TIKTOK_URL_WEBCAST = "https://webcast.tiktok.com/webcast/";
|
private static final String TIKTOK_URL_WEBCAST = "https://webcast.tiktok.com/webcast/";
|
||||||
|
public static final int TIKTOK_AGE_RESTRICTED_CODE = 4003110;
|
||||||
|
|
||||||
private final HttpClientFactory httpFactory;
|
private final HttpClientFactory httpFactory;
|
||||||
private final LiveClientSettings clientSettings;
|
private final LiveClientSettings clientSettings;
|
||||||
private final LiveUserDataMapper liveUserDataMapper;
|
private final LiveUserDataMapper liveUserDataMapper;
|
||||||
private final LiveDataMapper liveDataMapper;
|
private final LiveDataMapper liveDataMapper;
|
||||||
private final SignServerResponseMapper signServerResponseMapper;
|
|
||||||
private final GiftsDataMapper giftsDataMapper;
|
private final GiftsDataMapper giftsDataMapper;
|
||||||
|
|
||||||
public TikTokLiveHttpClient(HttpClientFactory factory, LiveClientSettings settings) {
|
public TikTokLiveHttpClient(HttpClientFactory factory, LiveClientSettings settings) {
|
||||||
@@ -55,7 +54,6 @@ public class TikTokLiveHttpClient implements LiveHttpClient {
|
|||||||
clientSettings = settings;
|
clientSettings = settings;
|
||||||
liveUserDataMapper = new LiveUserDataMapper();
|
liveUserDataMapper = new LiveUserDataMapper();
|
||||||
liveDataMapper = new LiveDataMapper();
|
liveDataMapper = new LiveDataMapper();
|
||||||
signServerResponseMapper = new SignServerResponseMapper();
|
|
||||||
giftsDataMapper = new GiftsDataMapper();
|
giftsDataMapper = new GiftsDataMapper();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,6 +64,10 @@ public class TikTokLiveHttpClient implements LiveHttpClient {
|
|||||||
|
|
||||||
public GiftsData.Response fetchGiftsData() {
|
public GiftsData.Response fetchGiftsData() {
|
||||||
var url = TIKTOK_URL_WEBCAST + "gift/list/";
|
var url = TIKTOK_URL_WEBCAST + "gift/list/";
|
||||||
|
var proxyClientSettings = clientSettings.getHttpSettings().getProxyClientSettings();
|
||||||
|
if (proxyClientSettings.isEnabled()) {
|
||||||
|
while (proxyClientSettings.hasNext()) {
|
||||||
|
try {
|
||||||
var optional = httpFactory.client(url)
|
var optional = httpFactory.client(url)
|
||||||
.build()
|
.build()
|
||||||
.toJsonResponse();
|
.toJsonResponse();
|
||||||
@@ -75,21 +77,28 @@ public class TikTokLiveHttpClient implements LiveHttpClient {
|
|||||||
}
|
}
|
||||||
var json = optional.get();
|
var json = optional.get();
|
||||||
return giftsDataMapper.map(json);
|
return giftsDataMapper.map(json);
|
||||||
|
} catch (TikTokProxyRequestException ignored) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var optional = httpFactory.client(url)
|
||||||
|
.build()
|
||||||
|
.toJsonResponse();
|
||||||
|
|
||||||
|
if (optional.isEmpty()) {
|
||||||
|
throw new TikTokLiveRequestException("Unable to fetch gifts information's");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var json = optional.get();
|
||||||
@Override
|
return giftsDataMapper.map(json);
|
||||||
public LiveUserData.Response fetchLiveUserData(String userName) {
|
|
||||||
return fetchLiveUserData(new LiveUserData.Request(userName));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public LiveUserData.Response fetchLiveUserData(LiveUserData.Request request) {
|
public LiveUserData.Response fetchLiveUserData(LiveUserData.Request request) {
|
||||||
|
var url = TIKTOK_URL_WEB + "api-live/user/room";
|
||||||
var proxyClientSettings = clientSettings.getHttpSettings().getProxyClientSettings();
|
var proxyClientSettings = clientSettings.getHttpSettings().getProxyClientSettings();
|
||||||
if (proxyClientSettings.isEnabled()) {
|
if (proxyClientSettings.isEnabled()) {
|
||||||
while (proxyClientSettings.hasNext()) {
|
while (proxyClientSettings.hasNext()) {
|
||||||
try {
|
try {
|
||||||
var url = TIKTOK_URL_WEB + "api-live/user/room";
|
|
||||||
var optional = httpFactory.client(url)
|
var optional = httpFactory.client(url)
|
||||||
.withParam("uniqueId", request.getUserName())
|
.withParam("uniqueId", request.getUserName())
|
||||||
.withParam("sourceType", "54")
|
.withParam("sourceType", "54")
|
||||||
@@ -105,7 +114,6 @@ public class TikTokLiveHttpClient implements LiveHttpClient {
|
|||||||
} catch (TikTokProxyRequestException ignored) {}
|
} catch (TikTokProxyRequestException ignored) {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var url = TIKTOK_URL_WEB + "api-live/user/room";
|
|
||||||
var optional = httpFactory.client(url)
|
var optional = httpFactory.client(url)
|
||||||
.withParam("uniqueId", request.getUserName())
|
.withParam("uniqueId", request.getUserName())
|
||||||
.withParam("sourceType", "54")
|
.withParam("sourceType", "54")
|
||||||
@@ -120,18 +128,13 @@ public class TikTokLiveHttpClient implements LiveHttpClient {
|
|||||||
return liveUserDataMapper.map(json);
|
return liveUserDataMapper.map(json);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public LiveData.Response fetchLiveData(String roomId) {
|
|
||||||
return fetchLiveData(new LiveData.Request(roomId));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public LiveData.Response fetchLiveData(LiveData.Request request) {
|
public LiveData.Response fetchLiveData(LiveData.Request request) {
|
||||||
|
var url = TIKTOK_URL_WEBCAST + "room/info";
|
||||||
var proxyClientSettings = clientSettings.getHttpSettings().getProxyClientSettings();
|
var proxyClientSettings = clientSettings.getHttpSettings().getProxyClientSettings();
|
||||||
if (proxyClientSettings.isEnabled()) {
|
if (proxyClientSettings.isEnabled()) {
|
||||||
while (proxyClientSettings.hasNext()) {
|
while (proxyClientSettings.hasNext()) {
|
||||||
try {
|
try {
|
||||||
var url = TIKTOK_URL_WEBCAST + "room/info";
|
|
||||||
var optional = httpFactory.client(url)
|
var optional = httpFactory.client(url)
|
||||||
.withParam("room_id", request.getRoomId())
|
.withParam("room_id", request.getRoomId())
|
||||||
.build()
|
.build()
|
||||||
@@ -146,7 +149,6 @@ public class TikTokLiveHttpClient implements LiveHttpClient {
|
|||||||
} catch (TikTokProxyRequestException ignored) {}
|
} catch (TikTokProxyRequestException ignored) {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var url = TIKTOK_URL_WEBCAST + "room/info";
|
|
||||||
var optional = httpFactory.client(url)
|
var optional = httpFactory.client(url)
|
||||||
.withParam("room_id", request.getRoomId())
|
.withParam("room_id", request.getRoomId())
|
||||||
.build()
|
.build()
|
||||||
@@ -160,20 +162,12 @@ public class TikTokLiveHttpClient implements LiveHttpClient {
|
|||||||
return liveDataMapper.map(json);
|
return liveDataMapper.map(json);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public LiveConnectionData.Response fetchLiveConnectionData(String roomId) {
|
|
||||||
return fetchLiveConnectionData(new LiveConnectionData.Request(roomId));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public LiveConnectionData.Response fetchLiveConnectionData(LiveConnectionData.Request request) {
|
public LiveConnectionData.Response fetchLiveConnectionData(LiveConnectionData.Request request) {
|
||||||
HttpResponse<byte[]> credentialsResponse = getOptionalProxyResponse(request).orElseGet(()-> {
|
HttpResponse<byte[]> credentialsResponse = getOptionalProxyResponse(request).orElseGet(()-> getStarterPayload(request.getRoomId()));
|
||||||
SignServerResponse signServerResponse = getSignedUrl(request.getRoomId());
|
|
||||||
return getWebsocketCredentialsResponse(signServerResponse.getSignedUrl());
|
|
||||||
});
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
var optionalHeader = credentialsResponse.headers().firstValue("set-cookie");
|
var optionalHeader = credentialsResponse.headers().firstValue("x-set-tt-cookie");
|
||||||
if (optionalHeader.isEmpty()) {
|
if (optionalHeader.isEmpty()) {
|
||||||
throw new TikTokSignServerException("Sign server did not return the set-cookie header");
|
throw new TikTokSignServerException("Sign server did not return the set-cookie header");
|
||||||
}
|
}
|
||||||
@@ -195,39 +189,21 @@ public class TikTokLiveHttpClient implements LiveHttpClient {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SignServerResponse getSignedUrl(String roomId) {
|
HttpResponse<byte[]> getStarterPayload(String room_id) {
|
||||||
var urlToSign = httpFactory
|
HttpClientBuilder builder = httpFactory.client(TIKTOK_SIGN_API)
|
||||||
.client(TikTokLiveHttpClient.TIKTOK_URL_WEBCAST + "im/fetch")
|
|
||||||
.withParam("room_id", roomId)
|
|
||||||
.build()
|
|
||||||
.toUrl();
|
|
||||||
|
|
||||||
|
|
||||||
var optional = httpFactory
|
|
||||||
.client(TikTokLiveHttpClient.TIKTOK_SIGN_API)
|
|
||||||
.withParam("client", "ttlive-java")
|
.withParam("client", "ttlive-java")
|
||||||
.withParam("uuc", "1")
|
.withParam("uuc", "1")
|
||||||
.withParam("url", urlToSign.toString())
|
.withParam("room_id", room_id);
|
||||||
.build()
|
|
||||||
.toJsonResponse();
|
if (clientSettings.getApiKey() != null)
|
||||||
|
builder.withParam("apiKey", clientSettings.getApiKey());
|
||||||
|
|
||||||
|
var optional = builder.build().toResponse();
|
||||||
|
|
||||||
if (optional.isEmpty()) {
|
if (optional.isEmpty()) {
|
||||||
throw new TikTokSignServerException("Unable to sign url: " + urlToSign);
|
|
||||||
}
|
|
||||||
|
|
||||||
var json = optional.get();
|
|
||||||
return signServerResponseMapper.map(json);
|
|
||||||
}
|
|
||||||
|
|
||||||
HttpResponse<byte[]> getWebsocketCredentialsResponse(String signedUrl) {
|
|
||||||
var optionalResponse = httpFactory
|
|
||||||
.clientEmpty(signedUrl)
|
|
||||||
.build()
|
|
||||||
.toResponse();
|
|
||||||
if (optionalResponse.isEmpty()) {
|
|
||||||
throw new TikTokSignServerException("Unable to get websocket connection credentials");
|
throw new TikTokSignServerException("Unable to get websocket connection credentials");
|
||||||
}
|
}
|
||||||
return optionalResponse.get();
|
return optional.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
Optional<HttpResponse<byte[]>> getOptionalProxyResponse(LiveConnectionData.Request request) {
|
Optional<HttpResponse<byte[]>> getOptionalProxyResponse(LiveConnectionData.Request request) {
|
||||||
@@ -235,9 +211,7 @@ public class TikTokLiveHttpClient implements LiveHttpClient {
|
|||||||
if (proxyClientSettings.isEnabled()) {
|
if (proxyClientSettings.isEnabled()) {
|
||||||
while (proxyClientSettings.hasNext()) {
|
while (proxyClientSettings.hasNext()) {
|
||||||
try {
|
try {
|
||||||
SignServerResponse signServerResponse = getSignedUrl(request.getRoomId());
|
HttpResponse<byte[]> credentialsResponse = getStarterPayload(request.getRoomId());
|
||||||
HttpResponse<byte[]> credentialsResponse = getWebsocketCredentialsResponse(signServerResponse.getSignedUrl());
|
|
||||||
clientSettings.getHttpSettings().getProxyClientSettings().rotate();
|
|
||||||
return Optional.of(credentialsResponse);
|
return Optional.of(credentialsResponse);
|
||||||
} catch (TikTokProxyRequestException | TikTokSignServerException ignored) {}
|
} catch (TikTokProxyRequestException | TikTokSignServerException ignored) {}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -67,16 +67,17 @@ public class HttpProxyClient extends HttpClient
|
|||||||
var request = prepareGetRequest();
|
var request = prepareGetRequest();
|
||||||
|
|
||||||
var response = client.send(request, HttpResponse.BodyHandlers.ofByteArray());
|
var response = client.send(request, HttpResponse.BodyHandlers.ofByteArray());
|
||||||
if (response.statusCode() != 200) {
|
if (response.statusCode() != 200)
|
||||||
proxySettings.setLastSuccess(false);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
proxySettings.setLastSuccess(true);
|
|
||||||
return Optional.of(response);
|
return Optional.of(response);
|
||||||
} catch (HttpConnectTimeoutException | ConnectException e) {
|
} catch (HttpConnectTimeoutException | ConnectException e) {
|
||||||
if (proxySettings.isAutoDiscard())
|
if (proxySettings.isAutoDiscard())
|
||||||
proxySettings.remove();
|
proxySettings.remove();
|
||||||
proxySettings.setLastSuccess(false);
|
throw new TikTokProxyRequestException(e);
|
||||||
|
} catch (IOException e) {
|
||||||
|
if (e.getMessage().contains("503") && proxySettings.isFallback()) // Indicates proxy protocol is not supported
|
||||||
|
return super.toResponse();
|
||||||
|
throw new TikTokProxyRequestException(e);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new TikTokLiveRequestException(e);
|
throw new TikTokLiveRequestException(e);
|
||||||
}
|
}
|
||||||
@@ -99,7 +100,6 @@ public class HttpProxyClient extends HttpClient
|
|||||||
try {
|
try {
|
||||||
Proxy proxy = new Proxy(Proxy.Type.SOCKS, proxySettings.next().toSocketAddress());
|
Proxy proxy = new Proxy(Proxy.Type.SOCKS, proxySettings.next().toSocketAddress());
|
||||||
|
|
||||||
System.err.println("Connecting to "+ url);
|
|
||||||
HttpsURLConnection socksConnection = (HttpsURLConnection) url.openConnection(proxy);
|
HttpsURLConnection socksConnection = (HttpsURLConnection) url.openConnection(proxy);
|
||||||
socksConnection.setSSLSocketFactory(sc.getSocketFactory());
|
socksConnection.setSSLSocketFactory(sc.getSocketFactory());
|
||||||
socksConnection.setConnectTimeout(httpClientSettings.getTimeout().toMillisPart());
|
socksConnection.setConnectTimeout(httpClientSettings.getTimeout().toMillisPart());
|
||||||
@@ -117,12 +117,12 @@ public class HttpProxyClient extends HttpClient
|
|||||||
|
|
||||||
var response = createHttpResponse(body, toUrl(), responseInfo);
|
var response = createHttpResponse(body, toUrl(), responseInfo);
|
||||||
|
|
||||||
proxySettings.setLastSuccess(true);
|
|
||||||
return Optional.of(response);
|
return Optional.of(response);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
|
if (e.getMessage().contains("503") && proxySettings.isFallback()) // Indicates proxy protocol is not supported
|
||||||
|
return super.toResponse();
|
||||||
if (proxySettings.isAutoDiscard())
|
if (proxySettings.isAutoDiscard())
|
||||||
proxySettings.remove();
|
proxySettings.remove();
|
||||||
proxySettings.setLastSuccess(false);
|
|
||||||
throw new TikTokProxyRequestException(e);
|
throw new TikTokProxyRequestException(e);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new TikTokLiveRequestException(e);
|
throw new TikTokLiveRequestException(e);
|
||||||
@@ -131,7 +131,7 @@ public class HttpProxyClient extends HttpClient
|
|||||||
throw new TikTokLiveRequestException("No more proxies available!");
|
throw new TikTokLiveRequestException("No more proxies available!");
|
||||||
} catch (NoSuchAlgorithmException | MalformedURLException | KeyManagementException e) {
|
} catch (NoSuchAlgorithmException | MalformedURLException | KeyManagementException e) {
|
||||||
// Should never be reached!
|
// Should never be reached!
|
||||||
System.out.println("handleSocksProxyRequest()! If you see this message, reach us on discord!");
|
System.out.println("handleSocksProxyRequest: If you see this, message us on discord!");
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
return Optional.empty();
|
return Optional.empty();
|
||||||
} catch (TikTokLiveRequestException e) {
|
} catch (TikTokLiveRequestException e) {
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ package io.github.jwdeveloper.tiktok.http.mappers;
|
|||||||
|
|
||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
import com.google.gson.JsonParser;
|
import com.google.gson.JsonParser;
|
||||||
|
import io.github.jwdeveloper.tiktok.TikTokLiveHttpClient;
|
||||||
import io.github.jwdeveloper.tiktok.data.models.Picture;
|
import io.github.jwdeveloper.tiktok.data.models.Picture;
|
||||||
import io.github.jwdeveloper.tiktok.data.models.users.User;
|
import io.github.jwdeveloper.tiktok.data.models.users.User;
|
||||||
import io.github.jwdeveloper.tiktok.data.models.users.UserAttribute;
|
import io.github.jwdeveloper.tiktok.data.models.users.UserAttribute;
|
||||||
@@ -43,6 +44,7 @@ public class LiveDataMapper {
|
|||||||
public LiveData.Response map(String json) {
|
public LiveData.Response map(String json) {
|
||||||
var response = new LiveData.Response();
|
var response = new LiveData.Response();
|
||||||
|
|
||||||
|
response.setJson(json);
|
||||||
|
|
||||||
var parsedJson = JsonParser.parseString(json);
|
var parsedJson = JsonParser.parseString(json);
|
||||||
var jsonObject = parsedJson.getAsJsonObject();
|
var jsonObject = parsedJson.getAsJsonObject();
|
||||||
@@ -63,6 +65,9 @@ public class LiveDataMapper {
|
|||||||
default -> LiveData.LiveStatus.HostNotFound;
|
default -> LiveData.LiveStatus.HostNotFound;
|
||||||
};
|
};
|
||||||
response.setLiveStatus(statusValue);
|
response.setLiveStatus(statusValue);
|
||||||
|
} else if (data.has("prompts") && jsonObject.has("status_code") &&
|
||||||
|
data.get("prompts").getAsString().isEmpty() && jsonObject.get("status_code").isJsonPrimitive()) {
|
||||||
|
response.setAgeRestricted(jsonObject.get("status_code").getAsInt() == TikTokLiveHttpClient.TIKTOK_AGE_RESTRICTED_CODE);
|
||||||
} else {
|
} else {
|
||||||
response.setLiveStatus(LiveData.LiveStatus.HostNotFound);
|
response.setLiveStatus(LiveData.LiveStatus.HostNotFound);
|
||||||
}
|
}
|
||||||
@@ -104,6 +109,22 @@ public class LiveDataMapper {
|
|||||||
response.setHost(user);
|
response.setHost(user);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (data.has("link_mic")) {
|
||||||
|
var element = data.getAsJsonObject("link_mic");
|
||||||
|
var multi_live = element.get("multi_live_enum").getAsInt();
|
||||||
|
var rival_id = element.get("rival_anchor_id").getAsInt();
|
||||||
|
var battle_scores = element.get("battle_scores").getAsJsonArray();
|
||||||
|
if (multi_live == 1) {
|
||||||
|
if (!battle_scores.isEmpty())
|
||||||
|
response.setLiveType(LiveData.LiveType.BATTLE);
|
||||||
|
else if (rival_id != 0)
|
||||||
|
response.setLiveType(LiveData.LiveType.CO_HOST);
|
||||||
|
else
|
||||||
|
response.setLiveType(LiveData.LiveType.BOX);
|
||||||
|
} else
|
||||||
|
response.setLiveType(LiveData.LiveType.SOLO);
|
||||||
|
}
|
||||||
|
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -111,6 +111,7 @@ public class TikTokListenersManager implements ListenersManager {
|
|||||||
EventConsumer eventMethodRef = (liveClient, event) ->
|
EventConsumer eventMethodRef = (liveClient, event) ->
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
method.setAccessible(true);
|
||||||
method.invoke(listener, liveClient, event);
|
method.invoke(listener, liveClient, event);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new TikTokEventListenerMethodException(e);
|
throw new TikTokEventListenerMethodException(e);
|
||||||
|
|||||||
@@ -22,12 +22,11 @@
|
|||||||
*/
|
*/
|
||||||
package io.github.jwdeveloper.tiktok.websocket;
|
package io.github.jwdeveloper.tiktok.websocket;
|
||||||
|
|
||||||
|
|
||||||
import io.github.jwdeveloper.tiktok.*;
|
import io.github.jwdeveloper.tiktok.*;
|
||||||
import io.github.jwdeveloper.tiktok.data.dto.ProxyData;
|
import io.github.jwdeveloper.tiktok.data.dto.ProxyData;
|
||||||
import io.github.jwdeveloper.tiktok.data.requests.LiveConnectionData;
|
import io.github.jwdeveloper.tiktok.data.requests.LiveConnectionData;
|
||||||
import io.github.jwdeveloper.tiktok.data.settings.*;
|
import io.github.jwdeveloper.tiktok.data.settings.*;
|
||||||
import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveException;
|
import io.github.jwdeveloper.tiktok.exceptions.*;
|
||||||
import io.github.jwdeveloper.tiktok.live.LiveClient;
|
import io.github.jwdeveloper.tiktok.live.LiveClient;
|
||||||
import org.java_websocket.client.WebSocketClient;
|
import org.java_websocket.client.WebSocketClient;
|
||||||
|
|
||||||
@@ -41,6 +40,8 @@ public class TikTokWebSocketClient implements SocketClient {
|
|||||||
private final TikTokLiveMessageHandler messageHandler;
|
private final TikTokLiveMessageHandler messageHandler;
|
||||||
private final TikTokLiveEventHandler tikTokEventHandler;
|
private final TikTokLiveEventHandler tikTokEventHandler;
|
||||||
private WebSocketClient webSocketClient;
|
private WebSocketClient webSocketClient;
|
||||||
|
|
||||||
|
private final TikTokWebSocketPingingTask pingingTask;
|
||||||
private boolean isConnected;
|
private boolean isConnected;
|
||||||
|
|
||||||
public TikTokWebSocketClient(
|
public TikTokWebSocketClient(
|
||||||
@@ -51,11 +52,11 @@ public class TikTokWebSocketClient implements SocketClient {
|
|||||||
this.messageHandler = messageHandler;
|
this.messageHandler = messageHandler;
|
||||||
this.tikTokEventHandler = tikTokEventHandler;
|
this.tikTokEventHandler = tikTokEventHandler;
|
||||||
isConnected = false;
|
isConnected = false;
|
||||||
|
pingingTask = new TikTokWebSocketPingingTask();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void start(LiveConnectionData.Response connectionData, LiveClient liveClient)
|
public void start(LiveConnectionData.Response connectionData, LiveClient liveClient) {
|
||||||
{
|
|
||||||
if (isConnected) {
|
if (isConnected) {
|
||||||
stop();
|
stop();
|
||||||
}
|
}
|
||||||
@@ -81,31 +82,15 @@ public class TikTokWebSocketClient implements SocketClient {
|
|||||||
private void connectDefault() {
|
private void connectDefault() {
|
||||||
try {
|
try {
|
||||||
webSocketClient.connect();
|
webSocketClient.connect();
|
||||||
|
pingingTask.run(webSocketClient);
|
||||||
isConnected = true;
|
isConnected = true;
|
||||||
} catch (Exception e)
|
} catch (Exception e) {
|
||||||
{
|
|
||||||
isConnected = false;
|
isConnected = false;
|
||||||
throw new TikTokLiveException("Failed to connect to the websocket", e);
|
throw new TikTokLiveException("Failed to connect to the websocket", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void connectProxy(ProxyClientSettings proxySettings) {
|
public void connectProxy(ProxyClientSettings proxySettings) {
|
||||||
while (proxySettings.hasNext()) {
|
|
||||||
ProxyData proxyData = proxySettings.next();
|
|
||||||
if (!tryProxyConnection(proxySettings, proxyData)) {
|
|
||||||
if (proxySettings.isAutoDiscard())
|
|
||||||
proxySettings.remove();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
isConnected = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (!isConnected)
|
|
||||||
throw new TikTokLiveException("Failed to connect to the websocket");
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean tryProxyConnection(ProxyClientSettings proxySettings, ProxyData proxyData) {
|
|
||||||
webSocketClient.setProxy(new Proxy(proxySettings.getType(), proxyData.toSocketAddress()));
|
|
||||||
try {
|
try {
|
||||||
if (proxySettings.getType() == Proxy.Type.SOCKS) {
|
if (proxySettings.getType() == Proxy.Type.SOCKS) {
|
||||||
SSLContext sc = SSLContext.getInstance("SSL");
|
SSLContext sc = SSLContext.getInstance("SSL");
|
||||||
@@ -116,10 +101,31 @@ public class TikTokWebSocketClient implements SocketClient {
|
|||||||
}}, null);
|
}}, null);
|
||||||
webSocketClient.setSocketFactory(sc.getSocketFactory());
|
webSocketClient.setSocketFactory(sc.getSocketFactory());
|
||||||
}
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
// This will never be thrown.
|
||||||
|
throw new TikTokProxyRequestException("Unable to set Socks proxy SSL instance");
|
||||||
|
}
|
||||||
|
while (proxySettings.hasNext()) {
|
||||||
|
ProxyData proxyData = proxySettings.next();
|
||||||
|
if (!tryProxyConnection(proxySettings, proxyData)) {
|
||||||
|
if (proxySettings.isAutoDiscard())
|
||||||
|
proxySettings.remove();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
pingingTask.run(webSocketClient);
|
||||||
|
isConnected = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!isConnected)
|
||||||
|
throw new TikTokLiveException("Failed to connect to the websocket");
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean tryProxyConnection(ProxyClientSettings proxySettings, ProxyData proxyData) {
|
||||||
|
try {
|
||||||
|
webSocketClient.setProxy(new Proxy(proxySettings.getType(), proxyData.toSocketAddress()));
|
||||||
webSocketClient.connect();
|
webSocketClient.connect();
|
||||||
return true;
|
return true;
|
||||||
} catch (Exception e)
|
} catch (Exception e) {
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -127,6 +133,7 @@ public class TikTokWebSocketClient implements SocketClient {
|
|||||||
public void stop() {
|
public void stop() {
|
||||||
if (isConnected && webSocketClient != null && webSocketClient.isOpen()) {
|
if (isConnected && webSocketClient != null && webSocketClient.isOpen()) {
|
||||||
webSocketClient.closeConnection(0, "");
|
webSocketClient.closeConnection(0, "");
|
||||||
|
pingingTask.stop();
|
||||||
}
|
}
|
||||||
webSocketClient = null;
|
webSocketClient = null;
|
||||||
isConnected = false;
|
isConnected = false;
|
||||||
|
|||||||
@@ -0,0 +1,50 @@
|
|||||||
|
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 = 250;
|
||||||
|
private final int MAX_TIMEOUT = 500;
|
||||||
|
|
||||||
|
public void run(WebSocket webSocket)
|
||||||
|
{
|
||||||
|
stop();
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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.16-Release</version>
|
<version>1.2.0-Release</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
@@ -60,6 +60,24 @@
|
|||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
<scope>compile</scope>
|
<scope>compile</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.github.jwdeveloper.tiktok</groupId>
|
||||||
|
<artifactId>extension-collector</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.github.jwdeveloper.tiktok</groupId>
|
||||||
|
<artifactId>extension-recorder</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.github.jwdeveloper.tiktok</groupId>
|
||||||
|
<artifactId>extension-collector</artifactId>
|
||||||
|
<version>1.2.0-Release</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
|
|||||||
@@ -0,0 +1,76 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2023-2023 jwdeveloper jacekwoln@gmail.com
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
* a copy of this software and associated documentation files (the
|
||||||
|
* "Software"), to deal in the Software without restriction, including
|
||||||
|
* without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
* permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
* the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
package io.github.jwdeveloper.tiktok;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
import io.github.jwdeveloper.tiktok.extension.collector.TikTokLiveCollector;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class CollectorExample {
|
||||||
|
|
||||||
|
|
||||||
|
private static String mongoUser;
|
||||||
|
|
||||||
|
private static String mongoPassword;
|
||||||
|
|
||||||
|
private static String mongoDatabase;
|
||||||
|
|
||||||
|
public static void main(String[] args) throws IOException {
|
||||||
|
|
||||||
|
var collector = TikTokLiveCollector.use(settings ->
|
||||||
|
{
|
||||||
|
settings.setConnectionUrl("mongodb+srv://" + mongoUser + ":" + mongoPassword + "@" + mongoDatabase + "/?retryWrites=true&w=majority");
|
||||||
|
settings.setDatabaseName("tiktok");
|
||||||
|
});
|
||||||
|
collector.connectDatabase();
|
||||||
|
|
||||||
|
var users = List.of("tehila_723", "dino123597", "domaxyzx", "dash4214", "obserwacje_live");
|
||||||
|
var sessionTag = "Tag1";
|
||||||
|
for (var user : users) {
|
||||||
|
TikTokLive.newClient(user)
|
||||||
|
.configure(liveClientSettings ->
|
||||||
|
{
|
||||||
|
liveClientSettings.setPrintToConsole(true);
|
||||||
|
})
|
||||||
|
.onError((liveClient, event) ->
|
||||||
|
{
|
||||||
|
event.getException().printStackTrace();
|
||||||
|
})
|
||||||
|
.addListener(collector.newListener(Map.of("sessionTag", sessionTag), document ->
|
||||||
|
{
|
||||||
|
if (document.get("dataType") == "message") {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}))
|
||||||
|
.buildAndConnectAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
System.in.read();
|
||||||
|
collector.disconnectDatabase();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -57,7 +57,7 @@ public class ListenerExample
|
|||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* Method in TikTokEventListener should meet 4 requirements to be detected
|
* Method in TikTokEventListener should meet 4 requirements to be detected
|
||||||
* - must have @TikTokEventHandler annotation
|
* - must have @TikTokEventObserver annotation
|
||||||
* - must have 2 parameters
|
* - must have 2 parameters
|
||||||
* - first parameter must be LiveClient
|
* - first parameter must be LiveClient
|
||||||
* - second must be class that extending TikTokEvent
|
* - second must be class that extending TikTokEvent
|
||||||
|
|||||||
@@ -24,8 +24,7 @@ package io.github.jwdeveloper.tiktok;
|
|||||||
|
|
||||||
import java.net.Proxy;
|
import java.net.Proxy;
|
||||||
|
|
||||||
public class ProxyExample
|
public class ProxyExample {
|
||||||
{
|
|
||||||
public static void main(String[] args) throws Exception {
|
public static void main(String[] args) throws Exception {
|
||||||
TikTokLive.newClient(SimpleExample.TIKTOK_HOSTNAME)
|
TikTokLive.newClient(SimpleExample.TIKTOK_HOSTNAME)
|
||||||
.configure(clientSettings -> {
|
.configure(clientSettings -> {
|
||||||
@@ -38,13 +37,16 @@ public class ProxyExample
|
|||||||
})
|
})
|
||||||
.onConnected((liveClient, event) ->
|
.onConnected((liveClient, event) ->
|
||||||
liveClient.getLogger().info("Connected "+liveClient.getRoomInfo().getHostName()))
|
liveClient.getLogger().info("Connected "+liveClient.getRoomInfo().getHostName()))
|
||||||
|
.onComment((liveClient, event) -> liveClient.getLogger().info(event.getUser().getName()+": "+event.getText()))
|
||||||
|
.onLike((liveClient, event) -> liveClient.getLogger().info(event.getUser().getName()+" sent "+event.getLikes()+"x likes!"))
|
||||||
.onDisconnected((liveClient, event) ->
|
.onDisconnected((liveClient, event) ->
|
||||||
liveClient.getLogger().info("Disconnect reason: "+event.getReason()))
|
liveClient.getLogger().info("Disconnect reason: "+event.getReason()))
|
||||||
.onLiveEnded((liveClient, event) ->
|
.onLiveEnded((liveClient, event) ->
|
||||||
liveClient.getLogger().info("Live Ended"))
|
liveClient.getLogger().info("Live Ended: "+liveClient.getRoomInfo().getHostName()))
|
||||||
.onError((liveClient, event) ->
|
.onError((liveClient, event) ->
|
||||||
event.getException().printStackTrace())
|
event.getException().printStackTrace())
|
||||||
.buildAndConnect();
|
.buildAndConnect();
|
||||||
|
|
||||||
System.in.read();
|
System.in.read();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2023-2023 jwdeveloper jacekwoln@gmail.com
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
* a copy of this software and associated documentation files (the
|
||||||
|
* "Software"), to deal in the Software without restriction, including
|
||||||
|
* without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
* permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
* the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
package io.github.jwdeveloper.tiktok;
|
||||||
|
|
||||||
|
|
||||||
|
import io.github.jwdeveloper.tiktok.extension.recorder.TikTokLiveRecorder;
|
||||||
|
import io.github.jwdeveloper.tiktok.extension.recorder.impl.event.TikTokLiveRecorderStartedEvent;
|
||||||
|
|
||||||
|
public class RecorderExample {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
|
||||||
|
TikTokLive.newClient("bangbetmenygy")
|
||||||
|
.configure(liveClientSettings ->
|
||||||
|
{
|
||||||
|
liveClientSettings.setPrintToConsole(true);
|
||||||
|
})
|
||||||
|
.onError((liveClient, event) ->
|
||||||
|
{
|
||||||
|
event.getException().printStackTrace();
|
||||||
|
})
|
||||||
|
.addListener(TikTokLiveRecorder.use(recorderSettings ->
|
||||||
|
{
|
||||||
|
recorderSettings.setFfmpegPath("C:\\Users\\ja\\IdeaProjects\\TikTokLiveJava\\extension-recorder\\libs\\ffmpeg.exe");
|
||||||
|
recorderSettings.setOutputPath("C:\\Users\\ja\\IdeaProjects\\TikTokLiveJava\\extension-recorder\\out");
|
||||||
|
recorderSettings.setOutputFileName("test.flv");
|
||||||
|
}))
|
||||||
|
.onEvent(TikTokLiveRecorderStartedEvent.class, (liveClient, event) ->
|
||||||
|
{
|
||||||
|
System.out.println(event.getDownloadData().getFullUrl());
|
||||||
|
})
|
||||||
|
.buildAndConnect();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -23,27 +23,18 @@
|
|||||||
package io.github.jwdeveloper.tiktok;
|
package io.github.jwdeveloper.tiktok;
|
||||||
|
|
||||||
import io.github.jwdeveloper.tiktok.data.events.TikTokSubNotifyEvent;
|
import io.github.jwdeveloper.tiktok.data.events.TikTokSubNotifyEvent;
|
||||||
import io.github.jwdeveloper.tiktok.data.events.TikTokSubscribeEvent;
|
|
||||||
import io.github.jwdeveloper.tiktok.data.events.envelop.TikTokChestEvent;
|
import io.github.jwdeveloper.tiktok.data.events.envelop.TikTokChestEvent;
|
||||||
import io.github.jwdeveloper.tiktok.data.events.gift.TikTokGiftEvent;
|
import io.github.jwdeveloper.tiktok.data.events.gift.TikTokGiftEvent;
|
||||||
import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveOfflineHostException;
|
|
||||||
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastGiftMessage;
|
|
||||||
import io.github.jwdeveloper.tiktok.utils.ConsoleColors;
|
import io.github.jwdeveloper.tiktok.utils.ConsoleColors;
|
||||||
import io.github.jwdeveloper.tiktok.utils.JsonUtil;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.URI;
|
|
||||||
import java.net.http.HttpClient;
|
|
||||||
import java.net.http.HttpRequest;
|
|
||||||
import java.net.http.HttpResponse;
|
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
|
|
||||||
public class SimpleExample {
|
public class SimpleExample {
|
||||||
public static String TIKTOK_HOSTNAME = "dash4214";
|
public static String TIKTOK_HOSTNAME = "dash4114";
|
||||||
|
|
||||||
public static void main(String[] args) throws IOException, InterruptedException {
|
public static void main(String[] args) throws IOException {
|
||||||
|
|
||||||
showLogo();
|
showLogo();
|
||||||
|
|
||||||
|
|||||||
466
README.md
466
README.md
@@ -29,8 +29,7 @@ A Java library inspired by [TikTokLive](https://github.com/isaackogan/TikTokLive
|
|||||||
The library 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.
|
The library 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. 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.
|
No credentials are required. 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.
|
||||||
|
|
||||||
# Contributors
|
|
||||||
[Library documentation for contributors](https://github.com/jwdeveloper/TikTokLiveJava/wiki)
|
|
||||||
|
|
||||||
<div align="center">
|
<div align="center">
|
||||||
<a href="https://www.youtube.com/watch?v=eerWGgUKc6c" align="right" target="blank"><img src="https://img.youtube.com/vi/eerWGgUKc6c/hqdefault.jpg" alt="IMAGE ALT TEXT" width="38%" align="right"></a>
|
<a href="https://www.youtube.com/watch?v=eerWGgUKc6c" align="right" target="blank"><img src="https://img.youtube.com/vi/eerWGgUKc6c/hqdefault.jpg" alt="IMAGE ALT TEXT" width="38%" align="right"></a>
|
||||||
@@ -50,6 +49,7 @@ Do you prefer other programming languages?
|
|||||||
#### Overview
|
#### Overview
|
||||||
- [Getting started](#getting-started)
|
- [Getting started](#getting-started)
|
||||||
- [Events](#events)
|
- [Events](#events)
|
||||||
|
- [Extensions](#extensions)
|
||||||
- [Listeners](#listeners)
|
- [Listeners](#listeners)
|
||||||
- [Contributing](#contributing)
|
- [Contributing](#contributing)
|
||||||
|
|
||||||
@@ -70,7 +70,7 @@ Maven
|
|||||||
<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.16-Release</version>
|
<version>1.2.0-Release</version>
|
||||||
<scope>compile</scope>
|
<scope>compile</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
@@ -87,7 +87,7 @@ dependencyResolutionManagement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation 'com.github.jwdeveloper.TikTok-Live-Java:Client:1.0.16-Release'
|
implementation 'com.github.jwdeveloper.TikTok-Live-Java:Client:1.1.0-Release'
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -166,37 +166,79 @@ TikTokLive.newClient("bangbetmenygy")
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Events
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
**Control**:
|
**Control**:
|
||||||
|
|
||||||
- [onConnected](#onconnected-tiktokconnectedevent)
|
|
||||||
- [onDisconnected](#ondisconnected-tiktokdisconnectedevent)
|
|
||||||
- [onReconnecting](#onreconnecting-tiktokreconnectingevent)
|
- [onReconnecting](#onreconnecting-tiktokreconnectingevent)
|
||||||
- [onError](#onerror-tiktokerrorevent)
|
- [onError](#onerror-tiktokerrorevent)
|
||||||
|
- [onConnected](#onconnected-tiktokconnectedevent)
|
||||||
|
- [onDisconnected](#ondisconnected-tiktokdisconnectedevent)
|
||||||
|
|
||||||
**Message**:
|
**Message**:
|
||||||
|
|
||||||
- [onEvent](#onevent-tiktokevent)
|
- [onEvent](#onevent-tiktokevent)
|
||||||
- [onSubscribe](#onsubscribe-tiktoksubscribeevent)
|
- [onEvent](#onevent-tiktokevent)
|
||||||
- [onQuestion](#onquestion-tiktokquestionevent)
|
|
||||||
- [onFollow](#onfollow-tiktokfollowevent)
|
|
||||||
- [onLike](#onlike-tiktoklikeevent)
|
|
||||||
- [onLiveEnded](#onliveended-tiktokliveendedevent)
|
|
||||||
- [onRoomInfo](#onroominfo-tiktokroominfoevent)
|
|
||||||
- [onShare](#onshare-tiktokshareevent)
|
|
||||||
- [onGiftCombo](#ongiftcombo-tiktokgiftcomboevent)
|
|
||||||
- [onEmote](#onemote-tiktokemoteevent)
|
|
||||||
- [onGift](#ongift-tiktokgiftevent)
|
|
||||||
- [onComment](#oncomment-tiktokcommentevent)
|
- [onComment](#oncomment-tiktokcommentevent)
|
||||||
- [onLivePaused](#onlivepaused-tiktoklivepausedevent)
|
- [onRoomInfo](#onroominfo-tiktokroominfoevent)
|
||||||
|
- [onGift](#ongift-tiktokgiftevent)
|
||||||
|
- [onSubscribe](#onsubscribe-tiktoksubscribeevent)
|
||||||
|
- [onFollow](#onfollow-tiktokfollowevent)
|
||||||
|
- [onGiftCombo](#ongiftcombo-tiktokgiftcomboevent)
|
||||||
|
- [onLiveEnded](#onliveended-tiktokliveendedevent)
|
||||||
|
- [onQuestion](#onquestion-tiktokquestionevent)
|
||||||
|
- [onShare](#onshare-tiktokshareevent)
|
||||||
- [onLiveUnpaused](#onliveunpaused-tiktokliveunpausedevent)
|
- [onLiveUnpaused](#onliveunpaused-tiktokliveunpausedevent)
|
||||||
|
- [onEmote](#onemote-tiktokemoteevent)
|
||||||
- [onJoin](#onjoin-tiktokjoinevent)
|
- [onJoin](#onjoin-tiktokjoinevent)
|
||||||
|
- [onLike](#onlike-tiktoklikeevent)
|
||||||
|
- [onLivePaused](#onlivepaused-tiktoklivepausedevent)
|
||||||
|
|
||||||
**Debug**:
|
**Debug**:
|
||||||
|
|
||||||
- [onWebsocketUnhandledMessage](#onwebsocketunhandledmessage-tiktokwebsocketunhandledmessageevent)
|
|
||||||
- [onWebsocketResponse](#onwebsocketresponse-tiktokwebsocketresponseevent)
|
- [onWebsocketResponse](#onwebsocketresponse-tiktokwebsocketresponseevent)
|
||||||
|
- [onWebsocketUnhandledMessage](#onwebsocketunhandledmessage-tiktokwebsocketunhandledmessageevent)
|
||||||
|
- [onHttpResponse](#onhttpresponse-tiktokhttpresponseevent)
|
||||||
- [onWebsocketMessage](#onwebsocketmessage-tiktokwebsocketmessageevent)
|
- [onWebsocketMessage](#onwebsocketmessage-tiktokwebsocketmessageevent)
|
||||||
# Examples
|
# Examples
|
||||||
|
<br>
|
||||||
|
|
||||||
|
## onReconnecting [TikTokReconnectingEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/TikTokReconnectingEvent.java)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
```java
|
||||||
|
TikTokLive.newClient("host-name")
|
||||||
|
.onReconnecting((liveClient, event) ->
|
||||||
|
{
|
||||||
|
|
||||||
|
})
|
||||||
|
.buildAndConnect();
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
## onError [TikTokErrorEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/TikTokErrorEvent.java)
|
||||||
|
|
||||||
|
|
||||||
|
General error event. You should handle this.
|
||||||
|
|
||||||
|
|
||||||
|
```java
|
||||||
|
TikTokLive.newClient("host-name")
|
||||||
|
.onError((liveClient, event) ->
|
||||||
|
{
|
||||||
|
|
||||||
|
})
|
||||||
|
.buildAndConnect();
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
## onConnected [TikTokConnectedEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/TikTokConnectedEvent.java)
|
## onConnected [TikTokConnectedEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/TikTokConnectedEvent.java)
|
||||||
@@ -238,32 +280,15 @@ TikTokLive.newClient("host-name")
|
|||||||
|
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
## onReconnecting [TikTokReconnectingEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/TikTokReconnectingEvent.java)
|
## onEvent [TikTokEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/common/TikTokEvent.java)
|
||||||
|
|
||||||
|
|
||||||
|
Base class for all events
|
||||||
```java
|
|
||||||
TikTokLive.newClient("host-name")
|
|
||||||
.onReconnecting((liveClient, event) ->
|
|
||||||
{
|
|
||||||
|
|
||||||
})
|
|
||||||
.buildAndConnect();
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<br>
|
|
||||||
|
|
||||||
## onError [TikTokErrorEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/TikTokErrorEvent.java)
|
|
||||||
|
|
||||||
|
|
||||||
General error event. You should handle this.
|
|
||||||
|
|
||||||
|
|
||||||
```java
|
```java
|
||||||
TikTokLive.newClient("host-name")
|
TikTokLive.newClient("host-name")
|
||||||
.onError((liveClient, event) ->
|
.onEvent((liveClient, event) ->
|
||||||
{
|
{
|
||||||
|
|
||||||
})
|
})
|
||||||
@@ -293,91 +318,15 @@ TikTokLive.newClient("host-name")
|
|||||||
|
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
## onSubscribe [TikTokSubscribeEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/TikTokSubscribeEvent.java)
|
## onComment [TikTokCommentEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/TikTokCommentEvent.java)
|
||||||
|
|
||||||
|
|
||||||
Triggers when a user creates a subscription.
|
Triggered every time a new chat comment arrives.
|
||||||
|
|
||||||
|
|
||||||
```java
|
```java
|
||||||
TikTokLive.newClient("host-name")
|
TikTokLive.newClient("host-name")
|
||||||
.onSubscribe((liveClient, event) ->
|
.onComment((liveClient, event) ->
|
||||||
{
|
|
||||||
|
|
||||||
})
|
|
||||||
.buildAndConnect();
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<br>
|
|
||||||
|
|
||||||
## onQuestion [TikTokQuestionEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/TikTokQuestionEvent.java)
|
|
||||||
|
|
||||||
|
|
||||||
Triggered every time someone asks a new question via the question feature.
|
|
||||||
|
|
||||||
|
|
||||||
```java
|
|
||||||
TikTokLive.newClient("host-name")
|
|
||||||
.onQuestion((liveClient, event) ->
|
|
||||||
{
|
|
||||||
|
|
||||||
})
|
|
||||||
.buildAndConnect();
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<br>
|
|
||||||
|
|
||||||
## onFollow [TikTokFollowEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/social/TikTokFollowEvent.java)
|
|
||||||
|
|
||||||
|
|
||||||
Triggers when a user follows the streamer. Based on social event.
|
|
||||||
|
|
||||||
|
|
||||||
```java
|
|
||||||
TikTokLive.newClient("host-name")
|
|
||||||
.onFollow((liveClient, event) ->
|
|
||||||
{
|
|
||||||
|
|
||||||
})
|
|
||||||
.buildAndConnect();
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<br>
|
|
||||||
|
|
||||||
## onLike [TikTokLikeEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/social/TikTokLikeEvent.java)
|
|
||||||
|
|
||||||
|
|
||||||
Triggered when a viewer sends likes to the streamer. For streams with many viewers, this event is not always triggered by TikTok.
|
|
||||||
|
|
||||||
|
|
||||||
```java
|
|
||||||
TikTokLive.newClient("host-name")
|
|
||||||
.onLike((liveClient, event) ->
|
|
||||||
{
|
|
||||||
|
|
||||||
})
|
|
||||||
.buildAndConnect();
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<br>
|
|
||||||
|
|
||||||
## onLiveEnded [TikTokLiveEndedEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/TikTokLiveEndedEvent.java)
|
|
||||||
|
|
||||||
|
|
||||||
Triggered when the live stream gets terminated by the host. Will also trigger the TikTokDisconnectedEvent event.
|
|
||||||
|
|
||||||
|
|
||||||
```java
|
|
||||||
TikTokLive.newClient("host-name")
|
|
||||||
.onLiveEnded((liveClient, event) ->
|
|
||||||
{
|
{
|
||||||
|
|
||||||
})
|
})
|
||||||
@@ -391,6 +340,8 @@ TikTokLive.newClient("host-name")
|
|||||||
## onRoomInfo [TikTokRoomInfoEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/room/TikTokRoomInfoEvent.java)
|
## onRoomInfo [TikTokRoomInfoEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/room/TikTokRoomInfoEvent.java)
|
||||||
|
|
||||||
|
|
||||||
|
Triggered when LiveRoomInfo got updated such as likes, viewers, ranking ....
|
||||||
|
|
||||||
|
|
||||||
```java
|
```java
|
||||||
TikTokLive.newClient("host-name")
|
TikTokLive.newClient("host-name")
|
||||||
@@ -403,73 +354,6 @@ TikTokLive.newClient("host-name")
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
<br>
|
|
||||||
|
|
||||||
## onShare [TikTokShareEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/social/TikTokShareEvent.java)
|
|
||||||
|
|
||||||
|
|
||||||
Triggers when a user shares the stream. Based on social event.
|
|
||||||
|
|
||||||
|
|
||||||
```java
|
|
||||||
TikTokLive.newClient("host-name")
|
|
||||||
.onShare((liveClient, event) ->
|
|
||||||
{
|
|
||||||
|
|
||||||
})
|
|
||||||
.buildAndConnect();
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<br>
|
|
||||||
|
|
||||||
## onGiftCombo [TikTokGiftComboEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/gift/TikTokGiftComboEvent.java)
|
|
||||||
|
|
||||||
|
|
||||||
Triggered every time gift is sent
|
|
||||||
|
|
||||||
@see GiftSendType it has 3 states
|
|
||||||
|
|
||||||
<p>Example when user sends gift with combo</p>
|
|
||||||
<p>>Combo: 1 -> comboState = GiftSendType.Begin</p>
|
|
||||||
<p>Combo: 4 -> comboState = GiftSendType.Active</p>
|
|
||||||
<p>Combo: 8 -> comboState = GiftSendType.Active</p>
|
|
||||||
<p>Combo: 12 -> comboState = GiftSendType.Finished</p>
|
|
||||||
|
|
||||||
Remember if comboState is Finished both TikTokGiftComboEvent and TikTokGiftEvent event gets triggered
|
|
||||||
|
|
||||||
|
|
||||||
```java
|
|
||||||
TikTokLive.newClient("host-name")
|
|
||||||
.onGiftCombo((liveClient, event) ->
|
|
||||||
{
|
|
||||||
|
|
||||||
})
|
|
||||||
.buildAndConnect();
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<br>
|
|
||||||
|
|
||||||
## onEmote [TikTokEmoteEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/TikTokEmoteEvent.java)
|
|
||||||
|
|
||||||
|
|
||||||
Triggered every time a subscriber sends an emote (sticker).
|
|
||||||
|
|
||||||
|
|
||||||
```java
|
|
||||||
TikTokLive.newClient("host-name")
|
|
||||||
.onEmote((liveClient, event) ->
|
|
||||||
{
|
|
||||||
|
|
||||||
})
|
|
||||||
.buildAndConnect();
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
## onGift [TikTokGiftEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/gift/TikTokGiftEvent.java)
|
## onGift [TikTokGiftEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/gift/TikTokGiftEvent.java)
|
||||||
@@ -493,15 +377,15 @@ TikTokLive.newClient("host-name")
|
|||||||
|
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
## onComment [TikTokCommentEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/TikTokCommentEvent.java)
|
## onSubscribe [TikTokSubscribeEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/TikTokSubscribeEvent.java)
|
||||||
|
|
||||||
|
|
||||||
Triggered every time a new chat comment arrives.
|
Triggers when a user creates a subscription.
|
||||||
|
|
||||||
|
|
||||||
```java
|
```java
|
||||||
TikTokLive.newClient("host-name")
|
TikTokLive.newClient("host-name")
|
||||||
.onComment((liveClient, event) ->
|
.onSubscribe((liveClient, event) ->
|
||||||
{
|
{
|
||||||
|
|
||||||
})
|
})
|
||||||
@@ -512,13 +396,101 @@ TikTokLive.newClient("host-name")
|
|||||||
|
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
## onLivePaused [TikTokLivePausedEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/TikTokLivePausedEvent.java)
|
## onFollow [TikTokFollowEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/social/TikTokFollowEvent.java)
|
||||||
|
|
||||||
|
|
||||||
|
Triggers when a user follows the streamer. Based on social event.
|
||||||
|
|
||||||
|
|
||||||
```java
|
```java
|
||||||
TikTokLive.newClient("host-name")
|
TikTokLive.newClient("host-name")
|
||||||
.onLivePaused((liveClient, event) ->
|
.onFollow((liveClient, event) ->
|
||||||
|
{
|
||||||
|
|
||||||
|
})
|
||||||
|
.buildAndConnect();
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
## onGiftCombo [TikTokGiftComboEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/gift/TikTokGiftComboEvent.java)
|
||||||
|
|
||||||
|
|
||||||
|
Triggered every time gift is sent
|
||||||
|
|
||||||
|
@see GiftSendType it has 3 states
|
||||||
|
|
||||||
|
<p>Example when user sends gift with combo</p>
|
||||||
|
<p>>Combo: 1 -> comboState = GiftSendType.Begin</p>
|
||||||
|
<p>Combo: 4 -> comboState = GiftSendType.Active</p>
|
||||||
|
<p>Combo: 8 -> comboState = GiftSendType.Active</p>
|
||||||
|
<p>Combo: 12 -> comboState = GiftSendType.Finsihed</p>
|
||||||
|
<p>
|
||||||
|
Remember if comboState is Finsihed both TikTokGiftComboEvent and TikTokGiftEvent event gets triggered
|
||||||
|
|
||||||
|
|
||||||
|
```java
|
||||||
|
TikTokLive.newClient("host-name")
|
||||||
|
.onGiftCombo((liveClient, event) ->
|
||||||
|
{
|
||||||
|
|
||||||
|
})
|
||||||
|
.buildAndConnect();
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
## onLiveEnded [TikTokLiveEndedEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/TikTokLiveEndedEvent.java)
|
||||||
|
|
||||||
|
|
||||||
|
Triggered when the live stream gets terminated by the host. Will also trigger the TikTokDisconnectedEvent event.
|
||||||
|
|
||||||
|
|
||||||
|
```java
|
||||||
|
TikTokLive.newClient("host-name")
|
||||||
|
.onLiveEnded((liveClient, event) ->
|
||||||
|
{
|
||||||
|
|
||||||
|
})
|
||||||
|
.buildAndConnect();
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
## onQuestion [TikTokQuestionEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/TikTokQuestionEvent.java)
|
||||||
|
|
||||||
|
|
||||||
|
Triggered every time someone asks a new question via the question feature.
|
||||||
|
|
||||||
|
|
||||||
|
```java
|
||||||
|
TikTokLive.newClient("host-name")
|
||||||
|
.onQuestion((liveClient, event) ->
|
||||||
|
{
|
||||||
|
|
||||||
|
})
|
||||||
|
.buildAndConnect();
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
## onShare [TikTokShareEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/social/TikTokShareEvent.java)
|
||||||
|
|
||||||
|
|
||||||
|
Triggers when a user shares the stream. Based on social event.
|
||||||
|
|
||||||
|
|
||||||
|
```java
|
||||||
|
TikTokLive.newClient("host-name")
|
||||||
|
.onShare((liveClient, event) ->
|
||||||
{
|
{
|
||||||
|
|
||||||
})
|
})
|
||||||
@@ -544,6 +516,25 @@ TikTokLive.newClient("host-name")
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
## onEmote [TikTokEmoteEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/TikTokEmoteEvent.java)
|
||||||
|
|
||||||
|
|
||||||
|
Triggered every time a subscriber sends an emote (sticker).
|
||||||
|
|
||||||
|
|
||||||
|
```java
|
||||||
|
TikTokLive.newClient("host-name")
|
||||||
|
.onEmote((liveClient, event) ->
|
||||||
|
{
|
||||||
|
|
||||||
|
})
|
||||||
|
.buildAndConnect();
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
## onJoin [TikTokJoinEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/social/TikTokJoinEvent.java)
|
## onJoin [TikTokJoinEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/social/TikTokJoinEvent.java)
|
||||||
@@ -561,6 +552,59 @@ TikTokLive.newClient("host-name")
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
## onLike [TikTokLikeEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/social/TikTokLikeEvent.java)
|
||||||
|
|
||||||
|
|
||||||
|
Triggered when a viewer sends likes to the streamer. For streams with many viewers, this event is not always triggered by TikTok.
|
||||||
|
|
||||||
|
|
||||||
|
```java
|
||||||
|
TikTokLive.newClient("host-name")
|
||||||
|
.onLike((liveClient, event) ->
|
||||||
|
{
|
||||||
|
|
||||||
|
})
|
||||||
|
.buildAndConnect();
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
## onLivePaused [TikTokLivePausedEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/TikTokLivePausedEvent.java)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
```java
|
||||||
|
TikTokLive.newClient("host-name")
|
||||||
|
.onLivePaused((liveClient, event) ->
|
||||||
|
{
|
||||||
|
|
||||||
|
})
|
||||||
|
.buildAndConnect();
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
## onWebsocketResponse [TikTokWebsocketResponseEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/websocket/TikTokWebsocketResponseEvent.java)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
```java
|
||||||
|
TikTokLive.newClient("host-name")
|
||||||
|
.onWebsocketResponse((liveClient, event) ->
|
||||||
|
{
|
||||||
|
|
||||||
|
})
|
||||||
|
.buildAndConnect();
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
## onWebsocketUnhandledMessage [TikTokWebsocketUnhandledMessageEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/websocket/TikTokWebsocketUnhandledMessageEvent.java)
|
## onWebsocketUnhandledMessage [TikTokWebsocketUnhandledMessageEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/websocket/TikTokWebsocketUnhandledMessageEvent.java)
|
||||||
@@ -582,17 +626,17 @@ TikTokLive.newClient("host-name")
|
|||||||
|
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
## onWebsocketResponse [TikTokWebsocketResponseEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/websocket/TikTokWebsocketResponseEvent.java)
|
## onHttpResponse [TikTokHttpResponseEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/http/TikTokHttpResponseEvent.java)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
```java
|
```java
|
||||||
TikTokLive.newClient("host-name")
|
TikTokLive.newClient("host-name")
|
||||||
.onWebsocketResponse((liveClient, event) ->
|
.onHttpResponse((liveClient, event) ->
|
||||||
{
|
{
|
||||||
|
|
||||||
})
|
})
|
||||||
.buildAndConnect();
|
.buildAndConnect();
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
@@ -602,24 +646,37 @@ TikTokLive.newClient("host-name")
|
|||||||
## onWebsocketMessage [TikTokWebsocketMessageEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/websocket/TikTokWebsocketMessageEvent.java)
|
## onWebsocketMessage [TikTokWebsocketMessageEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/websocket/TikTokWebsocketMessageEvent.java)
|
||||||
|
|
||||||
|
|
||||||
Triggered every time a protobuf encoded webcast message arrives. You can deserialize the binary object depending on the use case.
|
Triggered every time TikTok sends data. Data incoming as protobuf message.
|
||||||
|
You can deserialize the binary object depending on the use case.
|
||||||
|
|
||||||
|
|
||||||
```java
|
```java
|
||||||
TikTokLive.newClient("host-name")
|
TikTokLive.newClient("host-name")
|
||||||
.onWebsocketMessage((liveClient, event) ->
|
.onWebsocketMessage((liveClient, event) ->
|
||||||
{
|
{
|
||||||
|
|
||||||
})
|
})
|
||||||
.buildAndConnect();
|
.buildAndConnect();
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
|
|
||||||
|
## Extensions
|
||||||
|
|
||||||
|
List of extensions (addons) to TiktokLiveJava
|
||||||
|
that will save your time
|
||||||
|
|
||||||
|
- [Video Recorder](https://github.com/jwdeveloper/TikTokLiveJava/tree/master/extension-recorder)
|
||||||
|
- [Live data collector to database](https://github.com/jwdeveloper/TikTokLiveJava/tree/master/extension-collector)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Listeners
|
## Listeners
|
||||||
|
|
||||||
```java
|
```java
|
||||||
@@ -652,24 +709,24 @@ public static void main(String[] args) throws IOException {
|
|||||||
|
|
||||||
public static class CustomListener implements TikTokEventListener {
|
public static class CustomListener implements TikTokEventListener {
|
||||||
|
|
||||||
@TikTokEventHandler
|
@TikTokEventObserver
|
||||||
public void onLike(LiveClient liveClient, TikTokLikeEvent event) {
|
public void onLike(LiveClient liveClient, TikTokLikeEvent event) {
|
||||||
System.out.println(event.toString());
|
System.out.println(event.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@TikTokEventHandler
|
@TikTokEventObserver
|
||||||
public void onError(LiveClient liveClient, TikTokErrorEvent event) {
|
public void onError(LiveClient liveClient, TikTokErrorEvent event) {
|
||||||
// event.getException().printStackTrace();
|
// event.getException().printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
@TikTokEventHandler
|
@TikTokEventObserver
|
||||||
public void onComment(LiveClient liveClient, TikTokCommentEvent event) {
|
public void onComment(LiveClient liveClient, TikTokCommentEvent event) {
|
||||||
var userName = event.getUser().getName();
|
var userName = event.getUser().getName();
|
||||||
var text = event.getText();
|
var text = event.getText();
|
||||||
liveClient.getLogger().info(userName + ": " + text);
|
liveClient.getLogger().info(userName + ": " + text);
|
||||||
}
|
}
|
||||||
|
|
||||||
@TikTokEventHandler
|
@TikTokEventObserver
|
||||||
public void onGift(LiveClient liveClient, TikTokGiftEvent event) {
|
public void onGift(LiveClient liveClient, TikTokGiftEvent event) {
|
||||||
var message = switch (event.getGift()) {
|
var message = switch (event.getGift()) {
|
||||||
case ROSE -> "Thanks :)";
|
case ROSE -> "Thanks :)";
|
||||||
@@ -694,4 +751,7 @@ public static class CustomListener implements TikTokEventListener {
|
|||||||
|
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
|
[Library documentation for contributors](https://github.com/jwdeveloper/TikTokLiveJava/wiki)
|
||||||
|
|
||||||
Your improvements are welcome! Feel free to open an <a href="https://github.com/jwdeveloper/TikTok-Live-Java/issues">issue</a> or <a href="https://github.com/jwdeveloper/TikTok-Live-Java/pulls">pull request</a>.
|
Your improvements are welcome! Feel free to open an <a href="https://github.com/jwdeveloper/TikTok-Live-Java/issues">issue</a> or <a href="https://github.com/jwdeveloper/TikTok-Live-Java/pulls">pull request</a>.
|
||||||
|
|||||||
@@ -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.16-Release</version>
|
<version>1.2.0-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.16-Release</version>
|
<version>1.2.0-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.16-Release</version>
|
<version>1.2.0-Release</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
|||||||
@@ -97,6 +97,10 @@ public class CodeExample {
|
|||||||
//RoomId can be used as an override if you're having issues with HostId.
|
//RoomId can be used as an override if you're having issues with HostId.
|
||||||
//You can find it in the HTML for the livestream-page
|
//You can find it in the HTML for the livestream-page
|
||||||
settings.setRoomId("XXXXXXXXXXXXXXXXX");
|
settings.setRoomId("XXXXXXXXXXXXXXXXX");
|
||||||
|
|
||||||
|
//Optional:
|
||||||
|
//API Key for increased limit to signing server
|
||||||
|
settings.setApiKey("XXXXXXXXXXXXXXXXX");
|
||||||
})
|
})
|
||||||
.buildAndConnect();
|
.buildAndConnect();
|
||||||
// </code>
|
// </code>
|
||||||
|
|||||||
@@ -126,7 +126,6 @@ TikTokLive.newClient("bangbetmenygy")
|
|||||||
{
|
{
|
||||||
settings.setHostName("bangbetmenygy"); // This method is useful in case you want change hostname later
|
settings.setHostName("bangbetmenygy"); // This method is useful in case you want change hostname later
|
||||||
settings.setClientLanguage("en"); // Language
|
settings.setClientLanguage("en"); // Language
|
||||||
settings.setTimeout(Duration.ofSeconds(2)); // Connection timeout
|
|
||||||
settings.setLogLevel(Level.ALL); // Log level
|
settings.setLogLevel(Level.ALL); // Log level
|
||||||
settings.setPrintToConsole(true); // Printing all logs to console even if log level is Level.OFF
|
settings.setPrintToConsole(true); // Printing all logs to console even if log level is Level.OFF
|
||||||
settings.setRetryOnConnectionFailure(true); // Reconnecting if TikTok user is offline
|
settings.setRetryOnConnectionFailure(true); // Reconnecting if TikTok user is offline
|
||||||
@@ -152,35 +151,73 @@ TikTokLive.newClient("bangbetmenygy")
|
|||||||
|
|
||||||
**Control**:
|
**Control**:
|
||||||
|
|
||||||
- [onConnected](#onconnected-tiktokconnectedevent)
|
|
||||||
- [onDisconnected](#ondisconnected-tiktokdisconnectedevent)
|
|
||||||
- [onReconnecting](#onreconnecting-tiktokreconnectingevent)
|
- [onReconnecting](#onreconnecting-tiktokreconnectingevent)
|
||||||
- [onError](#onerror-tiktokerrorevent)
|
- [onError](#onerror-tiktokerrorevent)
|
||||||
|
- [onConnected](#onconnected-tiktokconnectedevent)
|
||||||
|
- [onDisconnected](#ondisconnected-tiktokdisconnectedevent)
|
||||||
|
|
||||||
**Message**:
|
**Message**:
|
||||||
|
|
||||||
- [onEvent](#onevent-tiktokevent)
|
- [onEvent](#onevent-tiktokevent)
|
||||||
- [onSubscribe](#onsubscribe-tiktoksubscribeevent)
|
- [onEvent](#onevent-tiktokevent)
|
||||||
- [onQuestion](#onquestion-tiktokquestionevent)
|
|
||||||
- [onFollow](#onfollow-tiktokfollowevent)
|
|
||||||
- [onLike](#onlike-tiktoklikeevent)
|
|
||||||
- [onLiveEnded](#onliveended-tiktokliveendedevent)
|
|
||||||
- [onRoomInfo](#onroominfo-tiktokroominfoevent)
|
|
||||||
- [onShare](#onshare-tiktokshareevent)
|
|
||||||
- [onGiftCombo](#ongiftcombo-tiktokgiftcomboevent)
|
|
||||||
- [onEmote](#onemote-tiktokemoteevent)
|
|
||||||
- [onGift](#ongift-tiktokgiftevent)
|
|
||||||
- [onComment](#oncomment-tiktokcommentevent)
|
- [onComment](#oncomment-tiktokcommentevent)
|
||||||
- [onLivePaused](#onlivepaused-tiktoklivepausedevent)
|
- [onRoomInfo](#onroominfo-tiktokroominfoevent)
|
||||||
|
- [onGift](#ongift-tiktokgiftevent)
|
||||||
|
- [onSubscribe](#onsubscribe-tiktoksubscribeevent)
|
||||||
|
- [onFollow](#onfollow-tiktokfollowevent)
|
||||||
|
- [onGiftCombo](#ongiftcombo-tiktokgiftcomboevent)
|
||||||
|
- [onLiveEnded](#onliveended-tiktokliveendedevent)
|
||||||
|
- [onQuestion](#onquestion-tiktokquestionevent)
|
||||||
|
- [onShare](#onshare-tiktokshareevent)
|
||||||
- [onLiveUnpaused](#onliveunpaused-tiktokliveunpausedevent)
|
- [onLiveUnpaused](#onliveunpaused-tiktokliveunpausedevent)
|
||||||
|
- [onEmote](#onemote-tiktokemoteevent)
|
||||||
- [onJoin](#onjoin-tiktokjoinevent)
|
- [onJoin](#onjoin-tiktokjoinevent)
|
||||||
|
- [onLike](#onlike-tiktoklikeevent)
|
||||||
|
- [onLivePaused](#onlivepaused-tiktoklivepausedevent)
|
||||||
|
|
||||||
**Debug**:
|
**Debug**:
|
||||||
|
|
||||||
- [onWebsocketUnhandledMessage](#onwebsocketunhandledmessage-tiktokwebsocketunhandledmessageevent)
|
|
||||||
- [onWebsocketResponse](#onwebsocketresponse-tiktokwebsocketresponseevent)
|
- [onWebsocketResponse](#onwebsocketresponse-tiktokwebsocketresponseevent)
|
||||||
|
- [onWebsocketUnhandledMessage](#onwebsocketunhandledmessage-tiktokwebsocketunhandledmessageevent)
|
||||||
|
- [onHttpResponse](#onhttpresponse-tiktokhttpresponseevent)
|
||||||
- [onWebsocketMessage](#onwebsocketmessage-tiktokwebsocketmessageevent)
|
- [onWebsocketMessage](#onwebsocketmessage-tiktokwebsocketmessageevent)
|
||||||
# Examples
|
# Examples
|
||||||
|
<br>
|
||||||
|
|
||||||
|
## onReconnecting [TikTokReconnectingEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/TikTokReconnectingEvent.java)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
```java
|
||||||
|
TikTokLive.newClient("host-name")
|
||||||
|
.onReconnecting((liveClient, event) ->
|
||||||
|
{
|
||||||
|
|
||||||
|
})
|
||||||
|
.buildAndConnect();
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
## onError [TikTokErrorEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/TikTokErrorEvent.java)
|
||||||
|
|
||||||
|
|
||||||
|
General error event. You should handle this.
|
||||||
|
|
||||||
|
|
||||||
|
```java
|
||||||
|
TikTokLive.newClient("host-name")
|
||||||
|
.onError((liveClient, event) ->
|
||||||
|
{
|
||||||
|
|
||||||
|
})
|
||||||
|
.buildAndConnect();
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
## onConnected [TikTokConnectedEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/TikTokConnectedEvent.java)
|
## onConnected [TikTokConnectedEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/TikTokConnectedEvent.java)
|
||||||
@@ -222,32 +259,15 @@ TikTokLive.newClient("host-name")
|
|||||||
|
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
## onReconnecting [TikTokReconnectingEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/TikTokReconnectingEvent.java)
|
## onEvent [TikTokEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/common/TikTokEvent.java)
|
||||||
|
|
||||||
|
|
||||||
|
Base class for all events
|
||||||
```java
|
|
||||||
TikTokLive.newClient("host-name")
|
|
||||||
.onReconnecting((liveClient, event) ->
|
|
||||||
{
|
|
||||||
|
|
||||||
})
|
|
||||||
.buildAndConnect();
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<br>
|
|
||||||
|
|
||||||
## onError [TikTokErrorEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/TikTokErrorEvent.java)
|
|
||||||
|
|
||||||
|
|
||||||
General error event. You should handle this.
|
|
||||||
|
|
||||||
|
|
||||||
```java
|
```java
|
||||||
TikTokLive.newClient("host-name")
|
TikTokLive.newClient("host-name")
|
||||||
.onError((liveClient, event) ->
|
.onEvent((liveClient, event) ->
|
||||||
{
|
{
|
||||||
|
|
||||||
})
|
})
|
||||||
@@ -277,91 +297,15 @@ TikTokLive.newClient("host-name")
|
|||||||
|
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
## onSubscribe [TikTokSubscribeEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/TikTokSubscribeEvent.java)
|
## onComment [TikTokCommentEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/TikTokCommentEvent.java)
|
||||||
|
|
||||||
|
|
||||||
Triggers when a user creates a subscription.
|
Triggered every time a new chat comment arrives.
|
||||||
|
|
||||||
|
|
||||||
```java
|
```java
|
||||||
TikTokLive.newClient("host-name")
|
TikTokLive.newClient("host-name")
|
||||||
.onSubscribe((liveClient, event) ->
|
.onComment((liveClient, event) ->
|
||||||
{
|
|
||||||
|
|
||||||
})
|
|
||||||
.buildAndConnect();
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<br>
|
|
||||||
|
|
||||||
## onQuestion [TikTokQuestionEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/TikTokQuestionEvent.java)
|
|
||||||
|
|
||||||
|
|
||||||
Triggered every time someone asks a new question via the question feature.
|
|
||||||
|
|
||||||
|
|
||||||
```java
|
|
||||||
TikTokLive.newClient("host-name")
|
|
||||||
.onQuestion((liveClient, event) ->
|
|
||||||
{
|
|
||||||
|
|
||||||
})
|
|
||||||
.buildAndConnect();
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<br>
|
|
||||||
|
|
||||||
## onFollow [TikTokFollowEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/social/TikTokFollowEvent.java)
|
|
||||||
|
|
||||||
|
|
||||||
Triggers when a user follows the streamer. Based on social event.
|
|
||||||
|
|
||||||
|
|
||||||
```java
|
|
||||||
TikTokLive.newClient("host-name")
|
|
||||||
.onFollow((liveClient, event) ->
|
|
||||||
{
|
|
||||||
|
|
||||||
})
|
|
||||||
.buildAndConnect();
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<br>
|
|
||||||
|
|
||||||
## onLike [TikTokLikeEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/social/TikTokLikeEvent.java)
|
|
||||||
|
|
||||||
|
|
||||||
Triggered when a viewer sends likes to the streamer. For streams with many viewers, this event is not always triggered by TikTok.
|
|
||||||
|
|
||||||
|
|
||||||
```java
|
|
||||||
TikTokLive.newClient("host-name")
|
|
||||||
.onLike((liveClient, event) ->
|
|
||||||
{
|
|
||||||
|
|
||||||
})
|
|
||||||
.buildAndConnect();
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<br>
|
|
||||||
|
|
||||||
## onLiveEnded [TikTokLiveEndedEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/TikTokLiveEndedEvent.java)
|
|
||||||
|
|
||||||
|
|
||||||
Triggered when the live stream gets terminated by the host. Will also trigger the TikTokDisconnectedEvent event.
|
|
||||||
|
|
||||||
|
|
||||||
```java
|
|
||||||
TikTokLive.newClient("host-name")
|
|
||||||
.onLiveEnded((liveClient, event) ->
|
|
||||||
{
|
{
|
||||||
|
|
||||||
})
|
})
|
||||||
@@ -375,6 +319,8 @@ TikTokLive.newClient("host-name")
|
|||||||
## onRoomInfo [TikTokRoomInfoEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/room/TikTokRoomInfoEvent.java)
|
## onRoomInfo [TikTokRoomInfoEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/room/TikTokRoomInfoEvent.java)
|
||||||
|
|
||||||
|
|
||||||
|
Triggered when LiveRoomInfo got updated such as likes, viewers, ranking ....
|
||||||
|
|
||||||
|
|
||||||
```java
|
```java
|
||||||
TikTokLive.newClient("host-name")
|
TikTokLive.newClient("host-name")
|
||||||
@@ -387,73 +333,6 @@ TikTokLive.newClient("host-name")
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
<br>
|
|
||||||
|
|
||||||
## onShare [TikTokShareEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/social/TikTokShareEvent.java)
|
|
||||||
|
|
||||||
|
|
||||||
Triggers when a user shares the stream. Based on social event.
|
|
||||||
|
|
||||||
|
|
||||||
```java
|
|
||||||
TikTokLive.newClient("host-name")
|
|
||||||
.onShare((liveClient, event) ->
|
|
||||||
{
|
|
||||||
|
|
||||||
})
|
|
||||||
.buildAndConnect();
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<br>
|
|
||||||
|
|
||||||
## onGiftCombo [TikTokGiftComboEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/gift/TikTokGiftComboEvent.java)
|
|
||||||
|
|
||||||
|
|
||||||
Triggered every time gift is sent
|
|
||||||
|
|
||||||
@see GiftSendType it has 3 states
|
|
||||||
|
|
||||||
<p>Example when user sends gift with combo</p>
|
|
||||||
<p>>Combo: 1 -> comboState = GiftSendType.Begin</p>
|
|
||||||
<p>Combo: 4 -> comboState = GiftSendType.Active</p>
|
|
||||||
<p>Combo: 8 -> comboState = GiftSendType.Active</p>
|
|
||||||
<p>Combo: 12 -> comboState = GiftSendType.Finsihed</p>
|
|
||||||
|
|
||||||
Remember if comboState is Finsihed both TikTokGiftComboEvent and TikTokGiftEvent event gets triggered
|
|
||||||
|
|
||||||
|
|
||||||
```java
|
|
||||||
TikTokLive.newClient("host-name")
|
|
||||||
.onGiftCombo((liveClient, event) ->
|
|
||||||
{
|
|
||||||
|
|
||||||
})
|
|
||||||
.buildAndConnect();
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<br>
|
|
||||||
|
|
||||||
## onEmote [TikTokEmoteEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/TikTokEmoteEvent.java)
|
|
||||||
|
|
||||||
|
|
||||||
Triggered every time a subscriber sends an emote (sticker).
|
|
||||||
|
|
||||||
|
|
||||||
```java
|
|
||||||
TikTokLive.newClient("host-name")
|
|
||||||
.onEmote((liveClient, event) ->
|
|
||||||
{
|
|
||||||
|
|
||||||
})
|
|
||||||
.buildAndConnect();
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
## onGift [TikTokGiftEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/gift/TikTokGiftEvent.java)
|
## onGift [TikTokGiftEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/gift/TikTokGiftEvent.java)
|
||||||
@@ -477,15 +356,15 @@ TikTokLive.newClient("host-name")
|
|||||||
|
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
## onComment [TikTokCommentEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/TikTokCommentEvent.java)
|
## onSubscribe [TikTokSubscribeEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/TikTokSubscribeEvent.java)
|
||||||
|
|
||||||
|
|
||||||
Triggered every time a new chat comment arrives.
|
Triggers when a user creates a subscription.
|
||||||
|
|
||||||
|
|
||||||
```java
|
```java
|
||||||
TikTokLive.newClient("host-name")
|
TikTokLive.newClient("host-name")
|
||||||
.onComment((liveClient, event) ->
|
.onSubscribe((liveClient, event) ->
|
||||||
{
|
{
|
||||||
|
|
||||||
})
|
})
|
||||||
@@ -496,13 +375,101 @@ TikTokLive.newClient("host-name")
|
|||||||
|
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
## onLivePaused [TikTokLivePausedEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/TikTokLivePausedEvent.java)
|
## onFollow [TikTokFollowEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/social/TikTokFollowEvent.java)
|
||||||
|
|
||||||
|
|
||||||
|
Triggers when a user follows the streamer. Based on social event.
|
||||||
|
|
||||||
|
|
||||||
```java
|
```java
|
||||||
TikTokLive.newClient("host-name")
|
TikTokLive.newClient("host-name")
|
||||||
.onLivePaused((liveClient, event) ->
|
.onFollow((liveClient, event) ->
|
||||||
|
{
|
||||||
|
|
||||||
|
})
|
||||||
|
.buildAndConnect();
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
## onGiftCombo [TikTokGiftComboEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/gift/TikTokGiftComboEvent.java)
|
||||||
|
|
||||||
|
|
||||||
|
Triggered every time gift is sent
|
||||||
|
|
||||||
|
@see GiftSendType it has 3 states
|
||||||
|
|
||||||
|
<p>Example when user sends gift with combo</p>
|
||||||
|
<p>>Combo: 1 -> comboState = GiftSendType.Begin</p>
|
||||||
|
<p>Combo: 4 -> comboState = GiftSendType.Active</p>
|
||||||
|
<p>Combo: 8 -> comboState = GiftSendType.Active</p>
|
||||||
|
<p>Combo: 12 -> comboState = GiftSendType.Finsihed</p>
|
||||||
|
<p>
|
||||||
|
Remember if comboState is Finsihed both TikTokGiftComboEvent and TikTokGiftEvent event gets triggered
|
||||||
|
|
||||||
|
|
||||||
|
```java
|
||||||
|
TikTokLive.newClient("host-name")
|
||||||
|
.onGiftCombo((liveClient, event) ->
|
||||||
|
{
|
||||||
|
|
||||||
|
})
|
||||||
|
.buildAndConnect();
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
## onLiveEnded [TikTokLiveEndedEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/TikTokLiveEndedEvent.java)
|
||||||
|
|
||||||
|
|
||||||
|
Triggered when the live stream gets terminated by the host. Will also trigger the TikTokDisconnectedEvent event.
|
||||||
|
|
||||||
|
|
||||||
|
```java
|
||||||
|
TikTokLive.newClient("host-name")
|
||||||
|
.onLiveEnded((liveClient, event) ->
|
||||||
|
{
|
||||||
|
|
||||||
|
})
|
||||||
|
.buildAndConnect();
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
## onQuestion [TikTokQuestionEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/TikTokQuestionEvent.java)
|
||||||
|
|
||||||
|
|
||||||
|
Triggered every time someone asks a new question via the question feature.
|
||||||
|
|
||||||
|
|
||||||
|
```java
|
||||||
|
TikTokLive.newClient("host-name")
|
||||||
|
.onQuestion((liveClient, event) ->
|
||||||
|
{
|
||||||
|
|
||||||
|
})
|
||||||
|
.buildAndConnect();
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
## onShare [TikTokShareEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/social/TikTokShareEvent.java)
|
||||||
|
|
||||||
|
|
||||||
|
Triggers when a user shares the stream. Based on social event.
|
||||||
|
|
||||||
|
|
||||||
|
```java
|
||||||
|
TikTokLive.newClient("host-name")
|
||||||
|
.onShare((liveClient, event) ->
|
||||||
{
|
{
|
||||||
|
|
||||||
})
|
})
|
||||||
@@ -528,6 +495,25 @@ TikTokLive.newClient("host-name")
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
## onEmote [TikTokEmoteEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/TikTokEmoteEvent.java)
|
||||||
|
|
||||||
|
|
||||||
|
Triggered every time a subscriber sends an emote (sticker).
|
||||||
|
|
||||||
|
|
||||||
|
```java
|
||||||
|
TikTokLive.newClient("host-name")
|
||||||
|
.onEmote((liveClient, event) ->
|
||||||
|
{
|
||||||
|
|
||||||
|
})
|
||||||
|
.buildAndConnect();
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
## onJoin [TikTokJoinEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/social/TikTokJoinEvent.java)
|
## onJoin [TikTokJoinEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/social/TikTokJoinEvent.java)
|
||||||
@@ -545,6 +531,59 @@ TikTokLive.newClient("host-name")
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
## onLike [TikTokLikeEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/social/TikTokLikeEvent.java)
|
||||||
|
|
||||||
|
|
||||||
|
Triggered when a viewer sends likes to the streamer. For streams with many viewers, this event is not always triggered by TikTok.
|
||||||
|
|
||||||
|
|
||||||
|
```java
|
||||||
|
TikTokLive.newClient("host-name")
|
||||||
|
.onLike((liveClient, event) ->
|
||||||
|
{
|
||||||
|
|
||||||
|
})
|
||||||
|
.buildAndConnect();
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
## onLivePaused [TikTokLivePausedEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/TikTokLivePausedEvent.java)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
```java
|
||||||
|
TikTokLive.newClient("host-name")
|
||||||
|
.onLivePaused((liveClient, event) ->
|
||||||
|
{
|
||||||
|
|
||||||
|
})
|
||||||
|
.buildAndConnect();
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
## onWebsocketResponse [TikTokWebsocketResponseEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/websocket/TikTokWebsocketResponseEvent.java)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
```java
|
||||||
|
TikTokLive.newClient("host-name")
|
||||||
|
.onWebsocketResponse((liveClient, event) ->
|
||||||
|
{
|
||||||
|
|
||||||
|
})
|
||||||
|
.buildAndConnect();
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
## onWebsocketUnhandledMessage [TikTokWebsocketUnhandledMessageEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/websocket/TikTokWebsocketUnhandledMessageEvent.java)
|
## onWebsocketUnhandledMessage [TikTokWebsocketUnhandledMessageEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/websocket/TikTokWebsocketUnhandledMessageEvent.java)
|
||||||
@@ -566,13 +605,13 @@ TikTokLive.newClient("host-name")
|
|||||||
|
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
## onWebsocketResponse [TikTokWebsocketResponseEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/websocket/TikTokWebsocketResponseEvent.java)
|
## onHttpResponse [TikTokHttpResponseEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/http/TikTokHttpResponseEvent.java)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
```java
|
```java
|
||||||
TikTokLive.newClient("host-name")
|
TikTokLive.newClient("host-name")
|
||||||
.onWebsocketResponse((liveClient, event) ->
|
.onHttpResponse((liveClient, event) ->
|
||||||
{
|
{
|
||||||
|
|
||||||
})
|
})
|
||||||
@@ -586,7 +625,8 @@ TikTokLive.newClient("host-name")
|
|||||||
## onWebsocketMessage [TikTokWebsocketMessageEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/websocket/TikTokWebsocketMessageEvent.java)
|
## onWebsocketMessage [TikTokWebsocketMessageEvent](https://github.com/jwdeveloper/TikTokLiveJava/blob/master/API/src/main/java/io/github/jwdeveloper/tiktok/data/events/websocket/TikTokWebsocketMessageEvent.java)
|
||||||
|
|
||||||
|
|
||||||
Triggered every time a protobuf encoded webcast message arrives. You can deserialize the binary object depending on the use case.
|
Triggered every time TikTok sends data. Data incoming as protobuf message.
|
||||||
|
You can deserialize the binary object depending on the use case.
|
||||||
|
|
||||||
|
|
||||||
```java
|
```java
|
||||||
@@ -602,6 +642,17 @@ TikTokLive.newClient("host-name")
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{{for item of data }}
|
||||||
|
|
||||||
|
{{if item is 2}}
|
||||||
|
|
||||||
|
my name is {{item.name}}
|
||||||
|
|
||||||
|
{{else}}
|
||||||
|
|
||||||
|
{{end}}
|
||||||
|
|
||||||
|
{{end}}
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
## Listeners
|
## Listeners
|
||||||
@@ -628,7 +679,7 @@ TikTokLive.newClient("host-name")
|
|||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* Method in TikTokEventListener should meet 4 requirements to be detected
|
* Method in TikTokEventListener should meet 4 requirements to be detected
|
||||||
* - must have @TikTokEventHandler annotation
|
* - must have @TikTokEventObserver annotation
|
||||||
* - must have 2 parameters
|
* - must have 2 parameters
|
||||||
* - first parameter must be LiveClient
|
* - first parameter must be LiveClient
|
||||||
* - second must be class that extending TikTokEvent
|
* - second must be class that extending TikTokEvent
|
||||||
@@ -636,24 +687,24 @@ TikTokLive.newClient("host-name")
|
|||||||
|
|
||||||
public static class CustomListener implements TikTokEventListener {
|
public static class CustomListener implements TikTokEventListener {
|
||||||
|
|
||||||
@TikTokEventHandler
|
@TikTokEventObserver
|
||||||
public void onLike(LiveClient liveClient, TikTokLikeEvent event) {
|
public void onLike(LiveClient liveClient, TikTokLikeEvent event) {
|
||||||
System.out.println(event.toString());
|
System.out.println(event.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@TikTokEventHandler
|
@TikTokEventObserver
|
||||||
public void onError(LiveClient liveClient, TikTokErrorEvent event) {
|
public void onError(LiveClient liveClient, TikTokErrorEvent event) {
|
||||||
// event.getException().printStackTrace();
|
// event.getException().printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
@TikTokEventHandler
|
@TikTokEventObserver
|
||||||
public void onComment(LiveClient liveClient, TikTokCommentEvent event) {
|
public void onComment(LiveClient liveClient, TikTokCommentEvent event) {
|
||||||
var userName = event.getUser().getName();
|
var userName = event.getUser().getName();
|
||||||
var text = event.getText();
|
var text = event.getText();
|
||||||
liveClient.getLogger().info(userName + ": " + text);
|
liveClient.getLogger().info(userName + ": " + text);
|
||||||
}
|
}
|
||||||
|
|
||||||
@TikTokEventHandler
|
@TikTokEventObserver
|
||||||
public void onGift(LiveClient liveClient, TikTokGiftEvent event) {
|
public void onGift(LiveClient liveClient, TikTokGiftEvent event) {
|
||||||
var message = switch (event.getGift()) {
|
var message = switch (event.getGift()) {
|
||||||
case ROSE -> "Thanks :)";
|
case ROSE -> "Thanks :)";
|
||||||
@@ -666,7 +717,7 @@ TikTokLive.newClient("host-name")
|
|||||||
liveClient.getLogger().info(message);
|
liveClient.getLogger().info(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
@TikTokEventHandler
|
@TikTokEventObserver
|
||||||
public void onAnyEvent(LiveClient liveClient, TikTokEvent event) {
|
public void onAnyEvent(LiveClient liveClient, TikTokEvent event) {
|
||||||
liveClient.getLogger().info(event.getClass().getSimpleName());
|
liveClient.getLogger().info(event.getClass().getSimpleName());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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.16-Release</version>
|
<version>1.2.0-Release</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
|||||||
64
extension-collector/README.md
Normal file
64
extension-collector/README.md
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
Collects live data to mongodb database
|
||||||
|
|
||||||
|
|
||||||
|
```xml
|
||||||
|
<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>1.1.0-Release</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.github.jwdeveloper.TikTok-Live-Java</groupId>
|
||||||
|
<artifactId>extension-collector</artifactId>
|
||||||
|
<version>1.1.0-Release</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
Usage
|
||||||
|
|
||||||
|
```java
|
||||||
|
public static void main(String[] args) throws IOException {
|
||||||
|
|
||||||
|
var collector = TikTokLiveCollector.use(settings ->
|
||||||
|
{
|
||||||
|
settings.setConnectionUrl("mongodb+srv://" + mongoUser + ":" + mongoPassword + "@" + mongoDatabase + "/?retryWrites=true&w=majority");
|
||||||
|
settings.setDatabaseName("tiktok");
|
||||||
|
});
|
||||||
|
collector.connectDatabase();
|
||||||
|
|
||||||
|
var users = List.of("tehila_723", "dino123597", "domaxyzx", "dash4214", "obserwacje_live");
|
||||||
|
var sessionTag = "Tag1";
|
||||||
|
for (var user : users) {
|
||||||
|
TikTokLive.newClient(user)
|
||||||
|
.configure(liveClientSettings ->
|
||||||
|
{
|
||||||
|
liveClientSettings.setPrintToConsole(true);
|
||||||
|
})
|
||||||
|
.onError((liveClient, event) ->
|
||||||
|
{
|
||||||
|
event.getException().printStackTrace();
|
||||||
|
})
|
||||||
|
.addListener(collector.newListener(Map.of("sessionTag", sessionTag), document ->
|
||||||
|
{
|
||||||
|
if (document.get("dataType") == "message") {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}))
|
||||||
|
.buildAndConnectAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
System.in.read();
|
||||||
|
collector.disconnectDatabase();
|
||||||
|
}
|
||||||
|
```
|
||||||
41
extension-collector/pom.xml
Normal file
41
extension-collector/pom.xml
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
<?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">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<parent>
|
||||||
|
<groupId>io.github.jwdeveloper.tiktok</groupId>
|
||||||
|
<artifactId>TikTokLiveJava</artifactId>
|
||||||
|
<version>1.2.0-Release</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
|
||||||
|
<artifactId>extension-collector</artifactId>
|
||||||
|
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.github.jwdeveloper.tiktok</groupId>
|
||||||
|
<artifactId>API</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.google.protobuf</groupId>
|
||||||
|
<artifactId>protobuf-java</artifactId>
|
||||||
|
<version>3.24.1</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.mongodb</groupId>
|
||||||
|
<artifactId>mongodb-driver-sync</artifactId>
|
||||||
|
<version>4.4.0</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.github.jwdeveloper.tiktok</groupId>
|
||||||
|
<artifactId>API</artifactId>
|
||||||
|
<version>1.2.0-Release</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
</project>
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2023-2023 jwdeveloper jacekwoln@gmail.com
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
* a copy of this software and associated documentation files (the
|
||||||
|
* "Software"), to deal in the Software without restriction, including
|
||||||
|
* without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
* permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
* the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
package io.github.jwdeveloper.tiktok.extension.collector;
|
||||||
|
|
||||||
|
import io.github.jwdeveloper.tiktok.extension.collector.api.LiveDataCollector;
|
||||||
|
import io.github.jwdeveloper.tiktok.extension.collector.api.data.LiveDataCollectorSettings;
|
||||||
|
import io.github.jwdeveloper.tiktok.extension.collector.impl.TikTokLiveDataCollector;
|
||||||
|
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
public class TikTokLiveCollector
|
||||||
|
{
|
||||||
|
|
||||||
|
public static TikTokLiveDataCollector use(Consumer<LiveDataCollectorSettings> consumer)
|
||||||
|
{
|
||||||
|
var settings = new LiveDataCollectorSettings();
|
||||||
|
consumer.accept(settings);
|
||||||
|
return new TikTokLiveDataCollector(settings);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -20,16 +20,11 @@
|
|||||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package io.github.jwdeveloper.tiktok.data.requests;
|
package io.github.jwdeveloper.tiktok.extension.collector.api;
|
||||||
|
|
||||||
import lombok.AllArgsConstructor;
|
import io.github.jwdeveloper.tiktok.listener.TikTokEventListener;
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
@Data
|
public interface LiveDataCollector extends TikTokEventListener
|
||||||
@AllArgsConstructor
|
|
||||||
public class SignServerResponse
|
|
||||||
{
|
{
|
||||||
private String signedUrl;
|
|
||||||
|
|
||||||
private String userAgent;
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package io.github.jwdeveloper.tiktok.extension.collector.api.data;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import org.bson.Document;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class CollectorListenerSettings {
|
||||||
|
private Map<String, Object> extraFields;
|
||||||
|
private Function<Document, Boolean> filter;
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2023-2023 jwdeveloper jacekwoln@gmail.com
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
* a copy of this software and associated documentation files (the
|
||||||
|
* "Software"), to deal in the Software without restriction, including
|
||||||
|
* without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
* permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
* the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
package io.github.jwdeveloper.tiktok.extension.collector.api.data;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class LiveDataCollectorSettings {
|
||||||
|
|
||||||
|
private String connectionUrl;
|
||||||
|
|
||||||
|
private String databaseName;
|
||||||
|
|
||||||
|
private String sessionTag;
|
||||||
|
|
||||||
|
|
||||||
|
public void setConnectionUrl(String connectionUrl) {
|
||||||
|
this.connectionUrl = connectionUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setConnectionUrl(Consumer<MongoDBConnectionStringBuilder> consumer) {
|
||||||
|
var builder = new MongoDBConnectionStringBuilder();
|
||||||
|
consumer.accept(builder);
|
||||||
|
connectionUrl = builder.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2023-2023 jwdeveloper jacekwoln@gmail.com
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
* a copy of this software and associated documentation files (the
|
||||||
|
* "Software"), to deal in the Software without restriction, including
|
||||||
|
* without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
* permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
* the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
package io.github.jwdeveloper.tiktok.extension.collector.api.data;
|
||||||
|
|
||||||
|
public class MongoDBConnectionStringBuilder {
|
||||||
|
private String username;
|
||||||
|
private String password;
|
||||||
|
private String database;
|
||||||
|
private String cluster;
|
||||||
|
|
||||||
|
public MongoDBConnectionStringBuilder setUsername(String username) {
|
||||||
|
this.username = username;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MongoDBConnectionStringBuilder setPassword(String password) {
|
||||||
|
this.password = password;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MongoDBConnectionStringBuilder setDatabase(String database) {
|
||||||
|
this.database = database;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MongoDBConnectionStringBuilder setCluster(String cluster) {
|
||||||
|
this.cluster = cluster;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String build() {
|
||||||
|
return String.format("mongodb+srv://%s:%s@%s/%s?retryWrites=true&w=majority",
|
||||||
|
username, password, cluster, database);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,90 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2023-2023 jwdeveloper jacekwoln@gmail.com
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
* a copy of this software and associated documentation files (the
|
||||||
|
* "Software"), to deal in the Software without restriction, including
|
||||||
|
* without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
* permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
* the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
package io.github.jwdeveloper.tiktok.extension.collector.impl;
|
||||||
|
|
||||||
|
import com.mongodb.ConnectionString;
|
||||||
|
import com.mongodb.MongoClientSettings;
|
||||||
|
import com.mongodb.ServerApi;
|
||||||
|
import com.mongodb.ServerApiVersion;
|
||||||
|
import com.mongodb.client.MongoClient;
|
||||||
|
import com.mongodb.client.MongoClients;
|
||||||
|
import com.mongodb.client.MongoCollection;
|
||||||
|
import com.mongodb.client.MongoDatabase;
|
||||||
|
import com.mongodb.client.model.Indexes;
|
||||||
|
import io.github.jwdeveloper.tiktok.extension.collector.api.data.CollectorListenerSettings;
|
||||||
|
import io.github.jwdeveloper.tiktok.extension.collector.api.data.LiveDataCollectorSettings;
|
||||||
|
import org.bson.Document;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.TreeMap;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
public class TikTokLiveDataCollector {
|
||||||
|
|
||||||
|
private final LiveDataCollectorSettings settings;
|
||||||
|
private MongoClient mongoClient;
|
||||||
|
private MongoDatabase database;
|
||||||
|
private MongoCollection<Document> collection;
|
||||||
|
|
||||||
|
public TikTokLiveDataCollector(LiveDataCollectorSettings settings) {
|
||||||
|
this.settings = settings;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void connectDatabase() {
|
||||||
|
var serverApi = ServerApi.builder()
|
||||||
|
.version(ServerApiVersion.V1)
|
||||||
|
.build();
|
||||||
|
var mongoSettings = MongoClientSettings.builder()
|
||||||
|
.applyConnectionString(new ConnectionString(settings.getConnectionUrl()))
|
||||||
|
.serverApi(serverApi)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
mongoClient = MongoClients.create(mongoSettings);
|
||||||
|
database = mongoClient.getDatabase(settings.getDatabaseName());
|
||||||
|
collection = database.getCollection("data");
|
||||||
|
collection.createIndex(Indexes.hashed("session"));
|
||||||
|
collection.createIndex(Indexes.hashed("dataType"));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void disconnectDatabase() {
|
||||||
|
mongoClient.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
public TikTokLiveDataCollectorListener newListener() {
|
||||||
|
return newListener(Map.of());
|
||||||
|
}
|
||||||
|
|
||||||
|
public TikTokLiveDataCollectorListener newListener(Map<String, Object> additionalFields) {
|
||||||
|
return newListener(additionalFields, (e)->true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TikTokLiveDataCollectorListener newListener(Map<String, Object> additionalFields,
|
||||||
|
Function<Document, Boolean> filter) {
|
||||||
|
var settings = new CollectorListenerSettings();
|
||||||
|
settings.setExtraFields(additionalFields);
|
||||||
|
settings.setFilter(filter);
|
||||||
|
return new TikTokLiveDataCollectorListener(collection, settings);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,122 @@
|
|||||||
|
package io.github.jwdeveloper.tiktok.extension.collector.impl;
|
||||||
|
|
||||||
|
import com.mongodb.client.MongoCollection;
|
||||||
|
import io.github.jwdeveloper.tiktok.annotations.TikTokEventObserver;
|
||||||
|
import io.github.jwdeveloper.tiktok.data.events.TikTokErrorEvent;
|
||||||
|
import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent;
|
||||||
|
import io.github.jwdeveloper.tiktok.data.events.control.TikTokConnectingEvent;
|
||||||
|
import io.github.jwdeveloper.tiktok.data.events.websocket.TikTokWebsocketResponseEvent;
|
||||||
|
import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveMessageException;
|
||||||
|
import io.github.jwdeveloper.tiktok.extension.collector.api.LiveDataCollector;
|
||||||
|
import io.github.jwdeveloper.tiktok.extension.collector.api.data.CollectorListenerSettings;
|
||||||
|
import io.github.jwdeveloper.tiktok.live.LiveClient;
|
||||||
|
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastResponse;
|
||||||
|
import io.github.jwdeveloper.tiktok.utils.JsonUtil;
|
||||||
|
import org.bson.Document;
|
||||||
|
|
||||||
|
import java.io.PrintWriter;
|
||||||
|
import java.io.StringWriter;
|
||||||
|
import java.util.Base64;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class TikTokLiveDataCollectorListener implements LiveDataCollector {
|
||||||
|
|
||||||
|
private final MongoCollection<Document> collection;
|
||||||
|
private final CollectorListenerSettings settings;
|
||||||
|
private String sessionId;
|
||||||
|
private String userName;
|
||||||
|
|
||||||
|
public TikTokLiveDataCollectorListener(MongoCollection<Document> collection, CollectorListenerSettings settings) {
|
||||||
|
this.collection = collection;
|
||||||
|
this.settings = settings;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@TikTokEventObserver
|
||||||
|
private void onResponse(LiveClient liveClient, TikTokWebsocketResponseEvent event) {
|
||||||
|
includeResponse(liveClient, event.getResponse());
|
||||||
|
event.getResponse().getMessagesList().forEach(message ->
|
||||||
|
{
|
||||||
|
includeMessage(liveClient, message);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@TikTokEventObserver
|
||||||
|
private void onEvent(LiveClient liveClient, TikTokEvent event) {
|
||||||
|
if (event instanceof TikTokConnectingEvent) {
|
||||||
|
sessionId = UUID.randomUUID().toString();
|
||||||
|
userName = liveClient.getRoomInfo().getHostName();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event instanceof TikTokErrorEvent) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
includeEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TikTokEventObserver
|
||||||
|
private void onError(LiveClient liveClient, TikTokErrorEvent event) {
|
||||||
|
event.getException().printStackTrace();
|
||||||
|
includeError(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void includeResponse(LiveClient liveClient, WebcastResponse message) {
|
||||||
|
var messageContent = Base64.getEncoder().encodeToString(message.toByteArray());
|
||||||
|
insertDocument(createDocument("response", "webcast", messageContent));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void includeMessage(LiveClient liveClient, WebcastResponse.Message message) {
|
||||||
|
var method = message.getMethod();
|
||||||
|
var messageContent = Base64.getEncoder().encodeToString(message.getPayload().toByteArray());
|
||||||
|
|
||||||
|
insertDocument(createDocument("message", method, messageContent));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void includeEvent(TikTokEvent event) {
|
||||||
|
var json = JsonUtil.toJson(event);
|
||||||
|
var content = Base64.getEncoder().encodeToString(json.getBytes());
|
||||||
|
var name = event.getClass().getSimpleName();
|
||||||
|
insertDocument(createDocument("event", name, content));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void includeError(TikTokErrorEvent event) {
|
||||||
|
var exception = event.getException();
|
||||||
|
var exceptionName = event.getException().getClass().getSimpleName();
|
||||||
|
|
||||||
|
var sw = new StringWriter();
|
||||||
|
var pw = new PrintWriter(sw);
|
||||||
|
event.getException().printStackTrace(pw);
|
||||||
|
var content = sw.toString();
|
||||||
|
|
||||||
|
var doc = createDocument("error", exceptionName, content);
|
||||||
|
if (exception instanceof TikTokLiveMessageException ex) {
|
||||||
|
doc.append("message", ex.messageToBase64())
|
||||||
|
.append("response", ex.webcastResponseToBase64());
|
||||||
|
}
|
||||||
|
insertDocument(doc);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void insertDocument(Document document) {
|
||||||
|
if (!settings.getFilter().apply(document)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
collection.insertOne(document);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private Document createDocument(String dataType, String dataTypeName, String content) {
|
||||||
|
var doc = new Document();
|
||||||
|
doc.append("session", sessionId);
|
||||||
|
for (var entry : settings.getExtraFields().entrySet()) {
|
||||||
|
doc.append(entry.getKey(), entry.getValue());
|
||||||
|
}
|
||||||
|
doc.append("tiktokUser", userName);
|
||||||
|
doc.append("dataType", dataType);
|
||||||
|
doc.append("dataTypeName", dataTypeName);
|
||||||
|
doc.append("content", content);
|
||||||
|
return doc;
|
||||||
|
}
|
||||||
|
}
|
||||||
56
extension-recorder/README.md
Normal file
56
extension-recorder/README.md
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
|
||||||
|
Records stream to flv file
|
||||||
|
|
||||||
|
|
||||||
|
```xml
|
||||||
|
<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>1.1.0-Release</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.github.jwdeveloper.TikTok-Live-Java</groupId>
|
||||||
|
<artifactId>extension-recorder</artifactId>
|
||||||
|
<version>1.1.0-Release</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
Usage
|
||||||
|
|
||||||
|
```java
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
|
||||||
|
TikTokLive.newClient("bangbetmenygy")
|
||||||
|
.configure(liveClientSettings ->
|
||||||
|
{
|
||||||
|
liveClientSettings.setPrintToConsole(true);
|
||||||
|
})
|
||||||
|
.onError((liveClient, event) ->
|
||||||
|
{
|
||||||
|
event.getException().printStackTrace();
|
||||||
|
})
|
||||||
|
.addListener(TikTokLiveRecorder.use(recorderSettings ->
|
||||||
|
{
|
||||||
|
recorderSettings.setFfmpegPath("C:\\Users\\ja\\IdeaProjects\\TikTokLiveJava\\extension-recorder\\libs\\ffmpeg.exe");
|
||||||
|
recorderSettings.setOutputPath("C:\\Users\\ja\\IdeaProjects\\TikTokLiveJava\\extension-recorder\\out");
|
||||||
|
recorderSettings.setOutputFileName("test.flv");
|
||||||
|
}))
|
||||||
|
.onEvent(TikTokLiveRecorderStartedEvent.class, (liveClient, event) ->
|
||||||
|
{
|
||||||
|
System.out.println(event.getDownloadData().getFullUrl());
|
||||||
|
})
|
||||||
|
.buildAndConnect();
|
||||||
|
|
||||||
|
}
|
||||||
|
```
|
||||||
33
extension-recorder/pom.xml
Normal file
33
extension-recorder/pom.xml
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
<?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>1.2.0-Release</version>
|
||||||
|
</parent>
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<artifactId>extension-recorder</artifactId>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.github.jwdeveloper.tiktok</groupId>
|
||||||
|
<artifactId>Client</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.github.jwdeveloper.tiktok</groupId>
|
||||||
|
<artifactId>API</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<maven.compiler.source>16</maven.compiler.source>
|
||||||
|
<maven.compiler.target>16</maven.compiler.target>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
</project>
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2023-2023 jwdeveloper jacekwoln@gmail.com
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
* a copy of this software and associated documentation files (the
|
||||||
|
* "Software"), to deal in the Software without restriction, including
|
||||||
|
* without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
* permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
* the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
package io.github.jwdeveloper.tiktok.extension.recorder;
|
||||||
|
|
||||||
|
import io.github.jwdeveloper.tiktok.extension.recorder.api.LiveRecorder;
|
||||||
|
import io.github.jwdeveloper.tiktok.extension.recorder.impl.RecorderListener;
|
||||||
|
import io.github.jwdeveloper.tiktok.extension.recorder.impl.data.RecorderSettings;
|
||||||
|
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
public class TikTokLiveRecorder
|
||||||
|
{
|
||||||
|
public static LiveRecorder use(Consumer<RecorderSettings> consumer)
|
||||||
|
{
|
||||||
|
return new RecorderListener(consumer);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static LiveRecorder use()
|
||||||
|
{
|
||||||
|
return use(x ->{});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2023-2023 jwdeveloper jacekwoln@gmail.com
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
* a copy of this software and associated documentation files (the
|
||||||
|
* "Software"), to deal in the Software without restriction, including
|
||||||
|
* without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
* permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
* the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
package io.github.jwdeveloper.tiktok.extension.recorder.api;
|
||||||
|
|
||||||
|
import io.github.jwdeveloper.tiktok.listener.TikTokEventListener;
|
||||||
|
|
||||||
|
public interface LiveRecorder extends TikTokEventListener {
|
||||||
|
|
||||||
|
void pause();
|
||||||
|
void unpause();
|
||||||
|
}
|
||||||
@@ -0,0 +1,198 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2023-2023 jwdeveloper jacekwoln@gmail.com
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
* a copy of this software and associated documentation files (the
|
||||||
|
* "Software"), to deal in the Software without restriction, including
|
||||||
|
* without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
* permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
* the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
package io.github.jwdeveloper.tiktok.extension.recorder.impl;
|
||||||
|
|
||||||
|
import com.google.gson.JsonParser;
|
||||||
|
import io.github.jwdeveloper.tiktok.annotations.TikTokEventObserver;
|
||||||
|
import io.github.jwdeveloper.tiktok.data.events.*;
|
||||||
|
import io.github.jwdeveloper.tiktok.data.events.http.TikTokRoomDataResponseEvent;
|
||||||
|
import io.github.jwdeveloper.tiktok.data.settings.LiveClientSettings;
|
||||||
|
import io.github.jwdeveloper.tiktok.extension.recorder.api.LiveRecorder;
|
||||||
|
import io.github.jwdeveloper.tiktok.extension.recorder.impl.data.*;
|
||||||
|
import io.github.jwdeveloper.tiktok.extension.recorder.impl.enums.LiveQuality;
|
||||||
|
import io.github.jwdeveloper.tiktok.live.LiveClient;
|
||||||
|
|
||||||
|
import javax.net.ssl.HttpsURLConnection;
|
||||||
|
import java.io.*;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||||
|
|
||||||
|
public class RecorderListener implements LiveRecorder {
|
||||||
|
|
||||||
|
private final Consumer<RecorderSettings> consumer;
|
||||||
|
private RecorderSettings settings;
|
||||||
|
private DownloadData downloadData;
|
||||||
|
private Thread liveDownloadThread;
|
||||||
|
|
||||||
|
public RecorderListener(Consumer<RecorderSettings> consumer) {
|
||||||
|
this.consumer = consumer;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void pause() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void unpause() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@TikTokEventObserver
|
||||||
|
private void onResponse(LiveClient liveClient, TikTokRoomDataResponseEvent event) {
|
||||||
|
settings = RecorderSettings.DEFAULT();
|
||||||
|
consumer.accept(settings);
|
||||||
|
|
||||||
|
var json = event.getLiveData().getJson();
|
||||||
|
|
||||||
|
liveClient.getLogger().info("Searching for live download url");
|
||||||
|
downloadData = settings.getPrepareDownloadData() != null ? settings.getPrepareDownloadData().apply(json) : mapToDownloadData(json);
|
||||||
|
|
||||||
|
if (downloadData.getDownloadLiveUrl().isEmpty())
|
||||||
|
liveClient.getLogger().warning("Unable to find download live url!");
|
||||||
|
else
|
||||||
|
liveClient.getLogger().info("Live download url found!");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TikTokEventObserver
|
||||||
|
private void onConnected(LiveClient liveClient, TikTokConnectedEvent event) {
|
||||||
|
liveDownloadThread = new Thread(() -> {
|
||||||
|
try {
|
||||||
|
var bufferSize = 1024;
|
||||||
|
var url = new URL(downloadData.getFullUrl());
|
||||||
|
HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
|
||||||
|
var headers = LiveClientSettings.DefaultRequestHeaders();
|
||||||
|
for (var entry : headers.entrySet()) {
|
||||||
|
connection.setRequestProperty(entry.getKey(), entry.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
var in = new BufferedInputStream(connection.getInputStream());
|
||||||
|
var path = settings.getOutputPath() + File.separator + settings.getOutputFileName();
|
||||||
|
var file = new File(path);
|
||||||
|
file.getParentFile().mkdirs();
|
||||||
|
var fileOutputStream = new FileOutputStream(file);
|
||||||
|
byte[] dataBuffer = new byte[bufferSize];
|
||||||
|
int bytesRead;
|
||||||
|
while ((bytesRead = in.read(dataBuffer, 0, bufferSize)) != -1) {
|
||||||
|
fileOutputStream.write(dataBuffer, 0, bytesRead);
|
||||||
|
}
|
||||||
|
in.close();
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
liveDownloadThread.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void downloadUsingStream(String urlStr, String file) throws IOException {
|
||||||
|
URL url = new URL(urlStr);
|
||||||
|
BufferedInputStream bis = new BufferedInputStream(url.openStream());
|
||||||
|
FileOutputStream fis = new FileOutputStream(file);
|
||||||
|
byte[] buffer = new byte[1024];
|
||||||
|
int count;
|
||||||
|
while ((count = bis.read(buffer, 0, 1024)) != -1)
|
||||||
|
fis.write(buffer, 0, count);
|
||||||
|
fis.close();
|
||||||
|
bis.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@TikTokEventObserver
|
||||||
|
private void onDisconnected(LiveClient liveClient, TikTokDisconnectedEvent event) {
|
||||||
|
if (isConnected())
|
||||||
|
liveDownloadThread.interrupt();
|
||||||
|
}
|
||||||
|
|
||||||
|
@TikTokEventObserver
|
||||||
|
private void onDisconnected(LiveClient liveClient, TikTokLiveEndedEvent event) {
|
||||||
|
if (isConnected())
|
||||||
|
liveDownloadThread.interrupt();
|
||||||
|
}
|
||||||
|
|
||||||
|
private int terminateFfmpeg(final Process process) {
|
||||||
|
if (!process.isAlive()) {
|
||||||
|
// ffmpeg -version, do nothing
|
||||||
|
return process.exitValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ffmpeg -f x11grab
|
||||||
|
System.out.println("About to destroy the child process...");
|
||||||
|
try (final OutputStreamWriter out = new OutputStreamWriter(process.getOutputStream(), UTF_8)) {
|
||||||
|
out.write('q');
|
||||||
|
} catch (final IOException ioe) {
|
||||||
|
ioe.printStackTrace();
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
if (!process.waitFor(5L, TimeUnit.SECONDS)) {
|
||||||
|
process.destroy();
|
||||||
|
process.waitFor();
|
||||||
|
}
|
||||||
|
return process.exitValue();
|
||||||
|
} catch (InterruptedException ie) {
|
||||||
|
System.out.println("Interrupted");
|
||||||
|
ie.printStackTrace();
|
||||||
|
Thread.currentThread().interrupt();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private DownloadData mapToDownloadData(String json) {
|
||||||
|
|
||||||
|
var parsedJson = JsonParser.parseString(json);
|
||||||
|
var jsonObject = parsedJson.getAsJsonObject();
|
||||||
|
var streamDataJson = jsonObject.getAsJsonObject("data")
|
||||||
|
.getAsJsonObject("stream_url")
|
||||||
|
.getAsJsonObject("live_core_sdk_data")
|
||||||
|
.getAsJsonObject("pull_data")
|
||||||
|
.get("stream_data")
|
||||||
|
.getAsString();
|
||||||
|
|
||||||
|
var streamDataJsonObject = JsonParser.parseString(streamDataJson).getAsJsonObject();
|
||||||
|
|
||||||
|
var urlLink = streamDataJsonObject.getAsJsonObject("data")
|
||||||
|
.getAsJsonObject(LiveQuality.origin.name())
|
||||||
|
.getAsJsonObject("main")
|
||||||
|
.get("flv")
|
||||||
|
.getAsString();
|
||||||
|
|
||||||
|
var sessionId = streamDataJsonObject.getAsJsonObject("common")
|
||||||
|
.get("session_id")
|
||||||
|
.getAsString();
|
||||||
|
|
||||||
|
//main
|
||||||
|
//https://pull-f5-tt03.fcdn.eu.tiktokcdn.com/stage/stream-3284937501738533765.flv?session_id=136-20240109000954BF818F1B3A8E5E39E238&_webnoredir=1
|
||||||
|
//Working
|
||||||
|
//https://pull-f5-tt03.fcdn.eu.tiktokcdn.com/game/stream-3284937501738533765_sd5.flv?_session_id=136-20240109001052D91FDBC00143211020C8.1704759052997&_webnoredir=1
|
||||||
|
//https://pull-f5-tt02.fcdn.eu.tiktokcdn.com/stage/stream-3861399216374940610_uhd5.flv?_session_id=136-20240109000223D0BAA1A83974490EE630.1704758544391&_webnoredir=1
|
||||||
|
|
||||||
|
return new DownloadData(urlLink, sessionId);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isConnected() {
|
||||||
|
return liveDownloadThread != null && liveDownloadThread.isAlive();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -20,18 +20,20 @@
|
|||||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package io.github.jwdeveloper.tiktok.http.mappers;
|
package io.github.jwdeveloper.tiktok.extension.recorder.impl.data;
|
||||||
|
|
||||||
import com.google.gson.JsonParser;
|
import lombok.AllArgsConstructor;
|
||||||
import io.github.jwdeveloper.tiktok.data.requests.SignServerResponse;
|
import lombok.Data;
|
||||||
|
|
||||||
public class SignServerResponseMapper {
|
@Data
|
||||||
public SignServerResponse map(String json) {
|
@AllArgsConstructor
|
||||||
var parsedJson = JsonParser.parseString(json);
|
public class DownloadData {
|
||||||
var jsonObject = parsedJson.getAsJsonObject();
|
|
||||||
|
|
||||||
var signUrl = jsonObject.get("signedUrl").getAsString();
|
private String downloadLiveUrl;
|
||||||
var userAgent = jsonObject.get("User-Agent").getAsString();
|
|
||||||
return new SignServerResponse(signUrl, userAgent);
|
private String sessionId;
|
||||||
|
|
||||||
|
public String getFullUrl() {
|
||||||
|
return downloadLiveUrl + "&_webnoredir=1&session_id=" + sessionId;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2023-2023 jwdeveloper jacekwoln@gmail.com
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
* a copy of this software and associated documentation files (the
|
||||||
|
* "Software"), to deal in the Software without restriction, including
|
||||||
|
* without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
* permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
* the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
package io.github.jwdeveloper.tiktok.extension.recorder.impl.data;
|
||||||
|
|
||||||
|
import io.github.jwdeveloper.tiktok.extension.recorder.impl.enums.LiveQuality;
|
||||||
|
import io.github.jwdeveloper.tiktok.extension.recorder.impl.enums.LiveFormat;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class RecorderSettings {
|
||||||
|
private String ffmpegPath;
|
||||||
|
private String quality;
|
||||||
|
private String format;
|
||||||
|
private String outputPath;
|
||||||
|
private String outputFileName;
|
||||||
|
private Function<String,DownloadData> prepareDownloadData;
|
||||||
|
private boolean startOnConnected;
|
||||||
|
|
||||||
|
public static RecorderSettings DEFAULT() {
|
||||||
|
return new RecorderSettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setQuality(LiveQuality quality) {
|
||||||
|
this.quality = quality.name();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFormat(LiveFormat format) {
|
||||||
|
this.format = format.name();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2023-2023 jwdeveloper jacekwoln@gmail.com
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
* a copy of this software and associated documentation files (the
|
||||||
|
* "Software"), to deal in the Software without restriction, including
|
||||||
|
* without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
* permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
* the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
package io.github.jwdeveloper.tiktok.extension.recorder.impl.enums;
|
||||||
|
|
||||||
|
public enum LiveFormat
|
||||||
|
{
|
||||||
|
MP4
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2023-2023 jwdeveloper jacekwoln@gmail.com
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
* a copy of this software and associated documentation files (the
|
||||||
|
* "Software"), to deal in the Software without restriction, including
|
||||||
|
* without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
* permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
* the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
package io.github.jwdeveloper.tiktok.extension.recorder.impl.enums;
|
||||||
|
|
||||||
|
public enum LiveQuality {
|
||||||
|
origin, hd_60, ao, hd, sd, ld,uhd_60
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2023-2023 jwdeveloper jacekwoln@gmail.com
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
* a copy of this software and associated documentation files (the
|
||||||
|
* "Software"), to deal in the Software without restriction, including
|
||||||
|
* without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
* permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
* the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
package io.github.jwdeveloper.tiktok.extension.recorder.impl.event;
|
||||||
|
|
||||||
|
import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent;
|
||||||
|
import io.github.jwdeveloper.tiktok.extension.recorder.impl.data.DownloadData;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@AllArgsConstructor
|
||||||
|
@Data
|
||||||
|
public class TikTokLiveRecorderStartedEvent extends TikTokEvent
|
||||||
|
{
|
||||||
|
DownloadData downloadData;
|
||||||
|
}
|
||||||
5
pom.xml
5
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.16-Release</version>
|
<version>1.2.0-Release</version>
|
||||||
<modules>
|
<modules>
|
||||||
<module>API</module>
|
<module>API</module>
|
||||||
<module>Client</module>
|
<module>Client</module>
|
||||||
@@ -16,6 +16,9 @@
|
|||||||
<module>Tools-EventsCollector</module>
|
<module>Tools-EventsCollector</module>
|
||||||
<module>Tools-ReadmeGenerator</module>
|
<module>Tools-ReadmeGenerator</module>
|
||||||
<module>Tools-EventsWebViewer</module>
|
<module>Tools-EventsWebViewer</module>
|
||||||
|
|
||||||
|
<module>extension-recorder</module>
|
||||||
|
<module>extension-collector</module>
|
||||||
</modules>
|
</modules>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
|
|||||||
Reference in New Issue
Block a user