mirror of
https://github.com/jwdeveloper/TikTokLiveJava.git
synced 2026-02-27 16:59:39 -05:00
Compare commits
9 Commits
dev-depend
...
develop-1.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b1954a708c | ||
|
|
14317337e9 | ||
|
|
947c9c49a2 | ||
|
|
f2bd07377b | ||
|
|
3f268f3a1a | ||
|
|
55fcf83870 | ||
|
|
8d3828cca8 | ||
|
|
1c88491b8c | ||
|
|
cfef082d3b |
@@ -50,16 +50,12 @@ public class ProxyData
|
||||
|
||||
return new ProxyData(address, port);
|
||||
} catch (NumberFormatException e) {
|
||||
throw new IllegalArgumentException("Port must be a valid integer!");
|
||||
throw new IllegalArgumentException("Port must be a valid integer!", e);
|
||||
} catch (UnknownHostException e) {
|
||||
throw new IllegalArgumentException("Address must be valid IPv4, IPv6, or domain name!");
|
||||
throw new IllegalArgumentException("Address must be valid IPv4, IPv6, or domain name!", e);
|
||||
}
|
||||
}
|
||||
|
||||
public ProxyData clone() {
|
||||
return new ProxyData(address, port);
|
||||
}
|
||||
|
||||
public InetSocketAddress toSocketAddress() {
|
||||
return new InetSocketAddress(address, port);
|
||||
}
|
||||
|
||||
@@ -27,18 +27,23 @@ import lombok.*;
|
||||
public class LiveUserData {
|
||||
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public static class Request {
|
||||
private String userName;
|
||||
private final String userName;
|
||||
|
||||
public Request(String userName) {
|
||||
if (userName == null || userName.isBlank())
|
||||
throw new IllegalArgumentException("Invalid empty username!");
|
||||
this.userName = userName;
|
||||
}
|
||||
}
|
||||
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public static class Response {
|
||||
private String json;
|
||||
private UserStatus userStatus;
|
||||
private String roomId;
|
||||
private long startedAtTimeStamp;
|
||||
private final String json;
|
||||
private final UserStatus userStatus;
|
||||
private final String roomId;
|
||||
private final long startTime;
|
||||
|
||||
public boolean isLiveOnline() {
|
||||
return userStatus == LiveUserData.UserStatus.Live || userStatus == LiveUserData.UserStatus.LivePaused;
|
||||
|
||||
@@ -97,7 +97,7 @@ public class HttpClientSettings {
|
||||
newSettings.getHeaders().putAll(new TreeMap<>(this.headers));
|
||||
newSettings.getCookies().putAll(new TreeMap<>(this.cookies));
|
||||
newSettings.getParams().putAll(new TreeMap<>(this.params));
|
||||
newSettings.proxyClientSettings = this.proxyClientSettings;
|
||||
newSettings.setProxyClientSettings(this.proxyClientSettings);
|
||||
|
||||
return newSettings;
|
||||
}
|
||||
|
||||
@@ -36,12 +36,12 @@ public class ProxyClientSettings implements Iterator<ProxyData>, Iterable<ProxyD
|
||||
private boolean enabled, autoDiscard = true, fallback = true;
|
||||
private Rotation rotation = Rotation.CONSECUTIVE;
|
||||
private final List<ProxyData> proxyList = new ArrayList<>();
|
||||
private int index = -1;
|
||||
private int index;
|
||||
private Proxy.Type type = Proxy.Type.DIRECT;
|
||||
private Consumer<ProxyData> onProxyUpdated = x -> {};
|
||||
|
||||
public boolean addProxy(String addressPort) {
|
||||
return proxyList.add(ProxyData.map(addressPort));
|
||||
return addProxy(ProxyData.map(addressPort).toSocketAddress());
|
||||
}
|
||||
|
||||
public boolean addProxy(String address, int port) {
|
||||
@@ -57,33 +57,27 @@ public class ProxyClientSettings implements Iterator<ProxyData>, Iterable<ProxyD
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
public synchronized boolean hasNext() {
|
||||
return !proxyList.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProxyData next() {
|
||||
var nextProxy = switch (rotation)
|
||||
{
|
||||
case CONSECUTIVE -> {
|
||||
index = (index+1) % proxyList.size();
|
||||
yield proxyList.get(index).clone();
|
||||
public synchronized ProxyData next() {
|
||||
try {
|
||||
var nextProxy = proxyList.get(index);
|
||||
onProxyUpdated.accept(nextProxy);
|
||||
return nextProxy;
|
||||
} finally {
|
||||
switch (rotation) {
|
||||
case CONSECUTIVE -> index = ++index % proxyList.size();
|
||||
case RANDOM -> index = (int) (Math.random() * proxyList.size());
|
||||
case NONE -> index = Math.max(index, 0);
|
||||
}
|
||||
case RANDOM -> {
|
||||
index = new Random().nextInt(proxyList.size());
|
||||
yield proxyList.get(index).clone();
|
||||
}
|
||||
case NONE -> {
|
||||
index = Math.max(index, 0);
|
||||
yield proxyList.get(index).clone();
|
||||
}
|
||||
};
|
||||
onProxyUpdated.accept(nextProxy);
|
||||
return nextProxy;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
public synchronized void remove() {
|
||||
proxyList.remove(index);
|
||||
}
|
||||
|
||||
@@ -97,8 +91,8 @@ public class ProxyClientSettings implements Iterator<ProxyData>, Iterable<ProxyD
|
||||
}
|
||||
}
|
||||
|
||||
public ProxyClientSettings clone()
|
||||
{
|
||||
@Override
|
||||
public ProxyClientSettings clone() {
|
||||
ProxyClientSettings settings = new ProxyClientSettings();
|
||||
settings.setEnabled(enabled);
|
||||
settings.setRotation(rotation);
|
||||
@@ -109,8 +103,21 @@ public class ProxyClientSettings implements Iterator<ProxyData>, Iterable<ProxyD
|
||||
return settings;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ProxyClientSettings{" +
|
||||
"enabled=" + enabled +
|
||||
", autoDiscard=" + autoDiscard +
|
||||
", fallback=" + fallback +
|
||||
", rotation=" + rotation +
|
||||
", proxyList=" + proxyList +
|
||||
", index=" + index +
|
||||
", type=" + type +
|
||||
'}';
|
||||
}
|
||||
|
||||
/**
|
||||
* With Iterable<?> interface you can use this object inside For loop!
|
||||
* With {@code Iterable<ProxyData>} interface, you can use this object inside for loop!
|
||||
*/
|
||||
@Override
|
||||
public Iterator<ProxyData> iterator() {
|
||||
|
||||
@@ -52,77 +52,70 @@ public interface EventsBuilder<T> {
|
||||
/**
|
||||
* Invoked whenever any event is triggered
|
||||
*
|
||||
* @param action
|
||||
* @return
|
||||
* @param action consumable action
|
||||
* @return self instance
|
||||
*/
|
||||
T onEvent(EventConsumer<TikTokEvent> action);
|
||||
|
||||
/**
|
||||
* Invoked when information about room (live) got updated such as viewer count, etc..
|
||||
*
|
||||
* @param action
|
||||
* @return
|
||||
* @param action consumable action
|
||||
* @return self instance
|
||||
*/
|
||||
T onRoomInfo(EventConsumer<TikTokRoomInfoEvent> action);
|
||||
|
||||
/**
|
||||
* Invoked when someone send message to chat
|
||||
*
|
||||
* @param action
|
||||
* @return
|
||||
* @param action consumable action
|
||||
* @return self instance
|
||||
*/
|
||||
T onComment(EventConsumer<TikTokCommentEvent> action);
|
||||
|
||||
|
||||
/**
|
||||
* Invoked when TikTokLiveJava makes http request and getting response
|
||||
*
|
||||
* @param action
|
||||
* @return
|
||||
* @param action consumable action
|
||||
* @return self instance
|
||||
*/
|
||||
T onHttpResponse(EventConsumer<TikTokHttpResponseEvent> action);
|
||||
|
||||
/**
|
||||
* Invoked when TikTok protocolBuffer data "message" was successfully mapped to event
|
||||
* events contains protocol-buffer "Message" and TikTokLiveJava "Event"
|
||||
*
|
||||
* @param action
|
||||
* @return
|
||||
* @param action consumable action
|
||||
* @return self instance
|
||||
*/
|
||||
T onWebsocketMessage(EventConsumer<TikTokWebsocketMessageEvent> action);
|
||||
|
||||
/**
|
||||
* Invoked when there was not found event mapper for TikTok protocolBuffer data "message"
|
||||
*
|
||||
* @param action
|
||||
* @return
|
||||
* @param action consumable action
|
||||
* @return self instance
|
||||
*/
|
||||
T onWebsocketUnhandledMessage(EventConsumer<TikTokWebsocketUnhandledMessageEvent> action);
|
||||
|
||||
/**
|
||||
* Invoked every time TikTok sends protocolBuffer data to websocket
|
||||
* Response contains list of messages that are later mapped to events
|
||||
* @param action
|
||||
* @return
|
||||
* @param action consumable action
|
||||
* @return self instance
|
||||
*/
|
||||
T onWebsocketResponse(EventConsumer<TikTokWebsocketResponseEvent> action);
|
||||
|
||||
|
||||
/**
|
||||
* Invoked for gifts that has no combo, or when combo finishes
|
||||
* @param action
|
||||
* @return
|
||||
* @param action consumable action
|
||||
* @return self instance
|
||||
*/
|
||||
T onGift(EventConsumer<TikTokGiftEvent> action);
|
||||
|
||||
/**
|
||||
* Invoked for gifts that has combo options such as roses
|
||||
* @param action
|
||||
* @return
|
||||
* @param action consumable action
|
||||
* @return self instance
|
||||
*/
|
||||
T onGiftCombo(EventConsumer<TikTokGiftComboEvent> action);
|
||||
|
||||
|
||||
T onQuestion(EventConsumer<TikTokQuestionEvent> action);
|
||||
|
||||
T onSubscribe(EventConsumer<TikTokSubscribeEvent> action);
|
||||
@@ -145,36 +138,36 @@ public interface EventsBuilder<T> {
|
||||
|
||||
/**
|
||||
* Invoked when client has been successfully connected to live
|
||||
* @param action
|
||||
* @return
|
||||
* @param action consumable action
|
||||
* @return self instance
|
||||
*/
|
||||
T onConnected(EventConsumer<TikTokConnectedEvent> action);
|
||||
|
||||
/**
|
||||
* Invoked before client has been successfully connected to live
|
||||
* @param action
|
||||
* @return
|
||||
* @param action consumable action
|
||||
* @return self instance
|
||||
*/
|
||||
T onPreConnection(EventConsumer<TikTokPreConnectionEvent> action);
|
||||
|
||||
/**
|
||||
* Invoked when client tries to reconnect
|
||||
* @param action
|
||||
* @return
|
||||
* @param action consumable action
|
||||
* @return self instance
|
||||
*/
|
||||
T onReconnecting(EventConsumer<TikTokReconnectingEvent> action);
|
||||
|
||||
/**
|
||||
* Invoked when client disconnected
|
||||
* @param action
|
||||
* @return
|
||||
* @param action consumable action
|
||||
* @return self instance
|
||||
*/
|
||||
T onDisconnected(EventConsumer<TikTokDisconnectedEvent> action);
|
||||
|
||||
/**
|
||||
* Invoked when exception was throed inside client or event handler
|
||||
* @param action
|
||||
* @return
|
||||
* @param action consumable action
|
||||
* @return self instance
|
||||
*/
|
||||
T onError(EventConsumer<TikTokErrorEvent> action);
|
||||
|
||||
|
||||
@@ -23,12 +23,14 @@
|
||||
package io.github.jwdeveloper.tiktok;
|
||||
|
||||
|
||||
import io.github.jwdeveloper.tiktok.data.settings.LiveClientSettings;
|
||||
import io.github.jwdeveloper.tiktok.gifts.TikTokGiftsManager;
|
||||
import io.github.jwdeveloper.tiktok.http.LiveHttpClient;
|
||||
import io.github.jwdeveloper.tiktok.live.GiftsManager;
|
||||
import io.github.jwdeveloper.tiktok.live.builder.LiveClientBuilder;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class TikTokLive {
|
||||
|
||||
@@ -82,13 +84,22 @@ public class TikTokLive {
|
||||
return CompletableFuture.supplyAsync(() -> isHostNameValid(hostName));
|
||||
}
|
||||
|
||||
/**
|
||||
* Use to get some data from TikTok about users are lives
|
||||
*
|
||||
* @return LiveHttpClient
|
||||
*/
|
||||
public static LiveHttpClient requests(Consumer<LiveClientSettings> consumer) {
|
||||
return new TikTokLiveHttpClient(consumer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Use to get some data from TikTok about users are lives
|
||||
*
|
||||
* @return LiveHttpClient
|
||||
*/
|
||||
public static LiveHttpClient requests() {
|
||||
return new TikTokLiveHttpClient();
|
||||
return requests(liveClientSettings -> {});
|
||||
}
|
||||
|
||||
private static GiftsManager giftsManager;
|
||||
|
||||
@@ -127,7 +127,7 @@ public class TikTokLiveClient implements LiveClient
|
||||
tikTokEventHandler.publish(this, new TikTokConnectingEvent());
|
||||
var userDataRequest = new LiveUserData.Request(liveRoomInfo.getHostName());
|
||||
var userData = httpClient.fetchLiveUserData(userDataRequest);
|
||||
liveRoomInfo.setStartTime(userData.getStartedAtTimeStamp());
|
||||
liveRoomInfo.setStartTime(userData.getStartTime());
|
||||
liveRoomInfo.setRoomId(userData.getRoomId());
|
||||
|
||||
if (clientSettings.isFetchGifts())
|
||||
|
||||
@@ -110,28 +110,22 @@ public class TikTokLiveClientBuilder implements LiveClientBuilder {
|
||||
public LiveClient build() {
|
||||
validate();
|
||||
|
||||
//Docs: https://github.com/jwdeveloper/DepenDance?tab=readme-ov-file#01-basic
|
||||
var dependance = Dependance.newContainer();
|
||||
|
||||
//config
|
||||
dependance.registerSingleton(LiveClientSettings.class, clientSettings);
|
||||
dependance.registerSingleton(Logger.class, LoggerFactory.create(clientSettings.getHostName(), clientSettings));
|
||||
dependance.registerSingleton(TikTokRoomInfo.class, container ->
|
||||
{
|
||||
var roomInfo = new TikTokRoomInfo();
|
||||
roomInfo.setHostName(clientSettings.getHostName());
|
||||
return roomInfo;
|
||||
});
|
||||
dependance.registerSingleton(Logger.class, LoggerFactory.create(clientSettings.getHostName(), clientSettings));
|
||||
|
||||
//messages
|
||||
dependance.registerSingleton(TikTokLiveEventHandler.class, eventHandler);
|
||||
dependance.registerSingleton(TikTokLiveMessageHandler.class);
|
||||
dependance.registerSingleton(TikTokLiveMapper.class, (container) ->
|
||||
{
|
||||
var dependace = (DependanceContainer) container.find(DependanceContainer.class);
|
||||
var mapper = MessagesMapperFactory.create(dependace);
|
||||
onCustomMappings.forEach(action -> action.accept(mapper));
|
||||
return mapper;
|
||||
});
|
||||
|
||||
//listeners
|
||||
dependance.registerSingletonList(TikTokEventListener.class, (e) -> listeners);
|
||||
@@ -147,6 +141,13 @@ public class TikTokLiveClientBuilder implements LiveClientBuilder {
|
||||
dependance.registerSingleton(LiveHttpClient.class, TikTokLiveHttpClient.class);
|
||||
}
|
||||
|
||||
/* TODO in future, custom proxy implementation that can be provided via builder
|
||||
* if(customProxy != null)
|
||||
* dependance.registerSingleton(TikTokProxyProvider.class,customProxy);
|
||||
* else
|
||||
* dependance.registerSingleton(TikTokProxyProvider.class,DefaultProxyProvider.class);
|
||||
*/
|
||||
|
||||
//gifts
|
||||
if (clientSettings.isFetchGifts()) {
|
||||
dependance.registerSingleton(GiftsManager.class, TikTokLive.gifts());
|
||||
@@ -157,7 +158,13 @@ public class TikTokLiveClientBuilder implements LiveClientBuilder {
|
||||
//mapper
|
||||
dependance.registerSingleton(TikTokGenericEventMapper.class);
|
||||
dependance.registerSingleton(TikTokMapperHelper.class, TikTokLiveMapperHelper.class);
|
||||
dependance.registerSingleton(TikTokLiveMapper.class);
|
||||
dependance.registerSingleton(TikTokMapper.class, (container) ->
|
||||
{
|
||||
var dependace = (DependanceContainer) container.find(DependanceContainer.class);
|
||||
var mapper = MessagesMapperFactory.create(dependace);
|
||||
onCustomMappings.forEach(action -> action.accept(mapper));
|
||||
return mapper;
|
||||
});
|
||||
|
||||
//mapper handlers
|
||||
dependance.registerSingleton(TikTokCommonEventHandler.class);
|
||||
@@ -183,9 +190,8 @@ public class TikTokLiveClientBuilder implements LiveClientBuilder {
|
||||
}
|
||||
|
||||
/**
|
||||
* To do figure out how to use Annotation processor can could dynamically
|
||||
* like Lombok generates methods for all possible events, everytime library
|
||||
* is compiled
|
||||
* To do figure out how to use Annotation processor.
|
||||
* Goal is to generates methods for all possible events, everytime library is compiled
|
||||
*/
|
||||
public TikTokLiveClientBuilder onUnhandledSocial(EventConsumer<TikTokUnhandledSocialEvent> event) {
|
||||
eventHandler.subscribe(TikTokUnhandledSocialEvent.class, event);
|
||||
|
||||
@@ -26,10 +26,7 @@ import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent;
|
||||
import io.github.jwdeveloper.tiktok.live.builder.EventConsumer;
|
||||
import io.github.jwdeveloper.tiktok.live.LiveClient;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
|
||||
public class TikTokLiveEventHandler {
|
||||
private final Map<Class<?>, Set<EventConsumer>> events;
|
||||
@@ -39,16 +36,8 @@ public class TikTokLiveEventHandler {
|
||||
}
|
||||
|
||||
public void publish(LiveClient tikTokLiveClient, TikTokEvent tikTokEvent) {
|
||||
if (events.containsKey(TikTokEvent.class)) {
|
||||
var handlers = events.get(TikTokEvent.class);
|
||||
handlers.forEach(handler -> handler.onEvent(tikTokLiveClient,tikTokEvent));
|
||||
}
|
||||
|
||||
if (!events.containsKey(tikTokEvent.getClass())) {
|
||||
return;
|
||||
}
|
||||
var handlers = events.get(tikTokEvent.getClass());
|
||||
handlers.forEach(handler -> handler.onEvent(tikTokLiveClient,tikTokEvent));
|
||||
Optional.ofNullable(events.get(TikTokEvent.class)).ifPresent(handlers -> handlers.forEach(handler -> handler.onEvent(tikTokLiveClient, tikTokEvent)));
|
||||
Optional.ofNullable(events.get(tikTokEvent.getClass())).ifPresent(handlers -> handlers.forEach(handler -> handler.onEvent(tikTokLiveClient, tikTokEvent)));
|
||||
}
|
||||
|
||||
public <T extends TikTokEvent> void subscribe(Class<?> clazz, EventConsumer<T> event) {
|
||||
@@ -60,21 +49,10 @@ public class TikTokLiveEventHandler {
|
||||
}
|
||||
|
||||
public <T extends TikTokEvent> void unsubscribe(EventConsumer<T> consumer) {
|
||||
for (var entry : events.entrySet()) {
|
||||
entry.getValue().remove(consumer);
|
||||
}
|
||||
events.forEach((key, value) -> value.remove(consumer));
|
||||
}
|
||||
|
||||
public <T extends TikTokEvent> void unsubscribe(Class<?> clazz, EventConsumer<T> consumer) {
|
||||
if (clazz == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!events.containsKey(clazz)) {
|
||||
return;
|
||||
}
|
||||
|
||||
var eventSet = events.get(clazz);
|
||||
eventSet.remove(consumer);
|
||||
}
|
||||
}
|
||||
Optional.ofNullable(clazz).map(events::get).ifPresent(consumers -> consumers.remove(consumer));
|
||||
}
|
||||
}
|
||||
@@ -23,6 +23,7 @@
|
||||
package io.github.jwdeveloper.tiktok;
|
||||
|
||||
import com.google.protobuf.InvalidProtocolBufferException;
|
||||
import io.github.jwdeveloper.dependance.injector.api.annotations.Inject;
|
||||
import io.github.jwdeveloper.tiktok.common.*;
|
||||
import io.github.jwdeveloper.tiktok.data.requests.*;
|
||||
import io.github.jwdeveloper.tiktok.data.settings.LiveClientSettings;
|
||||
@@ -32,6 +33,7 @@ import io.github.jwdeveloper.tiktok.http.mappers.*;
|
||||
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastResponse;
|
||||
|
||||
import java.net.http.HttpResponse;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class TikTokLiveHttpClient implements LiveHttpClient
|
||||
@@ -53,17 +55,19 @@ public class TikTokLiveHttpClient implements LiveHttpClient
|
||||
private final GiftsDataMapper giftsDataMapper;
|
||||
private final Logger logger;
|
||||
|
||||
public TikTokLiveHttpClient(HttpClientFactory factory, LiveClientSettings settings) {
|
||||
@Inject
|
||||
public TikTokLiveHttpClient(HttpClientFactory factory) {
|
||||
this.httpFactory = factory;
|
||||
this.clientSettings = settings;
|
||||
this.clientSettings = factory.getLiveClientSettings();
|
||||
this.logger = LoggerFactory.create("HttpClient-"+hashCode(), clientSettings);
|
||||
liveUserDataMapper = new LiveUserDataMapper();
|
||||
liveDataMapper = new LiveDataMapper();
|
||||
giftsDataMapper = new GiftsDataMapper();
|
||||
}
|
||||
|
||||
public TikTokLiveHttpClient() {
|
||||
this(new HttpClientFactory(LiveClientSettings.createDefault()), LiveClientSettings.createDefault());
|
||||
public TikTokLiveHttpClient(Consumer<LiveClientSettings> consumer) {
|
||||
this(new HttpClientFactory(LiveClientSettings.createDefault()));
|
||||
consumer.accept(clientSettings);
|
||||
}
|
||||
|
||||
public GiftsData.Response fetchRoomGiftsData(String room_id) {
|
||||
@@ -191,7 +195,7 @@ public class TikTokLiveHttpClient implements LiveHttpClient
|
||||
.withParam("internal_ext", webcastResponse.getInternalExt())
|
||||
.withParams(webcastResponse.getRouteParamsMapMap())
|
||||
.build()
|
||||
.toUrl();
|
||||
.toUri();
|
||||
|
||||
return new LiveConnectionData.Response(websocketCookie, webSocketUrl, webcastResponse);
|
||||
} catch (InvalidProtocolBufferException e) {
|
||||
|
||||
@@ -31,6 +31,7 @@ import io.github.jwdeveloper.tiktok.data.events.websocket.TikTokWebsocketUnhandl
|
||||
import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveMessageException;
|
||||
import io.github.jwdeveloper.tiktok.live.LiveClient;
|
||||
import io.github.jwdeveloper.tiktok.mappers.TikTokLiveMapper;
|
||||
import io.github.jwdeveloper.tiktok.mappers.TikTokMapper;
|
||||
import io.github.jwdeveloper.tiktok.messages.webcast.WebcastResponse;
|
||||
import io.github.jwdeveloper.tiktok.utils.Stopwatch;
|
||||
|
||||
@@ -41,9 +42,9 @@ public class TikTokLiveMessageHandler {
|
||||
private final TikTokLiveEventHandler tikTokEventHandler;
|
||||
private final TikTokLiveMapper mapper;
|
||||
|
||||
public TikTokLiveMessageHandler(TikTokLiveEventHandler tikTokEventHandler, TikTokLiveMapper mapper) {
|
||||
public TikTokLiveMessageHandler(TikTokLiveEventHandler tikTokEventHandler, TikTokMapper mapper) {
|
||||
this.tikTokEventHandler = tikTokEventHandler;
|
||||
this.mapper = mapper;
|
||||
this.mapper = (TikTokLiveMapper) mapper;
|
||||
}
|
||||
|
||||
public void handle(LiveClient client, WebcastResponse webcastResponse) {
|
||||
@@ -61,20 +62,19 @@ public class TikTokLiveMessageHandler {
|
||||
public void handleSingleMessage(LiveClient client, WebcastResponse.Message message)
|
||||
{
|
||||
var messageClassName = message.getMethod();
|
||||
if (!mapper.isRegistered(messageClassName)) {
|
||||
tikTokEventHandler.publish(client, new TikTokWebsocketUnhandledMessageEvent(message));
|
||||
return;
|
||||
}
|
||||
var stopwatch = new Stopwatch();
|
||||
stopwatch.start();
|
||||
var events = mapper.handleMapping(messageClassName, message.getPayload().toByteArray());
|
||||
var handlingTimeInMs = stopwatch.stop();
|
||||
var metadata = new MessageMetaData(Duration.ofNanos(handlingTimeInMs));
|
||||
if (!mapper.isRegistered(messageClassName))
|
||||
tikTokEventHandler.publish(client, new TikTokWebsocketUnhandledMessageEvent(message));
|
||||
else {
|
||||
var stopwatch = new Stopwatch();
|
||||
stopwatch.start();
|
||||
var events = mapper.handleMapping(messageClassName, message.getPayload().toByteArray());
|
||||
var handlingTimeInMs = stopwatch.stop();
|
||||
var metadata = new MessageMetaData(Duration.ofNanos(handlingTimeInMs));
|
||||
|
||||
for (var event : events) {
|
||||
tikTokEventHandler.publish(client, new TikTokWebsocketMessageEvent(message, event, metadata));
|
||||
tikTokEventHandler.publish(client, event);
|
||||
for (var event : events) {
|
||||
tikTokEventHandler.publish(client, new TikTokWebsocketMessageEvent(message, event, metadata));
|
||||
tikTokEventHandler.publish(client, event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -90,14 +90,14 @@ public class HttpClient {
|
||||
return toResponse().map(HttpResponse::body);
|
||||
}
|
||||
|
||||
public URI toUrl() {
|
||||
public URI toUri() {
|
||||
var stringUrl = prepareUrlWithParameters(url, httpClientSettings.getParams());
|
||||
return URI.create(stringUrl);
|
||||
}
|
||||
|
||||
protected HttpRequest prepareGetRequest() {
|
||||
var requestBuilder = HttpRequest.newBuilder().GET();
|
||||
requestBuilder.uri(toUrl());
|
||||
requestBuilder.uri(toUri());
|
||||
requestBuilder.timeout(httpClientSettings.getTimeout());
|
||||
httpClientSettings.getHeaders().forEach(requestBuilder::setHeader);
|
||||
|
||||
|
||||
@@ -23,7 +23,9 @@
|
||||
package io.github.jwdeveloper.tiktok.http;
|
||||
|
||||
import io.github.jwdeveloper.tiktok.data.settings.*;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
public class HttpClientFactory {
|
||||
private final LiveClientSettings liveClientSettings;
|
||||
|
||||
|
||||
@@ -95,7 +95,7 @@ public class HttpProxyClient extends HttpClient {
|
||||
public X509Certificate[] getAcceptedIssuers() { return null; }
|
||||
}}, null);
|
||||
|
||||
URL url = toUrl().toURL();
|
||||
URL url = toUri().toURL();
|
||||
|
||||
if (proxySettings.hasNext()) {
|
||||
try {
|
||||
@@ -117,7 +117,7 @@ public class HttpProxyClient extends HttpClient {
|
||||
|
||||
var responseInfo = createResponseInfo(socksConnection.getResponseCode(), headers);
|
||||
|
||||
var response = createHttpResponse(body, toUrl(), responseInfo);
|
||||
var response = createHttpResponse(body, toUri(), responseInfo);
|
||||
|
||||
return ActionResult.success(response);
|
||||
} catch (IOException e) {
|
||||
|
||||
@@ -40,7 +40,8 @@ import static io.github.jwdeveloper.tiktok.messages.enums.LinkMessageType.*;
|
||||
public class MessagesMapperFactory {
|
||||
public static TikTokLiveMapper create(DependanceContainer container) {
|
||||
|
||||
var mapper = container.find(TikTokLiveMapper.class);
|
||||
var helper = container.find(TikTokMapperHelper.class);
|
||||
var mapper = new TikTokLiveMapper(helper);
|
||||
|
||||
//ConnectionEvents events
|
||||
var commonHandler = container.find(TikTokCommonEventHandler.class);
|
||||
|
||||
@@ -23,14 +23,10 @@
|
||||
package io.github.jwdeveloper.tiktok.mappers;
|
||||
|
||||
import com.google.protobuf.GeneratedMessageV3;
|
||||
import io.github.jwdeveloper.tiktok.TikTokLive;
|
||||
import io.github.jwdeveloper.tiktok.data.events.common.TikTokEvent;
|
||||
import io.github.jwdeveloper.tiktok.mappers.data.MappingAction;
|
||||
import io.github.jwdeveloper.tiktok.mappers.data.MappingResult;
|
||||
import io.github.jwdeveloper.tiktok.mappers.data.*;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
|
||||
public class TikTokLiveMapper implements TikTokMapper {
|
||||
@@ -47,11 +43,7 @@ public class TikTokLiveMapper implements TikTokMapper {
|
||||
|
||||
@Override
|
||||
public TikTokMapperModel forMessage(String messageName) {
|
||||
if (!isRegistered(messageName)) {
|
||||
var model = new TikTokLiveMapperModel(messageName);
|
||||
mappers.put(messageName, model);
|
||||
}
|
||||
return mappers.get(messageName);
|
||||
return mappers.computeIfAbsent(messageName, TikTokLiveMapperModel::new);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -66,7 +58,6 @@ public class TikTokLiveMapper implements TikTokMapper {
|
||||
return model;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public TikTokMapperModel forMessage(Class<? extends GeneratedMessageV3> mapperName, MappingAction<MappingResult> onMapping) {
|
||||
var model = forMessage(mapperName);
|
||||
@@ -84,7 +75,6 @@ public class TikTokLiveMapper implements TikTokMapper {
|
||||
return globalMapperModel;
|
||||
}
|
||||
|
||||
|
||||
public boolean isRegistered(String mapperName) {
|
||||
return mappers.containsKey(mapperName);
|
||||
}
|
||||
@@ -94,23 +84,19 @@ public class TikTokLiveMapper implements TikTokMapper {
|
||||
}
|
||||
|
||||
public List<TikTokEvent> handleMapping(String messageName, byte[] bytes) {
|
||||
if (!isRegistered(messageName)) {
|
||||
return List.of();
|
||||
}
|
||||
var mapperModel = mappers.get(messageName);
|
||||
if (mapperModel == null)
|
||||
return List.of();
|
||||
|
||||
var inputBytes = mapperModel.getOnBeforeMapping().onMapping(bytes, messageName, mapperUtils);
|
||||
var globalInputBytes = globalMapperModel.getOnBeforeMapping().onMapping(inputBytes, messageName, mapperUtils);
|
||||
|
||||
|
||||
var mappingResult = mapperModel.getOnMapping().onMapping(globalInputBytes, messageName, mapperUtils);
|
||||
|
||||
if (mappingResult == null) {
|
||||
mappingResult = globalMapperModel.getOnMapping().onMapping(globalInputBytes, messageName, mapperUtils);
|
||||
}
|
||||
if (mappingResult == null)
|
||||
mappingResult = globalMapperModel.getOnMapping().onMapping(globalInputBytes, messageName, mapperUtils);
|
||||
|
||||
var afterMappingResult = mapperModel.getOnAfterMapping().apply(mappingResult);
|
||||
var globalAfterMappingResult = globalMapperModel.getOnAfterMapping().apply(MappingResult.of(mappingResult.getSource(), afterMappingResult));
|
||||
return globalAfterMappingResult;
|
||||
return globalMapperModel.getOnAfterMapping().apply(MappingResult.of(mappingResult.getSource(), afterMappingResult));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -24,8 +24,6 @@ package io.github.jwdeveloper.tiktok.websocket;
|
||||
|
||||
import org.java_websocket.WebSocket;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
public class TikTokWebSocketPingingTask
|
||||
{
|
||||
private Thread thread;
|
||||
@@ -36,8 +34,7 @@ public class TikTokWebSocketPingingTask
|
||||
public void run(WebSocket webSocket, long pingTaskTime)
|
||||
{
|
||||
stop();
|
||||
thread = new Thread(() -> pingTask(webSocket, pingTaskTime));
|
||||
thread.setName("pinging-task");
|
||||
thread = new Thread(() -> pingTask(webSocket, pingTaskTime), "pinging-task");
|
||||
isRunning = true;
|
||||
thread.start();
|
||||
}
|
||||
@@ -51,16 +48,13 @@ public class TikTokWebSocketPingingTask
|
||||
|
||||
private void pingTask(WebSocket webSocket, long pingTaskTime)
|
||||
{
|
||||
var random = new Random();
|
||||
while (isRunning) {
|
||||
try {
|
||||
if (!webSocket.isOpen()) {
|
||||
if (webSocket.isOpen()) {
|
||||
webSocket.sendPing();
|
||||
Thread.sleep(pingTaskTime+(int)(Math.random() * MAX_TIMEOUT));
|
||||
} else
|
||||
Thread.sleep(SLEEP_TIME);
|
||||
continue;
|
||||
}
|
||||
webSocket.sendPing();
|
||||
|
||||
Thread.sleep(pingTaskTime+random.nextInt(MAX_TIMEOUT));
|
||||
}
|
||||
catch (Exception e) {
|
||||
//TODO we should display some kind of error message
|
||||
|
||||
@@ -32,7 +32,7 @@ import java.time.Duration;
|
||||
import java.util.logging.Level;
|
||||
|
||||
public class ConnectionExample {
|
||||
public static String TIKTOK_HOSTNAME = "kvadromama_marina1";
|
||||
public static String TIKTOK_HOSTNAME = "yttvandroid";
|
||||
|
||||
public static void main(String[] args) throws IOException {
|
||||
|
||||
|
||||
@@ -69,9 +69,7 @@ public class Events_And_Gifts_Testing_Example
|
||||
|
||||
var fakeGift = TikTokGiftEvent.of(roseGift);
|
||||
var fakeComboGift = TikTokGiftComboEvent.of(roseGift, 12, GiftComboStateType.Begin);
|
||||
|
||||
var fakeMessage = TikTokCommentEvent.of("Mark", "Hello world");
|
||||
|
||||
var fakeSubscriber = TikTokSubscribeEvent.of("Mark");
|
||||
var fakeFollow = TikTokFollowEvent.of("Mark");
|
||||
var fakeLike = TikTokLikeEvent.of("Mark", 12);
|
||||
|
||||
Reference in New Issue
Block a user